Shaping Review — Round 1 (Codex)
+reviewed 2026-07-28/29 · over shape commits 513be735 (release-promotion-model, working tree) and 349bbd3d (receipt-tree-binding, via git show) · verdict REQUEST-CHANGES · 2 blockers + 5 major + 1 minor · all eight confirmed · dispositions applied same round, amended in place (shaping commits stay local)
Provenance correction — 2026-07-29
+This round was originally attributed to Codex GPT-5.4. The Codex runtime's job registry later proved the dispatch never executed there: the original forward died to machine sleep two minutes in with no output, and the retry's report was produced by the rescue wrapper agent itself — a Claude-native review, not a Codex one — in silent violation of its thin-forwarder contract. The findings stand: every one was independently verified against source before boarding, and round 3 attested the fixes. Attribution corrected; the filename keeps its stamped identity. Discovery record: journal discover(review) 2026-07-29.
Eight findings, eight confirmed, zero refuted — and the two blockers are the same wound. A design decision made in conversation after the shape was committed (changeset-pattern release notes, buffer retirement) never re-entered the document, and the write path it governs (writeReleaseChangelog) belonged to no task. The round's fix gives both a single owner: Decision 3 rewritten around release-notes.md, and a new TASK-008 owning note collection, the rung-aware write path, buffer retirement, and the workflow-pre-pr re-point. Codex also independently cleared the risks flagged in the brief: no package cycles (single package cli), no test-name collisions, the rc-cohort core-literal mapping is sound, ~15 spot-checked line citations accurate, and validate-push's regex is already channel-agnostic.
Findings
+ +Evidence
runReleaseApply calls writeReleaseChangelog unconditionally (release_dry_run.go:481), preview at :288-294; TASK-002 owned flags only, TASK-004 the stable path only, TASK-005 post-merge verification only — no task owned the writer, so an rc cut would still splice a section, contradicting the shape's own Problem #3.
Disposition
TASK-008 created owning the rung-aware write path (rc writes nothing, alpha/beta aggregate notes); Per-channel guardrails subsection now states the writer is TASK-008's and the guardrails verify what it produces.
Evidence
Journal decision(shape) 2026-07-28 19:21 settled per-change release-notes.md, buffer retirement, and the pre-PR hook re-point; the coherence amendment (a8dd5ad9→513be735) carried only the council edits; grep for release-notes.md across the tree returned zero; runNativeWorkflowPrePR (check.go:834) still blocks on an empty [Unreleased] untouched by either shape.
Disposition
Folded in wholesale: Decision 3 rewritten around the changeset pattern, Scope gains the release-notes bullet, Observable Workflow shows the fragment, Rabbit Holes and TASK-004's seed material re-seed from notes (shape-lines demoted to warned fallback), TASK-007 teaches the authoring discipline, TASK-008 owns mechanics + hook re-point, V6 added (TestReleaseNotesProjection).
Evidence
TASK-004's Out assigned non-promotion guardrails to TASK-005 while its own Steps implement the Decision 11 check for "rc cut and promotion"; TASK-005 never mentioned it — implementer-in-isolation risk in both directions.
Disposition
TASK-004's Out now names the helper explicitly: one shared check owned here covering both rc cut and promotion; TASK-005's Context pointers state it consumes and never reimplements.
Evidence
The incompatibility list (release_dry_run.go:163-200) checks fields that exist today; taken literally, "unchanged" leaves --post-merge --promote release accepted while the same sentence says post-merge takes no version input.
Disposition
Shape and TASK-002 now require adding both flags to the list, with a rejection test.
Evidence
No core in releaseValidBumps (release_dry_run.go:87-93); TASK-001 used "core bump" as category language, TASK-002 promoted it to CLI syntax.
Disposition
Now reads --bump major|minor|patch --channel alpha, matching the Observable Workflow.
Evidence
loaf change list --target 2.0.0 shows spec-conversion-and-guidance-sweep captured-only (brief + change.json); under the new trigger set its convert-first block fires at 2.0.0-rc.1 instead of stable, and neither shape said so.
Disposition
Sequencing now names the consequence and frames it as the discipline working as designed: an rc claims stable intent, alphas/betas flow regardless, the rc block is never a regression.
Evidence
Task relations are change-local by the work model's own rule; promotion's TASK-004 cannot declare blocked-by on receipt-tree-binding/TASK-001, so derived executability cannot see the gap.
Disposition
Accepted: cross-change relations are deliberately forbidden — cohort membership and git order carry sequencing. The prose carrier is now explicit: promotion's Sequencing states TASK-004 does not start until receipt-tree-binding lands on main.
Evidence
The registry (change_report.go:15-21) is approval/review/visual/audit/note; loaf change report new would refuse council; the board was hand-authored under the owner's new convention and no hook re-validates existing filenames.
Disposition
Accepted for now: the convention is owner-directed and newer than the registry. Adding council to the closed registry (and letting CLI stamping own the shell) is already scoped in INTENT-20260728-council-reports-become-visual-html-boards-in-the-change-folder-s-reports-directory.
Cleared by the round (checked, not defects)
+-
+
- No package cycles for the exported boundary constant — every file involved is
package cli; the "import" is an intra-package reference.
+ - No test-name collisions: none of the declared V-entry prefixes exist in
internal/clitoday.
+ - The rc-cohort mapping (strip prerelease, then existing byte-equality) composes with
change_release_gate.go:50-57, not against it.
+ - ~15 spot-checked file:line citations across both shapes accurate, including the three-way help drift (
cli_reference.go:90still says "during a lineage freeze").
+ validate-push's release-commit regex already matches prerelease and rc subjects — no hook change needed there.
+