feat(rt-register-check): port register-check.sh → rt register-check #579
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!579
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "i/568-rt-register-check"
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
Phase 6b validator port (ADR-0009 §3.3):
scripts/register-check.sh→rt register-check. The chamber-name / invented-jargon register-drift PR gate (release-toolkit#392). Three modes, dispatched positionally exactly as bashmain()reads$1:NOT a Cutter consumer. Exit per mode: file-scan
0/1;--git-log0/1/2(2 = missing/unresolvable RANGE);--stdin0/1.Refs #568 · Refs ADR-0009 §3.3 · the milestone-#79 register gate — the LAST Phase 6b port.
The heaviest port — a 3-mode scope-expansion, and the first stderr-compared gate
The last of the wire-existing trio, and the heaviest of Phase 6b: only
--stdinwas previously ported (gates.RegisterCheckStdin). file-scan (the workflow's primary PR gate) and--git-log(#403's commit-subject bypass gate, which the reusable workflow opts into) are new.register-check routes every mode's hits + summary to stderr (stdout is empty), so its compared surface is stderr + exit code (Sb) — honoring milestone #79's gate: "every validator's exit-code AND log-line-output byte-matches." This is the one batch member whose compared surface is stderr, which is why it adds an opt-in harness surface.
Substrate refinements
+SurfaceStderr(opt-in)io.Discard'd by a design note that itself carved out "where a gate routes a FAIL line there — a per-phase concern"; register-check IS that carve-out. Absent fromAllSurfaces→ every existing port's equivalence is byte-unchanged. Positive control:TestHarness_StderrMismatchReds. Ratified by Bosun as a design-sanctioned carve-out, not an override.+FileHit,+Allowlist,+ScanTree,+IsExemptLineFileHit(file:line:content) rather than aHitwithFile=""—--stdinhas no file context, soFile=""would be semantic abuse (cohesive-per-consumer, the #569 R2 shape).+register_check.gogates.RegisterCheckStdin+exitError(#572 F1).Fidelity handlings (each baked + tested)
[[ str == pat ]]*/?cross/(pure string pattern-match, no filesystem); Gofilepath.Match's*does not. Usingfilepath.Matchwould silently over-restrict the allow-list and let drift through where the bash gate allowed it. Ported as a bash-glob→regexp matcher;TestBashGlobMatchnames thedocs/*.mdvsdocs/adr/x.mddivergence explicitly, and mutation (1) reds it.--git-log%hdeterminism — the two scratch repos would otherwise produce different short SHAs. The oracle pins a fixed git identity + commit dates so tree+parent+msg+dates → identical SHA both sides, and the%h\tsubjecthit lines byte-match (the oracle-git-identity discipline).findreaddir vs GoWalkDirlexical → multi-file hit order diverges (the #572-F5 shape). Every drift scenario hits a single file (order unambiguous); multi-file order is unit-pinned, not the byte-oracle.--git-logendpoint errors are byte-faithful on the compared stderr (LC_ALL=C passes the bytes through; same as #572 em-dash / #569≤).Verification
cmd/rtTestRegisterCheckEquivalence— the prebuilt binary vs the real bash script over 12 scenarios (STDERR + exit): file-scan clean / drift / inline-exempt / allow-listed / binary-skip / no-paths;--git-logclean / drift / missing-range (exit 2) / bad-endpoint (exit 2);--stdinclean / drift.internal/register: the glob divergence, allow-list parse + dir-prefix + fall-through, the exemption filter,ScanTreeskip order;cmd/rt: each mode's stderr shape + the 3-state exit mapping;internal/harness:SurfaceStderrcapture + the planted-mismatch positive control.Mutation experiment (non-vacuity — three axes)
All reverted by re-edit; 0 residue.
Full gate green on host +
forgejo-ci-go:latest(go1.26.2):golangci-lint0 issues,go build,go vet, wholego test ./...,gofmt -lclean,shellcheckon the oracle clean.What this PR does NOT do
REGISTER_CHECK_PATTERNS(#435) adopter vocabulary override —internal/registeralready documents that override as deliberately unwired (an "orchestrator/config-injection concern", a landed decision from the Phase-3 register port). This PR honors that established boundary rather than overturning it inside the heaviest port. The reusable workflow wiresregister_patterns_override; if the Phase-7 workflow migration needsrtto honor it, that is a scoped follow-up (a small matcher-parametrization ofinternal/register), not this port.findreaddir vs GoWalkDirlexical diverges on order; the differential scenarios hit a single file, and multi-file order is unit-pinned (disclosed above, #572-F5 shape).Review — PR#579, rt register-check (Go port of register-check.sh, #568)
Independent deep-verify at head
518e5d3(basemain@1ed711d, incl #567). The heaviest + last Phase-6b port: all 3 modes, the first stderr-compared gate, a newinternal/harnesssurface, and the allowlist-glob fidelity crux. Read the 369-line oracle + the newinternal/register/filescan.go+ the harness change, ran the full gate (go1.26.2,build/vet/golangci-lint0 issues/go test ./...), reproduced all 3 mutations, and ran my own verifications on the three flagged risks — including a 20-case glob battery against real bash[[ ]].No must-fix, no should-consider. Every flagged fidelity risk holds. Details below.
The allowlist-glob crux — byte-faithful to bash, verified independently
The load-bearing risk: bash
[[ str == $pat ]]glob where*/?cross/(pure string match), vs Gofilepath.Matchwhere they do not. A naive port would silently over-restrict the allow-list.bashGlobToRegexpmaps*→.*,?→.(both cross/), with faithful[...]classes (!/^negation, leading-]literal, unclosed-[→literal), anchored\A…\z. I verified it three ways:[[ ]](my own test, bash-as-oracle): all 20 agree, including the cruxdocs/*.md↔docs/adr/x.md(both true,*crosses/),?-crosses-/(docs/a?c↔docs/a/c→ true), negation[!bc], leading-]member[]bc], unclosedfoo[, escaped\*, empty, multi-*.docs/adr/x.md+ allow-listdocs/*.md→ both bash and rt exit 0 (allow-listed via the cross-/glob); no allow-list → both exit 1 (drift flagged). Afilepath.Matchimpl would have exit 1 on the first — the divergence the port correctly avoids.*→[^/]*) reds exactlyTestBashGlobMatch+TestAllowlistAllows— the crux is load-bearing, non-vacuous.The trailing-
/directory-prefix (dirPrefixHasPrefix + glob arm, dir-first-then-glob) faithfully mirrors bash'sis_allowlistedlines 105→109, including the subtle quoted-prefix-is-literal detail (Go'sHasPrefixis literal, matching bash's quoted"$pat"*).SurfaceStderr (shared-instrument change) — opt-in, non-vacuous, zero-regression
The first gate whose compared surface is stderr required adding
SurfaceStderrtointernal/harness. Verified the shared-instrument change is safe:AllSurfaces = {SurfaceStdout, SurfaceExitCode}—SurfaceStderris deliberately absent, so a Case that doesn't list it inCompareis byte-unchanged.capture.gonow captures stderr (wasio.Discard) but only compares it when opted in.go test ./...green) — every prior port's equivalence is byte-identical.TestHarness_StderrMismatchRedsasserts VerdictRed + exactly one stderr diff at offset 4 onerr-a/err-b— a no-op stderr comparison would fail it. The instrument genuinely reds on a stderr divergence.The rest
build/vet/golangci-lint(0 issues)/go test ./...green; CI 8/8 on518e5d3.e2 80 94, Go source (178/182) =e2 80 94, on the--git-log range '…' — <endpoint>FAIL lines. Mutation M2 (em-dash→hyphen) reds exactly gitlog-bad-endpoint — load-bearing.%hdeterminismDisableFlagParsing+ manualargs[0] == "--git-log"/"--stdin"dispatch faithfully replicates bash's exact-match —--git-log=X→ both sides treat it as a path (exit 0). The faithful choice for acase/[[ ]]-dispatched script; the #578 cobra equals-form note correctly does not recur.Verdict
APPROVED, head-pinned at
518e5d3. The heaviest port lands with every fidelity risk independently confirmed: the allowlist glob is byte-faithful to real bash across a 20-case battery + end-to-end + mutation; theSurfaceStderrshared-instrument addition is opt-in, zero-regression (full suite green), and non-vacuously controlled; the em-dash is byte-faithful on the compared stderr; all 3 modes byte-match stderr+exit over 12 scenarios; the arg-dispatch faithfully avoids the cobra equals-form divergence; and #435 is explicitly deferred to #580. All 3 mutations reproduce narrowest-correct. This closes Phase 6b (6/6). Yours to land.— Surveyor