From 39d65020c9231856e11f302d6617a3487ee59a2e Mon Sep 17 00:00:00 2001 From: mintaka Date: Sun, 13 Sep 2026 16:25:24 -0400 Subject: [PATCH 1/3] docs(designs): scrub the private repo's former name and gate it (RIG-3756) Family 5 of the managed-boundary leak: the private repo's former proper name and live paths inside it, left behind when families 1-4 were scrubbed. The census that drove the earlier passes scoped itself to docs/ + AGENTS.md, so code and config were structurally invisible to it. Sweeping the tracked tree instead found the former name in apps/eng-docs and .moon/workspace.yml, and family 4 still alive in 11 files under tools/ and agent-image/. Records keep every technical claim; only the provenance descriptor changes. A path citation becomes the mechanism it establishes, so a reader with access can still find the source and a reader without one learns the design. The replacement vocabulary (prior art, out of tree, the fleet, managed-plane) all pre-existed in the corpus. The gate now scans for the former name too, but cannot do it whole-word: the word is ordinary English throughout go/ (a sealed sum type, a ciphertext sealed under a key, an egress-sealed agent). Measured over the tracked tree a whole-word scan flags 60 lines, every one legitimate -- a gate that is 100% false positives gets switched off. It matches only repo-shaped uses: a path inside the repo, its docsite host, its possessive, or the word followed by a repo noun. Tests pin both directions, including the three public names that carry the string and must never trip it. Code comments lose their migration narration outright rather than being reworded -- a public reader needs what the code does, not where it came from. Co-authored-by: Matt Wilkinson wip: resolve rebase conflicts --- .moon/workspace.yml | 7 +- apps/eng-docs/moon.yml | 2 +- apps/eng-docs/scripts/deploy.ts | 4 +- docs/designs/CONTRIBUTING.md | 6 +- .../agent/compass-agent-container-runtime.md | 2 +- .../agent/compass-forks-reversal/design.md | 22 +- .../compass-manager-comms-substrate/design.md | 2 +- .../ci/compass-agent-image-publish/design.md | 12 +- .../design.md | 2 +- .../infra/ci/compass-dogfood-e2e/design.md | 4 +- .../infra/ci/compass-dogfood-loop/design.md | 4 +- .../meta/compass-design-ledger/design.md | 2 +- .../repo/compass-design-docs-reorg/design.md | 12 +- docs/designs/repo/compass-eng-docs/design.md | 248 +++++++++--------- ...n-offline-redelivery-pre-settle-closure.md | 2 +- .../compass-mention-offline-redelivery.md | 2 +- .../design.md | 2 +- docs/designs/ui/compass-session-trace-diff.md | 4 +- .../design.md | 6 +- .../ui/compass-ux-foundation/design.md | 2 +- tools/agent-image-env-gate/env-check.ts | 2 +- tools/design-ledger-gate/moon.yml | 5 +- tools/orion-ref-gate/index.test.ts | 38 +++ tools/orion-ref-gate/index.ts | 52 +++- tools/renovate-preflight/moon.yml | 2 +- tools/renovate/bot-config.json5 | 2 +- tools/renovate/config.json5 | 10 +- tools/renovate/config.test.ts | 10 +- tools/renovate/moon.yml | 2 +- tools/renovate/package.json | 2 +- .../renovate/refresh-toolchain-hashes.test.ts | 3 +- tools/renovate/refresh-toolchain-hashes.ts | 6 +- 32 files changed, 267 insertions(+), 214 deletions(-) diff --git a/.moon/workspace.yml b/.moon/workspace.yml index 773d9d18a..608412e24 100644 --- a/.moon/workspace.yml +++ b/.moon/workspace.yml @@ -86,11 +86,10 @@ projects: stamp-gate: 'tools/stamp-gate' # The design-ledger gate: validates the Compass design-decision ledger # (docs/designs/DECISIONS.md), the per-record `Status:` headers, and - # dangling supersession/Record pointers (RIG-1187). Migrated from the sealed - # repo with the corpus it governs (RIG-1794). + # dangling supersession/Record pointers (RIG-1187). design-ledger-gate: 'tools/design-ledger-gate' # The orion-ref-gate boundary gate (RIG-2489): fail-closed scan that the PUBLIC - # compass repo carries no reference to the PRIVATE internal monorepo. Mirrors + # compass repo carries no out-of-tree reference the managed boundary forbids. Mirrors # design-ledger-gate; registered here so its check + typecheck + unit test run # in the moon-driven CI sweep — unregistered, moon never discovers it and the # boundary re-rots uncaught. @@ -138,7 +137,7 @@ projects: # silently inert (moon discovers projects only from this map) and the config # drift it fences ships uncaught. renovate: 'tools/renovate' - # The Renovate preflight probe (ported from the internal monorepo's preflight probe): + # The Renovate preflight probe: # checks the minted App token can see the repo before `bunx renovate` runs, # failing fast with a named diagnosis instead of Renovate's opaque # platform-unknown-error. Registered so its own typecheck + unit test gate. diff --git a/apps/eng-docs/moon.yml b/apps/eng-docs/moon.yml index 4c3b0baa2..d4c6d013a 100644 --- a/apps/eng-docs/moon.yml +++ b/apps/eng-docs/moon.yml @@ -5,7 +5,7 @@ # devenv toolchain on PATH. install/lint/format are inherited (bun tag → # root:install; biome + markdownlint are the root whole-repo sweep, which lints # the canonical docs/ sources — the generated src/content/docs/ mirror is -# gitignored and exempt). Public counterpart to sealed/apps/docs: no Cloudflare +# gitignored and exempt). Unlike the prior art's docs app: no Cloudflare # Access gate, no PostHog analytics. workspace: inheritedTasks: diff --git a/apps/eng-docs/scripts/deploy.ts b/apps/eng-docs/scripts/deploy.ts index 09d7904a8..31233abc9 100644 --- a/apps/eng-docs/scripts/deploy.ts +++ b/apps/eng-docs/scripts/deploy.ts @@ -5,8 +5,8 @@ // GitHub Actions workflow (RIG-1765). The engineering docsite lives on // Cloudflare Pages under the compass-eng-docs project. // -// Adapted from sealed apps/docs/scripts/deploy.ts — they share the same -// Cloudflare Pages deploy + PR-preview-comment shape and the three constants +// Shares the same Cloudflare Pages deploy + PR-preview-comment shape as the +// prior art, including the three constants // below (PROJECT_NAME, COMMENT_MARKER, SITE_LABEL). This docsite build gathers // the compass repo's markdown, so its preview comment also deep-links the .md // pages a PR changed (changedDocPages + commentBody's "Changed pages" section). diff --git a/docs/designs/CONTRIBUTING.md b/docs/designs/CONTRIBUTING.md index 9dea63760..8e6af9d53 100644 --- a/docs/designs/CONTRIBUTING.md +++ b/docs/designs/CONTRIBUTING.md @@ -7,7 +7,7 @@ a form they did not intend to publish. These five rules are the standing policy for every design record authored here going forward. Rules 1-4 match the sanitization the one-shot migration applied -to the records imported from the private `sealed` repo (new records should be +to records imported from out of tree (new records should be written this way from the start so they need no migration); rule 5 governs what happens to a record's inbound links when another record is deleted. @@ -26,8 +26,8 @@ harmless. A dead `linear.app` URL is worse than no URL. ## 2. No `oss/compass/` path prefixes -The private repo vendored Compass under `oss/compass/`. This repo **is** that -tree, without the prefix. Cite paths relative to the repo root: +Some imported records cite Compass paths under an `oss/compass/` prefix. This +repo **is** that tree, without the prefix. Cite paths relative to the repo root: - `oss/compass/go/internal/runtime/image.go` → `go/internal/runtime/image.go` - `oss/compass/apps/ui/src/stub-data.ts` → `apps/ui/src/stub-data.ts` diff --git a/docs/designs/agent/compass-agent-container-runtime.md b/docs/designs/agent/compass-agent-container-runtime.md index 931aa4f9c..669e0412c 100644 --- a/docs/designs/agent/compass-agent-container-runtime.md +++ b/docs/designs/agent/compass-agent-container-runtime.md @@ -485,7 +485,7 @@ transcript-scoped, not container-scoped.) ### Spec impact — supersession, by citation -Per the sealed frozen-record convention, merged records are never edited; +Per the frozen-record convention, merged records are never edited; this record supersedes specific claims by citing them, and the **impl PR's living-spec update** carries the replacement into `docs/specs/product/compass.md`: diff --git a/docs/designs/agent/compass-forks-reversal/design.md b/docs/designs/agent/compass-forks-reversal/design.md index ab57b0995..1c975aad9 100644 --- a/docs/designs/agent/compass-forks-reversal/design.md +++ b/docs/designs/agent/compass-forks-reversal/design.md @@ -23,7 +23,7 @@ machinery that existed only to carry them. - **FROZEN (Matt, 2026-08-19): shared `RigelBuild/{devenv,nix2container,oh-my-pi}` repos + combined patch work.** Compass consumes the shared canonical fork - repos — one canonical fork per upstream. Sealed patches useful to both the + repos — one canonical fork per upstream. Patches useful to both the fleet and compass land in the shared repos, never duplicated. Do not relitigate; tasks execute it. - **Shared-repo patch ownership is disjoint (forge coordination, 2026-08-19).** @@ -133,7 +133,7 @@ is compass's review point — not a mechanical path swap. `moon.yml` check task carries `/forks/devenv/**` as an affected-detection input glob (`agent-image-env-gate/moon.yml:58`). -**The sealed patch is compass-specific and load-bearing.** All of it sits in +**The `containers.nix` patch is compass-specific and load-bearing.** All of it sits in `forks/devenv/src/modules/containers.nix`: - Per-container `user`/`group`/`homeDir` options (`containers.nix:373` — @@ -154,7 +154,7 @@ UPSTREAM (verified 2026-08-19 against `RigelBuild/devenv@afed7bf3` `src/modules/containers.nix`: `homeDir = "/env";` hardcoded in a module-scope `let`, `envContainerName = builtins.getEnv "DEVENV_CONTAINER"` present, no per-container identity options). The shared `RigelBuild/devenv` fork carries no -sealed diff for this and has no devenv consumer of its own. Per Matt's ruling, +diff for this and has no devenv consumer of its own. Per Matt's ruling, compass's `containers.nix` patch set therefore **lands INTO `RigelBuild/devenv` first** (harmless to other consumers, required by compass), and only then does compass repoint to `github:RigelBuild/devenv`. A naive repoint before the patch @@ -177,7 +177,7 @@ rationale. path:../forks/nix2container#skopeo-nix2container`. The env-gate also globs `/forks/nix2container/**` (`agent-image-env-gate/moon.yml:59`). -**The sealed patch is shared.** `forks/nix2container/default.nix:396-399` drops +**This patch is shared.** `forks/nix2container/default.nix:396-399` drops relocated copyToRoot paths from the initialized nix DB: ```nix @@ -216,9 +216,9 @@ merge and the rev were re-verified at source before this fold.) ### oh-my-pi **Consumer shape: no *build* consumer, one *tooling* consumer.** The tree is -plain upstream at tag `v17.1.8` with no sealed diff (`forks/README.md:151-155` — -"Sealed changes: NONE … verified byte-identical to `can1357/oh-my-pi` at -`v17.1.8`"); no compass image or app build consumes it (`forks/README.md:214`). +plain upstream at tag `v17.1.8` with no local diff at all — verified +byte-identical to `can1357/oh-my-pi` at `v17.1.8` — and no compass image or +app build consumes it. But it is **not** consumer-free: the store door's credential-denylist generator reads the subtree directly — `go/internal/store/gen_credential_keys.go:42` (`const schemaRelPath = "../../../forks/oh-my-pi/packages/coding-agent/src/config/settings-schema.ts"`), @@ -244,7 +244,7 @@ removes 5892 of the 7424 vendored files in one move. The one real consumer — the generator — should read the npm-installed schema the agent actually runs (`packages/compass-agent/node_modules/@oh-my-pi/pi-coding-agent/src/config/settings-schema.ts`, pinned at `packages/compass-agent/package.json:19`), so the denylist tracks the version -in production rather than a vendored snapshot. The sealed deltas catalogued in +in production rather than a vendored snapshot. The deltas catalogued in `forks/README.md:156-197` live in the monorepo fork and are `RigelBuild/oh-my-pi`'s concern, not compass's. Drop-vs-consume is a load-bearing Open Question (OQ1) — but the one real consumer wanting the npm @@ -272,7 +272,7 @@ this record does not require it. - **Compass-own fork repos** (`RigelBuild/compass-devenv` etc., or reviving the per-upstream Copybara spoke repos) — rejected. Matt ruled shared canonical repos: one fork per upstream, patch work combined. Two forks of the same - upstream would duplicate the sealed patches and re-create the divergence this + upstream would duplicate the patch work and re-create the divergence this reversal exists to end. Frozen; not relitigated here. - **Defer until the fleet's reversal fully lands** — rejected. Only the nix2container lane has a genuine cross-repo dependency (the shared @@ -304,7 +304,7 @@ Contribute compass's devenv patch set into `RigelBuild/devenv`, and confirm the nix2container shared fix has landed. - **L0a — land the `containers.nix` patch in `RigelBuild/devenv`.** Port the - full sealed diff from `forks/devenv/src/modules/containers.nix` (per-container + full diff from `forks/devenv/src/modules/containers.nix` (per-container `user`/`group`/`homeDir` options with upstream values as defaults, `containers.nix:373-389`; the `$HOME`-staging guard; the `imageEnv` DEVENV_-filter, `containers.nix:181`; the config-only `buildingContainer` @@ -342,7 +342,7 @@ nix2container shared fix has landed. Interfaces: -- Consumes: `forks/devenv/src/modules/containers.nix` (the sealed diff, source +- Consumes: `forks/devenv/src/modules/containers.nix` (the diff, source of truth for L0a); the shared nix-DB-drop fix on `RigelBuild/nix2container`. - Produces: `RigelBuild/devenv` `main` rev carrying the patch; `RigelBuild/nix2container` `master` rev carrying the shared fix. These two diff --git a/docs/designs/agent/compass-manager-comms-substrate/design.md b/docs/designs/agent/compass-manager-comms-substrate/design.md index 5098bbd78..8c3ce2113 100644 --- a/docs/designs/agent/compass-manager-comms-substrate/design.md +++ b/docs/designs/agent/compass-manager-comms-substrate/design.md @@ -292,7 +292,7 @@ DL-054 amendment). Every task below inherits these; task briefs do not restate them. -- **Two-repo split.** This record lives in `sealed` (design corpus); +- **Two-repo split.** This design corpus lives out of tree; implementation lands in `RigelBuild/compass`. All file:line citations below are into the compass clone. - **Additive-only proto changes.** New fields, new enum values, new RPCs, new diff --git a/docs/designs/infra/ci/compass-agent-image-publish/design.md b/docs/designs/infra/ci/compass-agent-image-publish/design.md index f95229c2a..a2188131b 100644 --- a/docs/designs/infra/ci/compass-agent-image-publish/design.md +++ b/docs/designs/infra/ci/compass-agent-image-publish/design.md @@ -8,10 +8,10 @@ Tracking: RIG-1690 (blocks compass-native RIG-1683/T2, RIG-1685/T4, RIG-1687/T6) > `agent-image/*`, `.github/workflows/*`, `forks/*`, `go/cmd/*`, `ci.yml`, > `devenv.nix`, `packages/compass-agent/*`, and `docs/architecture/*` citation > below is a path in that repo at HEAD `b3fc25311`, not this one (line numbers -> drift as the code evolves; resolve them against that commit). It lives in the -> sealed design corpus (`docs/designs/infra/ci/`) because that is where the wave's design +> drift as the code evolves; resolve them against that commit). It lives out of +> tree because that is where the wave's design > records freeze; the `docs/designs/ui/*` cross-references (e.g. DL-112) -> are paths in this (sealed) corpus. +> are paths in this corpus. > > **Superseded in part** (RIG-1746, Matt 2026-08-25): the *CI-placement* > decision below — a separate `.github/workflows/publish-agent-image.yml` @@ -517,11 +517,11 @@ Interfaces: ## Open Questions -- **[Resolved] Record placement.** This record lives in the sealed design - corpus (`docs/designs/infra/ci/`), the wave's canonical home for frozen +- **[Resolved] Record placement.** This record lives out of tree, + the wave's canonical home for frozen design records, beside the other `compass-*` records. T4 folds the durable operational content into the compass repo's `docs/architecture/build-and-ci.md` - once implemented; this record stays the design of record in sealed. + once implemented; this record stays the design of record out of tree. - **[Non-load-bearing] GA release tag.** RIG-1687 will likely want `:v` alongside `:git-`; T1's tag-list CLI makes that a no-redesign later add. Deferred to GA planning. diff --git a/docs/designs/infra/ci/compass-dogfood-e2e-steer-deliver-seam/design.md b/docs/designs/infra/ci/compass-dogfood-e2e-steer-deliver-seam/design.md index 1fb72df44..e2bf33775 100644 --- a/docs/designs/infra/ci/compass-dogfood-e2e-steer-deliver-seam/design.md +++ b/docs/designs/infra/ci/compass-dogfood-e2e-steer-deliver-seam/design.md @@ -278,7 +278,7 @@ In dependency order — T2 depends on T1, T3 on T1+T2. (window-scoped to each recipient's turn settle): peer-1 no `deliver`, spawner no `steer` for that id. -Note on ledgers: this record lives in the sealed platform design corpus +Note on ledgers: this record lives out of tree (`docs/designs/platform/`), which the design-ledger-gate governs only for the **product** corpus (`docs/designs/product/DECISIONS.md`). A platform record adds no DECISIONS row and declares no ledger delta, mirroring its frozen parent diff --git a/docs/designs/infra/ci/compass-dogfood-e2e/design.md b/docs/designs/infra/ci/compass-dogfood-e2e/design.md index 06368beb2..2c93196b5 100644 --- a/docs/designs/infra/ci/compass-dogfood-e2e/design.md +++ b/docs/designs/infra/ci/compass-dogfood-e2e/design.md @@ -11,7 +11,7 @@ Status: Draft > for the Dogfood milestone. The design targets the **`RigelBuild/compass`** > repo; every `go/*`, `proto/*`, `packages/*`, `apps/*`, and `devenv.nix:*` > citation below is a path in that repo at origin/main HEAD `abdb412c`, not -> this one. It lives in the sealed design corpus because that is where the +> this one. It lives out of tree because that is where the > wave's design records freeze. ## Problem / Intent @@ -45,7 +45,7 @@ messaging with @mention delivery, (5) teardown + resume from durable state — becomes the first scenario set authored on the harness and remains the concrete Dogfood acceptance gate. -Note on ledgers: this record lives in the sealed design corpus +Note on ledgers: this record lives out of tree (`docs/designs/platform/`), which the design-ledger-gate governs only for the **product** corpus (`docs/designs/product/DECISIONS.md`). A platform record adds no DECISIONS row and declares no ledger delta, so nothing here is diff --git a/docs/designs/infra/ci/compass-dogfood-loop/design.md b/docs/designs/infra/ci/compass-dogfood-loop/design.md index 5a98d2648..0a591ba60 100644 --- a/docs/designs/infra/ci/compass-dogfood-loop/design.md +++ b/docs/designs/infra/ci/compass-dogfood-loop/design.md @@ -8,7 +8,7 @@ Status: Active > end to end. The design targets the **`RigelBuild/compass`** repo (its > `devenv.nix`, `agent-image/`, and `go/cmd/*` binaries); every `devenv.nix:*`, > `agent-image/*`, and `go/cmd/*` citation below is a path in that repo at HEAD -> `21241f720`, not this one. It lives in the sealed design corpus because that is +> `21241f720`, not this one. It lives out of tree because that is > where the wave's design records freeze. ## Problem / Intent @@ -26,7 +26,7 @@ self-signed cert) and idles, and a real session is driven end to end (`CommsService.CreateAgent` → `CompassService.ProvisionAgentWorkspace` → `StartAgentSession`), so a real container spawns and runs an agent turn. -Note on ledgers: this record lives in the sealed design corpus +Note on ledgers: this record lives out of tree (`docs/designs/platform/`), which the design-ledger-gate governs only for the **product** corpus (`docs/designs/product/DECISIONS.md`). A platform record adds no DECISIONS row and declares no ledger delta, so nothing here is ledger-tracked; diff --git a/docs/designs/meta/compass-design-ledger/design.md b/docs/designs/meta/compass-design-ledger/design.md index aa88b6530..d67fc7400 100644 --- a/docs/designs/meta/compass-design-ledger/design.md +++ b/docs/designs/meta/compass-design-ledger/design.md @@ -203,7 +203,7 @@ fast-follow diff-aware core promotes it to gate-checked (merge-base compare). ### 4. The workflow rule — same-PR ledger flip + code-comment citation The ledger is the ONE living exception to freeze-on-merge, BY DESIGN. It -stays consistent with the freeze model the same way specs do — the sealed +stays consistent with the freeze model the same way specs do — the convention "update the matching `docs/specs/` doc *in the same PR* as the code" (`AGENTS.md:73-74`) extends to the ledger: **the PR that freezes a record also appends its new decision rows and flips any rows it supersedes.** diff --git a/docs/designs/repo/compass-design-docs-reorg/design.md b/docs/designs/repo/compass-design-docs-reorg/design.md index 2b727864f..a12967381 100644 --- a/docs/designs/repo/compass-design-docs-reorg/design.md +++ b/docs/designs/repo/compass-design-docs-reorg/design.md @@ -27,7 +27,7 @@ this record). Two problems: also collides with the fleet-wide sense of "platform" (the shared infrastructure layer), making it doubly ambiguous in a product repo. The bucket is an accident of migration: the eng-docs migration record itself asserted - "`platform/` — a sealed-monorepo domain — does not exist in compass" + "`platform/` — an out-of-tree domain — does not exist in compass" (`docs/designs/repo/compass-eng-docs/design.md:386-387`), yet 17 records now live there. @@ -205,7 +205,7 @@ docs/designs/platform/compass-renovate-migration.md"), `buf.gen.yaml:9`, `packages/compass-agent/src/transport/*` file comments, and gate/test fixtures (`tools/design-ledger-gate/index.test.ts`, `tools/orion-ref-gate/index.test.ts` — fixture strings, not live paths). Inside the corpus, 41 more `docs/designs/platform` -prose citations. Two cited paths are **already dead** (sealed-repo records that +prose citations. Two cited paths are **already dead** (out-of-tree records that never migrated, pre-existing rot, out of scope but noted): `buf.gen.yaml:9` (`docs/designs/platform/go-toolchain-default.md`) and `devenv.nix:208` (`docs/designs/platform/ci-toolchain-shared-defs.md`). @@ -486,8 +486,8 @@ the gate expansion it forces, and the migration strategy: *metadata* edits ride the same standard: Status-header normalization to the gate grammar (`index.ts:87`) for newly-governed records, and one-line corrections of a record's stale self-described location - (`compass-agent-image-publish.md:8-11,500-504` says it "lives in the sealed - design corpus") — location metadata and machine-checked headers, not + (`compass-agent-image-publish.md:8-11,500-504` says it "lives out of tree") + — location metadata and machine-checked headers, not decisions. ## Alternatives considered @@ -849,8 +849,8 @@ Interfaces: ### T9 — Post-move verification sweep Repo-wide grep proves zero live references to `docs/designs/platform/` (the -two pre-existing dead sealed citations `buf.gen.yaml:9` / `devenv.nix:208` are -re-pointed to prose or left with an explicit "sealed-private" annotation — +two pre-existing dead citations `buf.gen.yaml:9` / `devenv.nix:208` are +re-pointed to prose or left with an explicit "out-of-tree" annotation — executor's call, flagged in the PR) and that the only remaining `docs/designs/product/` paths are the T10-deferred native-family records and their Record cells. Docsite build renders every record; spot-check routes for diff --git a/docs/designs/repo/compass-eng-docs/design.md b/docs/designs/repo/compass-eng-docs/design.md index 6d04e0ea6..021b65f46 100644 --- a/docs/designs/repo/compass-eng-docs/design.md +++ b/docs/designs/repo/compass-eng-docs/design.md @@ -19,7 +19,7 @@ naming and `docs.compass.rigel.build` domain. This site takes This record is itself the first artifact under the new convention: it is authored in `RigelBuild/compass` at -`docs/designs/repo/compass-eng-docs/design.md`, not in sealed. +`docs/designs/repo/compass-eng-docs/design.md`, not out of tree. ## Problem / Intent @@ -28,16 +28,15 @@ invisible to the public the product is being built in the open for; the public `RigelBuild/compass` repo has no docsite and no `docs/designs/` tree (only `docs/architecture/build-and-ci.md`, verified this session). Move the Compass records + specs here and publish them on a -public Starlight engineering docs site with sealed's per-PR-preview UX, +public Starlight engineering docs site with the prior art's per-PR-preview UX, re-based from Woodpecker onto GitHub Actions and with no Cloudflare Access gate. ## Global Constraints -- **Public repo, public site — no access gate.** sealed's docsite is - "gated to the team via Cloudflare Access" - (`sealed/apps/docs/astro.config.mjs:9-10`: "to - sealed-docs.rigel.build via Cloudflare Pages, gated to the team via - Cloudflare Access"). The compass mirror deliberately drops the Access gate: +- **Public repo, public site — no access gate.** The prior art's docsite is + gated to the team via Cloudflare Access — its Astro config deploys the built + site to a team-only host fronted by Cloudflare Access. The compass mirror + deliberately drops the Access gate: the site is public. Nothing in the docsite build, deploy, or content may assume an authenticated reader. - **Fork-PR secret hygiene.** The repo is public, so `pull_request` events @@ -53,8 +52,8 @@ re-based from Woodpecker onto GitHub Actions and with no Cloudflare Access gate. (`compass/.prototools:6-8`). New shared JS deps ride the root catalog (`compass/package.json:5`: "pins shared dependency versions via the catalog"); app runtime deps (astro, @astrojs/starlight, github-slugger, - sharp) go in `apps/eng-docs/package.json` following sealed's shape - (`sealed/apps/docs/package.json:13-19`). + sharp) go in `apps/eng-docs/package.json` following the prior art's shape + (its docs app declares these same runtime deps). - **One CI job, no matrix.** compass CI is deliberately a single job running `moon ci :ci` on PRs and `moon run :ci` on main (`compass/.github/workflows/ci.yml:4`: "ONE JOB, NOT A MATRIX — the central @@ -74,10 +73,9 @@ re-based from Woodpecker onto GitHub Actions and with no Cloudflare Access gate. - **Security sections are kept.** Matt ruled that the 13 records carrying threat-model / security-boundary / egress sections are fine to expose. Do not strip or soften them. -- **Generated content is gitignored.** As in sealed - (`sealed/apps/docs/package.json:5`: "Content under src/content/docs/ is - generated by scripts/gather.ts … and is gitignored; edit the canonical - sources, not the generated copy"). +- **Generated content is gitignored.** As in the prior art: content under + `src/content/docs/` is generated by `scripts/gather.ts` and is gitignored; + edit the canonical sources, not the generated copy. - **markdownlint governs the canonical sources.** compass already lints all `*.md` with `ignores: ["forks/*/**"]` (`compass/.markdownlint-cli2.jsonc:8-10`); migrated records must pass it. @@ -89,42 +87,37 @@ re-based from Woodpecker onto GitHub Actions and with no Cloudflare Access gate. ## Approach -Mirror sealed's docsite mechanism — one Starlight app, a gather script that +Mirror the prior art's docsite mechanism — one Starlight app, a gather script that mirrors the repo's reviewed markdown into a gitignored content collection, a generated sidebar, per-page GitHub editUrl, pagefind search, and a deploy script that pushes `dist/` to Cloudflare Pages and upserts a preview-URL PR comment — with two deliberate divergences: **CI is GitHub Actions, not Woodpecker**, and **the site is public with no Access gate**. -### (a) The site: `apps/eng-docs`, a compass-adapted mirror of sealed's docsite +### (a) The site: `apps/eng-docs`, a compass-adapted mirror of the prior art's docsite -sealed's shape, extracted at source this session: +The prior art's shape, extracted at source this session: - **App layout** — `apps/eng-docs/{astro.config.mjs,package.json,moon.yml, tsconfig.json,src/,public/,scripts/{gather.ts,deploy.ts}}` with `src/content/docs/` + `src/sidebar.generated.ts` generated and gitignored. - **Gather** mirrors every tracked `*.md` (minus exclusions) into the content - collection, classified into nav sections. sealed's taxonomy - (`gather.ts:43-51`): `designs / specs / research / team / packages / infra / - contributing`. Its classifier keys `docs//…` to the matching section - and routes everything else to contributing/packages - (`gather.ts:94-123`). Exclusions come from the canonical - `.markdownlint-cli2.jsonc` `ignores` list — "the single source of truth" - (`gather.ts:126-137`, `parseExclusions` returns - `[...ignores, "oss/seal/**", "**/outputs/**"]`). + collection, classified into nav sections. The prior art's taxonomy: + `designs / specs / research / team / packages / infra / contributing`. Its + classifier keys `docs//…` to the matching section and routes + everything else to contributing/packages. Exclusions come from the canonical + `.markdownlint-cli2.jsonc` `ignores` list — "the single source of truth" — + its `parseExclusions` returns `[...ignores, "oss/seal/**", "**/outputs/**"]`. - **Per-page editUrl** — `editUrlFor` builds - `https://github.com/${REPO_SLUG}/edit/main/${sourcePath}` - (`gather.ts:203-205`), with `REPO_SLUG = "RigelBuild/compass"` - (`gather.ts:25`). + `https://github.com/${REPO_SLUG}/edit/main/${sourcePath}`, with + `REPO_SLUG = "RigelBuild/compass"`. - **Starlight config** — `pagefind: true`, generated `sidebar`, `editLink`, - `lastUpdated`, expressiveCode tokyo-night - (`astro.config.mjs:51-66`). + `lastUpdated`, expressiveCode tokyo-night. - **moon tasks** — `gather` (inputs `/**/*.md` + the markdownlint config, so - moon's affected graph rebuilds the site whenever any gathered doc changes, - `moon.yml:18-25`), `build` (`bunx astro build`, deps `['gather']`, - `moon.yml:27-39`), `check` (`bunx astro check`, `moon.yml:43-52`), and - `deploy`/`deploy-preview` (`runInCI: false`, both `bun scripts/deploy.ts`, - `moon.yml:69-74`). + moon's affected graph rebuilds the site whenever any gathered doc changes), + `build` (`bunx astro build`, deps `['gather']`), `check` (`bunx astro + check`), and `deploy`/`deploy-preview` (`runInCI: false`, both + `bun scripts/deploy.ts`). The compass adaptation: @@ -137,13 +130,13 @@ The compass adaptation: - **`REPO_SLUG = "RigelBuild/compass"`**; editUrl points here. - **Exclusions**: compass's `.markdownlint-cli2.jsonc` `ignores` is `["forks/*/**"]` (`compass/.markdownlint-cli2.jsonc:10`); the gather adds - its own tree + `**/outputs/**` as sealed's does, and drops the + its own tree + `**/outputs/**` as the prior art's does, and drops the `oss/seal/**` special case (no such tree here). -- **`packagePath`'s `oss` special case drops** (`sealed gather.ts:78` +- **`packagePath`'s `oss` special case drops** (the prior art's `gather.ts` special-cases `apps|oss` two-segment package ids; compass keeps `apps` and gains nothing for `oss`, which does not exist here). -- **No Cloudflare Access, no PostHog identity inheritance** — sealed's - `cross_subdomain_cookie` PostHog block (`astro.config.mjs:26-46`) depends on +- **No Cloudflare Access, no PostHog identity inheritance** — the prior art's + `cross_subdomain_cookie` PostHog block depends on the Access-identified apex; the compass site ships either no analytics or a plain PostHog snippet (Open Question Q4 covers the domain; analytics rides the same decision). @@ -154,31 +147,29 @@ The compass adaptation: docs-affecting PR builds the site as part of the one CI job at zero workflow churn. - **Accepted cost — any markdown edit rebuilds the site in the required - check.** `gather`'s inputs are the repo-wide `/**/*.md` glob (mirroring - sealed), and `build`/`check` depend on it inside the one required + check.** `gather`'s inputs are the repo-wide `/**/*.md` glob (mirroring the + prior art), and `build`/`check` depend on it inside the one required `moon ci :ci` gate — so moon's affected graph triggers a full gather + `astro build` + `astro check` on ANY PR touching ANY `*.md`, not just docs PRs (a one-line README fix blocks on a full corpus build). Same tradeoff - sealed accepts for its one-job gate (`ci.yml:20-22`); named here, not free. + the prior art accepts for its one-job gate; named here, not free. The narrow alternative — scope `gather` inputs to `docs/**/*.md` + the - contributing files — is rejected to keep parity with sealed's glob and avoid + contributing files — is rejected to keep parity with the prior art's glob and avoid a package-README doc link silently going stale un-rebuilt. ### (b) Per-PR preview: a GHA workflow doing `wrangler pages deploy` -sealed's preview UX, at source: Woodpecker's Petrel policy fans out +The prior art's preview UX, at source: Woodpecker's Petrel policy fans out `docs-site:deploy` on `push:main` and `docs-site:deploy-preview` on -`pull_request` (`sealed/ci/pipeline.ts:554-563`), both `runInCI: false` moon -tasks running `bun scripts/deploy.ts` (`sealed/apps/docs/moon.yml:69-74`). -`deploy.ts` picks the Pages `--branch` from the event — production is the -`"main"` alias, a PR deploys under its SOURCE branch and refuses to fall back -("Never fall back to a target branch on a PR — that would risk deploying a -preview over production", `deploy.ts:62-79`) — runs -`wrangler pages deploy dist --project-name=… --branch=… --commit-dirty=true` -(`deploy.ts:82-94`), parses the preview URL from wrangler output -(`deploy.ts:101-104`), and upserts a marker-keyed PR comment with the preview -link + changed-page deep links via the gh CLI (`deploy.ts:41`, -`COMMENT_MARKER = ""`). +`pull_request`, both `runInCI: false` moon tasks running +`bun scripts/deploy.ts`. `deploy.ts` picks the Pages `--branch` from the +event — production is the `"main"` alias, a PR deploys under its SOURCE branch +and refuses to fall back ("Never fall back to a target branch on a PR — that +would risk deploying a preview over production") — runs +`wrangler pages deploy dist --project-name=… --branch=… --commit-dirty=true`, +parses the preview URL from wrangler output, and upserts a marker-keyed PR +comment with the preview link + changed-page deep links via the gh CLI +(`COMMENT_MARKER = ""`). The compass version keeps `deploy.ts` (adapted) and swaps the driver from Woodpecker to a dedicated GHA workflow, `.github/workflows/eng-docs-deploy.yml`: @@ -189,15 +180,15 @@ Woodpecker to a dedicated GHA workflow, `.github/workflows/eng-docs-deploy.yml`: PRs have no secrets and must not attempt a deploy (Global Constraints). - **Not part of `moon ci :ci`**: the deploy is CD, needs `CLOUDFLARE_API_TOKEN`/`CLOUDFLARE_ACCOUNT_ID` secrets, and must not red - the hermetic gate — the same split sealed makes (`runInCI: false`, - `moon.yml:63-68`: "CD (runInCI:false): the Petrel policy … fans these out - only when affected and gates the event"). The workflow runs + the hermetic gate — the same split the prior art makes (`runInCI: false`: + "CD (runInCI:false): the Petrel policy … fans these out only when affected + and gates the event"). The workflow runs `moon run compass-eng-docs:build` then `bun scripts/deploy.ts` (or `moon run compass-eng-docs:deploy` via `moon exec`-equivalent; the task keeps `runInCI: false` so the CI gate never runs it). -- **Env adaptation**: `deploy.ts` reads Woodpecker `CI_*` vars - (`deploy.ts:21-31`: `CI_PIPELINE_EVENT`, `CI_COMMIT_SOURCE_BRANCH`, - `CI_COMMIT_SHA`, `CI_REPO`, `CI_COMMIT_PULL_REQUEST`, `GH_TOKEN`). The +- **Env adaptation**: the prior art's `deploy.ts` reads Woodpecker `CI_*` vars + (`CI_PIPELINE_EVENT`, `CI_COMMIT_SOURCE_BRANCH`, `CI_COMMIT_SHA`, `CI_REPO`, + `CI_COMMIT_PULL_REQUEST`, `GH_TOKEN`). The compass copy reads the GHA equivalents: `GITHUB_EVENT_NAME`, `GITHUB_HEAD_REF`, `GITHUB_REPOSITORY`, PR number from `github.event.pull_request.number`, the commit SHA from an EXPLICIT @@ -215,9 +206,9 @@ Woodpecker to a dedicated GHA workflow, `.github/workflows/eng-docs-deploy.yml`: Pages keys deployments by `--branch`: the production branch is the alias, any other branch yields a preview deployment with its own stable URL (; - same model sealed relies on, `deploy.ts:33-34`). `cloudflare/wrangler-action` - exists but adds nothing over invoking wrangler from `deploy.ts` as sealed - does — rejected to keep one deploy code path across both repos' docsites. + same model the prior art relies on). `cloudflare/wrangler-action` + exists but adds nothing over invoking wrangler from `deploy.ts` as the prior + art does — rejected to keep one deploy code path across both repos' docsites. **Alternative considered — Cloudflare Pages GitHub integration** (Pages builds the site itself on every push; automatic previews, zero workflow): @@ -229,7 +220,7 @@ provides. Direct Upload keeps the build in the one pinned toolchain. **Alternative considered — docsite deploy inside `moon ci :ci`**: rejected; the CI job is the hermetic required check and must stay secret-free for fork -PRs; deploys are event-gated CD (mirrors sealed's `runInCI: false` split). +PRs; deploys are event-gated CD (mirrors the prior art's `runInCI: false` split). ### (c) Sanitization / rewrite policy — the four classes @@ -239,9 +230,9 @@ Repeatable rules applied by the migration task and binding on future records: Warden is a designed Compass component, not a foreign product: the ledger's first row reads "Compass is an agent development environment: named workstream agents supervised by a Dispatcher, gated by a Warden" - (`sealed/docs/designs/product/DECISIONS.md:37`, DL-001), and the v0.3 + (DL-001), and the v0.3 design record's §4.3 opens "Warden is the always-on security auditor" - (`sealed/docs/designs/product/compass.md:85-87` — the design record, not + (the v0.3 design record, not the living spec, whose Warden mentions are thin and scattered). Stripping it would gut the corpus. What stays PRIVATE is seal-the-product internals: records whose @@ -252,7 +243,7 @@ Repeatable rules applied by the migration task and binding on future records: (`compass-0.4/design.md:25-27`: "Cotal (Apache-2.0, NATS/JetStream)") — keep verbatim. Rule of thumb: a reference is kept when the referent is a Compass component or public OSS; it is de-linked (kept as prose, link - dropped) when the referent is a private sealed artifact. + dropped) when the referent is a private artifact out of tree. 2. **Private tracker links (SEA-####, linear.app).** *Keep the ID, strip the link.* ~50 distinct SEA IDs are load-bearing provenance (records cite each other through them); a dead `linear.app/rigelbuild/...` URL is worse @@ -264,7 +255,7 @@ Repeatable rules applied by the migration task and binding on future records: `RIG-1234` mentions are untouched. Public readers see an opaque internal ticket ID — honest and harmless. 3. **`oss/compass/**` path rewrite.** *Strip the prefix.* 19 records cite - `oss/compass/` paths from sealed's vendored era; the public repo's + `oss/compass/` paths from the prior art's vendored era; the public repo's layout is the same tree without the prefix — e.g. `oss/compass/go/internal/runtime/image.go` (`compass-agent-container-runtime.md:54`) is `go/internal/runtime/image.go` @@ -285,15 +276,15 @@ Repeatable rules applied by the migration task and binding on future records: ### (d) Migration timing -Compass-record design PRs may be in flight in sealed against the old convention +Compass-record design PRs may be in flight out of tree against the old convention at migration time (as of this session's open-PR list: **#1096** (`docs/designs/platform/compass-dogfood-e2e/design.md`), **#1095** (edits a product compass record), **#1087** (platform compass-agent GHCR record), plus **#1089** and **#1075** (compass-ux)). **Q5 ruled all-at-once**, so the -migration is a SINGLE PR carrying the full corpus at sealed `main` at -branch-cut — no wave-1/wave-2 split. An individual sealed design PR still open -when the migration branch cuts is reconciled into that one PR rather than -deferred: the executor either lands it in sealed first and includes the merged +migration is a SINGLE PR carrying the full corpus at the out-of-tree `main` at +branch-cut — no wave-1/wave-2 split. An individual out-of-tree design PR still +open when the migration branch cuts is reconciled into that one PR rather than +deferred: the executor either lands it out of tree first and includes the merged record, or re-targets it to compass. This is coherent with Q2 (compass is the source of truth): review continues in the public repo, so migrating a still-under-review record does not strand its threads — they simply continue @@ -307,15 +298,15 @@ Q1–Q5 are all RULED (see Open Questions); T6 is dropped per Q5. ### T1 — Site scaffold + moon registration -Create `apps/eng-docs/` mirroring sealed's app shape, minus Access/PostHog, +Create `apps/eng-docs/` mirroring the prior art's app shape, minus Access/PostHog, and register the project. Interfaces: -- Consumes: `sealed/apps/docs/{astro.config.mjs,package.json,moon.yml,tsconfig.json,src/styles/custom.css,src/content.config.ts,.gitignore,public/favicon.svg}` as templates (read from the sealed clone; do not import at build time). +- Consumes: the prior art's docs app files as templates — its `astro.config.mjs`, `package.json`, `moon.yml`, `tsconfig.json`, `src/styles/custom.css`, `src/content.config.ts`, `.gitignore`, `public/favicon.svg` (read from the out-of-tree clone; do not import at build time). - Produces: - `apps/eng-docs/astro.config.mjs` — `site` set per Q4's ruling (placeholder `https://compass-eng-docs.pages.dev` until the domain lands), `starlight({ title: "Compass Engineering Docs", pagefind: true, sidebar, editLink: {}, lastUpdated: true, tableOfContents: {...}, expressiveCode: {...} })`; NO `head` PostHog block, NO Access assumptions. - - `apps/eng-docs/package.json` — name `@compass/eng-docs`, scripts `{ gather, dev, build, preview, check }` as sealed's (`sealed/apps/docs/package.json:6-12`); deps `astro`, `@astrojs/starlight`, `@astrojs/check`, `github-slugger`, `sharp` via `catalog:` entries added to the root `package.json` `workspaces.catalog`. + - `apps/eng-docs/package.json` — name `@compass/eng-docs`, scripts `{ gather, dev, build, preview, check }` as the prior art's; deps `astro`, `@astrojs/starlight`, `@astrojs/check`, `github-slugger`, `sharp` via `catalog:` entries added to the root `package.json` `workspaces.catalog`. - `apps/eng-docs/moon.yml` — tasks `gather` (command `bun scripts/gather.ts`, inputs `['scripts/gather.ts', '/**/*.md', '/.markdownlint-cli2.jsonc']`, outputs `['src/content/docs', 'src/sidebar.generated.ts']`), `build` (`bunx astro build`, deps `['gather']`, outputs `['dist']`), `check` (`bunx astro check`, deps `['gather']`), `deploy` + `deploy-preview` (`bun scripts/deploy.ts`, deps `['build']`, `options.runInCI: false`), and a `ci` task depending on `['build', 'check']` so the project joins `moon ci :ci`. - `.moon/workspace.yml` — add `compass-eng-docs: 'apps/eng-docs'` under `projects`, same change (per `workspace.yml:41-47`'s silent-inert warning). - `apps/eng-docs/.gitignore` — `src/content/docs/`, `src/sidebar.generated.ts`, `dist/`, `.astro/`. @@ -327,13 +318,13 @@ Port `gather.ts` + `gather.test.ts` with the compass taxonomy. Interfaces: -- Consumes: `sealed/apps/docs/scripts/gather.ts` (491 lines) + `gather.test.ts` as the port source. +- Consumes: the prior art's `gather.ts` (491 lines) + `gather.test.ts` as the port source. - Produces: `apps/eng-docs/scripts/gather.ts` with: - - `const REPO_SLUG = "RigelBuild/compass"` (editUrl base, mirrors `sealed gather.ts:25,203-205`). - - `const DOMAINS = ["designs", "specs", "architecture"] as const` (replaces sealed's `["designs","specs","research","team"]`, `gather.ts:31`). - - `SECTIONS` in sidebar order: Designs, Specs, Architecture, Packages, Contributing (drops sealed's Research/Team/Infra, `gather.ts:43-51`). - - `packagePath` drops the `oss` arm (`sealed gather.ts:78`, keep the `apps` two-segment case). - - `parseExclusions` returns `[...ignores, "**/outputs/**"]` (drops `"oss/seal/**"`, `sealed gather.ts:131-137`); ignores read from `compass/.markdownlint-cli2.jsonc` (currently `["forks/*/**"]`). + - `const REPO_SLUG = "RigelBuild/compass"` (editUrl base, mirrors the prior art's `gather.ts`). + - `const DOMAINS = ["designs", "specs", "architecture"] as const` (replaces the prior art's `["designs","specs","research","team"]`). + - `SECTIONS` in sidebar order: Designs, Specs, Architecture, Packages, Contributing (drops the prior art's Research/Team/Infra). + - `packagePath` drops the `oss` arm (present in the prior art's `gather.ts`; keep the `apps` two-segment case). + - `parseExclusions` returns `[...ignores, "**/outputs/**"]` (drops `"oss/seal/**"` from the prior art's list); ignores read from `compass/.markdownlint-cli2.jsonc` (currently `["forks/*/**"]`). - `CONTRIBUTING_FILES` = compass's root convention files: `README.md`, `AGENTS.md`, `CONTRIBUTING.md`, `forks/README.md`. - Everything else (frontmatter injection, H1 strip, link rewriting, sidebar generation, index page) ports unchanged. - Produces: `apps/eng-docs/scripts/gather.test.ts` — the ported unit suite with fixtures updated to compass paths (classification of `docs/designs/repo/x.md`, `go/README.md` → packages, exclusion of `forks/oh-my-pi/**`). @@ -345,11 +336,11 @@ Port `deploy.ts` to GHA env vars; add the CD workflow. Interfaces: -- Consumes: `sealed/apps/docs/scripts/deploy.ts` (495 lines) + `deploy.test.ts` as the port source; Cloudflare Direct Upload docs (cited in Approach (b)). +- Consumes: the prior art's `deploy.ts` (495 lines) + `deploy.test.ts` as the port source; Cloudflare Direct Upload docs (cited in Approach (b)). - Produces: `apps/eng-docs/scripts/deploy.ts` with: - `const PROJECT_NAME = "compass-eng-docs"` (Q4), `COMMENT_MARKER = ""`, `SITE_LABEL = "Compass engineering docs"`. - - `interface DeployEnv { GITHUB_EVENT_NAME?; GITHUB_HEAD_REF?; GITHUB_SHA?; PR_HEAD_SHA?; GITHUB_REPOSITORY?; PR_NUMBER?; GH_TOKEN?; CLOUDFLARE_API_TOKEN?; CLOUDFLARE_ACCOUNT_ID? }` — replaces the Woodpecker `CI_*` set (`sealed deploy.ts:21-31`). The recorded commit SHA is `PR_HEAD_SHA` on PRs (= `github.event.pull_request.head.sha`) and `GITHUB_SHA` on push; never `GITHUB_SHA` on a PR (it is the merge commit, not the branch head). - - `isPullRequest(env)` → `env.GITHUB_EVENT_NAME === "pull_request"`; `deployBranch(env)` keeps the refuse-to-fall-back invariant on `GITHUB_HEAD_REF` (`sealed deploy.ts:68-79`); `wranglerArgs`, `parsePreviewUrl`, `commentBody`, `changedDocPages`, escape/encode helpers port unchanged. + - `interface DeployEnv { GITHUB_EVENT_NAME?; GITHUB_HEAD_REF?; GITHUB_SHA?; PR_HEAD_SHA?; GITHUB_REPOSITORY?; PR_NUMBER?; GH_TOKEN?; CLOUDFLARE_API_TOKEN?; CLOUDFLARE_ACCOUNT_ID? }` — replaces the Woodpecker `CI_*` set (from the prior art's `deploy.ts`). The recorded commit SHA is `PR_HEAD_SHA` on PRs (= `github.event.pull_request.head.sha`) and `GITHUB_SHA` on push; never `GITHUB_SHA` on a PR (it is the merge commit, not the branch head). + - `isPullRequest(env)` → `env.GITHUB_EVENT_NAME === "pull_request"`; `deployBranch(env)` keeps the refuse-to-fall-back invariant on `GITHUB_HEAD_REF` (per the prior art's `deploy.ts`); `wranglerArgs`, `parsePreviewUrl`, `commentBody`, `changedDocPages`, escape/encode helpers port unchanged. - Produces: `.github/workflows/eng-docs-deploy.yml`: - `on: { push: { branches: [main] }, pull_request: {} }`; `permissions: { contents: read, pull-requests: write }`; `concurrency: eng-docs-deploy-${{ github.ref }}` with `cancel-in-progress: true`. - One job `deploy`, `if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository` (fork guard); steps: checkout, setup-bun/node/moon from `.prototools` pins (reuse `ci.yml`'s pin-reading step, `ci.yml:154-196`), `moon run compass-eng-docs:build`, then `bun scripts/deploy.ts` with `env: { CLOUDFLARE_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}, CLOUDFLARE_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}, GH_TOKEN: ${{ github.token }}, PR_NUMBER: ${{ github.event.pull_request.number }}, PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }} }`. @@ -363,50 +354,50 @@ checklist for future records. Interfaces: -- Consumes: the sealed corpus enumerated this session — the 38 product design records (37 matching `sealed/docs/designs/product/compass-*` plus `sealed/docs/designs/product/compass.md`, the v0.3 base record whose name has no hyphen and so is not matched by the `compass-*` glob), `sealed/docs/designs/platform/compass-dogfood-loop/design.md`, `sealed/docs/specs/product/compass.md`, `sealed/docs/specs/product/README.md`. +- Consumes: the out-of-tree corpus enumerated this session — the 38 product design records (37 matching `docs/designs/product/compass-*` plus `docs/designs/product/compass.md`, the v0.3 base record whose name has no hyphen and so is not matched by the `compass-*` glob), `docs/designs/platform/compass-dogfood-loop/design.md`, `docs/specs/product/compass.md`, `docs/specs/product/README.md`. - Produces: `tools/docs-migrate/migrate.ts` (one-shot, deleted at the end of the migration) applying, per file: (1) linear.app link strip — BOTH the inline `[SEA-](https://linear.app/…)` and the reference-definition `[SEA-]: https://linear.app/…` forms → `SEA-`; (2) `oss/compass/` prefix strip in paths/links/code spans; (3) link-to-private-record conversion for `seal-*.md` targets → plain prose; (4) NO edits to security sections. Emits a per-file diff summary for review. Editorial brackets (the self-referential internal-record claims, Approach (c) class 3) are applied by hand in the same PR, listed in the PR body. - Produces: `docs/designs/CONTRIBUTING.md` (or a section in root `CONTRIBUTING.md`) stating the four rules as the standing policy for records authored here. - Test cycle: `bun test tools/docs-migrate` over fixture snippets for each class (including the reference-definition link form); post-run grep gates (authoritative over the rewrite regexes — the run fails if any form slipped): zero `linear.app` matches, zero `oss/compass` matches under `docs/designs/**` + `docs/specs/**`; `markdownlint-cli2` clean. -### T5 — Full-corpus migration + sealed-side removal (Q1/Q2/Q5 ruled) +### T5 — Full-corpus migration + out-of-tree removal (Q1/Q2/Q5 ruled) Land the whole Compass corpus in compass in a single PR (Q5: all at once); -remove it from sealed. compass is the source of truth going forward (Q2), so -design review continues here, not in sealed. +remove it from the out-of-tree source. compass is the source of truth going forward (Q2), so +design review continues here, not out of tree. Interfaces: -- Consumes: T4's script output over the full corpus at sealed `main` at - branch-cut — the 38 product design records, - `compass-dogfood-loop/design.md`, and both product specs. Any sealed design - PR still open at migration time is reconciled to compass rather than split - into a later wave (executor sequences: merge-in-sealed-first then migrate, or - re-target the PR to compass — both keep the corpus whole); the +- Consumes: T4's script output over the full corpus at the out-of-tree `main` + at branch-cut — the 38 product design records, + `compass-dogfood-loop/design.md`, and both product specs. Any out-of-tree + design PR still open at migration time is reconciled to compass rather than + split into a later wave (executor sequences: merge-out-of-tree-first then + migrate, or re-target the PR to compass — both keep the corpus whole); the wave-1/wave-2 split is dropped per Q5. - Produces (compass PR): `docs/designs/product/**` (the 38 product records), `docs/designs/product/compass-dogfood-loop/design.md` (a Compass - product-process design; `platform/` — a sealed-monorepo domain — does not + product-process design; `platform/` — an out-of-tree domain — does not exist in compass, and repo-tooling records like THIS one live under `docs/designs/repo/`), `docs/specs/product/{compass.md,README.md}`, plus (Q1 ruled MOVE) `docs/designs/product/DECISIONS.md` + `tools/design-ledger-gate/**` (ported; - `PRODUCT_DIR` stays `docs/designs/product`, `index.ts:45`) + a + the gate's `PRODUCT_DIR` constant stays `docs/designs/product`) + a `design-ledger-gate` moon project registered in `.moon/workspace.yml` with a `ci` task. -- Produces (sealed PR, sequenced after the compass PR merges): delete the - migrated trees; leave `sealed/docs/designs/product/README.md` pointing at the - public repo; sealed's residual ledger keeps the seal-product rows - DL-045/DL-046 (Q1); sealed's gather needs no change (deleted files simply - stop being gathered). +- Produces (out-of-tree PR, sequenced after the compass PR merges): delete the + migrated trees; leave the out-of-tree `docs/designs/product/README.md` + pointing at the public repo; the out-of-tree residual ledger keeps the + seal-product rows DL-045/DL-046 (Q1); the out-of-tree gather needs no change + (deleted files simply stop being gathered). - Test cycle: compass `moon run :ci` green (docsite builds the full corpus; ledger gate green after the move); site renders the ledger and both spec - pages; sealed `moon run docs-site:build` green post-removal; + pages; the out-of-tree `moon run docs-site:build` green post-removal; `tools/docs-migrate/` deleted after the one-shot run. ### T6 — Wave-2 straggler sweep — DROPPED (Q5 ruled all at once) Q5 ruled "all at once", so there is no separate wave-2 sweep: T5 migrates the -whole corpus in one PR and deletes `tools/docs-migrate/` at the end. Any sealed +whole corpus in one PR and deletes `tools/docs-migrate/` at the end. Any out-of-tree design PR still open at migration time is reconciled to compass by T5 (see T5 Consumes), not deferred to a later wave. @@ -415,12 +406,12 @@ Consumes), not deferred to a later wave. Interfaces: - Consumes: Q4 ruling (below) — project `compass-eng-docs`, custom domain - `eng.compass.rigel.build`, provisioned via sealed's Pulumi IaC lane. -- Produces: the `compass-eng-docs` Pages project via sealed's Pulumi IaC (sealed - precedent: the docsite got "its OWN Pages:Edit-scoped token once RIG-1119 - provisions the project", `sealed/ci/pipeline.ts:334-336`); repo secrets - `CLOUDFLARE_API_TOKEN` (Pages:Edit-scoped, least-privilege per - `pipeline.ts:321-324`) + `CLOUDFLARE_ACCOUNT_ID` on `RigelBuild/compass`; + `eng.compass.rigel.build`, provisioned via the fleet's Pulumi IaC lane. +- Produces: the `compass-eng-docs` Pages project via the fleet's Pulumi IaC + (prior-art precedent: the docsite got its OWN Pages:Edit-scoped token once + RIG-1119 provisioned the project); repo secrets `CLOUDFLARE_API_TOKEN` + (Pages:Edit-scoped, least-privilege per the prior art) + `CLOUDFLARE_ACCOUNT_ID` + on `RigelBuild/compass`; production branch set to `main`. NOTE: creating the Pages project + seeding the two repo secrets is an operator step (not agent-executable). - Test cycle: T3's scratch-PR preview + main production deploy succeed end to end. @@ -431,7 +422,7 @@ Interfaces: - [ ] T2 — `gather.ts`/`gather.test.ts` ported to the compass taxonomy; this record renders. - [ ] T3 — `deploy.ts` on GHA env + `.github/workflows/eng-docs-deploy.yml` with the fork guard. - [ ] T4 — sanitization migration script + standing policy doc (Q3 ruled; classes final). -- [ ] T5 — full-corpus migration (all records, one PR) + sealed-side removal; ledger + ledger-gate moved to compass (Q1/Q2/Q5 ruled). +- [ ] T5 — full-corpus migration (all records, one PR) + out-of-tree removal; ledger + ledger-gate moved to compass (Q1/Q2/Q5 ruled). - [ ] T6 — DROPPED: Q5 ruled all-at-once; wave-2 sweep folded into T5. - [ ] T7 — Cloudflare Pages `compass-eng-docs` + `eng.compass.rigel.build` + secrets provisioned via Pulumi (Q4 ruled). @@ -441,14 +432,13 @@ Batched for Matt — ALL RULED (below): Q1/Q2/Q4/Q5 ruled 2026-08-05, Q3 ruled earlier. T5 and T7 execute against these rulings; T6 is dropped (Q5). - **Q1 — Does the design-ledger + ledger-gate + gather tooling move to - compass, or stay in sealed?** The ledger is Compass-titled and - Compass-governed ("Compass design-decision ledger", - `sealed/docs/designs/product/DECISIONS.md:1`) and the gate hardcodes - `PRODUCT_DIR = "docs/designs/product"` - (`sealed/tools/design-ledger-gate/index.ts:45`), so it follows the corpus. + compass, or stay out of tree?** The ledger is Compass-titled and + Compass-governed (its ledger is titled "Compass design-decision ledger") and + the gate hardcodes `PRODUCT_DIR = "docs/designs/product"` (in its + `design-ledger-gate` tool), so it follows the corpus. **RULED (Matt): MOVE ledger + ledger-gate to compass** (the gate ports with its path constant unchanged); the two seal-product rows (DL-045, - DL-046, `DECISIONS.md:197-198`) stay behind in a small sealed-side residual + DL-046) stay behind in a small out-of-tree residual ledger next to the seal records they cite. `gather.ts` is NOT shared — each repo keeps its own copy (they already diverge on taxonomy); no extraction. Verified the cut is edge-clean: DL-045/DL-046 are the ONLY rows under the @@ -460,22 +450,22 @@ earlier. T5 and T7 execute against these rulings; T6 is dropped (Q5). security model" but that is not a ledger EDGE). Q1 is the most defensible choice, not the weakest. - **Q2 — Is compass the SOURCE OF TRUTH for Compass records going forward, or - a published mirror gathered from sealed?** **RULED (Matt): SOURCE OF + a published mirror gathered from out of tree?** **RULED (Matt): SOURCE OF TRUTH.** A mirror leaves every design PR on a non-public surface, defeating build-in-the-open (readers see outputs, not the review process); it also needs a cross-repo sync job that can silently drift. Authoring here means the design PRs, review threads, and preview links are all public — the point of the exercise. This record dogfoods the ruling. - Named consequence of moving the corpus out of sealed (T5 deletes the sealed - trees): several ACTIVE non-compass sealed records cite INTO the compass + Named consequence of moving the corpus out of tree (T5 deletes the out-of-tree + trees): several ACTIVE non-compass out-of-tree records cite INTO the compass corpus by bare `file:line`/§ anchor (verified: `sea-1023-acp-session.md`, `sea-1115-agent-provisioning-cotal.md`, `platform/go-toolchain-default.md` at ~40 refs, `platform/repo-structure-reorg.md`, others) whose lane is seal/agent/platform, so they do NOT migrate. Mitigating: these are bare-prose citations, NOT Markdown hyperlinks (a link-form grep returns - zero), so sealed's own `gather.ts` renders no 404 — only the human/agent + zero), so the out-of-tree `gather.ts` renders no 404 — only the human/agent grounding value is severed. Recommendation: leave-as-historical (the SEA ID - and record name in the prose still name the target) plus the sealed-side + and record name in the prose still name the target) plus the out-of-tree `README.md` pointer T5 already leaves at `docs/designs/product/`; a per-file pointer stub is not worth the churn. - **Q3 — Warden/Cotal cross-product references: hold-and-omit vs @@ -493,23 +483,23 @@ earlier. T5 and T7 execute against these rulings; T6 is dropped (Q5). migrate — out of the Compass corpus — and compass records linking to them de-link to plain prose (class 1). - **Q4 — Cloudflare Pages project + custom domain: does one exist, who - provisions?** No compass Pages project exists (sealed's pipeline knows only - `sealed-docs` + the marketing site, `sealed/ci/pipeline.ts:333-343`). + provisions?** No compass Pages project exists (the prior art's pipeline knows + only its own docsite + the marketing site). **RULED (Matt):** provision a new `compass-eng-docs` project + a - Pages:Edit-scoped token via sealed's existing Pulumi IaC lane (the RIG-1119 - precedent, `pipeline.ts:334-336`), production branch `main`; custom domain + Pages:Edit-scoped token via the fleet's existing Pulumi IaC lane (the RIG-1119 + precedent), production branch `main`; custom domain `eng.compass.rigel.build` (Matt ruled). The `docs.compass` naming and `docs.compass.rigel.build` domain are deliberately RESERVED for the future user-facing product docsite (a separate site), so this engineering docs site takes the `eng.` subdomain. Until the domain lands the site ships - on `compass-eng-docs.pages.dev`. Analytics (PostHog snippet, minus sealed's + on `compass-eng-docs.pages.dev`. Analytics (PostHog snippet, minus the prior art's Access-cookie inheritance) rides the domain decision. - **Q5 — Migration scope: all 39 at once vs settled-now + in-flight-after freeze?** **RULED (Matt): all at once** — migrate the full corpus in one PR, no two-wave split (supersedes the wave recommendation). Coherent with Q2: because compass is the source of truth, design review continues in the public repo, so the "strands review threads" cost the two-wave split was meant to - avoid is instead accepted — any sealed design PR still open at migration time - is reconciled to compass by T5 (merge-in-sealed-first then migrate, or + avoid is instead accepted — any out-of-tree design PR still open at migration time + is reconciled to compass by T5 (merge-out-of-tree-first then migrate, or re-target to compass — executor sequences), not deferred to a later wave. T6 is therefore dropped. diff --git a/docs/designs/server/compass-mention-offline-redelivery-pre-settle-closure.md b/docs/designs/server/compass-mention-offline-redelivery-pre-settle-closure.md index dd397dd28..b8a191ee5 100644 --- a/docs/designs/server/compass-mention-offline-redelivery-pre-settle-closure.md +++ b/docs/designs/server/compass-mention-offline-redelivery-pre-settle-closure.md @@ -5,7 +5,7 @@ Status: Draft Tracker: RIG-2490. Sibling follow-up to: `compass-mention-offline-redelivery.md` (RIG-1641) — per -the sealed frozen-record convention this record ADDS a sibling; the merged +the frozen-record convention this record ADDS a sibling; the merged RIG-1641 record is never edited in place. All file+line grounding below was verified against the working tree this run (jj workspace off main `48d4a7cd`). diff --git a/docs/designs/server/compass-mention-offline-redelivery.md b/docs/designs/server/compass-mention-offline-redelivery.md index 9361f90c1..3d6b36a93 100644 --- a/docs/designs/server/compass-mention-offline-redelivery.md +++ b/docs/designs/server/compass-mention-offline-redelivery.md @@ -15,7 +15,7 @@ of this record). DL-071/DL-073 stay Active — this record amends the frozen OQ-3 offline clause by citation, it does not reverse the steer-only precedence or the control-op shapes. -> **Amends `compass-notification-delivery` (frozen).** Per the sealed +> **Amends `compass-notification-delivery` (frozen).** Per the frozen-record > convention a later change ADDS a record (sibling precedent: > `compass-sidebar-pins-unreachable-amendment`, > `compass-server-ownership-layer-amendment`); the frozen record is never diff --git a/docs/designs/server/compass-server-ownership-layer-amendment/design.md b/docs/designs/server/compass-server-ownership-layer-amendment/design.md index d8f42ebdf..3c0889ea4 100644 --- a/docs/designs/server/compass-server-ownership-layer-amendment/design.md +++ b/docs/designs/server/compass-server-ownership-layer-amendment/design.md @@ -5,7 +5,7 @@ Tracker: SEA > **Extends #995 (frozen).** This record is a sibling amendment to > `docs/designs/server/compass-server-ownership-layer/design.md` (merged in -> #995). The merged record is frozen; per sealed convention a later change ADDS +> #995). The merged record is frozen; per the frozen-record convention a later change ADDS > a record. This amendment reconciles #995's forge-shaped proto type family to > the single canonical `compass.v1` family frozen by > `docs/designs/server/compass-issue-model/design.md` (#1018). diff --git a/docs/designs/ui/compass-session-trace-diff.md b/docs/designs/ui/compass-session-trace-diff.md index 9567a604f..7d4cc886b 100644 --- a/docs/designs/ui/compass-session-trace-diff.md +++ b/docs/designs/ui/compass-session-trace-diff.md @@ -78,8 +78,8 @@ decisions, all three forks from the brief: use a diff library. `apps/ui/package.json:7-11` carries three runtime deps (`@compass/client`, `@tauri-apps/api`, `solid-js`); this adds one, `diff` (jsdiff) — verified resolvable from the workspace registry at -`9.0.0` (`bun pm view diff version`), so the offline-leaning workspace (sealed -monorepo, LAN registry) is not a blocker. jsdiff ships a battle-tested Myers +`9.0.0` (`bun pm view diff version`), so an offline-leaning workspace +(LAN registry) is not a blocker. jsdiff ships a battle-tested Myers O(ND) implementation: **linear space** (no `m×n` table), but O((m+n)·D) *time* in the edit distance D. The hand-rolled table's load-bearing risk was **memory** — `FileDiff` holds whole-file texts (`session-events.ts:22-27`) with diff --git a/docs/designs/ui/compass-sidebar-pins-unreachable-amendment/design.md b/docs/designs/ui/compass-sidebar-pins-unreachable-amendment/design.md index c8d60fc5e..12d863f6f 100644 --- a/docs/designs/ui/compass-sidebar-pins-unreachable-amendment/design.md +++ b/docs/designs/ui/compass-sidebar-pins-unreachable-amendment/design.md @@ -15,12 +15,12 @@ escape hatch is needed in the PR body. > **Amends `compass-sidebar-pins` (frozen).** This record is a sibling > amendment to `docs/designs/ui/compass-sidebar-pins/design.md` (RIG-1632, -> DL-096). The merged record is frozen; per sealed convention a later change +> DL-096). The merged record is frozen; per the frozen-record convention a later change > ADDS a record. This amendment supersedes the frozen record's §T2 > unresolvable-pin filtering and §T3 fluctuation-coercion clauses per Matt's > ruling of 2026-08-02 (PR #98's review medium). All file+line grounding below -> was verified against the working trees this run: the frozen record in the -> sealed repo, the shipped implementation in the compass repo +> was verified against the working trees this run: the frozen record out of +> tree, the shipped implementation in the compass repo > (`apps/ui/src/…`, post-merge #98). ## Problem / Intent diff --git a/docs/designs/ui/compass-ux-foundation/design.md b/docs/designs/ui/compass-ux-foundation/design.md index ae20224ce..4e860ee67 100644 --- a/docs/designs/ui/compass-ux-foundation/design.md +++ b/docs/designs/ui/compass-ux-foundation/design.md @@ -2,7 +2,7 @@ Status: Draft Linear: RIG-1663 -Supersedes: the pre-freeze draft of this record (sealed PR #1075; its +Supersedes: the pre-freeze draft of this record (an out-of-tree PR; its DL-114..122 block never shipped) That pre-freeze draft was authored against a *provisional* brand identity; the diff --git a/tools/agent-image-env-gate/env-check.ts b/tools/agent-image-env-gate/env-check.ts index 72a081a1f..583c29a2f 100644 --- a/tools/agent-image-env-gate/env-check.ts +++ b/tools/agent-image-env-gate/env-check.ts @@ -18,7 +18,7 @@ // the initialized nix DB — non-reproducible bloat and phantom DB entries. Two // such vars exist (`DEVENV_PROFILE`, a 266-path dev profile; `DEVENV_TASK_FILE`, // the tasks.json), each neutralized consumer-side in agent-image/devenv.nix -// (mkForce to a non-store placeholder, gated on isBuilding, as the internal monorepo ships it). +// (mkForce to a non-store placeholder, gated on isBuilding). // This gate is the regression backstop for that // neutralization, plus a build-host-home leak check that catches a builder path // baked into ANY key (a non-reproducible-across-hosts defect). Both invariants diff --git a/tools/design-ledger-gate/moon.yml b/tools/design-ledger-gate/moon.yml index 9355e8810..6ef131e62 100644 --- a/tools/design-ledger-gate/moon.yml +++ b/tools/design-ledger-gate/moon.yml @@ -8,11 +8,10 @@ # whole-repo tasks on the root project (/moon.yml), so this leaf has no own # bun.lock and never runs its own install. # -# Migrated from the sealed repo (RIG-1794): the Compass design corpus + ledger -# now live here, so the gate that governs them lives here too. Compass CI is a +# Compass CI is a # single moon-driven `CI` job (.github/workflows/ci.yml runs `moon run :ci`), # so the `ci` aggregate below is swept automatically — no separate meta.ts -# wiring (unlike sealed's Woodpecker pipeline). +# wiring (unlike the prior art's Woodpecker pipeline). layer: 'tool' language: 'typescript' tags: ['bun', 'ci-group.bun'] diff --git a/tools/orion-ref-gate/index.test.ts b/tools/orion-ref-gate/index.test.ts index a07406f62..e65f0881b 100644 --- a/tools/orion-ref-gate/index.test.ts +++ b/tools/orion-ref-gate/index.test.ts @@ -50,6 +50,44 @@ describe("lineHasToken — whole-word, case-insensitive", () => { }); }); +describe("lineHasToken — the former name, matched only in repo-shaped uses", () => { + test("a path inside the private repo is a reference", () => { + expect(lineHasToken("See `sealed/ci/pipeline.ts:554` for the job")).toBe( + true, + ); + }); + test("its possessive, docsite host, and repo-noun uses are references", () => { + expect(lineHasToken("following sealed's shape")).toBe(true); + expect(lineHasToken("deployed to sealed-docs.rigel.build")).toBe(true); + expect(lineHasToken("this record lives in the sealed design corpus")).toBe( + true, + ); + expect(lineHasToken("per sealed convention a later change ADDS")).toBe( + true, + ); + }); + // The word is ordinary English throughout go/: a whole-word scan flags 60 + // tracked lines, every one legitimate. These pin the narrowing that keeps + // the gate usable. + test("the English engineering word is not a reference", () => { + expect(lineHasToken("Frame is a sealed sum type")).toBe(false); + expect(lineHasToken("the row was sealed under a known key")).toBe(false); + expect(lineHasToken("an egress-sealed agent holds no server token")).toBe( + false, + ); + expect(lineHasToken("gochecksumtype for sealed-interface sum types")).toBe( + false, + ); + }); + test("genuinely public names carrying the string are not references", () => { + expect(lineHasToken("github.com/sealedsecurity/compass/go")).toBe(false); + expect(lineHasToken("Sealed Security Inc → Rigel AI Software Inc")).toBe( + false, + ); + expect(lineHasToken("ci.sealedsecurity.com")).toBe(false); + }); +}); + describe("isCarveOut", () => { test("the gate's own source is carved out", () => { expect(isCarveOut("tools/orion-ref-gate/index.ts")).toBe(true); diff --git a/tools/orion-ref-gate/index.ts b/tools/orion-ref-gate/index.ts index a77d181fa..742ee1693 100644 --- a/tools/orion-ref-gate/index.ts +++ b/tools/orion-ref-gate/index.ts @@ -43,9 +43,30 @@ import { $ } from "bun"; -/** The private monorepo's token. Whole-word, case-insensitive. */ +/** + * The private repo's current name. Whole-word, case-insensitive: a bare + * `orion` in this repo is always the private repo. + */ export const PRIVATE_TOKEN = "orion"; +/** + * The private repo's FORMER name, which imported records still carry. It + * cannot be scanned whole-word like the current one: `sealed` is also ordinary + * English this codebase uses constantly — a sealed sum type, a ciphertext + * sealed under a key, an egress-sealed agent. Measured over the tracked tree, + * a whole-word scan flags 60 lines, every one of them legitimate; a gate that + * is 100% false positives gets switched off. + * + * So match only the shapes that name the REPO: a path inside it, its docsite + * host, its possessive, or the word followed by a repo-ish noun. + */ +export const LEGACY_NAME_PATTERNS: readonly RegExp[] = [ + /\bsealed\/[a-z]/i, + /\bsealed-docs\b/i, + /\bsealed's\b/i, + /\bsealed (repo|monorepo|design corpus|platform|convention|PR #)/i, +]; + /** * Repo-relative path prefixes never scanned. A reference under one of these is * either a generated copy (eng-docs / bun.lock) or this gate's own description @@ -97,13 +118,15 @@ export function isCarveOut(path: string): boolean { } /** - * Whole-word, case-insensitive match for the private token in one line. The - * gate's own compound name (`orion-ref-gate`) is not a private-repo reference, - * so a bare `orion` immediately followed by `-ref-gate` does not count. + * Case-insensitive match for a private-repo reference in one line: the current + * name whole-word, or one of the former name's repo-shaped patterns. The + * gate's own compound name (`orion-ref-gate`) is not a reference, so a bare + * `orion` immediately followed by `-ref-gate` does not count. */ export function lineHasToken(text: string): boolean { const stripped = text.replace(/orion-ref-gate/gi, ""); - return new RegExp(`\\b${PRIVATE_TOKEN}\\b`, "i").test(stripped); + if (new RegExp(`\\b${PRIVATE_TOKEN}\\b`, "i").test(stripped)) return true; + return LEGACY_NAME_PATTERNS.some((re) => re.test(stripped)); } /** @@ -167,15 +190,20 @@ export async function runOnce(deps: Deps): Promise { } /** - * `git grep -nwI -i ` over tracked files. `git grep` exits 0 with - * matches, 1 on no match (a legitimately clean, empty result), and >=2 on a - * real error (e.g. not a git work tree). We must distinguish the last from the - * clean case: swallowing it would make the gate report clean on a broken scan — - * fail-OPEN, the exact false-green a fail-closed gate exists to stop. Exit >=2 - * throws, so runOnce's catch returns exit 2. + * `git grep -nEI` for either name over tracked files. The regex is a coarse + * pre-filter — `lineHasToken` makes the real decision, so this only has to be + * a superset of it. `sealed` is matched bare here and narrowed there. + * + * `git grep` exits 0 with matches, 1 on no match (a legitimately clean, empty + * result), and >=2 on a real error (e.g. not a git work tree). We must + * distinguish the last from the clean case: swallowing it would make the gate + * report clean on a broken scan — fail-OPEN, the exact false-green a + * fail-closed gate exists to stop. Exit >=2 throws, so runOnce's catch + * returns exit 2. */ async function gitGrep(): Promise { - const res = await $`git grep -nwiI ${PRIVATE_TOKEN}`.nothrow().quiet(); + const pattern = `\\b(${PRIVATE_TOKEN}|sealed)`; + const res = await $`git grep -nEiI ${pattern}`.nothrow().quiet(); if (res.exitCode >= 2) throw new Error( `git grep exited ${res.exitCode}: ${res.stderr.toString().trim()}`, diff --git a/tools/renovate-preflight/moon.yml b/tools/renovate-preflight/moon.yml index 9d728941f..af96eb42f 100644 --- a/tools/renovate-preflight/moon.yml +++ b/tools/renovate-preflight/moon.yml @@ -8,7 +8,7 @@ # affected graph — this project carries only the code + its unit gate. Compass # CI is a single moon-driven `CI` job (.github/workflows/ci.yml runs # `moon run :ci`), which sweeps the tasks below automatically — no separate -# meta.ts wiring (unlike the internal monorepo's CI/CD pipeline). install/lint/format +# meta.ts wiring (unlike the prior art's CI/CD pipeline). install/lint/format # inherited via the `bun` tag (.moon/tasks/tag-bun.yml). layer: 'tool' language: 'typescript' diff --git a/tools/renovate/bot-config.json5 b/tools/renovate/bot-config.json5 index e19bda76c..b35b0112f 100644 --- a/tools/renovate/bot-config.json5 +++ b/tools/renovate/bot-config.json5 @@ -28,7 +28,7 @@ // NOT pinned here: Renovate autodetects it from the per-run installation // token, so an explicit value could only ever be a stale or malformed copy of // what the token already carries. Omitting gitAuthor is the correct App-auth - // posture (unlike the internal monorepo, which authenticates as a bot USER via a PAT and so + // posture (unlike the prior art, which authenticates as a bot USER via a PAT and so // must name that user). One consequence: this drops the App-slug paste-back // step from the RIG-2432 provisioning runbook — nothing to fill in post-registration. onboarding: false, // config already committed; no onboarding PR diff --git a/tools/renovate/config.json5 b/tools/renovate/config.json5 index cceb7dd2a..4e44621f7 100644 --- a/tools/renovate/config.json5 +++ b/tools/renovate/config.json5 @@ -62,9 +62,9 @@ labels: ["dependencies"], // Explicit allowlist for the current stack. `github-actions` is present here - // (unlike the internal monorepo, whose meta jobs moved off GHA): compass runs all CI on GitHub + // (unlike the prior art, whose meta jobs moved off GHA): compass runs all CI on GitHub // Actions and keeps every workflow `uses:` SHA-pinned — see the github-actions - // manager rationale below. Dropped vs the internal monorepo: `cargo`/`rust-toolchain` (no Rust), + // manager rationale below. Dropped because compass has none: `cargo`/`rust-toolchain` (no Rust), // `woodpecker` (no Woodpecker), and `nix`. Compass now DOES carry a root // flake (flake.nix/flake.lock, added for the distribution flake + gtk4/OTel // work), but the nix manager stays off deliberately: the flake's nixpkgs is @@ -356,7 +356,7 @@ // (`{ version = "1.26.6"; }`, version-only — hashes come from go-overlay) and // DERIVES the `go_X_Y_Z` overlay attr name in devenv.nix:30-31 via // lib.replaceStrings. So devenv.nix contains no literal `go_X_Y_Z` string to - // regex (the internal monorepo tracked devenv.nix; compass tracks go.nix instead). The + // regex (the prior art tracked devenv.nix; compass tracks go.nix instead). The // version is dotted in go.nix, so there is NO dots↔underscores gymnastics — // capture it straight for the golang-version datasource, and devenv.nix picks // it up automatically at eval time. A go bump rewrites go.nix and no hash @@ -458,7 +458,7 @@ // Un-group them so each language pin opens its OWN branch and PR. Because // compass's go manager now ALSO targets a file under this glob // (tools/toolchain/versions/go.nix), this one rule un-groups all four pins — - // the internal monorepo's separate go un-group rule (its go lived in devenv.nix, off-glob) is + // the prior art's separate go un-group rule (its go lived in devenv.nix, off-glob) is // NOT needed here. matchFileNames: ["tools/toolchain/versions/*.nix"], groupName: null, @@ -638,7 +638,7 @@ matchDepNames: ["cachix/devenv-nixpkgs"], groupName: "devenv nixpkgs channel", // DAILY, aligned to the same before-4am-ET window the daily cron lands in - // (see `timezone` above). This is a deliberate compass divergence from the internal monorepo, + // (see `timezone` above). This is a deliberate compass divergence from the prior art, // whose rule schedules weekly (`before 4am on monday`) to bound `rolling`'s // near-daily churn — Matt's ruling for compass: nixpkgs tracks daily too. schedule: ["before 4am"], diff --git a/tools/renovate/config.test.ts b/tools/renovate/config.test.ts index 40add9e94..f719f18d1 100644 --- a/tools/renovate/config.test.ts +++ b/tools/renovate/config.test.ts @@ -8,10 +8,9 @@ import config from "./config.json5"; // module does no I/O at import (main() is behind import.meta.main). import { FOD_ENTRIES } from "./refresh-fod-hashes.ts"; -// Guard suite for compass's self-hosted Renovate config (RIG-2432). Ported from -// the internal monorepo's config.test.ts and adapted to compass's config + -// ecosystems (bun catalog, devenv-nixpkgs channel, toolchain pins, gomod, GitHub -// Actions; no rust/pulumi/woodpecker). The .json5 configs load via Bun's loader. +// Guard suite for compass's self-hosted Renovate config (RIG-2432). Covers compass's +// config + ecosystems (bun catalog, devenv-nixpkgs channel, toolchain pins, gomod, +// GitHub Actions; no rust/pulumi/woodpecker). The .json5 configs load via Bun's loader. type PostUpgradeTasks = { commands?: string[]; @@ -503,7 +502,8 @@ describe("tools/renovate devenv nixpkgs lockstep", () => { // Branch-mode lockstep task over the files the script writes: devenv.lock + // package.json (biome catalog) + bun.lock (steps 2/4/5), flake.nix + flake.lock - // (step 6), and agent-image/entrypoint.nix (the FOD outputHash). + // (step 6), and agent-image/entrypoint.nix (the FOD outputHash). compass has + // NO committed inner-rev guard file. // The FOD refresh is required: a channel bump moves pkgs.bun (the FOD builder) // and, when the biome pin moves, re-resolves the bun.lock closure — either can diff --git a/tools/renovate/moon.yml b/tools/renovate/moon.yml index 15ed86d6f..58485ee50 100644 --- a/tools/renovate/moon.yml +++ b/tools/renovate/moon.yml @@ -1,7 +1,7 @@ # yaml-language-server: $schema=https://moonrepo.dev/schemas/project.json # # renovate (RIG-2432) — self-hosted Renovate config + lockstep postUpgradeTask -# scripts for compass, ported from the internal monorepo's renovate config. A bun/TypeScript +# scripts for compass. A bun/TypeScript # package; a hoisted root-workspace member (`bun` tag): install is inherited via # .moon/tasks/tag-bun.yml (the shared root install) and lint/format are whole-repo # tasks on the root project (/moon.yml), so this leaf has no own bun.lock and diff --git a/tools/renovate/package.json b/tools/renovate/package.json index a25468302..811a2e8f2 100644 --- a/tools/renovate/package.json +++ b/tools/renovate/package.json @@ -2,7 +2,7 @@ "name": "@compass/renovate", "private": true, "type": "module", - "description": "Self-hosted Renovate config + lockstep postUpgradeTask scripts for compass (RIG-2432): repo config, bot config, toolchain-hash + devenv-nixpkgs relock scripts, and the config guard suite. Ported from the internal monorepo's renovate config, adapted to compass's tools/* layout, ecosystems, and GitHub Actions runner.", + "description": "Self-hosted Renovate config + lockstep postUpgradeTask scripts for compass (RIG-2432): repo config, bot config, toolchain-hash + devenv-nixpkgs relock scripts, and the config guard suite.", "module": "config.json5", "devDependencies": { "@types/bun": "catalog:", diff --git a/tools/renovate/refresh-toolchain-hashes.test.ts b/tools/renovate/refresh-toolchain-hashes.test.ts index f0fcbd498..3679198e1 100644 --- a/tools/renovate/refresh-toolchain-hashes.test.ts +++ b/tools/renovate/refresh-toolchain-hashes.test.ts @@ -6,8 +6,7 @@ import { dirname, join } from "node:path"; import { $ } from "bun"; import { readVersion, rewriteHash } from "./refresh-toolchain-hashes.ts"; -// Regression test for tools/renovate/refresh-toolchain-hashes.ts (RIG-2432, -// ported from the internal monorepo's test). +// Regression test for tools/renovate/refresh-toolchain-hashes.ts (RIG-2432). // // The bug this guards against: the script's path constants are all // repo-root-relative (the pin files), but the gate `git diff --quiet "$base_ref" diff --git a/tools/renovate/refresh-toolchain-hashes.ts b/tools/renovate/refresh-toolchain-hashes.ts index 300d6a19f..6692c89a3 100755 --- a/tools/renovate/refresh-toolchain-hashes.ts +++ b/tools/renovate/refresh-toolchain-hashes.ts @@ -13,9 +13,9 @@ // bump re-prefetches bun.nix alone. Requires nix (nix-command) on PATH, provided // by the runner; run via bun. -// bun/TypeScript port of the internal monorepo's refresh-toolchain-hashes -// (RIG-2432), scoped to compass's three vendored binary toolchains. Every -// observable behaviour is preserved 1:1. +// Scoped to compass's three vendored binary toolchains (bun, node, moon). A +// per-file self-gate, per-leg hash refresh that fails loud on a missing marker / +// hash line, and idempotence. import { $ } from "bun"; From 837280acd39d0b7f56b4e6b2842166789617d28b Mon Sep 17 00:00:00 2001 From: mintaka Date: Sun, 13 Sep 2026 18:48:28 -0400 Subject: [PATCH 2/3] fix(orion-ref-gate): close the former-name false-negative hole (RIG-3756) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review findings on PR #1216, both mediums on the gate rather than the scrub. The narrow pattern set missed two citation shapes, and both are shapes this scrub removed BY HAND — so the standing backstop would not have caught its own regression: - the space form, `sealed apps/docs/scripts/deploy.ts`, which is the most natural way to cite a file in another repo - the hyphenated repo-noun, `sealed-monorepo` / `sealed-repo` / `sealed-private` The space-form arm anchors on a source-file extension rather than on any slash-bearing token. A looser form false-positives on ordinary English, which carries slashes too: "values sealed and/or rotated" and "sealed in transit/at rest" both match a bare `sealed\s+\S*/`. Validated at 15/15 engineering-word negatives and 9/9 leak shapes; zero hits over the tracked tree. The module header contradicted the code after the two-name change, still reading "orion ONLY / a single blunt token beats a clever regex" while the former name is matched by exactly such a narrowing set. Rewritten to state both names and why the asymmetry is deliberate: blunt where the token is unambiguous, narrow where it collides with English. Also drops `\b` from the git grep pre-filter. It is a GNU extension, not base POSIX ERE, and a toolchain change that made git treat it literally would match nothing and exit 1 — a legitimately-clean signal — so the gate would fail OPEN. The pre-filter only has to be a superset; lineHasToken owns the boundary. Verified superset: 174 unanchored vs 168 anchored lines. Tests 26 -> 29. Mutation-tested: removing the two arms turns 29 pass/0 fail into 26 pass/3 fail. Co-authored-by: Matt Wilkinson --- tools/orion-ref-gate/index.test.ts | 22 ++++++++++++ tools/orion-ref-gate/index.ts | 54 +++++++++++++++++++++--------- 2 files changed, 61 insertions(+), 15 deletions(-) diff --git a/tools/orion-ref-gate/index.test.ts b/tools/orion-ref-gate/index.test.ts index e65f0881b..52608a9a5 100644 --- a/tools/orion-ref-gate/index.test.ts +++ b/tools/orion-ref-gate/index.test.ts @@ -56,6 +56,28 @@ describe("lineHasToken — the former name, matched only in repo-shaped uses", ( true, ); }); + // The space form, not the slash form: citing a file in another repo by + // ` ` is the most natural shape, and every one of these is a + // line this scrub removed by hand — so the gate has to catch its own + // regression, not just the form that happened to be written with a slash. + test("a space-separated path or bare filename citation is a reference", () => { + expect( + lineHasToken("Adapted from sealed apps/docs/scripts/deploy.ts"), + ).toBe(true); + expect(lineHasToken("mirrors `sealed gather.ts:25,203-205`")).toBe(true); + expect(lineHasToken("ported from sealed flake.nix")).toBe(true); + }); + // Prose carries slashes too, so the space form anchors on a source-file + // extension rather than on any slash-bearing token. + test("slash-bearing English prose is not a reference", () => { + expect(lineHasToken("values sealed and/or rotated")).toBe(false); + expect(lineHasToken("rows sealed in transit/at rest")).toBe(false); + }); + test("a hyphenated repo-noun is a reference", () => { + expect(lineHasToken("a sealed-monorepo domain")).toBe(true); + expect(lineHasToken("sealed-repo records")).toBe(true); + expect(lineHasToken('the "sealed-private" annotation')).toBe(true); + }); test("its possessive, docsite host, and repo-noun uses are references", () => { expect(lineHasToken("following sealed's shape")).toBe(true); expect(lineHasToken("deployed to sealed-docs.rigel.build")).toBe(true); diff --git a/tools/orion-ref-gate/index.ts b/tools/orion-ref-gate/index.ts index 742ee1693..ef721acb2 100644 --- a/tools/orion-ref-gate/index.ts +++ b/tools/orion-ref-gate/index.ts @@ -9,15 +9,26 @@ // sweep removed the existing references; this gate keeps the boundary from // silently re-rotting, the same way design-ledger-gate keeps the ledger honest. // -// SCOPE: orion ONLY. This gate scans for one token and does not double as a -// general brand-token gate; other one-time cleanups that are not being re-added -// need no standing scan here. +// SCOPE: the private repo's two names ONLY — the current one and the former +// one imported records still carry. This gate does not double as a general +// brand-token gate; other one-time cleanups that are not being re-added need +// no standing scan here. // -// What counts as a reference: the whole-word token `orion` (any case), which -// catches the repo name, `RigelBuild/orion`, an `orion ` citation, and -// "ported from orion" provenance prose alike. The scan is deliberately blunt — -// a single blunt token with a small, explicit allowlist beats a clever regex -// that tries to tell a "good" orion from a "bad" one. +// What counts as a reference, and why the two names differ: +// - `orion` (current) is scanned WHOLE-WORD, any case — the repo name, +// `RigelBuild/orion`, an `orion ` citation, and "ported from orion" +// provenance prose alike. A bare `orion` in this repo is always the repo, +// so a blunt token with a small explicit allowlist is the right shape. +// - `sealed` (former) CANNOT be scanned that way: it is also ordinary +// English this codebase uses constantly (a sealed sum type, a ciphertext +// sealed under a key, an egress-sealed agent), and it is in the public +// company name. A whole-word scan measures 60 tracked lines, all +// legitimate. So it is matched only in repo-SHAPED uses — +// LEGACY_NAME_PATTERNS, whose docstring carries the tradeoff. +// +// The asymmetry is deliberate: blunt where the token is unambiguous, narrow +// where it collides with English. A gate that is all false positives on one of +// its tokens gets switched off, which protects neither. // // CARVE-OUTS (never scanned): // - tools/orion-ref-gate/** this gate's own source + fixtures name the token @@ -57,12 +68,19 @@ export const PRIVATE_TOKEN = "orion"; * a whole-word scan flags 60 lines, every one of them legitimate; a gate that * is 100% false positives gets switched off. * - * So match only the shapes that name the REPO: a path inside it, its docsite - * host, its possessive, or the word followed by a repo-ish noun. + * So match only the shapes that name the REPO: a path inside it (slash- or + * space-separated), its docsite host, its possessive, or the word followed by + * a repo-ish noun (spaced or hyphenated). + * + * The space-form arm requires the cited token to END in a source-file + * extension. A looser `sealed\s+\S*\/` matches ordinary prose, because English + * carries slashes too — "values sealed and/or rotated" and "sealed in + * transit/at rest" both false-positive without the extension anchor. */ export const LEGACY_NAME_PATTERNS: readonly RegExp[] = [ /\bsealed\/[a-z]/i, - /\bsealed-docs\b/i, + /\bsealed\s+[\w.-]+(?:\/[\w.-]+)*\.(?:ts|tsx|js|jsx|go|nix|md|json5?|ya?ml|toml|sh|py|rs|lock)\b/i, + /\bsealed-(?:repo|monorepo|docs|private)\b/i, /\bsealed's\b/i, /\bsealed (repo|monorepo|design corpus|platform|convention|PR #)/i, ]; @@ -190,9 +208,10 @@ export async function runOnce(deps: Deps): Promise { } /** - * `git grep -nEI` for either name over tracked files. The regex is a coarse - * pre-filter — `lineHasToken` makes the real decision, so this only has to be - * a superset of it. `sealed` is matched bare here and narrowed there. + * `git grep -nEI` for either name over tracked files, unanchored. The regex is + * a coarse pre-filter — `lineHasToken` makes the real decision, so this only + * has to be a superset of it. Both names are matched bare here and narrowed + * there. * * `git grep` exits 0 with matches, 1 on no match (a legitimately clean, empty * result), and >=2 on a real error (e.g. not a git work tree). We must @@ -202,7 +221,12 @@ export async function runOnce(deps: Deps): Promise { * returns exit 2. */ async function gitGrep(): Promise { - const pattern = `\\b(${PRIVATE_TOKEN}|sealed)`; + // No `\b` here: it is a GNU extension, not base POSIX ERE. If a toolchain + // change ever made git treat it literally, the pre-filter would match + // nothing and git grep would exit 1 — a legitimately-clean signal — so the + // gate would fail OPEN. The pre-filter only has to be a superset; + // lineHasToken owns the word boundary. + const pattern = `(${PRIVATE_TOKEN}|sealed)`; const res = await $`git grep -nEiI ${pattern}`.nothrow().quiet(); if (res.exitCode >= 2) throw new Error( From 18663ca56780978731eedbb3c09b87f3eda8854b Mon Sep 17 00:00:00 2001 From: mintaka Date: Sun, 13 Sep 2026 19:09:24 -0400 Subject: [PATCH 3/3] docs(orion-ref-gate): cite the pattern the prose examples fail under (RIG-3756) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Review round 2 on PR #1216: high 0, medium 0, low 2. This closes the one low that was a real defect; the other is explicitly informational (the reviewer adjudicated the extension-anchor narrowing as correct and recommended no change). The docstring justified the extension anchor by naming `sealed\s+\S*\/`, then attributed two false positives to it. Only the first actually fails under that pattern: in "rows sealed in transit/at rest" the `\S*` stops at the space before "in", so no slash is adjacent to the token run. Both examples fail under the DEPLOYED arm with its extension anchor stripped, which is the pattern the argument is really about — I had probed the deployed arm and then written up a different regex. A maintainer testing the cited one would find it does not hold and might conclude the anchor is unnecessary. Now names the anchor-stripped arm, and records the trade it buys: a directory-only citation and an off-list extension are missed, deliberately, because broadening to a bare `sealed /` puts those prose hits back and an all-false-positive gate gets switched off. Also makes the whole-word measurement exact. It read "flags 60 lines"; the count outside this gate's own carve-out is 59. A published number that drifts is worse than a stated magnitude, so it now gives the magnitude and scopes the exact figure to its measurement. Verified every claim the docstring now makes: both prose examples clean under the deployed arm, both documented misses confirmed, all three citation shapes still caught. Tests 29 pass / 0 fail; gate clean; root:ci rc=0. Co-authored-by: Matt Wilkinson --- tools/orion-ref-gate/index.ts | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/tools/orion-ref-gate/index.ts b/tools/orion-ref-gate/index.ts index ef721acb2..9ed8e16e9 100644 --- a/tools/orion-ref-gate/index.ts +++ b/tools/orion-ref-gate/index.ts @@ -64,18 +64,24 @@ export const PRIVATE_TOKEN = "orion"; * The private repo's FORMER name, which imported records still carry. It * cannot be scanned whole-word like the current one: `sealed` is also ordinary * English this codebase uses constantly — a sealed sum type, a ciphertext - * sealed under a key, an egress-sealed agent. Measured over the tracked tree, - * a whole-word scan flags 60 lines, every one of them legitimate; a gate that - * is 100% false positives gets switched off. + * sealed under a key, an egress-sealed agent. A whole-word scan of the tracked + * tree flags dozens of lines (59 outside this gate's own carve-out when the + * scan was widened), every one of them legitimate; a gate that is 100% false + * positives gets switched off. * * So match only the shapes that name the REPO: a path inside it (slash- or * space-separated), its docsite host, its possessive, or the word followed by * a repo-ish noun (spaced or hyphenated). * * The space-form arm requires the cited token to END in a source-file - * extension. A looser `sealed\s+\S*\/` matches ordinary prose, because English - * carries slashes too — "values sealed and/or rotated" and "sealed in - * transit/at rest" both false-positive without the extension anchor. + * extension. Drop that anchor and the same arm matches ordinary prose, because + * English carries slashes too: "values sealed and/or rotated" and "rows sealed + * in transit/at rest" both false-positive once the extension is optional. + * + * It therefore misses a directory-only citation ("sealed apps/docs/") and an + * extension outside the list. That is the accepted trade: broadening to a bare + * `sealed /` re-introduces those prose hits, and an all-false- + * positive gate gets switched off, which protects nothing. */ export const LEGACY_NAME_PATTERNS: readonly RegExp[] = [ /\bsealed\/[a-z]/i,