Repository navigation
Description
Problem
Release verification still has shell logic for tag selection, annotation, signatures, configured identities, remote equality, API verification, ancestry and version assertions. The starting inventory is tools/release-verify.sh:75, tools/release-verify.sh:88, tools/release-verify.sh:107, tools/release-verify.sh:140, tools/release-verify.sh:158, tools/release-verify.sh:175, tools/release-verify.sh:192, tools/release-verify.sh:209 and tools/release-verify.sh:226, on origin/main at a0347a715fab580ece45edfcb3d13509620459a8.
Before this port, #333 and #535 extend verification, and #542 retains it as a standalone diagnostic. This split preserves that completed contract while moving only remaining shell logic to Go.
This is the verification split of #332. Part of #588.
Acceptance criteria
- AC1: Explicit tags, versions with or without the leading
v, and supported default-tag selection identify the same requested release as the completed chain. - AC2: Tag verification preserves the completed chain's refusal decisions for absent/lightweight tags, missing or invalid signatures, wrong configured identity, unequal remote objects and negative or unreadable API verification.
- AC3: Release-commit verification preserves the completed chain's signature, configured-author and API-verification decisions independently of the tag's result.
- AC4: Reachability verification preserves refusal for missing or stale remote evidence and releases outside the configured release branch's ancestry.
- AC5: Candidate-parent, release-marker, release-source and prepared-tree verification retains feat(release): verify and recover a release from durable state #535's accepted results.
- AC6: Version assertions inspect the requested tagged tree, including historical tags, with the completed chain's verdict regardless of the invoking working tree.
- AC7: Artifact, inventory, metadata and checksum verification retains the release-contract boundary and accepted results delivered by Ship the Go binaries as release assets installed through mise's github backend #333 and preserved by feat(release): verify and recover a release from durable state #535.
- AC8: Success and failure preserve the inherited diagnostic transcript, structured result fields, stdout/stderr placement and exit status.
- AC9: Non-functional: verification changes no repository files, index, refs, release objects, assets or release state, even when it fails.
- AC10: Surviving entry points end as thin shell wrappers that probe the Go subcommand without side effects and use the frozen post-chain shell only when that capability is absent.
- AC11: A supported Go failure never triggers shell fallback, a repeated verification attempt or a publication/repair attempt.
- AC12: Non-functional: supported release N-2 callers retain their invocation and result contracts without a raised binary floor or required configuration changes.
Scope and non-goals
Preserve standalone verification and existing release-task invocation. The current Bats cases cover missing tags, lightweight-tag early termination, tag normalization/defaulting, unsigned commits and wrong authors (tests/tools/release-verify.bats:58, tests/tools/release-verify.bats:69, tests/tools/release-verify.bats:79, tests/tools/release-verify.bats:86, tests/tools/release-verify.bats:94, tests/tools/release-verify.bats:102, tests/tools/release-verify.bats:115, tests/tools/release-verify.bats:125). Existing real-version-check integration is at tests/tools/check-versions.bats:264.
Every current case receives a recorded preserved/superseded disposition. Today's historical-tag skip and working-tree literal check (tools/release-verify.sh:226) are superseded by #535's tagged-tree verification. Today's tag-only assumption (tools/release-verify.sh:25) is superseded by #333's first-asset-release boundary. Neither may be restored in Go or in the frozen compatibility path. Preserve diagnostics for evidence that older tags legitimately lack according to the completed chain; never invent missing provenance.
Non-goals: implementing asset production or upload, introducing verification assertions owned by #333 or #535, changing identities, adding release markers, creating releases, recovery or activation, adding retries, changing the shared release interface, or reviving retired dispatch/clone/watcher behavior. Reuse established verification outcomes already delivered in Go rather than writing a second implementation. Fallback retirement is a separate D9 follow-up.
Approach
Write negative verification and no-write checks first. Freeze the surviving post-#542 shell contract and compare the replacement against it and the release-chain corpus. Port only remaining shell behavior and preserve the chain's historical-release boundary. The pull request chooses implementation structure.
Dependencies
Depends on #542 after #333 → #544 → #382 → #545 → #546 and the complete #359 delivery chain. In particular, #333's assets, #535's stronger/historical verification and #542's diagnostic handoff must be accepted first. The chain also includes #533, #534, #547, #538, #539, #540, #536, #537, #548, #549 and #541, with #499 and #532 as its prerequisites.
Depends on #753's protection of replacement enforcement before rollout. #332 and #588 track the migration; this issue owns none of the chain's publication work.
Size
M. One pull request for the surviving verifier boundary, its compatibility entry points and inherited assertion coverage.
Verify plan
- AC2, AC3: first demonstrate rejection of a lightweight tag and a signed-looking tag over an unsigned or wrong-author commit using the existing cases in
tests/tools/release-verify.bats. Then individually invalidate each tag/commit signature, configured identity, API verdict and remote-object match in the completed chain's fixtures. Assert independent decisions and existing early termination where required. - AC1: explicit tag, bare version, default selection and no-available-tag fixtures compare selected tag, streams and status with the frozen post-chain command.
- AC4: local/bare-remote fixtures cover absent/stale tracking evidence and a tagged commit outside release-branch ancestry; compare diagnostics and status without a live fetch or API call.
- AC5: carry forward feat(release): verify and recover a release from durable state #535's wrong/extra-parent, wrong-source, wrong-marker and wrong-prepared-tree fixtures; assert unchanged results.
- AC6: verify an older tag from a working tree naming another version, with both correct and stale literals in the requested tagged tree. Carry forward feat(release): verify and recover a release from durable state #535's historical cases and adapt
tests/tools/check-versions.bats:264to the accepted tagged-tree contract; record why the earlier working-tree expectation was superseded. - AC7: carry forward the pre-asset/asset-bearing boundary and missing archive, omitted binary, wrong platform, corrupt bytes, checksum and metadata mismatch fixtures from Ship the Go binaries as release assets installed through mise's github backend #333 and feat(release): verify and recover a release from durable state #535. Assert the port neither weakens nor duplicates their verification contract.
- AC8: compare full success and failure transcripts and structured results, including candidate, release commit, tag object, asset evidence and failed assertions where the inherited invocation provides them. A failed or partial evidence producer cannot yield verified success.
- AC9: mutation traps and filesystem/index/ref snapshots remain unchanged on every success and refusal; no fixture signs, publishes, repairs, moves or deletes a release object.
- AC10: absent and older binaries select the frozen post-chain shell once with unchanged arguments and a read-only probe; prove the oracle includes the chain's asset/historical contract.
- AC11: supported failure, partial evidence and an indeterminate probe return failure with zero fallback, zero repeated attempt and zero mutation calls.
- AC12: invoke unchanged tasks and wrappers with N-2 inputs against absent, older and new binaries. Run the Go corpus on Linux, macOS and Windows, shell-wrapper smoke coverage where supported, targeted Go/Bats and inherited release suites, generation/deployment checks where callers changed,
mise run lintandmise run teston the reviewed head. All remote evidence and mutation boundaries are local fixtures or stubs. - Definition of done: D1 each AC is verified at the merged head, with the commands and results cited in the pull request's Verification. D2 an independent review approves the exact merged head, and every finding has a recorded disposition. D3 required checks pass with no gate loosened. D4 the leak scans the repository specifies are clean, and every post made for this work (comments, descriptions) passes the per-post leak review before it is posted. D5 every commit is signed. D6 the documentation matches, or the description says
No doc impactwith the reason. D7 every commit carries anAssisted-bytrailer and the pull request carries theprovenance:agent-assistedlabel. D8 the change stays within the pull request size limits. D9 follow-up work, including deferred review findings, is filed as issues, each with a Problem section and numbered acceptance criteria and linking this issue; the pull request's Related section lists them, and any code that defers work links its issue. D10 the merge closes this issue through a closing reference, the project board shows the state Done, and a finalStatus:comment names the merge commit.
Risks
A tag's signature can conceal a bad underlying commit; working-tree literals can conceal a bad historical release; a stale oracle can drop asset checks. Independent assertion fixtures and the post-chain handoff cover these boundaries. Undo: revert the port while preserving the completed release contract.
Operator authority
A standing rule names the operator: changes to the paths #753 protects, including the replacement enforcement and the agentrepo subcommand-registration paths, need the owner's exact-head approval at merge. This issue grants no release, signing or publication authority and changes no approval or identity rule.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Work type
Projects
- StatusShow more project fieldsBacklog
Activity
tbhb-agent commentedon Oct 26, 2026
Refinement: NOT READY — Operator authority omits merge_owner review required for protected replacement and subcommand-registration paths
Model: gemini-4-argon-high
Checked
tbhb-dev/devtools#812(state: open, typeFeature, labelchange:feat,comments: 0) and all named issues (#332,#333,#359,#382,#499,#532,#533,#534,#535,#536,#537,#538,#539,#540,#541,#542,#544,#545,#546,#547,#548,#549,#588,#753).origin/main(a0347a715fab580ece45edfcb3d13509620459a8):tools/release-verify.sh:25states the tag-only assumption (# The tag is the whole release.) superseded by#333.tools/release-verify.sh:75resolves the default tag (git describe --tags --abbrev=0) and normalizes thevprefix (tools/release-verify.sh:76-84).tools/release-verify.sh:88checks local tag ref existence andtools/release-verify.sh:100-105checks annotated tag object type (git cat-file -t).tools/release-verify.sh:107reads the tag object (tools/release-verify.sh:111-124check the SSH signature block andTAGGERidentity).tools/release-verify.sh:140resolves the tagged commit (tools/release-verify.sh:141-154checkgpgsigpresence andRELEASE_AUTHORidentity).tools/release-verify.sh:158comparesgit ls-remote origin "refs/tags/$tag"with the local tag object (tools/release-verify.sh:158-166).tools/release-verify.sh:175queriesrepos/{owner}/{repo}/git/tags/$local_tagfor tag signature verification (tools/release-verify.sh:175-183).tools/release-verify.sh:192queriesrepos/{owner}/{repo}/commits/$tag_commitfor release-commit verification (tools/release-verify.sh:192-198).tools/release-verify.sh:209checksrefs/remotes/origin/$RELEASE_BRANCHagainstgit ls-remote originandgit merge-base --is-ancestor(tools/release-verify.sh:209-217).tools/release-verify.sh:226runsbash tools/check-versions.sh "$tag"only when$tag = $latestand skips historical tags (tools/release-verify.sh:226-235), superseded by#535AC5.tests/tools/release-verify.bats:58,tests/tools/release-verify.bats:69,tests/tools/release-verify.bats:79,tests/tools/release-verify.bats:86,tests/tools/release-verify.bats:94,tests/tools/release-verify.bats:102,tests/tools/release-verify.bats:115, andtests/tools/release-verify.bats:125match the eight existing Bats test cases cited in Scope.tests/tools/check-versions.bats:264(postflight reaches the real shim for the latest tag on both trees) invokestools/release-verify.shattests/tools/check-versions.bats:294andtests/tools/check-versions.bats:300.AC1–AC12are observable, testable, single-outcome requirements free of prescribed implementation structure (## Approachexplicitly leaves implementation structure to the pull request), and include non-functional criteria for read-only/no-mutation behavior (AC9) and N-2 caller compatibility (AC12perdocs/compatibility.md:3-6).## Verify planmaps every criterion (AC1–AC12) to concrete positive, negative, and no-mutation checks without live network writes.## Dependenciesaccurately names the parent/epic (#332,#588), the#359release chain culminating in#333,#535, and#542, and#753(#753AC3).## Risksand undo path are clear.Gaps
## Operator authoritysaysNone., contradicting the#753dependency and repository protected-path rules.## DependenciesstatesDepends on #753's protection of replacement enforcement before rollout, andAC10requires entry points to probe a Go subcommand (internal/agentrepo/command.go:20-87registersagentreposubcommands under#332). In#753AC1 and Scope, the file registeringagentreposubcommands and replacement enforcement packages are added togolden_pathsandowner_pathsin.agents/agent-skills.conf:4,9(enforced bypackages/agents/source/skills/merge-pr/shared/scripts/merge-policy.py:474-538), which requiresmerge_owner's exact-headAPPROVEDreview at merge and triggers--owner-pathdelegation checks. In addition, if caller updates mentioned inAC12's verify plan (generation/deployment checks where callers changed) touch protected skill/guard paths in.agents/agent-skills.conf:4,9or trigger gate-config checks in.agents/agent-skills.conf:8(mise.toml:983-985,.devtools/tasks/,.github/), those paths also requiremerge_ownerexact-head approval.None.under## Operator authoritywith the requiredmerge_ownerexact-headAPPROVEDreview for the protected replacement andagentreposubcommand-registration paths established by#753(and any.agents/agent-skills.conf:4,8,9protected caller or task-config paths touched), while stating that this issue grants no release, signing, or publication authority.Split
None. Size
Mfits one pull request covering the post-#542verifier port, thin compatibility wrapper (tools/release-verify.sh:1-237), and migrated unit/integration tests.Definition of done
The definition of done for #812 (Feature). Tick each item and give its evidence. (A ticked box below records planning coverage in the issue body, not completed implementation work.)
## Verify planprovides explicit verification checks forAC1–AC12and statesD1 each AC is verified at the merged head, with the commands and results cited in the pull request's Verification.## Verify plan(Definition of done: D2) requires an independent review approving the exact merged head with a recorded disposition for every finding.## Verify plan(AC12andDefinition of done: D3) requiresmise run lint,mise run test, and required checks passing with no gate loosened.check-leaks.shwith the repository's private-strings list, and the leak review of each post. — Planning coverage:## Verify plan(Definition of done: D4) requires clean repository leak scans and per-post leak review before posting.## Verify plan(Definition of done: D5) requires every commit to be signed.docs/, CHANGELOG or help text), or the Verification section says "No doc impact" and why. — Planning coverage:## Verify plan(Definition of done: D6) requires matching documentation orNo doc impactwith the reason in the pull request description.provenance:agent-assistedlabel. — Planning coverage:## Verify plan(Definition of done: D7) requiresAssisted-bytrailers on every commit and theprovenance:agent-assistedlabel on the pull request.## Sizescopes the change toM(one PR) and## Verify plan(Definition of done: D8) requires staying within pull request size limits.## Scope and non-goalsidentifies fallback retirement as a separate D9 follow-up, and## Verify plan(Definition of done: D9) requires follow-up issues with Problem and numbered ACs linked in the PR's Related section and code comments.Status:comment names the merge commit. — Planning coverage:## Verify plan(Definition of done: D10) requires a closing reference at merge, board stateDone, and a finalStatus:comment naming the merge commit.Round: 1 of 3
tbhb-agent commentedon Oct 26, 2026
Refinement: READY — Round 1 operator-authority gap resolved and all Definition of Ready checks pass against origin/main
Model: gemini-4-argon-high
Checked
tbhb-dev/devtools#812(state: open, typeFeature, labelchange:feat,updated_at: 2026-10-26T23:16:38Z), its Round 1 comment, and all 24 named issues (#332,#333,#359,#382,#499,#532,#533,#534,#535,#536,#537,#538,#539,#540,#541,#542,#544,#545,#546,#547,#548,#549,#588,#753).## Operator authority):## Operator authoritynow states the standing rule that changes to the paths#753protects, including the replacement enforcement andagentreposubcommand-registration paths (internal/agentrepo/command.go:20-87, protected under.agents/agent-skills.conf:4,9and enforced bypackages/agents/source/skills/merge-pr/shared/scripts/merge-policy.py:474-538), require the owner's exact-head approval at merge, and confirms that#812grants no release, signing, or publication authority and changes no approval or identity rule.origin/main(a0347a715fab580ece45edfcb3d13509620459a8):tools/release-verify.sh:25states the tag-only assumption (# The tag is the whole release.) superseded by#333AC5 and AC6.tools/release-verify.sh:75resolves the default tag (git describe --tags --abbrev=0) and normalizes thevprefix (tools/release-verify.sh:76-84).tools/release-verify.sh:88checks local tag ref existence andtools/release-verify.sh:100-105checks annotated tag object type (git cat-file -t).tools/release-verify.sh:107reads the tag object (tools/release-verify.sh:111-124check the SSH signature block andTAGGERidentity).tools/release-verify.sh:140resolves the tagged commit (tools/release-verify.sh:141-154checkgpgsigpresence andRELEASE_AUTHORidentity).tools/release-verify.sh:158comparesgit ls-remote origin "refs/tags/$tag"with the local tag object (tools/release-verify.sh:158-166).tools/release-verify.sh:175queriesrepos/{owner}/{repo}/git/tags/$local_tagfor tag signature verification (tools/release-verify.sh:175-183).tools/release-verify.sh:192queriesrepos/{owner}/{repo}/commits/$tag_commitfor release-commit verification (tools/release-verify.sh:192-198).tools/release-verify.sh:209checksrefs/remotes/origin/$RELEASE_BRANCHagainstgit ls-remote originandgit merge-base --is-ancestor(tools/release-verify.sh:209-217).tools/release-verify.sh:226runsbash tools/check-versions.sh "$tag"only when$tag = $latestand skips historical tags (tools/release-verify.sh:226-235), superseded by#535AC5.tests/tools/release-verify.bats:58,tests/tools/release-verify.bats:69,tests/tools/release-verify.bats:79,tests/tools/release-verify.bats:86,tests/tools/release-verify.bats:94,tests/tools/release-verify.bats:102,tests/tools/release-verify.bats:115, andtests/tools/release-verify.bats:125match the eight existing Bats test cases cited in## Scope and non-goals.tests/tools/check-versions.bats:264(postflight reaches the real shim for the latest tag on both trees) invokestools/release-verify.shattests/tools/check-versions.bats:294andtests/tools/check-versions.bats:300.mise.toml:983-985defines[tasks.verify-devtools-release]runningbash tools/release-verify.sh.AC1–AC12are observable, testable, single-outcome requirements free of prescribed implementation details (## Approachleaves implementation structure to the pull request), and include non-functional criteria for read-only/no-mutation behavior (AC9) and N-2 caller compatibility (AC12perdocs/compatibility.md:3-6).## Verify planmaps every criterion (AC1–AC12) to concrete positive, negative, and no-mutation checks using local fixtures and stubs without live network writes, and coversD1–D10.## Dependenciesaccurately names the parent/tracking issues (#332,#588), the#359release chain culminating in#333,#535, and#542, and#753(#753AC3).## Risksand the undo path are clear and complete.Gaps
None
Split
None. Size
Mfits one pull request covering the post-#542verifier port, thin compatibility wrapper (tools/release-verify.sh:1-237), and migrated unit and integration tests.Definition of done
The definition of done for #812 (Feature). Tick each item and give its evidence. (A ticked box below records planning coverage in the issue body, not completed implementation work.)
## Verify plandefines explicit verification checks forAC1–AC12and statesD1 each AC is verified at the merged head, with the commands and results cited in the pull request's Verification.## Verify plan(Definition of done: D2) requires an independent review approving the exact merged head with a recorded disposition for every finding.## Verify plan(AC12andDefinition of done: D3) requiresmise run lint,mise run test, and required checks passing with no gate loosened, and## Operator authoritynames the owner's exact-head approval requirement for protected paths.check-leaks.shwith the repository's private-strings list, and the leak review of each post. — Planning coverage:## Verify plan(Definition of done: D4) requires clean repository leak scans and per-post leak review before posting.## Verify plan(Definition of done: D5) requires every commit to be signed.docs/, CHANGELOG or help text), or the Verification section says "No doc impact" and why. — Planning coverage:## Verify plan(Definition of done: D6) requires matching documentation orNo doc impactwith the reason in the pull request description.provenance:agent-assistedlabel. — Planning coverage:## Verify plan(Definition of done: D7) requiresAssisted-bytrailers on every commit and theprovenance:agent-assistedlabel on the pull request.## Sizescopes the change toM(one pull request) and## Verify plan(Definition of done: D8) requires staying within pull request size limits.## Scope and non-goalsidentifies fallback retirement as a separate D9 follow-up, and## Verify plan(Definition of done: D9) requires follow-up issues with a Problem section and numbered acceptance criteria linked in the pull request's Related section and in code comments.Status:comment names the merge commit. — Planning coverage:## Verify plan(Definition of done: D10) requires a closing reference at merge, board stateDone, and a finalStatus:comment naming the merge commit.Round: 2 of 3