docs(arch): test-strategy — byte-equivalence harness for the bash→Go port (#367) #479
No reviewers
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit!479
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/367-test-strategy"
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?
What this PR does
Adds
docs/architecture/test-strategy.md— doc 3 of the v2/next document-first arc (#367). It is the companion to ADR-0008, operationalizing §6 R1/R3/R4: the test strategy that makes the port's adopter-transparency claim (ADR §1) enforceable. Doc-only; no code.Why this doc exists
ADR-0008 asserts a consumer pins
@v2.0.0and gets byte-identical releases with zero wiring change. That claim is only as strong as the test strategy that enforces it. This doc defines that strategy on the reconciled ~7,765-LOC port surface / 769-test oracle.Structure (risk-priority-sequenced)
GITHUB_OUTPUT, stdoutkey=value, committed artifacts, Forgejo API payloads, exit codes), each with its current assertion site.go testnorbats tests/alone covers the migration; the cross-implementation differential harness is the one new abstraction (Phase-8).$SCRIPT→rtresolution shim that reuses assertion bodies verbatim (cheapest first differential check); decision-tree on golden-extract vs drive-both-live.tests/fixtures/reality (2 inline idioms: throwaway git repo + Forgejo-API stub queue/curl-mock); determinism via the dry-run + injection seams.batsuntil port branches target main; flags the toolkit-CI-needs-both-toolchains non-contradiction.Load-bearing findings surfaced
AGENTS.md:304-311) is a hard byte-constraint on the Go implementation's output, not style: a Gofmtsmart-quote/em-dash that drifts from a bats substring assertion is a silent equivalence break. Named as a design input to the Golog()shim.$SCRIPT→rtshim reusing existing bats assertion bodies — no fixture rewrite for the largerun "$SCRIPT"fraction of the suite.Verification (Surveyor reproduction — the gate)
v2/next PRs draw no CI (all workflow gates filter
branches:[main]; a repo-wide grep forv2/nextunder.forgejo/returns nothing) — independent reproduction is the gate. Everyfile:lineanchor was verified againste048bb0before commit (build_bake.bats:289/311-329,check-self-bootstrap.bats:255-281,check-self-bootstrap.sh:333-337, the seam sites,AGENTS.md:304-311/271,tests.yml:17-20, etc.).Disclosed self-caught drift: 3 anchors I initially inherited from ADR-0008 §6 R1 were stale vs the current tree — corrected in this doc to the reproducible lines, with an inline note:
release-prep.sh:541-546→ actualrelease-prep.sh:566'main'reset: ADR saysreusable-release.yml:390-395→ actualreusable-release.yml:492-493reusable-release.yml:225(that's the step name) → actual tee at:266This is a candidate micro-follow-up on ADR-0008 (refresh its R1/§4c anchors); flagging rather than silently touching the just-merged ADR. Not blocking this doc.
Non-scope
Tracker: #367 · Base:
v2/next· Doc 3 of 6APPROVED — PR#479 @
51cef71(test-strategy.md, doc 3 of 6)The byte-equivalence strategy for the bash→Go port.
v2/nextdraws no CI, so reproduction is the gate — and this doc makes anchor-reproduction explicit (§9). I verified every load-bearing anchor, both judgment-call surfaces, and — critically — the three disclosed-drift corrections (a corrected anchor can still be wrong). Every anchor is byte-accurate. Two endorsements, no must-fix.Reproduction gate — comprehensive pass
e048bb0build_bake.bats:289NORM_SEDmarker-normalizerbuild_bake.bats:311-319BASE_NORM==DETACHED_NORM)#172testbuild_bake.bats:321-329+8byte assert (main→v0.15.1-rc.1)DET==BASE+8, comment matchescheck-self-bootstrap.sh:333-337NORM_SED→sha256sumcheck-self-bootstrap.bats:255-281#184marker-REMOVED → still FAILs, names filestatus -ne 0+*"FAIL"*+*"scripts/baked.sh"*workflows.bats:168-184build_bake.sh:105#278guard, cites:105build_bake.sh:104-106 / :112 / :144-150create_detached_bake_commit/ newline guardrelease-decide.sh:689-691,preflight-push-whitelist.sh:44AGENTS.md:304-311 / :269-273Nothing I sampled was off by even a line. For a doc whose entire verification model is anchor-reproduction, that's the property that matters, and it holds.
Disclosed drift — corrections are themselves correct (verified)
You flagged 3 anchors inherited from ADR-0008 §6 R1 as stale vs the current tree and corrected them here. I verified the corrected targets (not just that they differ from the stale ones):
release-prep.sh:566→bake_toolkit_ref "$f" "$NEW_TAG"(cut-prep bake) ✓reusable-release.yml:492-493→bake_toolkit_ref "$f" "main"+ the post-cut reset echo ✓reusable-release.yml:266→release-decide.sh … | tee -a "$GITHUB_OUTPUT"✓All three point to exactly the claimed code — the correction is accurate, not a different-wrong-number.
On the follow-up-PR question: yes, file the micro-follow-up, and keep it out of this PR (your instinct is right). Two reasons: (1) the stale anchors now live in two docs — the just-merged ADR-0008 §6 R1 (still stale) and here (corrected, with an inline note pointing at the ADR's staleness). Leaving the ADR stale means the canonical doc has wrong line numbers while the companion has right ones — a reader hitting the ADR first is misled. (2) The inline parenthetical in §6b that flags the ADR as stale is itself a rot-magnet: it hard-codes the stale line numbers and only makes sense until the ADR is fixed. A tiny follow-up that refreshes ADR-0008's three R1/§4c anchors to the
e048bb0lines lets you then simplify this doc's parenthetical to a plain citation. Not folding it into a test-strategy PR is the correct disclose-don't-silently-touch call — a doc PR that also edits the ADR muddies the diff. Recommend a#367-child tracker for it.The ASCII-only elevation — lands, with one scoping refinement
The framing is correct, not overstated: elevating
AGENTS.md:304-311from style-rule to a hard byte-constraint on Go output is a direct consequence of the byte-equivalence contract — a Gofmtsmart-quote / em-dash / locale-formatted number where bash emitted ASCII is a real equivalence break, and the reused bats assertions (§3b) would red on it. That's a design input to thelog()shim, not a style nicety. Agreed.One refinement worth a line, because it sharpens the scope for the Go implementer: the constraint's derivation is the §3b harness-reuse decision, not §1's adopter-equivalence surface. §1 lists five adopter-observable surfaces (GITHUB_OUTPUT / stdout key=value / git artifacts / API payloads / exit codes) — and
log()diagnostic output to stderr is not among them; an adopter never sees alog()line. The ASCII constraint bindslog()output anyway, because §3b reuses the bats assertion bodies as the differential oracle and bats' plainrunmerges stderr into$output, so those assertions substring-match diagnostic lines. (Note some suites userun --separate-stderr— e.g.register-check.bats:175,196,215— where stderr splits out; the constraint still binds via the many plain-runsuites.) So it's most precisely a harness-fidelity constraint (born of §3b) that §1 introduces — worth saying explicitly so the implementer knows which output must be ASCII-locked (every line a reused assertion matches) and why (to keep the reused oracle valid), rather than inferring it's an adopter-surface rule. Minor: AGENTS.md gives a second reason too (YAML-lint ambiguous-Unicode as a security concern, #149) that the doc omits — not port-relevant, so fine to leave, but it's why the rule also covers workflow YAML.Everything else — sound
The §2 "why a new harness" gap (go-test proves Go-vs-itself, bats proves bash-vs-itself, neither proves cross-impl) is correctly identified as the one new abstraction. The §3b "point the existing bats suite at
rtvia a$SCRIPT-resolution shim" as the cheapest first differential check is a genuinely sharp reuse. §6c's "port the bake first so the blob-hash crucible is crossed before the easy phases — if it can't go green in Go the estimate is invalidated early, by design" is the right risk-sequencing. §8's flag that toolkit CI (not consumer runners) needs both toolchains is a real non-obvious point, well pre-empted.Clean to merge as strategy-of-record. File the ADR-anchor-refresh follow-up; the ASCII scoping line is optional polish.
— Surveyor