Agentic AI Atlasby a5c.ai
OverviewWikiGraphFor AgentsEdgesSearchWorkspace
/
GitHubDocsDiscord
iiRecord
Agentic AI Atlas · WP-RN-07 record: release machinery → Artifact Registry, `fabric/<branch>/v*` tags, waves, verifier, recovery
page:docs-specs-platform-gaps-phase1-rn-07-releasea5c.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-phase1-rn-07-release

Reading · 35 min

WP-RN-07 record: release machinery → Artifact Registry, `fabric/<branch>/v*` tags, waves, verifier, recovery reference

Executed 2026-10-03 on branch phase1/rename-train of a5c-ai/fabric (draft PR 4). Spec: docs/specs/platform-gaps/15-private-isolation-rename.md WP-RN-07 (§1.2 invariants, §1.3 retag discipline, §4.1–§4.3), 00-intent.md D10/D17–D21, 40-packaging.md §2.2/§2.3/§5. Owner decisions at Gate A: "Approve (Recommended)"; verifier workflow "Enable now" (enabled and first dispatched by the orchestrator); naming "Keep both". The public repository a5c-ai/babysitter was never written to (pushedat 2026-09-16T19:59:50Z at start and end; tag count 404 at start and end, 0 fabric/ tags there; upstream remote push = nopush), nothing was published to any registry (npm publish ran only with --dry-run, locally against a fixture npm and once against Artifact Registry with a reader credential, which the registry refused at the existence query — see §6), and no tag was created (fabric tags: the same 3 gke-cutover- tags before and after).

Pagewiki/docs/specs/platform-gaps/phase1/rn-07-release.mdOutgoing · 0Incoming · 1

WP-RN-07 record: release machinery → Artifact Registry, `fabric/<branch>/v*` tags, waves, verifier, recovery

Executed 2026-10-03 on branch phase1/rename-train of a5c-ai/fabric (draft PR #4). Spec: docs/specs/platform-gaps/15-private-isolation-rename.md WP-RN-07 (§1.2 invariants, §1.3 retag discipline, §4.1–§4.3), 00-intent.md D10/D17–D21, 40-packaging.md §2.2/§2.3/§5. Owner decisions at Gate A: "Approve (Recommended)"; verifier workflow "Enable now" (enabled and first dispatched by the orchestrator); naming "Keep both". The public repository a5c-ai/babysitter was never written to (pushed_at 2026-09-16T19:59:50Z at start and end; tag count 404 at start and end, 0 fabric/ tags there; upstream remote push = no_push), nothing was published to any registry (npm publish ran only with --dry-run, locally against a fixture npm and once against Artifact Registry with a reader credential, which the registry refused at the existence query — see §6), and no tag was created (fabric tags: the same 3 gke-cutover-* tags before and after).

1. What the train looks like now

Code
publish-npm-private.yml (push main|staging|develop; dispatch = dry run unless dry_run=false)
  resolve_release ──► verify_release_artifacts (release-artifact-verifier.yml, 43 pkgs, no tolerance)
        │                      │
        └──────────────────────┴──► publish_candidates  (needs both; if verifier == success)
                                      WIF auth ─► google-artifactregistry-auth ─► npm ping AR
                                      verify --write release-version.json (identity re-validated)
                                      sync-workspace-versions ─► verify-manifests ─► publish-isolation-guard
                                      assert-channel-tags --mode preflight --registry AR
                                      build waves (release-matrix --format waves, npm run build per member)
                                      publish waves (publish-package-from-tag.mjs, FABRIC_RELEASE_PUBLISH=1,
                                                     candidate-<version>, --registry AR)   [dry run: --dry-run]
                                      assert-channel-tags --dist-tag candidate-<v> --mode final
                                ──► published_consumer_validation (live-stack-published.yml, exact version)
                                ──► promote_release_channel  (release-promotion.cjs promote --evidence)
                                ──► assert_release_channel_tags (every package, channel == version)
                                ──► create_release_tag (release-tags.yml → fabric/<branch>/v<version>)

publish-packages-from-tag.yml (push tags fabric/**; dispatch tag=)
  release_identity (tag-source: version/channel/registry from the tag; refuses a tag the train created)
  ──► verify_release_artifacts (strict, against the TAG tree)
  ──► publish_non_plugin_packages (same sequence; existing versions only candidate-tagged → idempotent)
  ──► published_consumer_validation ──► promote_release_channel (+ final assertion)

live-stack-published.yml   WIF + AR credential; published_consumer = fresh project + .npmrc routing +
                           install/import/bin smoke of all 43 + §3.1 global-install smoke; live lanes install
                           the §3.1 CLIs from AR at the exact version (no --force), run the live stack
fix-npm-tags.yml           dispatch-only AR dist-tag repair (audit | set), dry run unless dry_run=false
release-tags.yml           fabric/<branch>/v<version>, fabric-release-* provenance, this repo only

Derived publication waves at HEAD (13 waves, 43 packages; node scripts/release-matrix.cjs --group all-publishable --format waves): 1 catalog control-plane harness-observability harness-tasks harness-triggers operator trust · 2 harness-extensions harness-hooks-core harness-policy · 3 harness-core + the 12 harness-hooks-* leaves · 4 console-ui harness-codecs harness-config harness-hooks-cli harness-mock model-gateway · 5 harness-gateway harness-launch harness-tools · 6 harness-cli · 7 harness-sdk · 8 console-tui harness-channels orchestrator-sdk · 9 agent-runtime-engine observer · 10 agent-runtime-core · 11 agent-runtime-platform · 12 agent-runtime-cli · 13 orchestrator.

2. What changed, per file

FileChange
scripts/lib/release-version.cjsTAG_PREFIX = 'fabric' (exported, with TAG_MESSAGE_KEY_PREFIX = 'fabric-release-'); tag body fabric release <v> (<branch>) + fabric-release-{version,branch,source,commit,run}; parseTagMessage reads only those keys; parseReleaseTag rejects every other namespace (babysitter/* included); npmDistTags/assertChannelTags take registry and pass --registry (default: the root manifest's fabric.privateRegistry); reconcile error names the fabric/<branch>/v<version> tag
scripts/release-version.cjsevery emitted identity (resolve, verify, from-tag, tag-source) carries registry; --github-output therefore exports registry=; assert-channel-tags --registry <url> (default AR); header documents the private train and the unchanged channel semantics
scripts/publish-package-from-tag.mjsprivate scope from the fabric block; G1 asserted on the manifest at publication time (manifestProblems + exact publishConfig.registry); --registry <AR> on publish/view/dist-tag add; no --access; FABRIC_RELEASE_PUBLISH=1 explicit opt-in replaces the NODE_AUTH_TOKEN gate; --dry-run runs the whole sequence with npm publish --dry-run; a /-shaped ref outside fabric/ is refused as a channel source; npm output naming the public registry is a hard failure
scripts/lib/release-promotion.cjs, scripts/release-promotion.cjsexactVersionExists and the planned dist-tag add commands carry --registry <AR>; assert-installed --prefix <dir> for the throwaway global prefix
scripts/verify-published-release.mjsthe fresh consumer gets .npmrc = @fabricstack:registry=<AR> (recorded in install.log)
scripts/verify-release-artifacts.mjsthe clean consumer gets the same routing line (internal deps still resolve from checkout-packed tarballs; an escaped edge now fails at AR, never resolves a stranger's package on npmjs)
scripts/fix-broken-latest-tags.mjsrewritten: inventory-derived, --registry <AR> on every call, refuses the public registry; audit mode (latest → prerelease / empty artifact / missing latest, proposes last healthy release) and --set <dist-tag>=<exact> whole-inventory repair that refuses to retag if any package lacks the version; dry run unless --fix; --package, --json
scripts/check-package-metadata.cjsRELEASE_MATRIX_SURFACES = [publish-npm-private.yml, publish-packages-from-tag.yml] — the coverage gate is live again (verify:metadata: 43 packages, 0 violations)
scripts/ci/publish-isolation-guard.cjsG2(c)/G3 whole-tree rules unconditional (npmjs-publish-context, npmjs-credential are findings in every workflow; no legacy-train notice class; --private-train no-op alias); header rewritten
scripts/lib/registry-pin.cjsdoc: the flag is a no-op alias everywhere since WP-RN-07
scripts/ci/fixtures/publish-guards/g3/{positive/legacy-train-notice-only → negative/legacy-train-publish}the public-train shape is now a NEGATIVE fixture (npmjs-publish-context, npmjs-credential)
.github/workflows/publish-npm-private.ymlNEW — see §1
.github/workflows/publish-packages-from-tag.ymlfabric/**; WIF + helper; registry from the tag identity; wave-derived build replaces the hand-listed @a5c-ai builds; FABRIC_RELEASE_PUBLISH=1; candidate assertion; no registry-url, no NPM_TOKEN; the sync_external_plugins_develop job removed (it pushes public marketplace repositories — WP-RN-11's surface)
.github/workflows/live-stack-published.ymlWIF + helper in published_consumer and every live lane; no registry-url; §3.1 global-install smoke step (WP-RN-06 AC2, --@fabricstack:registry=<AR> per call, --prefix, EEXIST fails, exact bin sets orchestrator then harness harness-hooks orchestrator); live lanes install orchestrator orchestrator-sdk harness-sdk agent-runtime-cli harness-hooks-cli at the exact version, no --force, EEXIST fails; assert-installed on those five; harness install; bins --version smoke
.github/workflows/fix-npm-tags.ymldispatch-only (push trigger registers it, job gated), WIF + helper, modes audit/set, dry_run default true
.github/workflows/release-tags.yml, release-artifact-verifier.ymlheaders for the private namespace / the consumer routing line (logic unchanged)
.github/workflows/ci.ymlguard comment no longer spells the public registry host; release-tooling job comment describes the expected-green state
.github/workflows/ar-smoke.ymlthe dry-run assertion refuses any npmjs mention (stricter than the host literal)
.github/workflows/publish.ymluntouched: it is the GKE deploy pipeline and carried no npm publish job (WP-RN-01 de-mirrored it; the @a5c-ai/genty-web-app build at line 178 is a retirement-listed private shell, not a publish path)
docs/RELEASE-RUNBOOK.mdNEW operator runbook (invariants, normal train, dry-run commands, consumer validation, half-published recovery, dist-tag repair, credentials, FIX-005 follow-up, pending G3/G4 owner actions, public-namespace checks)
docs/release-pipeline.md, docs/VERSIONING.md, docs/user-guide/private-install.md, docs/release-recovery-runbook.mdmodel rewritten for AR; links to the runbook; the public-train runbook carries a superseded banner
packages/adapters/hooks/cli/package.json//deferred-dependency note → docs/RELEASE-RUNBOOK.md § 7.1
testssee §4

3. Decisions recorded

**Roadmap conflict and reconciliation (review M4, 2026-10-04):** 50-roadmap-workpackages.md wrote the M1 evidence as the literal fabric/staging/v7.0.0 (M1 exit criterion 1, risk 7, WP-RM-02 AC1), which parseReleaseTag rejects (from-tag --tag fabric/staging/v7.0.0 → "must encode a staging prerelease of the form <major>.<minor>.<patch>-staging.<short-sha>", exit 1), so the criterion could never be satisfied as written. Owner decision at the pre-Gate-B interview: **"Spec 15 wins: staging = 7.0.1-staging.<sha>"** — the resolver's inherited channel scheme is kept, and the roadmap wording was amended with a dated note: the staging evidence for M1 is the tag fabric/staging/v7.0.1-staging.<sha> publishing all 43 @fabricstack/* packages at that exact version under dist-tag staging; fabric/main/v7.0.0 (channel latest) is the promotion evidence of the later main train. The resolver's rejection message now names both accepted shapes (fabric/main/v<X.Y.Z> and fabric/<staging|develop>/v<X.Y.Z>-<branch>.<sha>); the runbook §0 carries the same reconciliation row.

  • **Staging/develop version shape kept**: spec 15 §4.1 says the dist-tag/channel scheme "carries over unchanged … the resolver logic ports as-is" and §4.2 adds nothing about the version shape, so staging resolves 7.0.1-staging.<sha> (FIX-001 commit-pinned prerelease) and main resolves 7.0.0. Nothing re-derives either.
  • **Registry is part of the release identity** (registry field) and named explicitly on every npm view / dist-tag add / publish of the train, on top of G1 and the committed .npmrc routing.
  • **Opt-in instead of a token gate**: AR credentials live in $HOME/.npmrc after the helper, so "credentials present" is not observable the way NODE_AUTH_TOKEN was; publication now requires FABRIC_RELEASE_PUBLISH=1, set only by the two publish workflows after WIF auth. A local invocation can never publish; --dry-run rehearses.
  • **Scope routing per call for global installs** (--@fabricstack:registry=<AR>), not --registry <AR>: a global --registry would send third-party dependencies to AR (a standard repository, not a proxy) and 404. The WP-RN-06 AC2 command list used --registry $AR; the runbook and the workflow use the scoped form.
  • **No external-plugin sync in the release path**: sync-external-plugins.yml/sync-atlas-plugins.yml push public marketplace repositories; they are WP-RN-11's and are not called by either AR publish workflow (pinned by verify-release-artifacts.test.mjs).
  • **Build order = publication waves**, sequential within the publish job (npm run build --if-present --workspace=<pkg> per member): several packages chain root build:* scripts through --prefix, so parallel wave builds would race on shared outputs; correctness over speed in the release lane. The verifier (its own job) builds every package the same way.
  • **G2(c)/G3 hard in default mode**: with every publish path on AR there is no legacy train left to tolerate; the fixture that documented the tolerance is now the negative that proves the rule.
  • **ci.yml/ar-smoke.yml wording**: the orchestrator's gate greps every workflow for the literal public-registry host (comments included), so the guard comment and the smoke assertion no longer spell it; the assertion got stricter (npmjs), the rule text lives in the script.

4. Tests rewritten (before → after) and added

Before this WP npm run test:release-tooling was red in CI with exactly 9 inherited names (run 37144046853, # tests 163 / pass 154 / fail 9); each asserted the PUBLIC train's publish.yml shape.

Before (failing)After (passing) — same invariant, private shape, equal or stricter
both release workflows PUBLISH every public hooks leaf, derived from the inventorysame name; surfaces = publish-npm-private.yml + publish-packages-from-tag.yml; every leaf covered by derivation AND no leaf named in executable text at all; no @a5c-ai/hooks-adapter-
both release workflows BUILD the derived hooks leaves before publishing themsame name; both build the whole train from the derived waves in a step preceding the wave-publish step; no hand-listed hooks builds
publication order publishes the Genty leaf before the hooks CLIsame name; both consume the waves, publish only through the helper (no literal npm publish, no publish_staging_* jobs); waveOf(leaf) < waveOf(cli) kept
both release workflows still cover the whole inventory once comments are ignoredsame name; surfaces retargeted (0 violations on both)
FIX-010: the publish workflow calls the published-consumer workflow with the exact release versionsame name; with.release_version and with.candidate_dist_tag from needs.resolve_release.outputs, needs includes publish_candidates, ref: github.sha
FIX-010: channel promotion is a separate job that depends on the published-consumer validationunchanged assertions, new workflow
FIX-010: the channel-tag assertion and the release tag follow the validated promotionunchanged assertions, new workflow
the release path runs the packed-artifact gate with no tolerance leftnew workflow; also packages: ''
FIX-011: the branch release cannot publish unless the packed-artifact matrix passespublish_candidates needs + if-checks the verifier; it is the ONLY job running the helper; validation/promotion/assertion/tag are transitively gated

Also adjusted: the recovery workflow acts on the RESOLVED release tag, never on github.sha (the external-plugin sync assertion became "no such job may exist"); FIX-005: the hooks CLI Genty pin … (runbook = docs/RELEASE-RUNBOOK.md, leaf = @fabricstack/harness-hooks-agent-runtime); release-version.test.mjs (20 tag literals → fabric/, babysitter/* rejection + TAG_PREFIX pinned); publish-package-from-tag.test.mjs (FABRIC_RELEASE_PUBLISH opt-in, fabric/ refs); publish-guards.test.mjs (default-mode findings, no notices, the six release workflows scanned, no workflow mentions the public host, touching-private list = 11 workflows). No test deleted or skipped.

New scripts/__tests__/private-release-train.test.mjs (15 tests at the first review, 21 after the 2026-10-04 review fixes — §9; the "19" this record carried until the second review predated the two additions that landed with the rehearsal fixes; cross-platform fake npm — .cmd shim on Windows): resolver prints AR + fabric/ tag for main/staging/develop and verify/from-tag carry the registry; public tags and provenance rejected; every workflow parses (yaml) and none mentions the public host or an npmjs secret; WIF + helper + .npmrc diff check on every AR workflow, no registry-url, id-token: write where auth runs; strict matrix gate before publish on both paths with step order sync → preflight → build → publish → candidate assertion and explicit --registry; promotion depends on validation, exactly one promote, assertion then tag, fabric/** tag trigger, no tag job in recovery; release-tags.yml shape; coverage gate live on both surfaces (0 violations over 43); consumer lane scope routing + §3.1 global-install smoke + exact-version live-lane installs; helper: no publish without opt-in, --dry-run shape (--tag candidate-<v> --ignore-scripts --registry <AR> --dry-run, no --access), opt-in publish + idempotent candidate-tag on re-run, G1 refusal with zero npm calls, fabric/ refs only; dist-tag repair: inventory-derived, every call ends with --registry <AR>, read-only audit, --fix, --set refuses a half-published train and a mutable version.

4b. Cross-platform test infrastructure (so the orchestrator's gate can be green on this machine)

The orchestrator's gate includes npm run test:release-tooling, which had never been green on this Windows machine: the fake-npm fixtures of four suites were #!/bin/sh files that cmd.exe cannot resolve (RN-05: 37 fail pristine, "npm-stub-on-PATH tests, impossible on Windows"), and the verifier's bin smoke spawned the POSIX .bin/<name> shim where npm on Windows links <name>.cmd. Fixed without touching any assertion: (1) scripts/__tests__/release-version.test.mjs and publish-package-from-tag.test.mjs fakes ported from sh to node (same behaviour: log, E404/error/appear-after/published-list), and all four fakes (release-promotion, verify-published-release included) gain an npm.cmd that delegates to the same node file; (2) the verify-published-release.test.mjs fake install now links <bin>.cmd like real npm does on Windows; (3) scripts/verify-release-artifacts.mjs and scripts/verify-published-release.mjs smoke <bin>.cmd through a shell on Windows (the verifier's exec no longer substitutes npm.cmd for a .cmd command). Windows result: release-version 31/31, publish-package-from-tag, release-promotion, verify-published-release 12/12, verify-release-artifacts 24/24, hooks-atlas-ownership 6/6 — the suites that were environmental are now proof on both platforms; CI (Linux) unchanged.

Incident while recording this (kept for honesty, like PKG-01's): an inline node -e "..." edit of this record carried backticks inside a bash double-quoted string, so bash executed the backtick fragments as command substitutions — one of them started scripts/verify-release-artifacts.mjs over the full matrix (read-only; builds into temp). It was stopped after 5 packages, the stray node process killed, git status confirmed only the 7 intended files were modified, and the edit was redone from a script file. Nothing was published, committed or pushed by the slip.

5. Gates and runs

CheckResult
node scripts/release-version.cjs resolve --branch staging --sha 78df5013cffc7.0.1-staging.78df5013cffc / staging / fabric/staging/v7.0.1-staging.78df5013cffc / registry: https://us-central1-npm.pkg.dev/boot-464019/fabric-npm/
… resolve --branch main …7.0.0 / latest / fabric/main/v7.0.0 / same registry; verify --version 7.0.0 --print registry → the AR URL
… from-tag --tag babysitter/main/v6.0.3exit 1: does not match fabric/<branch>/v<version>
verify-manifests --version 7.0.0All synchronized manifests are at release version 7.0.0.
publish-isolation-guard.cjs --self-test16/16 assertions passed; repository scan clean (131 files, 0 findings, 0 legacy-train notice(s)) (re-run 2026-10-04 on 6c9f9eed9; the first review saw 15/15 — the legacy-name-template fixture added one assertion)
public-push-guard.cjs --self-test24/24 … repository scan clean (354 files, 0 findings) (re-run 2026-10-04 on 6c9f9eed9; 350 files at the first review)
npm run verify:metadataMetadata verification passed. Publishable inventory: 43 public packages. (coverage gate live on both surfaces)
every workflow YAMLjs-yaml + yaml parse: 0 invalid (31 files)
grep -rln registry.npmjs.org .github/workflowsnothing (live-stack-published retargeted too)
docsmarkdownlint 0 errors, docs-link-check 0 failures, docs-style-check 0 issues
node --test scripts/__tests__/private-release-train.test.mjs21/21 (re-run 2026-10-04 on 6c9f9eed9 after the §9 additions; 15/15 at the first review)
npm run test:release-tooling (this machine, Windows)before: 163 tests / 109 pass / 54 fail (Windows baseline, incl. the 9 CI names); after: 178 / 146 / 32 — 0 newly failing names, 22 baseline names fixed; the 32 remaining are the #!/bin/sh fake-npm suites that cannot shadow npm.cmd on Windows (release-version FIX-001 assertions, publish-package-from-tag, verify-published-release, verify-release-artifacts bin-smoke/.cmd, hooks CLI packed consumer) — documented as environmental by RN-05/RN-06/PKG-01/PKG-02; CI is authoritative
CI release-tooling jobrun 37147345462 (eaffe818c): **success** (first green since the WP-RN-05 split); run 37147698801 (d0c5e47b2): **success**; run 37149333707 (7635c68e9, final head): **success** — https://github.com/a5c-ai/fabric/actions/runs/37149333707
CI test job (Lint, Tests, Package)run 37147698801: **success**; run 37149333707 (final head): **success**; also success: Public-push guard, Publish-isolation guards (G1-G6), Observer Dashboard, Workspace Coverage. Inherited and untouched (not this WP's): Gateway Node engine floor (22) / (22.13.0) — failure, as before this WP. **Docs QA was NOT inherited on 7635c68e9 (run 37149333707) or 55036e19c (run 37150847430)** — correction 2026-10-04 (review M5), replacing the earlier "failure, as before this WP" claim for that job: on both heads Docs QA failed *earlier* than the baseline, in docs:links, on RELEASE-RUNBOOK.md links unresolved in the strict Docusaurus scope — a new failure introduced by this WP's 870b425ee (the runbook's cross-links), found by triage-C. Fixed in 20ef45aa9 (docs/RELEASE-RUNBOOK.md added to strictDocInclude in docs-site/docusaurus.config.js; the links to the user guide and the superseded runbook rewritten as pathname:/// links); from 20ef45aa9 on (run 37152039889) Docs QA reaches docs:freshness and fails there with the baseline's identical 7-entry freshness list — inherited only from that commit onward. Run 37147345462 had Publish-isolation red on three publish-guards assertions still encoding the legacy-train tolerance (fixed in d0c5e47b2) and its test/Observer jobs cancelled by the next push
orchestrator gate (verbatim, this machine)started on the final tree (7635c68e9) to the scratchpad; the Claude Code session **killed it mid-suite for critically low system memory** ("stopped because the system is running low on memory … do not start it again on your own") after All synchronized manifests are at release version 7.0.0. and 31 logged tests (the not ok lines in the partial log are whole test FILES aborted by the kill, not assertions, plus the hooks-CLI packed-consumer test that passes 6/6 alone — the catalog-rebuild race PKG-02 documented). Not restarted per the notice. Equivalent proof: every suite of test:release-tooling run individually on this machine after the cross-platform fix is green (§4b), and CI's release-tooling job is green on every pushed head (eaffe818c, d0c5e47b2, 7635c68e9); the other four gate members are green locally (verify-manifests, publish-isolation-guard 15/15 + 0 findings, public-push-guard 24/24 + 0 findings, the npmjs grep lists nothing)

6. Dry-run proof and what the registry answered

node scripts/publish-package-from-tag.mjs --workspace=@fabricstack/trust --release-version=7.0.0 --skip-build --dry-run against the real Artifact Registry with the reader credential (google-artifactregistry-auth for tal@a5c.ai, npm ping → PONG): the helper stopped at the existence query with Registry query for @fabricstack/trust@7.0.0 failed (exit 1) without reporting E404 … npm error code E403 … The caller does not have permission — the fail-closed path (a non-404 answer is never read as "unpublished"). The same 403 came back for @fabricstack/smoke (which exists) and for a made-up name, from npm view and from a direct bearer-token GET, so it is the account's read permission on the npm endpoint, not a resolver defect; gcloud artifacts … get-iam-policy shows tal@a5c.ai as roles/artifactregistry.reader (phase 0 record), which was enough for the phase-0 install transcript. Follow-up for the owner (not in this WP's power): confirm the reader binding still resolves for npm reads (possibly a conditional/expired grant); CI's service account is the writer and is the identity every workflow uses. The helper's --dry-run shape itself is proven by the fixture-backed test (publish --workspace … --tag candidate-<v> --ignore-scripts --registry <AR> --dry-run, no --access, no mutation).

**Correction (review M1, 2026-10-04) — what the whole-train rehearsal actually is.** The sentence this record first carried here ("the whole-train rehearsal is the workflow_dispatch default of publish-npm-private.yml, which is what Gate B should run first") was false on two counts, both found by the release-machinery review: (a) the helper ran its exact-internal-dependency gate under --dry-run against the registry, and on the first train the registry is empty, so every wave ≥ 2 failed (--workspace=@fabricstack/harness-policy … --dry-run → "Required internal dependency @fabricstack/harness-tasks@7.0.0 is not published yet", exit 1 against a fake E404 npm); (b) publish-npm-private.yml is unregistered on any branch GitHub can dispatch from (gh api repos/a5c-ai/fabric/actions/workflows/publish-npm-private.yml → 404) until it lands on staging, and that push IS the live train (dry_run=false on a push event). Fixes: the helper's --dry-run now accepts an exact internal pin that a publishable workspace of the checkout carries at exactly that version ("published by an earlier wave of this train"; every other pin keeps the strict registry check), and a new --rehearsal mode (implies --dry-run) issues no registry query at all for a credential-less job while still running the real npm publish --dry-run (npm never contacts the registry on a dry run — lib/commands/publish.js: if (!dryRun) await libpub(...)); the real publication path is byte-for-byte the strict one (fixture tests: dry-run passes on a two-wave fixture with an empty registry, the opt-in path still fails with the dependency-order message, a pin outside the train still fails in both modes). ci.yml gained the job **release-train-rehearsal** (pull_request): the train's publish_candidates sequence end-to-end for the staging identity of the PR head — resolve → lockstep check + guards → release plan written and validated → sync + verify-manifests + guard → derived wave build → SDK package health → wave publish --rehearsal (same parallelism) → proof that all 13 waves completed, 43/43 packages dry-run-published, 43 publish commands all carrying --dry-run, no published line, no dist-tag add, no npmjs in any log; the packed-artifact gate is logged as covered by release-artifact-verifier.yml on the same PR and the two registry-facing assertions as skipped by design. No credential, no id-token: write, no FABRIC_RELEASE_PUBLISH. **Gate B should read it this way: the first real run of publish-npm-private.yml is the staging merge; the rehearsal evidence is this job (run URL in §9) plus the verifier's 43/43.**

7. Verifier run(s)

RunHeadResult
37144046853 (orchestrator's dispatch, 1 of 3)78df5013cfailed at step Release tooling tests (# fail 9, the inherited names); the packed-artifact matrix never ran — the inherited red was the only blocker of the first 43-package exactness + bin-smoke run
37147369892 (dispatch 2 of 3)eaffe818cRelease tooling tests **passed** (the 9 inherited names green on Linux); failed at Publish-isolation gate self-test on the same three publish-guards assertions (fixed in d0c5e47b2)
37147720098 (dispatch 3 of 3)d0c5e47b2**success** — https://github.com/a5c-ai/fabric/actions/runs/37147720098 — every step green; Verify packed artifacts (full matrix, --exactness, allow_known_failures=false): **43 passed / 0 failed** — agent-runtime-cli, agent-runtime-core, agent-runtime-engine, agent-runtime-platform, catalog, console-tui, console-ui, control-plane, harness-channels, harness-cli, harness-codecs, harness-config, harness-core, harness-extensions, harness-gateway, harness-hooks-agent-runtime, harness-hooks-antigravity, harness-hooks-claude, harness-hooks-cli, harness-hooks-codex, harness-hooks-copilot, harness-hooks-core, harness-hooks-cursor, harness-hooks-gemini, harness-hooks-hermes, harness-hooks-oh-my-pi, harness-hooks-openclaw, harness-hooks-opencode, harness-hooks-pi, harness-launch, harness-mock, harness-observability, harness-policy, harness-sdk, harness-tasks, harness-tools, harness-triggers, model-gateway, observer, operator, orchestrator, orchestrator-sdk, trust — the first packed 43-package exactness + bin-smoke run anywhere; exports-exactness scan 43 manifests / 6386 files / 19042 specifiers / 0 findings. No AR lane is blocked on Gate B: the pre-publication gate resolves internal deps from checkout-packed tarballs and needs no registry credential; the post-publication consumer (live-stack-published.yml) is the lane that waits for the first publication

8. Honesty: what is proven and what waits for Gate B

  • **Prepared + dry-run-proven, not done**: AC1 (an end-to-end staging release publishing all 43 packages to AR, moving staging, creating one fabric/staging/v… tag), AC2 (verify/channel assertions against AR with published packages), AC3 (a from-tag recovery rehearsal under a candidate dist-tag), and the published-consumer validation against AR (including the §3.1 global-install smoke) can only run once Gate B merges the branch and the train publishes. Every mechanism is wired, parses, is shape-tested, and is exercised against fixture registries; nothing was published to any registry.
  • **AC4 holds now**: the public repository's tag namespace shows no new tags (404 before and after; 0 fabric/ tags).
  • **Windows**: 32 release-tooling tests are environmental here (sh fake-npm shims); CI's release-tooling job is the proof of the full suite. The baseline run of the suite was started before the first edit and finished after several edits, so its failing-name set is contaminated by an edit-in-flight (one test later fixed); the comparison was repeated against the final tree.
  • **Reader 403 (review M6) — resolved 2026-10-04**: §6 keeps the original fail-closed transcript. The orchestrator verified with a fresh gcloud access token that the human reader binding works: gcloud artifacts repositories get-iam-policy fabric-npm --location=us-central1 --format=json shows roles/artifactregistry.reader for user:tal@a5c.ai; npx -y google-artifactregistry-auth --repo-config=.npmrc --credential-config="$HOME/.npmrc" followed by npm view @fabricstack/smoke --@fabricstack:registry=https://us-central1-npm.pkg.dev/boot-464019/fabric-npm/ printed 0.0.0-smoke.4; a direct bearer-token GET of the package document answered 200. The 2026-10-03 E403 was an expired token (the helper had been run against a stale credential), not a missing or conditional binding. Prerequisite kept: **re-authenticate first** (npx google-artifactregistry-auth; tokens live about an hour) before any local read-only runbook command; the runbook's "CI-only until verified" markers are lifted (runbook §0a, §6). No workflow depends on the human credential.
  • **Workflow state (review M2, amended by review-2 M8) — 2026-10-04**: live-stack-published.yml, release-tags.yml, publish-packages-from-tag.yml and fix-npm-tags.yml were disabled_manually on a5c-ai/fabric (never run there) and nothing listed enabling them as a Gate-B prerequisite; the owner enabled all four at the pre-Gate-B interview ("Enable all four now"). **No trigger fires pre-merge** — the legacy copies of those files on main/staging are workflow_call/dispatch-only or trigger on babysitter/** tags — **but a MANUAL dispatch of fix-npm-tags.yml without --ref, or with --ref main, or with --ref staging before the merge, would run the legacy npmjs copy**, and that copy is armed: main and staging carry the same blob (git rev-parse origin/staging:.github/workflows/fix-npm-tags.yml origin/main:… → 44112b847 twice), whose workflow_dispatch input dry_run defaults to false, which checks out staging, uses registry-url: https://registry.npmjs.org/ with NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}, and whose else branch runs scripts/fix-broken-latest-tags.mjs --fix — a live npm dist-tag add @a5c-ai/<pkg>@<v> latest against the PUBLIC packages with the still org-wide NPM_TOKEN (M7 pending). The runbook never lists that form (its §5 dispatches carry -f mode=…, which the legacy inputs reject with 422), so the exposure was narrow, but until this amendment only human restraint prevented it — the earlier sentence here ("Nothing can fire pre-merge") asserted more than the triggers show. **Mitigation taken by the orchestrator on 2026-10-04**: fix-npm-tags.yml was re-DISABLED (workflow 352401959, disabled_manually, updated 2026-10-04T09:22:41+03:00, 0 runs ever on fabric); the other three — live-stack-published.yml 352401978, release-tags.yml 352401989, publish-packages-from-tag.yml 352401984 — stay active, as does release-artifact-verifier.yml 352401988. The orchestrator re-enables fix-npm-tags.yml immediately after PR #4 merges to staging, as part of Gate B, once M7 is verified. Do not dispatch fix-npm-tags.yml until PR #4 is on staging and main and M7 is verified. Every gh workflow run in the runbook carries --ref for the same reason (review M3), and the runbook now states that --ref staging is itself the legacy copy until the merge.
  • **Not done by design**: sync-external-plugins.yml / sync-atlas-plugins.yml (public marketplace repos, WP-RN-11); documented_install lane of live-stack-published.yml still exercises the public marketplace bootstrap and stays channel-gated (skipped pre-promotion; WP-RN-11); scripts/release-notes.mjs, bump-version.mjs, rollback-release.sh legacy helpers untouched (no workflow invokes them); the fabricstack npmjs org (G4) remains an owner action. **G3 / review M7 — owner action, required BEFORE anyone dispatches fix-npm-tags.yml, i.e. before its Gate-B re-enable** (moved forward from "before Gate B" by review-2 M8, 2026-10-04): the organization secret NPM_TOKEN is still visible to all repositories (gh api orgs/a5c-ai/actions/secrets/NPM_TOKEN --jq .visibility → all, re-checked 2026-10-04), fabric included, and the legacy workflow copies on main and staging reference it; the owner restricts its repository selection in the GitHub UI. Verification: gh api orgs/a5c-ai/actions/secrets/NPM_TOKEN --jq .visibility → selected, and fabric absent from gh api orgs/a5c-ai/actions/secrets/NPM_TOKEN/repositories --jq '.repositories[].name'.
  • **Owner decision 2026-10-05 — "Consumer-only gate for the first train"**: after publish run 37279009004 (7.0.1-staging.643131fbd416: all 43 candidates published and asserted, the exact-version published-consumer validation green, the three openai/gpt-5.5 live lanes red — an invalid OPENAI_API_KEY organization secret, invalid_api_key, plus Claude Code 2.1.2xx's unauthenticated /api/hello preflight against the transport-adapter proxy, fixed in the same fix-forward PR), the owner chose not to rotate the key now and to gate the first train's promotion on the exact-version consumer job. Implemented on fix/consumer-only-gate: promote_release_channel (branch train and from-tag recovery) depends on the callee outputs consumer_result and promotable and evaluates with !cancelled() while checking every upstream result explicitly; record_validation records the lanes with --live-lanes-gate derived from the repository/organization variable FABRIC_LIVE_LANES_GATE (unset or informational → informational, listed under informationalFailures; required → the full gate, and then the called workflow's aggregate result must be green too; the script's own default is required); no lane is continue-on-error. Unchanged: the consumer job itself (install/import/bin smoke of all 43 + §3.1 global-install), the packed-artifact gate, the candidate assertion, the tag-after-promotion order, the no-npmjs invariants. Condition to restore the full gate: a valid OPENAI_API_KEY (runbook §7.2). Spec 15 §4.2 does not state the live-lane gate as binding (WP-RN-07's test requirement names the consumer job), so no spec amendment was needed; the runbook §0a/§1/§3/§7.2 carry the dated amendment.
  • **No guard or test weakened**: the flipped fixture became a negative; --private-train is accepted as a no-op; every rewritten assertion is listed in §4 with its stricter form.

9. Release-machinery review fixes (2026-10-04)

The release-machinery review of 20ef45aa9 scored 87 (threshold 90; every criterion ≥ 80; no blocking finding) with seven mustFix items. Owner decisions at the pre-Gate-B interview, verbatim: M4 "Spec 15 wins: staging = 7.0.1-staging.<sha>"; M2 "Enable all four now" (done by the orchestrator); M6/M7 "I'll do both before Gate B". Each fix is its own commit on phase1/rename-train; the gates of §5 were re-run (tails in the review-fix task output). Nothing was published, no tag was created, no workflow was enabled or disabled by the fixes, and the public repository's pushed_at stayed 2026-09-16T19:59:50Z.

FindingWhat changedProof
**M1** whole-train dry-run rehearsal impossible pre-merge (helper's dependency gate fails on an empty registry from wave 2; publish-npm-private.yml undispatchable before it is on staging, and that push is live)scripts/publish-package-from-tag.mjs: under --dry-run, an exact internal pin carried by a publishable workspace of the checkout at that exact version is accepted as "published by an earlier wave of this train" (logged), every other pin keeps the strict registry check; new --rehearsal (implies --dry-run) issues no registry query at all and hard-fails a pin outside the train; the exact npm publish … --dry-run command is logged. Real path untouched. ci.yml: new job release-train-rehearsal (see §6 correction) — the train's publish_candidates sequence for the staging identity of the PR head, --rehearsal per package in the derived waves, proof step (13/13 waves, 43/43 would-publish lines, 43 publish commands all with --dry-run, no published, no dist-tag add, no npmjs), no credential / OIDC / opt-in. Runbook §0a/§2 rewritten: first real run = staging merge; this job + verifier 43/43 = rehearsal evidence; the stale ci.yml comment calling the verifier "owner-disabled" correctedprivate-release-train.test.mjs: "--dry-run satisfies an exact internal pin from this train when the registry has nothing yet; the real path still refuses it" (two-wave fixture, empty fake registry: dry-run exit 0 with one view of the package itself and none of the pin, opt-in path exit 1 with the dependency-order message, a 0.9.0 pin not in the checkout exit 1 in dry-run); "--rehearsal issues no registry query at all …" (exactly one npm call, publish … --dry-run; non-train pin → exit 1, zero npm calls; --rehearsal + opt-in still dry-run only); "ci.yml rehearses the whole train in dry-run mode on every PR, without a credential and without any way to publish" (job shape, order, notices, proof greps). CI: the Release train rehearsal (dry-run, all packages) job of the ci.yml run on the final head — URL below
**M2** four workflows disabled_manuallyOwner enabled live-stack-published.yml, release-tags.yml, publish-packages-from-tag.yml, fix-npm-tags.yml (2026-10-04); recorded in §8 and runbook §0a with the verification command; the "disabled" caveats dropped. **Amended by review-2 M8 (§9.3)**: fix-npm-tags.yml re-disabled the same day until Gate B re-enables it after the merge and M7`gh api repos/a5c-ai/fabric/actions/workflows --paginate --jq '.workflows[] \
**M3** runbook dispatches without --ref bind to main's legacy npmjs workflowsEvery gh workflow run in docs/RELEASE-RUNBOOK.md (and in the superseded docs/release-recovery-runbook.md) carries `--ref <staging\tag>; the runbook's header note explains the default-branch binding and the legacy copies on main; §4.3 notes that a dispatch must come from the tag or staging/main (the helper refuses a /`-shaped feature-branch ref)
**M4** roadmap literal fabric/staging/v7.0.0 rejected by the resolverRoadmap M1 criterion 1, risk 7, WP-RM-02 AC1 amended with a dated note (fabric/staging/v7.0.1-staging.<sha> publishes all 43 at that version under staging; fabric/main/v7.0.0 is the promotion evidence); parseReleaseTag rejection names both accepted shapes; §3 of this record and runbook §0 carry the reconciliationnode scripts/release-version.cjs from-tag --tag fabric/staging/v7.0.0 → exit 1, "…an exact version like 7.0.0 is never published from staging (it is main's, as fabric/main/v7.0.0). Accepted tag shapes: fabric/main/v<major>.<minor>.<patch> … and fabric/<staging\
**M5** Docs QA misreported as inherited on 7635c68e9/55036e19c§5 CI table corrected: failing in docs:links on this WP's RELEASE-RUNBOOK.md links on both heads; fixed in 20ef45aa9; inherited (docs:freshness, identical 7-entry list) from 20ef45aa9 ontriage-C record (run 37150847430 / 37149333707)
**M6** human reader credential → 403 on every AR readFirst recorded as owner-committed before Gate B (§8, runbook §0a/§6) with the verification commands; **resolved 2026-10-04** by the orchestrator with a fresh token — the E403 was an expired credential; the runbook's "CI-only until verified" markers are lifted and the "re-authenticate first" prerequisite is keptgcloud artifacts repositories get-iam-policy fabric-npm --location=us-central1 --format=json → roles/artifactregistry.reader for user:tal@a5c.ai; npx google-artifactregistry-auth + npm view @fabricstack/smoke --@fabricstack:registry=<AR> → 0.0.0-smoke.4; direct bearer GET → 200
**M7** NPM_TOKEN org secret visible to all repositoriesRecorded as owner-committed before Gate B (§8, runbook §7.2) with the verification command; **ordering moved forward by review-2 M8 (§9.3)**: required before anyone dispatches fix-npm-tags.yml, i.e. before its Gate-B re-enablenot performed by this task (owner action); still all on 2026-10-04; verification: gh api orgs/a5c-ai/actions/secrets/NPM_TOKEN --jq .visibility → selected, fabric absent from its repositories

9.1 What the rehearsal job found on its first runs — three defects of the real train

The release-train-rehearsal job runs the train's publish_candidates sequence over the real tree, and its first runs failed on three defects that the live staging train would have hit in the same step, before publishing anything. Each was fixed in its own commit with a pinning test; none is a rehearsal-only problem.

Run (head)FailureRoot causeFix
37176658216 (1b9dd488b)step "Record and validate the release plan": Error: Cannot find module './release-version.json'scripts/release-version.cjs verify advertised --write in its usage but only resolve and from-tag honoured it; publish-npm-private.yml runs verify … --write release-version.json and then requires the file — the identical step2a359be61: verify --write records the VALIDATED identity (and --commit), writes nothing on a mismatch; test: written plan equals the resolver identity, both workflows carry the verify … --write contract
37176949592 (2a359be61)wave 1: every helper GITHUB_REF_NAME "4/merge" is neither a release branch nor a fabric/<branch>/v<version> release tagon a pull_request the ref is <n>/merge; the helper refuses a /-shaped non-fabric/ ref as a channel source by design (kept). Rehearsal-specific: the train runs on a push where the ref is the channel branchb6fc8f4c4 set it via step env: — ignored, because the runner writes GITHUB_* defaults after the step's env: block (run 37178013213 proved it); 7b4cedd10 exports it in the step's shell (export GITHUB_REF_NAME="$REHEARSAL_BRANCH"), the same channel the release plan names
37178840931 (7b4cedd10)wave 1: harness-observability and trust reached [dry-run] would publish; catalog, control-plane, harness-tasks, harness-triggers, operator refused: the checked-out workspace manifest is 0.0.0-fixture.0 but the release version is 7.0.1-staging.<sha>discoverPackages() walked every package.json under the root into a name-keyed map; scripts/ci/fixtures/publish-guards/g5/negative/duplicate-bin/packages/<name>/package.json carry the REAL names at 0.0.0-fixture.0 and, walked after packages/, shadowed the workspaces. The real train's publish job runs the same helper over the same tree: wave 1 of the live train would have failed identically (the first review's local probes — trust, harness-policy — were names without a fixture)cb8ab8c54: packages are the root workspaces members (resolveWorkspaceDirs, the inventory's and the lockstep check's source); two members with one name are a hard failure; test: a fixture manifest with a real name outside the workspaces does not shadow the member, duplicates fail with zero npm calls, no whole-tree walk remains. Real-tree probe: --workspace=@fabricstack/catalog --release-version=7.0.0 --skip-build --rehearsal → [dry-run] would publish @fabricstack/catalog@7.0.0 … (rehearsal: registry not queried)

9.2 The green rehearsal and the CI state of the final head

**ci.yml run 37179946474 (head cb8ab8c54) — <https://github.com/a5c-ai/fabric/actions/runs/37179946474>**: Release train rehearsal (dry-run, all packages) **success** (job 111370301481, <https://github.com/a5c-ai/fabric/actions/runs/37179946474/job/111370301481>); its proof step printed waves completed: 13/13; packages dry-run-published: 43/43; publish commands: 43 and Rehearsal reached wave 13/13; 43/43 packages dry-run-published; 0 publish commands without --dry-run — no published line, no dist-tag add, no npmjs in any helper log, no credential, no OIDC token, no opt-in. Other jobs of the same run: Release tooling tests **success** (the 21-test private-release-train suite included), Lint/Tests/Package **success**, Public-push guard **success**, Publish-isolation guards **success**, Observer Dashboard **success**, Workspace Coverage **success**; Docs QA **failure** (inherited: docs:links passed, docs:freshness fails with the baseline's identical 7-entry stale list — verified on runs 37176658216 and 37178840931 as well), Gateway Node engine floor (22) / (22.13.0) **failure** (inherited, as before this WP). The run's overall conclusion is therefore failure for the three inherited jobs only. Release-tooling was green on every pushed head of this revision (37176658216, 37176949592, 37178013213, 37178840931, 37179946474).

**ci.yml run 37180964707 (head 6c9f9eed9, the final head of this revision) — <https://github.com/a5c-ai/fabric/actions/runs/37180964707>** (closes the "its ci.yml run was not awaited" gap of the previous revision of this record): Release train rehearsal (dry-run, all packages) **success** (job 111373287978: waves completed: 13/13; packages dry-run-published: 43/43; publish commands: 43), Release tooling tests **success** (job 111373288077, # tests 184 / # pass 184), Lint/Tests/Package **success** (job 111373288079, 47/47 steps), Public-push guard, Publish-isolation guards, Observer Dashboard, Workspace Coverage **success**; the three inherited reds only: Docs QA (job 111373288051 — docs:lint, docs:snippets, docs:links pass; docs:freshness fails on the identical 7-entry stale list: 04-agent-events, GAP-PROMPT-011, reference-repos/README, repo-with-babysitter-processes, faq, glossary, advanced-multi-phase), Gateway Node engine floor (22) job 111373288074 and (22.13.0) job 111373288031 (62 ##[error] lines each, the pre-existing TS2307/TS7006 set, scope-normalised diff against the baseline empty). Verifier run **37180964710** (release-artifact-verifier.yml, pull_request, 6c9f9eed9) — <https://github.com/a5c-ai/fabric/actions/runs/37180964710> — **success** (packed matrix 43/43, allowKnownFailures=false).

**Gate B reads it this way:** the first real run of publish-npm-private.yml is the staging merge; its rehearsal evidence is this job (the whole publish_candidates sequence over the real tree, dry-run, all 43 packages through all 13 waves — which already found and forced the fix of three defects the live train would have hit, §9.1) plus the verifier's 43/43 (release-artifact-verifier.yml on the same PR).

Nice-to-haves taken: the dry-run fixture now carries an exact internal pin (the M1 class cannot recur silently); runbook §4.2 makes "re-run the failed publish_candidates job" the first recovery option and keeps §4.3 for a dead run; §4.3 carries the /-ref dispatch note; §4 states that the failed wave is *partially* published (parallel helpers, wait collects every sibling). Not taken: operator --version / orchestrator-mcp --version printing versions (product-code changes in two CLIs, outside a review-fix revision; the live lanes smoke --version on the five §3.1 CLIs that implement it and the verifier smokes --help on these two).

9.3 Second release-machinery review (2026-10-04, score 91) — M8 and nice-to-haves

The second release-machinery review of 6c9f9eed9 scored 91 (threshold 90; every criterion ≥ 88; no blocking finding) and confirmed M1–M7 addressed. It raised one docs-only mustFix, **M8**, and this revision of the record is its fix; nothing in code, workflows or manifests changed.

FindingWhat changedProof
**M8** "Nothing can fire pre-merge" (this record §8, runbook §0a/§5) omitted the MANUAL dispatch path of the then-active legacy fix-npm-tags.yml copy on main/staging (dry_run default false, npmjs + NPM_TOKEN, --fix)§8 M2 paragraph rewritten with the precise statement (no trigger fires; a manual dispatch without --ref / --ref main / --ref staging before the merge runs the legacy copy live); the orchestrator's mitigation recorded (fix-npm-tags.yml re-disabled 2026-10-04, re-enabled at Gate B after the merge and M7); M7 moved to "before anyone dispatches fix-npm-tags.yml" (§8, §9 table, runbook §0a/§7.2); runbook header note, §0a and §5 state that the staging copy is also legacy until the merge and carry the sentence "Do not dispatch fix-npm-tags.yml until PR #4 is on staging and main and M7 is verified."gh api repos/a5c-ai/fabric/actions/workflows/352401959 --jq .state → disabled_manually (updated 2026-10-04T09:22:41+03:00; …/runs → total_count: 0); private-release-train.test.mjs "every gh workflow run in the runbooks names its --ref" now also asserts the runbook carries the do-not-dispatch sentence — 21/21
nice-to-have: test count / gate tails / §9.2§4 says 21 tests; §5 tails refreshed to 16/16 (publish-isolation-guard) and 354 files (public-push-guard), 21/21 (suite); §9.2 closed with run 37180964707 and verifier run 37180964710the three commands re-run on 6c9f9eed9 (tails in §5)
nice-to-have: first-train abortrunbook §4 and §5 state that a post-promotion abort of the FIRST staging train is fix-forward only (no earlier version on AR for --set staging=<previous>; the script refuses a version any package lacks) and that consumers of the brand-new scope are unaffectedrunbook §4, §5
nice-to-have: M6resolved (see §8): fresh token, policy shows reader, npm view → 0.0.0-smoke.4, bearer GET 200; "re-authenticate first" keptrunbook §0a, §6

Not taken in this revision (recorded for the follow-up list): ci.yml re-cats every accumulated helper log after each wave (410 notice lines for 43 publishes) — cosmetic, CI-only; the 16 real-named fixture manifests under scripts/ci/fixtures/publish-guards/g5/negative/duplicate-bin/packages/ remain a shadowing hazard for any OTHER tool that walks package.json files (the publish helper itself is immune since cb8ab8c54); ruleset 24103129 still enforces no required status checks; operator --version / orchestrator-mcp --version; the ESM-only posture note in docs/reference/package-publics.md. The first review's remaining nice-to-haves (console-tui vitest suite in CI, ci-oracle/staging-test-shape deletion, pkg-02 §5a lockfile numbers) are also carried to the follow-up list in the PR body.

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