Skip to content

fix(deps): the gonuts pin is one version, everywhere — manifest truth, glob fence, mechanical bump (#791) - #798

Merged
c03rad0r merged 1 commit into
mainfrom
fence/791-gonuts-pin-ssot
Oct 11, 2026
Merged

c03rad0r merged 1 commit into
mainfrom
fence/791-gonuts-pin-ssot

Conversation

@Amperstrand

Copy link
Copy Markdown
Collaborator

Closes #791. Single commit, off current main (4614ac2). Freeze-compatible: CI/tests/tooling only — the one dependency change is a dev tool (scripts/token-recovery) moving to the version main already pins everywhere else; no shipped surface moves.

The drift, and what now makes it impossible

Three incidents, one root cause (#791): carriers enumerated in prose and in a checker scoped to src/, while go.mod files exist repo-wide.

Incident Now caught by
#780 hand-bumped 4 of 5 carriers; scripts/token-recovery stayed at v0.10.0 (predating the fork's #480/#495/#496 counter fixes) glob discovery + identity fence, at commit/push time
#771 pinned a pseudo-version while #780 pinned the tag — same 8 lines, two semantics same fence (one string, everywhere) + AGENTS rule that pseudo-versions are branch-only
v0.13.2 (fix for open P2 #705) existed 11 minutes after v0.13.1; nobody compared --latest leg in release-check.sh — a release is not cut on a stale pin

The pieces

  1. Truth: packaging/build-inputs.json gains .gonuts (repo, version, rule comment) — the same manifest-truth idiom as go.version and portal.commit.
  2. Fence: tests/contract/check-gonuts-pin.py — discovers carriers by repo-root rglob("go.mod") (the test(contract): four drift fences — fragment identity, toolchain ceiling, SSID matcher table, clean-container lane #775 ceiling's enumeration), matches BOTH go.mod require shapes, and refuses any disagreement with the manifest, including a go.sum that never recorded the truth version (the half-update shape). Offline, milliseconds. --latest is the network leg: real tag AND newest stable tag — wired ONLY into scripts/release-check.sh, because failing every open PR the moment the fork tags would be noise; refusing to cut a release is the catch.
  3. Verdicts: tests/contract/gonuts-pin_test.sh — 7 planted-drift cases (both require shapes, the stale-carrier shape, the sum-lag shape, a self-consistent pseudo-version accepted offline, missing manifest key, carrierless tree). A fence that cannot fail is decoration.
  4. Bump: scripts/bump-gonuts.sh <tag> — manifest first, then every discovered carrier via go get + go mod tidy (never hand-edited sums), then the full --latest verdict. A half-update cannot happen.
  5. Wiring: hooks/pre-commit (offline only; triggers on go.mod/go.sum/build-inputs.json; network stays out of hooks), both workflow twins (offline, beside deps-sync), release-check.sh (offline + --latest).
  6. AGENTS.md: the "four go.mod files today" enumeration is replaced by the rule + the check's name — counts never appear in prose again. The stale "via the replace directive" claim is dropped (the tree pins require-only; verified).
  7. The fence's first catch, fixed in-tree: scripts/token-recovery raised v0.10.0 → v0.13.0 (the version main already pins). Builds and vets clean against v0.13.0 — the fork's API surface it uses survived three minors.

Verification (this branch)

Interplay with the open train

Router honesty

No router-visible surface is exercised: the shipped binary's module graph is untouched (the four src carriers stay at v0.13.0), and the fence is offline tooling. The token-recovery change is dev-tooling-only.

…, glob fence, mechanical bump (#791)

The wallet fork's pin drifted three ways in one release week: a hand
bump moved four carriers and left a fifth (scripts/token-recovery) three
minors behind; two open PRs pinned the same lines to a tag and a
pseudo-version; a newer fork tag carrying an open-P2 fix went unnoticed.

- packaging/build-inputs.json names the pin (.gonuts.version) as the
  single source of truth, beside the go and portal pins.
- tests/contract/check-gonuts-pin.py discovers carriers by glob (both
  go.mod require shapes — the single-line form hid the token-recovery
  stale pin from the checker's first draft) and refuses any
  disagreement, offline, in pre-commit and both CI twins; --latest
  (release-check only) refuses a release while the fork has a newer
  stable tag.
- tests/contract/gonuts-pin_test.sh: 7 planted-drift verdicts.
- scripts/bump-gonuts.sh rewrites manifest and every carrier together.
- scripts/token-recovery raised v0.10.0 -> v0.13.0 (the fence's first
  catch; builds and vets clean against the new pin).
- AGENTS.md states the rule and the check, never a carrier count.
@Amperstrand

Copy link
Copy Markdown
Collaborator Author

Verdict: CLEAN — land it, and land it FIRST among the pin PRs. Every mechanism piece #791 specified is present, the fence has real teeth (re-proven live here, including against #781's exact shape), and the ordering constraint it creates for #781 is the feature working, not a defect.

Reviewed against PR-REVIEW.md's 13 criteria + the AGENTS.md fund-safety lens, with #791 read first as the contract. Mapping the issue's six mechanism pieces to this diff: manifest truth (.gonuts in build-inputs.json, same idiom as go.version/portal.commit) ✓; identity fence by repo-root rglob("go.mod") matching both require shapes — the single-line form is the one that hid token-recovery from the checker's first draft, and the shipped suite plants it ✓; go.sum half-update catch ✓; verdicts harness with 7 planted-drift cases ✓; mechanical bump (bump-gonuts.sh: manifest first, toolchain-computed sums, then the full --latest verdict) ✓; staleness gate wired only into release-check, not PR lanes, exactly the issue's noise argument ✓; AGENTS.md rewritten rule-not-enumeration, dropping the false "via the replace directive" claim — I confirmed main's replace block is local-modules-only, gonuts is require-only ✓. Closes #791 is earned.

What I ran (isolated worktree at 81778a3): gonuts-pin_test.sh 7/7; offline identity on your branch — 5 carriers discovered, all v0.13.0, PASS; --latest live against the real fork — refuses v0.13.0 naming newer stable v0.14.0 with the bump command in the message (the release-time gate doing the #705 catch); check-deps-sync 136/136; changelog fragments 18/18; merge-tree against current main (behind today's #787/#799) — clean, including the AGENTS.md edit beside #799's doctrine section. The pre-commit wiring matches the three-layer hook contract posted on #791 (advisory, offline-only, triggered by go.mod/go.sum/build-inputs.json) — network stays in release-check where it belongs.

The fence's teeth, re-proven on the next live incident: I applied #781's four carrier bumps (v0.13.2, as pushed) onto this tree and ran the fence — 8 findings, every go.mod and go.sum named with the fix command. That is not a hypothetical drift shape; it is the exact state main would reach if #781 merged without the unified bump. The negative control the house demands exists twice over: shipped fixtures and the real adjacent PR.

Notes, none blocking: version_key sorts a prerelease suffix above its release (v0.13.3-rc1 would outrank v0.13.3) — harmless while the fork tags only clean versions, worth a one-line inversion when it first tags one; PIN_RE would also match an exclude-directive line for the fork (block-shaped, no require prefix) — no excludes exist in-tree today, same one-line guard when relevant; and folding the token-recovery bump in-tree rather than the issue's companion PR is defensible — the fence's first live catch being fixed by the same commit that ships it is the right story, and the body tells it.

Ordering / freeze call: CI/tests/tooling only plus a dev-tool dependency — freeze-compatible, rides 0.6.0. Merge before #781's rebase: after this lands, main is deliberately --latest-blocked (v0.14.0 exists, tree pins v0.13.0), and that block is the intended prompt for scripts/bump-gonuts.sh v0.14.0 to ride #781's rebase — which also resolves #781's token-recovery outlier and closes the loop on #780's disposition (its v0.13.1 pin can no longer land as-is; fold its classifier hunks into #781 and close it superseded).

@c03rad0r

Copy link
Copy Markdown
Contributor

🏷️ Next action — ready-to-merge

Ready to merge — review verdict CLEAN/land; mergeable with no open gates.

@c03rad0r c03rad0r removed the wave:4 Covered by the wave-4 review pass label Oct 10, 2026

@Amperstrand Amperstrand left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

13-criteria pre-review (rubric pass, evidence attached)

Verdict: ready to merge pending a write-access approval.

  • (1) Body/diff match: body claims manifest-truth pin + glob fence + mechanical bump — diff delivers exactly that (build-inputs.json .gonuts.version, check-gonuts-pin.py glob discovery, bump-gonuts.sh, release-check gate). Refs #791. ✅
  • (2/3) Hygiene: single commit, fresh base, no attribution footers. ✅
  • (4) Does what it says: ran the fences on the head tree — gonuts-pin_test.sh 7 cases, 0 failed; check-gonuts-pin.py discovers 5 carriers by glob (confirming the doc-rot: the hand-maintained "four go.mod" list missed scripts/token-recovery). ✅
  • (5) Coherent whole: also repairs the drifted carrier (scripts/token-recovery was 3 minors behind). In-scope for #791. ✅
  • (6) Idioms: glob-discovery + manifest-truth + planted-drift verdicts — exactly the AGENTS.md drift doctrine. ✅
  • (7) Deps: no new dependency surface (scripts only). ✅
  • (8) Tests: fence + negative control verified: planted a bad pin → check refuses (drift not accepted). ✅
  • (9) Docs: AGENTS.md updated to remove the rotting enumeration; changelog fragment present. ✅
  • (10–13) Security/cross-cutting: no portal surface, no secret handling, no protocol behavior. ✅

Merging note for the approver: #781 carries this branch's full payload (built on top of it) — merge #798 first, then #781 (delta = the v0.14.0 pin + #705 fragment), then #780 needs a trim (its pin changes become redundant; its unique content = fee-verdict fixtures + cloud-lab Dockerfile hoist).

@ — one approval unblocks the chain.

@c03rad0r
c03rad0r self-requested a review October 11, 2026 11:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status:ready-to-merge Approved + mergeable + gates met — merge now

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gonuts-tollgate pin drifts: single-source-of-truth pin (manifest + rglob fence + mechanical bump + release-time latest-tag gate)

2 participants