Agentic AI Atlasby a5c.ai
OverviewWikiGraphFor AgentsEdgesSearchWorkspace
/
GitHubDocsDiscord
iiRecord
Agentic AI Atlas · WP-RN-08 record: t3code intake naming rules — the no-double-rename gate
page:docs-specs-platform-gaps-phase0-no-double-renamea5c.ai
Search record views/
Record · tabs

Available views

II.Record viewspp. 1 - 1
overviewarticlejsongraph
III.Related pagespp. 1 - 1
II.
Page reference

page:docs-specs-platform-gaps-phase0-no-double-rename

Reading · 9 min

WP-RN-08 record: t3code intake naming rules — the no-double-rename gate reference

Executed 2026-09-28 on branch phase0/hard-split-registry-guards of a5c-ai/fabric. Spec: docs/specs/platform-gaps/15-private-isolation-rename.md "WP-RN-08", §3.3 (the migrated-unit table, binding), §3.1/§3.2 (name matrix), §5 interaction rules 1, 2 and 4; intent 00-intent.md D17–D21 and acceptance criterion 7; roadmap 50-roadmap-workpackages.md (WP-RN-08 blocks WP-T3-01; M0 exit criterion 4: "the no-double-rename gate trips on a fixture @t3code/x manifest"). Builds on WP-RN-04 (publish-guards.md: the publish-isolation CI job and the single scope constant) and the scope re-lock (scope-relock.md). The public repository a5c-ai/babysitter was never written to (gh api repos/a5c-ai/babysitter --jq .pushedat stayed 2026-09-16T19:59:50Z; only GET calls were issued), nothing was published, no infrastructure changed.

Pagewiki/docs/specs/platform-gaps/phase0/no-double-rename.mdOutgoing · 0Incoming · 1

WP-RN-08 record: t3code intake naming rules — the no-double-rename gate

Executed 2026-09-28 on branch phase0/hard-split-registry-guards of a5c-ai/fabric. Spec: docs/specs/platform-gaps/15-private-isolation-rename.md "WP-RN-08", §3.3 (the migrated-unit table, binding), §3.1/§3.2 (name matrix), §5 interaction rules 1, 2 and 4; intent 00-intent.md D17–D21 and acceptance criterion 7; roadmap 50-roadmap-workpackages.md (WP-RN-08 blocks WP-T3-01; M0 exit criterion 4: "the no-double-rename gate trips on a fixture @t3code/x manifest"). Builds on WP-RN-04 (publish-guards.md: the publish-isolation CI job and the single scope constant) and the scope re-lock (scope-relock.md). The public repository a5c-ai/babysitter was never written to (gh api repos/a5c-ai/babysitter --jq .pushed_at stayed 2026-09-16T19:59:50Z; only GET calls were issued), nothing was published, no infrastructure changed.

What the gate checks

scripts/ci/no-double-rename.cjs (CommonJS, Node ≥ 22, no dependencies; runs before npm ci) scans every workspace package.json (root workspaces globs) plus every package.json up to four path segments deep under packages/, apps/ and infra/ — so a unit dropped into a spec 15 §3.3 directory without a workspaces entry is still seen, and apps/commander (not a workspace) is covered. The private scope is the single constant in the root package.json fabric block (scripts/lib/registry-pin.cjs); the name matrix is parsed from spec 15 itself by scripts/lib/rename-spec.cjs (§2 rejected scopes, §3.1 43 rows including the expanded hooks template row with genty → agent-runtime, §3.2 8 renamable workspaces + the 8-shell retirement row, §3.3 10 migrated units), so the gate cannot drift from the spec text.

"New unit" = a manifest whose name is not in the baseline inventory. Findings (exit 1), each printed as <manifest>:<line of "name">: [rule] message:

RuleTrips when
t3code-scope-namename matches @t3code/*
t3-prefix-namename is t3-* (bare) or @<scope>/t3-*
upstream-t3code-namename is one t3code's own manifests carry in the pinned snapshot: @t3tools/*, t3, t3code-*, effect-acp, effect-codex-app-server (the snapshot's real names are @t3tools/contracts, effect-acp, effect-codex-app-server, @t3tools/ssh, @t3tools/tailscale, @t3tools/client-runtime, t3, @t3tools/web, @t3tools/desktop, t3code-relay — none of them is @t3code/*, so the spec's pattern alone would not have caught a verbatim import)
legacy-scope-new-unita NEW unit carries @a5c-ai/*; the spec 15 §3.2 retirement list (T-27, 8 shells) is exempt
foreign-scope-new-unita NEW unit is in any scope other than @fabricstack (the message names a spec 15 §2 rejected scope when it is one)
unscoped-new-unita NEW unit has no scope
private-scope-name-not-in-speca @fabricstack/* name is not in the §3.1/§3.2 new-name column or the §3.3 table (an interim name such as @fabricstack/effect-acp)
spec-directory-wrong-namea manifest sits in a §3.1/§3.2/§3.3 target directory but carries another name — e.g. packages/catalog holding @a5c-ai/atlas, the "move now, rename later" double rename; retirement-listed names are excepted
retirement-list-driftthe RETIRED_UNITS constant in the script no longer equals the spec 15 §3.2 retirement row (the constant is kept so a reviewer sees the list; the spec text is authoritative)

Notices (never failing): a baseline package found at a directory other than its baselined one; a manifest without a name. There is no waiver annotation: the only way past the gate is a manifest that carries a spec 15 name in a spec 15 directory, or a reviewed baseline change.

Baseline generation

scripts/ci/fixtures/no-double-rename/baseline-packages.json is written by node scripts/ci/no-double-rename.cjs --write-baseline from the tree: 59 entries { name, dir } sorted by directory — the 43 @a5c-ai/* publishables, the 15 @a5c-ai/* private workspaces (8 renamable + 7 retired shells + @a5c-ai/genty-web-app, i.e. the whole §3.2 column) and a5c-commander. scripts/ci/no-double-rename.test.mjs pins the file to the tree (regenerating in memory must equal the file) and asserts that the baseline name set equals spec 15's current-name column exactly, so any inventory change is a deliberate, reviewed diff and the spec's "confirmed from the live inventory" claim stays mechanically true. Migrated units are never added to the baseline: they pass because they carry a §3.3 name, not because they are known.

Fixtures (red, then green)

Under scripts/ci/fixtures/no-double-rename/ (self-contained roots with the fabric block, consumed by --self-test and by the node:test suite):

FixtureManifestResult
negative/t3code-scopepackages/x = @t3code/xpackages/x/package.json:2: [t3code-scope-name] @t3code/x is a t3code-scoped name; migrated units land only as @fabricstack/<spec 15 §3.3 name> (+ foreign-scope-new-unit), exit 1 — **WP-RN-08 AC2 / M0 exit criterion 4**
negative/t3-prefixpackages/t3-x = t3-x[t3-prefix-name], exit 1
negative/legacy-scope-new-unitpackages/new-unit = @a5c-ai/new-unit (public)[legacy-scope-new-unit], exit 1
negative/rejected-scopepackages/x under the spec 15 §2 rejected scope proposal[foreign-scope-new-unit] ... is a rejected scope (spec 15 §2), exit 1
negative/upstream-namepackages/contracts = @t3tools/contracts, packages/acp = effect-acp, infra/relay = t3code-relay[upstream-t3code-name] + [spec-directory-wrong-name] on all three, exit 1
negative/old-name-in-spec-dirpackages/catalog = @a5c-ai/atlas[spec-directory-wrong-name] packages/catalog is the spec 15 directory of @fabricstack/catalog but the manifest is named @a5c-ai/atlas, exit 1
negative/interim-private-namepackages/acp = @fabricstack/effect-acp (pinned to AR)[private-scope-name-not-in-spec] + [spec-directory-wrong-name], exit 1
positive/migrated-unitpackages/contracts = @fabricstack/contracts, apps/environment = @fabricstack/environment (bin environment-server), both pinned to AR0 findings
positive/baseline-unchangedpackages/atlas = @a5c-ai/atlas0 findings

node scripts/ci/no-double-rename.cjs --self-test → every negative trips with a file:line on the "name" line, both positives pass, then ok repository scan — 59 manifest(s), 0 findings, 0 notice(s), 0 new unit(s) and no-double-rename self-test: 10/10 assertions passed (7 negative, 2 positive fixtures; retirement list: 8 units), exit 0. The node:test suite (npm run test:no-double-rename, 16 tests) additionally proves on synthetic roots that a rename in place (packages/atlas → @fabricstack/catalog), a move with the new name, and a §3.3 birth (packages/contracts = @fabricstack/contracts, infra/relay = @fabricstack/relay) pass, that every other birth name trips, that retirement-listed shells stay exempt with an empty baseline, that a manifest without a workspaces entry is scanned, and that the CLI exits 1 with packages/x/package.json:2: [t3code-scope-name] @t3code/x ... on the AC2 fixture.

Spec 10 naming check (AC1)

scripts/ci/check-spec10-names.cjs parses spec 15 §3.3 into the canonical set and asserts docs/specs/platform-gaps/10-t3code-migration.md references migrated units only by those @fabricstack/… names: violations are t3code-scope-name, t3-prefix-name (a t3-* token quoted as code and not a path), upstream-t3code-name (@t3tools/*, t3code-*), legacy-scope-name (@a5c-ai/<x> where <x> is not a §3.1/§3.2 current name — existing fabric units may be cited by their current name under interaction rule 3), rejected-scope-name (any spec 15 §2 rejected scope), interim-private-name (@fabricstack/<x> outside §3.1/§3.2/§3.3), and missing-migrated-name / missing-migrated-dir (each of the ten §3.3 names and directories must appear). The allow-rule is explicit and narrow, and every allowed hit is printed as a notice: the glob forms @t3code/*, t3-*, @a5c-ai/* (spec 10 restating the rule), a t3-/t3code- token inside a path segment (t3:docs/internals/t3-connect.md, research/t3code-architecture.md), and a forbidden name inside a code span immediately preceded on the same line by "upstream name" or "upstream package" (the provenance form). A bare hyphenated token outside a code span is prose (the four/five t3code-blind actions, spec 10 §4.3) and is not a name.

Result on the binding text: **0 violations, 12 notices** (lines 18 and 237: the three rule-statement globs; lines 5, 206, 236, 475: upstream path citations; line 214: @a5c-ai/comm-adapter, an existing fabric unit in the §7 consumer inventory). All ten §3.3 names and all ten directories are present. **No change to spec 10 was needed**; its final text already references only §3.3 names. --self-test first proves scripts/ci/fixtures/no-double-rename/spec10/negative.md trips all eight rules (25 violations) and exercises all three allow forms as notices, then checks the real spec 10: check-spec10-names self-test: passed (10 §3.3 names checked).

CI wiring and intake documents

  • .github/workflows/ci.yml, job publish-isolation (WP-RN-04's guard job), new step "No-double-rename gate and spec-10 naming check (WP-RN-08)": node scripts/ci/no-double-rename.cjs --self-test, node scripts/ci/check-spec10-names.cjs --self-test, npm run test:no-double-rename. js-yaml loads the file; job list unchanged (public-push-guard, publish-isolation, docs-quality, test, gateway-node-engine, workspace-coverage, observer-dashboard).
  • Root package.json: "test:no-double-rename": "node --test scripts/ci/no-double-rename.test.mjs". test:publish-guards runs a single file and was left untouched.
  • .github/PULL_REQUEST_TEMPLATE/upstream-intake.md and docs/UPSTREAM-INTAKE.md §10 now carry the naming rules: a unit entering fabric lands only as @fabricstack/<spec 15 §3.3 name> in the §3.3 directory, pinned to Artifact Registry; never @t3code/*, t3-*, the upstream t3code names, @a5c-ai/* or any other scope for a new unit; the gate enforces it and has no waiver.

Acceptance criteria

ACStatus
(1) spec 10's final text references @fabricstack/{contracts,acp,codex-protocol,ssh,tailscale,environment,client-runtime,console-web,console-desktop,relay} and no interim names**Done, mechanically**: check-spec10-names.cjs → 0 violations; runs in CI so the Gate-B cross-check cannot regress
(2) the CI assertion trips on a fixture @t3code/x manifest**Done**: negative/t3code-scope, packages/x/package.json:2: [t3code-scope-name], exit 1; asserted by --self-test and by the node:test suite
(3) the first real landed fork (T-01/T-02 output) passes the gate un-waived**Not yet exercisable** — no fork has landed (Phase 0 has no migrated unit). Owned by WP-T3-01 AC3 and WP-T3-02 AC5 (roadmap M2 exit criterion 1). The gate is in place for them, see below

How WP-T3-01 / WP-T3-02 pass it un-waived

1. Each landed unit's package.json is born with the §3.3 name and in the §3.3 directory (@fabricstack/contracts at packages/contracts, @fabricstack/acp at packages/acp, …, @fabricstack/relay at infra/relay), with publishConfig.registry = the Artifact Registry URL (guard G1) and, for the three (private) rows, private: true. Upstream names (@t3tools/contracts, effect-acp, t3code-relay, t3) may appear only in UPSTREAM.json, LICENSE-THIRD-PARTY and provenance headers — never in a name field. 2. The baseline is not touched: a migrated unit passes because its name is in spec 15, not because it is baselined. If --write-baseline shows a diff in a migration PR, something landed under a non-spec name. 3. The intake PR fills the "Naming rules" checklist of the template and cites node scripts/ci/no-double-rename.cjs output (0 findings) as test evidence; the publish-isolation job is the mechanical proof. There is no allow annotation or environment flag that relaxes the gate. 4. If spec 15 §3.3 changes at Gate B, the spec text is edited first and the gate follows automatically (it parses the table); check-spec10-names.cjs then tells spec 10 which references to update.

Gates run (from `C:/work/fabric`)

  • Orchestrator gate, verbatim: node scripts/ci/no-double-rename.cjs --self-test && echo NDR-PASS → ... no-double-rename self-test: 10/10 assertions passed (7 negative, 2 positive fixtures; retirement list: 8 units) then NDR-PASS.
  • npm run test:no-double-rename → # tests 16 / # pass 16 / # fail 0.
  • node scripts/ci/check-spec10-names.cjs --self-test → passed (fixture: 25 violations across all 8 rules; spec 10: 0 violations, 12 notices).
  • npm run test:publish-guards → 17/17; node scripts/ci/publish-isolation-guard.cjs --self-test → repository scan clean (122 files — it now also sees the new fixture manifests — 0 findings, 8 legacy-train notices).
  • node scripts/ci/public-push-guard.cjs → 214 files, 0 findings, 0 suppressed; npm run guard:packages → package-integrity guard passed; node --test scripts/__tests__/publishable-packages.test.mjs → 7/7 (still 43 @a5c-ai/* publishables).
  • js-yaml loads ci.yml; node scripts/docs-style-check.cjs and npx markdownlint-cli2 clean on every edited document.

Commits (branch `phase0/hard-split-registry-guards`, pushed)

See git log --oneline -- scripts/ci/no-double-rename.cjs docs/specs/platform-gaps/phase0/no-double-rename.md; the SHAs are recorded in the WP output.

Article source

The article body is owned directly by this record.

Related pages

No related wiki pages for this record.

Shortcuts

Open overview
Open JSON
Open graph