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..52608a9a5 100644 --- a/tools/orion-ref-gate/index.test.ts +++ b/tools/orion-ref-gate/index.test.ts @@ -50,6 +50,66 @@ 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, + ); + }); + // 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); + 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..9ed8e16e9 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 @@ -43,9 +54,43 @@ 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. 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. 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, + /\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, +]; + /** * 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 +142,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 +214,26 @@ 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, 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 + * 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(); + // 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( `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";