docs(release): the release runbook for builders and the release-path pattern doc (#4805) - #4835
Conversation
No preview deploy
|
|
review-doc: FAIL @ b0d8581 — changes-requested Reviewed-head: @ b0d8581 Verified PR #4835 against the acceptance criteria of #4805 (incl. its 2026-08-03 plan-gate amendment) + the doc-hygiene checklist. Class: non-blocking, doc-only. This is a documentation PR whose value is accuracy, and it was gated as a factual document. The substance is unusually well-grounded — every mechanism claim below was checked against the committed artifacts on Acceptance criteria
Provenance — both deviations from the dispatch brief landed accurately; no citation fabricated
Mechanism claims — each checked against the committed files on
Doc hygiene
Blocking findings
Routing note. The claim-vs-ground-truth finding traces to #4805's stated goal (a runbook a builder can follow), so it is in-scope and blocks here rather than being filed separately. It is captured as the FAIL row above — the seam the repair round reads — and no acceptance criterion was appended to #4805. Read the PR head (§HEAD): all files under review sourced from CI at head: green — 39 success, 7 skipped, zero failing or pending; Failing items above must be addressed before this PR can merge. The PR stays open and unmerged; #4805 stays open and assigned. Re-request review once they're satisfied. review-doc does not merge — Verdict-written: 2026-08-03T06:36:43Z |
… the empty-environment hazard (#4805) The runbook stated at two sites that `@kampus/fabrika-cli` has no Trusted Publisher registration and that a `fabrika-cli-v*` release therefore 403s. That is false: the registration exists, recorded on #4800 with npm's own confirmation (this repo, workflow filename `publish.yml`). Both published packages are registered, so no 403 is expected, and the old text sent a builder hunting for a failure that should not occur. Corrected rather than softened, at both sites: - `.patterns/release-path.md` `## Current state` and `DEVELOPMENT.md`'s 403 paragraph now state both packages are registered, cite #4800 as the record, and say plainly that registration state is a web-UI fact — npm exposes no trusted-publisher field over the CLI or registry API, so npmjs.com (Settings -> Publishing) is the only authority and nothing here re-derives it. - The mechanism explanation survives unchanged: publish.yml resolves -> installs -> typechecks -> builds -> publishes, so an OIDC failure lands after a green build and consumes no version. That is how you recognise a real failure; it is just no longer predicted. - The standing hazard is now prominent in both docs: the registration's environment field is deliberately empty because publish.yml declares no `environment:` key. A change that adds one must edit the registrations in the same change or publishing silently breaks with a 403 that looks like nothing is wrong. The fail-site table row for a 403 now reads as a registration that stopped matching the workflow, not a missing one. Addresses the review-doc FAIL on PR #4835.
|
review-doc: FAIL @ c70dbcf — changes-requested Reviewed-head: @ c70dbcf Re-gate of PR #4835 against #4805's acceptance criteria + the doc-hygiene checklist, at the new head. The prior FAIL was bound to Class (probed, not assumed). Read the PR head (§HEAD). Every file under review was read from Acceptance criteria
Doc hygiene
F1 — [FAIL] claim-vs-ground-truth: the docs now assert an unobserved outcome (the other direction of the same defect)The prior FAIL was right that the docs asserted a registration state they could not support. The repair corrected the fact — and then over-shot into a second unsupported claim, in the opposite direction. What the docs say at head:
What is verified. Registration is real and correctly bound — #4800 is But registered is not exercised, and this gate verified that independently rather than taking it on report:
An OIDC/Trusted-Publishing publish stamps attestations; a token publish does not. So Why that makes the current wording a defect, not a nitpick. The docs' load-bearing job here is telling a builder how to read a red publish run. At the exact moment that guidance is most likely to be needed — fabrika's first-ever OIDC publish, the first use of a registration nobody has watched work — the docs say a 403 is not expected and, if one fires, that a registration stopped matching. For fabrika that diagnosis is wrong by construction: nothing had started matching yet. The doc would send a builder hunting a regression in a path that had never run. Attribution — this is the operator's defect, not the author's. The repair brief handed to the lane over-corrected ("both packages are registered, there is no expected 403, both runs should succeed") and has since been retracted. The author implemented that brief faithfully and disclosed the reasoning under Remedy (both sites). State only what is observed, in neither direction:
Everything else in the repaired paragraphs is correct and should be preserved as-is: the mechanism ( F2 — [PASS]
|
|
review-doc: PASS @ 655594e — merge-ready Reviewed-head: @ 655594e Re-gate of PR #4835 against the acceptance criteria of #4805 (incl. its 2026-08-03 plan-gate amendment) + the doc-hygiene checklist, at the new head. The prior FAIL was bound to Routing, re-run here — not inherited.
The one thing gated: the docs must assert no outcome in either directionGround truth re-derived here, independently, before reading the diff:
An OIDC publish stamps attestations; a manual token publish does not. So the pipeline-cli registration is proven exercised, The five required properties, each verified at the head:
The author-disclosed extra: the "Facts the runbook carries" bullet in the PR bodyCorrect call. That bullet is this PR summarising its own diff, and it still restated the retracted "a 403 is not expected". Leaving it would have left the body describing a head it no longer matches — a reader arriving at the PR would have been handed the exact claim the diff landed to remove. It is disclosed as its own Confirming nothing else movedThe delta Every previously-verified claim re-read at this head and intact:
The Acceptance criteria (#4805 — unchanged this round, re-confirmed at the new head)
Doc hygiene
Branch mechanics (verified, deliberately not gated — tracked as #4826)The head branch was still pinned by an earlier lane worktree, so the scripted rebase refused. The author used the Merge-readiness at this head
Read the PR head (§HEAD): every file under review was sourced from All checks pass. This PR is merge-ready. review-doc does not merge — Verdict-written: 2026-08-03T07:25:45Z |
|
ship-it: merge-queue ejection detected — PR #4835 was enqueued but the queue dropped it without merging (still open, no longer queued, not merged). Enqueued 2026-08-03T07:29:45Z, |
|
ship-it: merge-queue ejection detected — PR #4835 was enqueued but the queue dropped it without merging (still open, no longer queued, not merged). Likely a textual conflict on the batch ref or a combined-batch CI failure (ADR 0132; GitHub "Managing a merge queue"). Routing back to repair/re-queue — this is NOT a shipped state. |
…-path pattern doc (#4805) Cutting a release stopped being knowledge held in an issue thread. Two surfaces, each with its own job per the repo doc contract: - `DEVELOPMENT.md` gains a `## Releasing` section for a builder who has never cut one: what derives a version (path routing, not commit scope), what the standing Release PR is, what to check before merging it, what the merge does (tags → publish.yml → registry), and how to read a red publish run. - `.patterns/release-path.md` records the shape of the path and each constraint a future change must not break, with its enforcement site or ruling — and says so plainly where a constraint has no live ADR home. - `.patterns/index.md` lists the new doc under CI / pipeline. Both point at ADR 0239 for the reasoning rather than restating it. Grounded against the landed artifacts (release-please.yml, publish.yml, the config and manifest, PR #4833), not against the epic's prose. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… the empty-environment hazard (#4805) The runbook stated at two sites that `@kampus/fabrika-cli` has no Trusted Publisher registration and that a `fabrika-cli-v*` release therefore 403s. That is false: the registration exists, recorded on #4800 with npm's own confirmation (this repo, workflow filename `publish.yml`). Both published packages are registered, so no 403 is expected, and the old text sent a builder hunting for a failure that should not occur. Corrected rather than softened, at both sites: - `.patterns/release-path.md` `## Current state` and `DEVELOPMENT.md`'s 403 paragraph now state both packages are registered, cite #4800 as the record, and say plainly that registration state is a web-UI fact — npm exposes no trusted-publisher field over the CLI or registry API, so npmjs.com (Settings -> Publishing) is the only authority and nothing here re-derives it. - The mechanism explanation survives unchanged: publish.yml resolves -> installs -> typechecks -> builds -> publishes, so an OIDC failure lands after a green build and consumes no version. That is how you recognise a real failure; it is just no longer predicted. - The standing hazard is now prominent in both docs: the registration's environment field is deliberately empty because publish.yml declares no `environment:` key. A change that adds one must edit the registrations in the same change or publishing silently breaks with a 403 that looks like nothing is wrong. The fail-site table row for a 403 now reads as a registration that stopped matching the workflow, not a missing one. Addresses the review-doc FAIL on PR #4835.
…ther way (#4805) The gate's F1: both docs asserted an unobserved outcome. pipeline-cli's Trusted Publisher registration is proven by exercise (two green publish.yml runs, attestations on the artifact); fabrika-cli's is recorded on #4800 but has never fired, so its first release run is the first use of it. Widen the 403 diagnosis from 'stopped matching' to 'does not match — either it never did (first use) or it stopped', so a red first run does not send a builder hunting a regression in a path that never ran. Keep the fail-closed framing: a 403 publishes nothing, no version number is burned, re-running after fixing the registration recovers cleanly. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
655594e to
b22fd6a
Compare
|
review-doc: PASS @ b22fd6a — merge-ready Reviewed-head: @ b22fd6a Re-gate after the rebase onto current Class: non-blocking. Rebase integrity (the specific ask). Verified PR #4835 against the acceptance criteria of #4805 + the doc-hygiene checklist: Acceptance criteria
Doc hygiene
Specialist fan-out (Step 4b) — claim-vs-ground-truth, re-derived from source, not from the PR body Every load-bearing factual claim was checked against the authoritative file or live state, since this doc's whole value is being true:
Non-blocking observation, not a gate finding and no AC appended: dangling-reference: none. omitted-case: none. Read the PR head (§HEAD): all files under review sourced from All checks pass. This PR is merge-ready. review-doc does not merge — Verdict-written: 2026-08-09T17:36:01Z |
Fixes #4805
Writes the release procedure down where the two audiences read it, grounded against the landed artifacts rather than the epic's prose — ADR 0239,
.github/workflows/release-please.yml,.github/workflows/publish.yml,release-please-config.json,.release-please-manifest.json, and PR #4833 (the first real Release PR, read but not touched).What changed
DEVELOPMENT.md→ new## Releasingpublish.yml→ registry), and a fail-site table for reading a red publish run — including how to read a 403..patterns/release-path.md(new).patterns/index.mdBoth docs point at ADR 0239 for the reasoning rather than restating it.
Facts the runbook carries
fix(pipeline-cli):with a fabrika-only diff bumps fabrika-cli.pnpm publish, nevernpm publish— npm cannot resolvecatalog:and would ship a literal"catalog:"..ts— Node refuses to strip types undernode_modules.releases_createdis repo-wide; the workflow gates on the per-path<path>--release_createdoutputs, and the pattern doc says why so nobody "simplifies" it back.CHANGELOG.md; pointing release-please at the root is banned.pipeline-cli's Trusted Publisher registration is proven by exercise — two greenpublish.ymlrelease runs, and the published artifact carries the attestations only an OIDC publish stamps.fabrika-cli's is recorded on HUMAN: bootstrap-publish @kampus/fabrika-cli and register it as an npm Trusted Publisher for publish.yml #4800 but never exercised: its first release run is the first use of it, and that run is the proof. So a 403 means the registration does not match — either it never did (a first use) or it stopped, and both branches are readable by someone staring at a red run. Both docs keep the mechanism that makes a real one recognisable:publish.ymlresolves → installs → typechecks → builds → publishes, so an OIDC failure lands after a green build and consumes no version — no version number is burned, and re-running after fixing the registration recovers cleanly. Both also state that registration state is a web-UI fact npm exposes over no CLI or registry API, so npmjs.com (Settings → Publishing) is the only authority.publish.yml's exact filename — renaming or splitting it invalidates every registration. And the registration's environment field is deliberately empty becausepublish.ymldeclares noenvironment:key: a change that adds one must edit the registrations in the same change, or publishing breaks with a 403 that looks like nothing is wrong.packageManager, andpnpm/action-setupmust not gain aversion:input. Recorded with the explicit "do not reintroduce it on ADR 0076's authority" warning, so a builder reconciling doc against file cannot manufacture the second pin.Deviations
Declined guidance — Said: the dispatch brief said the npm-version-immutability constraint has no ADR home. Did: both docs cite ADR 0239 for it, and the pattern doc states that ADR 0076 does not rule it. Why: 0239's Context rules it explicitly ("No ADR has ruled this before — this one does") on the
@kampus/fabrika-cli@0.1.0bootstrap near-miss, and its Records section notes an earlier draft's attribution to 0076 as corrected. Citing "no home" would have been wrong in the other direction. Disposition: no action needed — the citation is the accurate one.Declined guidance — Said: the dispatch brief said the compiled-JS-never-raw-
.tsconstraint has no ADR home. Did: the doc says "no live ADR rules this" and homes it to ADR 0076 §1 (superseded by 0103, which does not restate it) pluspublish.yml's comment citing Published @kampus/epic-ledger@0.1.0 is unrunnable — ships src/*.ts bin, no build (ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING) #405. Why: the constraint is written down, just not in a live ADR; a flat "no home" would have over-claimed, and inventing a live citation would have been worse. Disposition: no action needed; nothing fabricated.Declined guidance — Said: Write the release runbook: the DEVELOPMENT.md section for builders and the .patterns/ doc for the release path constraints #4805's original constraint list asks the runbook to record that the
pnpm/action-setuppin must stay on 10.x. Did: the docs record the pin as living once in the rootpackageManager, and warn against ever adding aversion:input topnpm/action-setup. Why: Write the release runbook: the DEVELOPMENT.md section for builders and the .patterns/ doc for the release path constraints #4805's 2026-08-03 plan-gate amendment corrects the original constraint, and the workflows agree — nopnpm/action-setupuse in this repo carries aversion:input. Disposition: the plan-gate amendment on Write the release runbook: the DEVELOPMENT.md section for builders and the .patterns/ doc for the release path constraints #4805 is the authority; no ADR needed.(repair round 1) Declined guidance — Said: the
review-docFAIL's remedy asked for the Trusted Publisher claim to be reworded as unconfirmed and needing a human eyeball, explicitly declining to resolve which way the registration question lands. Did: corrected the claim outright instead of hedging it — both docs now state that both packages are registered, cite HUMAN: bootstrap-publish @kampus/fabrika-cli and register it as an npm Trusted Publisher for publish.yml #4800 as the record, and delete the expected-403 guidance rather than soften it. The mechanism paragraph the gate asked to preserve is preserved, and the empty-environment hazard is now prominent in both docs. Why: HUMAN: bootstrap-publish @kampus/fabrika-cli and register it as an npm Trusted Publisher for publish.yml #4800 is closed/completed and pastes npm's own confirmation string with the field table (repositorykamp-us/phoenix, workflow filenamepublish.yml, environment deliberately empty), which settles the fact the gate correctly declined to settle from the CLI. A hedge would still have sent a builder hunting for a failure that should not occur. Disposition: no ADR needed; both docs cite HUMAN: bootstrap-publish @kampus/fabrika-cli and register it as an npm Trusted Publisher for publish.yml #4800 as the record and state that registration status is a web-UI fact no CLI can confirm, so nothing here is asserted as agent-verified.(repair round 1) Out-of-scope change — Said: the repair brief scoped the round to the two flagged sites. Did: also amended
.patterns/release-path.md§9 (the workflow-filename constraint) to carry the empty-environment:half of the same binding. Why: §9 is where that constraint is stated for a future change to read; leaving the hazard only inDEVELOPMENT.mdwould put it where a builder reads it and not where an editor ofpublish.ymldoes. Disposition: for the reviewer to judge; it is the same constraint, not a new one.(repair round 2) Retracted premise — Said: round 1's dispatch brief asserted that "both packages are registered, no expected 403, both runs should succeed", and the round implemented it faithfully (see the round-1 entry above). That premise has since been retracted by the dispatcher as an over-correction. Did: replaced both assertions with the observed distinction —
pipeline-cli's registration is proven by exercise (two green publish runs; attestations on the artifact),fabrika-cli's is recorded on HUMAN: bootstrap-publish @kampus/fabrika-cli and register it as an npm Trusted Publisher for publish.yml #4800 but never exercised, so its first release run is the first use and therefore the proof. Neither doc now predicts an outcome in either direction, and the 403 diagnosis widens from "stopped matching" to "does not match — either it never did (first use) or it stopped". Why: on fabrika's first-ever OIDC publish, "a registration stopped matching" is wrong by construction — nothing had started matching — so the fail-site guidance misdiagnosed the single most likely 403 moment and would send a builder hunting a regression in a path that had never run. Disposition: no ADR needed; the correction is stated with its own re-derivable check (dist.attestationson the published artifact) rather than an asserted authority, and the empty-environment:hazard, the mechanism paragraph and the HUMAN: bootstrap-publish @kampus/fabrika-cli and register it as an npm Trusted Publisher for publish.yml #4800 citation are all preserved unchanged.(repair round 2) Out-of-scope change — Said: the round-2 brief scoped the fix to the two flagged doc passages. Did: also updated the How to read a 403 bullet in this body's Facts the runbook carries list, which restated the retracted claim. Why: that bullet is this PR's own summary of its diff; leaving it asserting "a 403 is not expected" would have left the body describing a head it no longer matches. Disposition: for the reviewer to judge — no
## Deviationsentry was rewritten, and no doc content beyond the two flagged passages changed.Verification
pipeline-cli cp-classify classifyover the three changed paths →not-control-plane [path-clear-no-content-source](exit 3) — "no path matched the live CONTROL_PLANE_RE and no.decisions/**file is present … Proven ordinary."state: closed,state_reason: completed, closed2026-08-03T04:35:00Z, with the04:22:42Zcomment carrying npm's confirmation and the four discharged ACs.DEVELOPMENT.md#releasing,release-path.md#adding-a-third-published-package) match real headings.leak-guardclean over all 3 doc surfaces; every path cited is repo-relative.