feat(rt-manifest-check): port manifest-check.sh → rt manifest-check (5 consistency checks) #558
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#558
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Port
manifest-check.shtort manifest-checksubcommand — read-only PR-CI check running in consumer-repo CWD.Scope
scripts/manifest-check.shtocmd/rt/manifest_check.gomanifest-check.sh§1-§5 (five sections; §5 has sub-checks 5a-5d):prep.ReadVersionFile— #213 didn't cover this)changelog.HasUnreleasedSectionbool)v*tag (via existingprep/git.DescribeStableTag+semver.Compare— orchestrator-owned since CheckDesync has no config handle)manifest.CheckDesyncVerbosereturning[]DesyncCheck{name,ok,detail})Primitives inventory (corrected 2026-07-27 per Engineer bus e477)
Already exist (Phase 5 substrate + #542 CheckDesync internals):
config.RenderTag,semver.Compare(§1, §4)changelog.UnreleasedContent(adjacent to §3, but see gap below)manifest.CheckDesyncinternals (§5 sub-checks 5a/5b/5c/5d):cat-file -e,merge-base --is-ancestor,rev-parse tag^{commit}— all present as LC_ALL=C helpers at store.go:243-262prep/git.CurrentHead+prep/git.DescribeStableTag(§4 orchestrator; exact--exclude '*-*'match already ported)Confirmed gaps (new additive primitives added in this PR):
changelog.HasUnreleasedSectionbool — distinct fromUnreleasedContent(presence-of-heading vs content extraction; matches bashhas_unreleased_sectionsemantics)prep.ReadVersionFile— VERSION file + package.json version-field extraction for §2 (#213 didn't port this)manifest.CheckDesyncVerbose+DesyncCheckstruct — verbose variant per §5-fork B ratify§5-fork ratification note (2026-07-27, bus e477)
Engineer's framing-verify surfaced a real fork on §5 line-emission: CheckDesync returns a single first-failure verdict, but
manifest-check.sh§5 emits PER-SUB-CHECK OK/FAIL lines to STDOUT and runs 5c/5d independent of 5a/5b (accumulates). Equivalence harness compares stdout VERBATIM → orchestrator needs per-sub-check line granularity CheckDesync's current signature doesn't expose.Rejected: (A) orchestrator re-derives 5a-5c inline with its own git calls → DUPLICATES safety-critical git-desync logic across two callsites — precisely where a shape-of-(c)-hole would recur (Surveyor's discipline from #554). Single source of truth for git-desync semantics is load-bearing on a check whose failure mode is "manifest lied about the tree."
Ratified (Bosun 2026-07-27): (B) refine
manifest.Storewith a verbose variant returning[]DesyncCheck{name, ok, detail}.CheckDesyncbecomeslen(fail)==0over the verbose variant's result — existing callers (Cutter step (b), tests) untouched. Additive-dormant shape same as B-request/nil-Manifest at #556.Post-ratify scope-narrowing (Engineer bus 33de): B needs NO public dir-injection API.
store_test.go:214already sets gitDir in-package for unit tests; cmd/rt equivalence harness runs the rt process with CWD=fixture sogitDir="."resolves. So B's surface is exactly the verbose variant +len(fail)==0rewrite — no constructor change.Refinement accounting: this refines
manifest.Store(the substrate authored at #542), NOT Cutter. The 3/5 accretion count is Cutter-specific; this refinement does NOT tick that count.manifest.Store's "frozen at #542" claim gets refined here as reality intrudes — §3.3 pattern applies to substrates other than Cutter too. Naming the manifest.Store refinement consciously in the record: manifest.Store gains verbose variant of desync-check with per-sub-check structured result; CheckDesync becomes trivial wrapper over verbose variant returninglen(fail)==0.C2-lenient parse framing-refinement (2026-07-27, bus c9ab)
Engineer's build surfaced a substrate correction to my tracker's stated "manifest.Read does C2 = bash jq-empty" mapping:
Substrate finding:
manifest.ReadwithDisallowUnknownFieldsis STRICTER than the bash oracle's C2 diagnostic. The bash oracle's §5 diagnoses valid-JSON-but-non-C2 manifests field-by-field ("missing last_released_sha field" etc.), which requires lenient JSON parsing.manifest.Readwould reject the manifest outright and Go would emit a different error message than bash — violating the byte-verbatim equivalence-harness gate.Ratified (Bosun 2026-07-27, bus c9ab): §5 parses LENIENTLY using
json.Valid+ per-field extract for faithfulness to the bash oracle's diagnostic surface. Git checks still route throughCheckDesyncVerbose(fork B honored — no duplicate git-desync logic).Not a weakening — this PRESERVES the oracle's exact error messages, which IS the equivalence-harness gate for byte-verbatim stdout comparison. Lenient-vs-strict parse is a per-callsite concern; §5's callsite specifically wants lenient for diagnostic fidelity, while Cutter's step-(b) manifest.Read stays strict (correct for the write-side idempotency check).
Substrate-of-record correction anchor: my tracker's stated primitive mapping was substrate-optimistic (assumed manifest.Read strict-mode was oracle-faithful). Engineer's build-time framing-verify caught the divergence. This is the 5th same-shape correction this arc (siblings: rolling-mode over-tick, 4-vs-3 refinement count, Fire-replay-naturally assertion, git-primitive-gap inventory misread, and this one). Pattern is now deep: my ratify-time substrate mappings consistently need framing-verify pass to reach substrate honesty. The correction cycle IS the discipline working (surface + reason + accept-correction → clean revision) rather than a defect in the ratify process.
AC
rt manifest-checkcompiles + all 5 sections port byte-faithful tomanifest-check.shCheckDesyncVerbosereturns[]DesyncCheck{name, ok, detail};CheckDesyncbecomes trivial wrapper returninglen(fail)==0— all existing callers byte-unchangedchangelog.HasUnreleasedSectionbool primitive addedprep.ReadVersionFileprimitive added for VERSION file + package.json version-field extraction (§2)json.Valid + per-field extractparse to preserve bash oracle's per-field diagnostic messagesmanifest-check.shbyte-oracle (stdout VERBATIM comparison)go vet ./...+golangci-lint runcleanRelated
manifest.Store'sCheckDesyncsurface (adds verbose variant; keeps thin CheckDesync wrapper for existing callers)Filed 2026-07-27 by Bosun. Structural framing ratified 2026-07-27 per Engineer framing-verify (bus 8dcb). §5 fork ratified B (manifest.Store verbose variant) per Engineer framing-verify (bus e477). Post-ratify scope-narrowing (no constructor change needed) per Engineer bus 33de. C2-lenient parse ratified per Engineer build-time framing-refinement (bus c9ab). Bosun-authored primitive gap list corrected (bus e477): 5a/5b/5c/5d git-ops ALREADY EXIST inside CheckDesync; sub-fork on git-primitive-home is MOOT and removed.
AC-hygiene sweep 2026-07-30 (Quartermaster; per Bosun d6d1/8361 dispatch, revised split 9d88): all 9 ACs substrate-verified as done-not-ticked → ticked per Engineer's cluster-grading (bus 53c5 @ main
3cca3b9: full go test 19 pkgs 0 FAIL + golangci-lint 0 issues). No exceptions, no done-with-disclosure caveats. Programmatic write per Engineer's shape (bus f680): re-fetched immediately pre-PUT + baseline-asserted (expected [ ]-count matched) + per-AC exact-once substitution + re-fetch byte-verify post-PUT.CLOSED via PR#564 merged @
c1cf08a(2026-07-27 06:23 CEST, rebase-merge, HTTP 200, gate 4/4 byte-verified pre-fire).ACs re-derived from merged substrate + Surveyor's independent deep-verify (bus ade5), applying the "name the coverage surface" discipline:
rt manifest-checkcompiles + all 5 sections port byte-faithful tomanifest-check.sh— surface: full-gate green host + forgejo-ci-go:latest; Surveyor's §5 5c mismatch-line-drop catch produced a permanent coverage fix (regression harness fixture)CheckDesyncVerbosereturns[]DesyncCheck{name, ok, detail};CheckDesyncbecomes trivial wrapper returninglen(fail)==0— surface: existing callers byte-unchanged (all Cutter step-(b) tests remain green); fork B honoredchangelog.HasUnreleasedSectionbool primitive added — surface: distinct from UnreleasedContent, matches bashhas_unreleased_sectionsemanticsprep.ReadVersionFileprimitive added for VERSION file + package.json version-field extraction (§2) — surface: #213 didn't cover this; new additive primitivejson.Valid + per-field extractparse to preserve bash oracle's per-field diagnostic messages — surface: C2-lenient parse ratified per bus c9ab; preserves byte-verbatim harness gatemanifest-check.shbyte-oracle — surface: byte-verbatim stdout comparison with regression pin for §5 5c mismatch line non-vacuous (Surveyor mutation-verified)go vet ./...+golangci-lint runclean — surface: CI gate confirmsAll ratifications honored (bus 8dcb → d6b8, bus e477 → e1bd, bus c9ab → a8b8):
Surveyor's REQUEST_CHANGES 4615 caught a real defect that both Engineer's equivalence harness AND unit tests missed: §5 5c mismatch line dropped " (mismatch)" vs bash oracle. Engineer's fix (bus 17b3) landed as one-liner + new regression harness fixture (proven non-vacuous via mutation) + comment nit. The permanent fix isn't just the one-liner — the harness fixture closes the coverage gap that let it slip past the automation layer. This is exactly the composite-milestone-gate design's expected value from Surveyor's adversarial-verify layer.
Refinement accounting: 3/5 Cutter accretions HOLDS.
manifest.Storerefined (verbose variant) — separate substrate from Cutter, not tracked in the 3/5 count.Phase 6 status after this close: 5/6 sub-trackers merged (#554 Cutter foundation + #556 rt-prep + #557 rt-release + #559 rt-prune-rc-tags + #558 rt-manifest-check). Phase 6 orchestrator/utility port arc COMPLETE — all 4 orchestrator ports + Cutter foundation in main. Remaining: #555 rt-decide (pure-decision, 826 LOC, awaiting operator disposition on Pilot chamber-wake) + #499 (folds into Cutter, closes at Phase 6 gate when #555 lands + composite harness green).
Closed by Bosun 2026-07-27 06:23 CEST per Engineer's Refs-only convention.