Repository navigation
Description
Problem
Part of #588. This is the staged-comparison slice of #329.
At origin/main (a0347a715fab580ece45edfcb3d13509620459a8), staged scans compare index blobs with a base and allow inherited literal counts (.devtools/scripts/check-leaks.sh:189, .devtools/scripts/check-leaks.sh:306). Pattern configuration comes from the base (.devtools/scripts/check-leaks.sh:779). A port that scans checkout bytes or treats this as a full-index gitleaks scan would change the gate.
Acceptance criteria
- AC1:
--stagedchecks the changed index entries and their indexed contents against the selected base, with the same results as the frozen shell regardless of unstaged edits or submodule diff settings. - AC2: Inherited private-literal occurrence counts do not block an unrelated edit or line shift, while added occurrences are findings at their index locations, with the same per-path and per-entry accounting as the frozen shell.
- AC3: Renames, copies, type and mode changes, empty files, binary content, symlink contents and gitlink names retain the staged scanner's current findings, including names newly made private and renames away from private names.
- AC4: Staged pattern checks and path allowances use the selected base's configuration; changing checkout or index configuration cannot weaken that scan, and working-tree skips have no effect.
- AC5: The selected base remains the explicit
DEVTOOLS_LEAK_BASEtree when supplied, otherwise HEAD's tree, or the empty tree only for a genuinely unborn branch. - AC6: A corrupt or unmerged index, invalid base, failed private-list discovery, unreadable blob or unreadable configuration returns status 2 instead of a clean result.
- AC7: Results retain statuses 0/1/2, the current streams, entry and rule labels, index line or binary locations and opaque sensitive names, without printing private values or sensitive error arguments.
- AC8: Non-functional: scanning leaves the caller's index, refs and working files unchanged.
- AC9: Non-functional: consumer entry points end as thin shell wrappers that probe Go subcommand support without writes or consuming input, use the unchanged frozen shell for absent binary or capability, and run supported execution once with preserved streams and status and no fallback after failure.
- AC10: Non-functional: native Go behavior works on Linux, macOS and Windows, and existing N-2 consumers require no configuration or binary-floor change.
- AC11: Task mode selection and published hook contracts retain their current behavior.
- AC12: Non-functional: no temporary matched content remains after the scan finishes.
Scope and non-goals
In scope: the staged comparison and configuration boundary and its existing callers. Source evidence: .devtools/scripts/check-leaks.sh:189, .devtools/scripts/check-leaks.sh:306, .devtools/scripts/check-leaks.sh:779, .devtools/tasks/leaks.toml:6 and .pre-commit-hooks.yaml:128.
Coverage includes .devtools/scripts/check-leaks.bats:226, .devtools/scripts/check-leaks.bats:279, .devtools/scripts/check-leaks.bats:358, .devtools/scripts/check-leaks.bats:404, .devtools/scripts/check-leaks.bats:516, .devtools/scripts/check-leaks.bats:535, .devtools/scripts/check-leaks.bats:627 and every staged regression from .devtools/scripts/check-leaks.bats:1578 through .devtools/scripts/check-leaks.bats:1744.
Overlap: AC2 and AC6 absorb #501's retained private-list consumption and incomplete-input refusal for this mode; new source lookup, source precedence and notices, and provisioning remain #501. AC1 preserves indexed-byte isolation also required by #551 AC4, but it does not absorb that issue's full-index gitleaks coverage. #551's local/ci modes, history/base resolver, caller changes and owner-approved coverage reduction stay out. Neither issue is closed by this port.
Non-goals: rescanning unchanged indexed files as a new policy, changing inherited-literal allowances, source provisioning, publication or whole-object scan modes, and changing hook IDs or stages. The frozen shell's staged pattern behavior is preserved even where it differs from literal occurrence accounting. Fallback retirement is a separate N-2 follow-up under D9.
Approach
Move the scoped behavior to tested Go, with failing cases first. The mechanism is the implementer's choice within these outcomes. Keep the compatibility implementation frozen.
Dependencies
Blocked by #753 before replacement enforcement is activated; cite its merged protection evidence. #329 tracks the port. #501 and #551 retain the excluded behavior changes. #661 supplies the compatibility policy; #333 is distribution work, not a higher binary floor for this port.
Size
M. One pull request for the staged comparison contract and caller compatibility.
Verify plan
First write failing Go cases for an index-only finding, an extra inherited occurrence and an unreadable index blob. Port all scoped Bats cases before reducing shell coverage.
- AC1: clean index versus leaky checkout and the reverse, partial staging in both directions, unchanged and deleted entries, and submodule entries with ignore settings; compare shell and Go selection and results.
- AC2, AC3: per-path and per-entry budgets, same-line additions, line shifts, renames with and without new occurrences, rename away from and into a private name, copies, mode and regular-file/symlink changes, empty and binary files, gitlink names and unusual path bytes. Compare all finding locations and counts with the frozen shell.
- AC4: pin a base rule and allowance, then weaken each in the checkout and index independently; the original finding remains. An invalid working-tree skip file must not affect this mode. Include inherited patterns as well as literals to prove their distinct behavior.
- AC5: explicit amend parent, default HEAD, genuine unborn branch, invalid explicit base and a broken non-unborn HEAD; assert selected behavior and absence of a guessed fallback.
- AC6, AC7: inject index, blob, base-configuration and private-list failures, including output before failure; compare status and streams and assert no partial clean result or disclosed value, path or expression.
- AC8: compare index entries, refs and working-file bytes before and after success and failure.
- AC12: inspect the fixture temporary area for retained matched content after success and every failure class.
- AC9: exercise the real entry point with absent binary, absent capability, supported clean/finding/error results and output-then-error; assert preserved arguments and streams, single execution and zero fallback after supported failure. Probe errors refuse without consuming stdin.
- AC10: native platform matrix and unchanged N-2 consumer fixtures; shell parity where Bash exists. Record the same 100-changed-file staged fixture over 20 warm process runs for shell and Go, with build time excluded, and investigate regressions.
- AC11: run the published staged hook and task with explicit arguments, with no-argument
DEVTOOLS_LEAK_MODE=staged, and with an explicit range overriding task default selection; compare IDs, stages and task argument boundaries. Check the adoption text against these results. - Run the branch binary through
mise run test-leaksand affected commit-hook regressions, thenmise run check, fresh coverage and both coverage-floor tasks. Confirm replacement protection and registration coverage from build(agents): protect replacement Go enforcement paths #753. If skill sources change, regenerate, measure tokens and deploy in the documented order, then runmise run check-generated-skills. - 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
Confusing indexed bytes with checkout bytes can miss a staged literal; treating pattern scans like literal budgets can weaken the gate. Inherited values are intentionally tolerated only as the current comparison defines. Undo: revert this PR to restore the staged shell path and callers.
Operator authority
standing rule names the operator: activate replacement enforcement only after #753 and satisfy its exact-head owner-review requirements; this port grants no gate-loosening authority.
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Work type
Projects
- StatusShow more project fieldsBacklog
Activity
tbhb-agent commentedon Oct 26, 2026
Refinement: READY — staged leak comparison contract, non-goal boundaries, #753 prerequisite, and verification coverage are complete
Model: gemini-4-argon-high
Checked
originidentifiestbhb-dev/devtoolsandorigin/mainresolves toa0347a715fab580ece45edfcb3d13509620459a8. Read live issue#816(open, Feature, labelchange:feat, zero comments) and the issues it names (#588,#329,#501,#551,#753,#661,#333), plus#573and#277referenced by the parent/slice context.origin/main(a0347a715fab580ece45edfcb3d13509620459a8). Staged literal budget accounting lives at.devtools/scripts/check-leaks.sh:189(.devtools/scripts/check-leaks.sh:195-202), staged index-versus-base blob emission lives at.devtools/scripts/check-leaks.sh:306(.devtools/scripts/check-leaks.sh:310-338), and base-tree configuration loading for.leak-allowand.leak-patternslives at.devtools/scripts/check-leaks.sh:779(.devtools/scripts/check-leaks.sh:779-812)..devtools/scripts/check-leaks.sh:189-203,.devtools/scripts/check-leaks.sh:269-287, and.devtools/scripts/check-leaks.sh:306-338, including--ignore-submodules=none,--diff-filter=ACMRTU, rename/copy base content attribution to destination labels (.devtools/scripts/check-leaks.sh:324-329), symlink blob contents, binary NUL detection (.devtools/scripts/check-leaks.sh:260-273), and160000gitlink path checks (.devtools/scripts/check-leaks.sh:324,332)..devtools/scripts/check-leaks.sh:204-212,.devtools/scripts/check-leaks.sh:764(leak-skip.shloaded only whenmode == tree), and.devtools/scripts/check-leaks.sh:796-812(.leak-allowand.leak-patternsread from$base_treeblobs)..devtools/scripts/check-leaks.sh:784-795(DEVTOOLS_LEAK_BASE^{tree}when set, otherwiseHEAD^{tree}, or the empty tree only whenHEADis a symbolic ref whose target ref does not yet exist)..devtools/scripts/check-leaks.sh:75-92,.devtools/scripts/check-leaks.sh:146,152,171-180,215-221,242-245,.devtools/scripts/check-leaks.sh:314,.devtools/scripts/check-leaks.sh:801, and.devtools/scripts/check-leaks.sh:830-840,873-876.packages/agents/source/skills/rebase/shared/scripts/marker-scan.sh:6-12anddocs/compatibility.md:1-35), Linux/macOS/Windows support and N-2 consumer compatibility (AC10), task mode dispatch in.devtools/tasks/leaks.toml:6-13and theleaks-stagedhook in.pre-commit-hooks.yaml:126-133(AC11), and temporary file cleanup after completion or failure (AC12,.devtools/scripts/check-leaks.sh:81-93).#501/#551(#573) boundaries: All cited Bats line references in.devtools/scripts/check-leaks.bats:226,.devtools/scripts/check-leaks.bats:279,.devtools/scripts/check-leaks.bats:358,.devtools/scripts/check-leaks.bats:404,.devtools/scripts/check-leaks.bats:516,.devtools/scripts/check-leaks.bats:535,.devtools/scripts/check-leaks.bats:627, and.devtools/scripts/check-leaks.bats:1578-1744matchorigin/mainexactly.#501's new worktree/machine private-string lookup, precedence, source notices, and provisioning remain non-goals owned by#501.#551's (and open PR#573's)devtools:gitleaks--mode local/--mode cisplit, full-index gitleaks snapshot scan, strict origin base resolver, caller rewiring, and owner-approved local history coverage reduction remain non-goals owned by#551. Publication (--publish) and whole-object (--range,--pre-push,--pre-push-hook) modes stay out of scope.#277check:#753(open,refinement:ready) is properly listed as a blocker before replacement enforcement is activated, with merged protection evidence required at merge, satisfying#753AC3.#588(open) and#329(open) track the overall shell-to-Go migration and leak/pre-push port.#661(closed) supplies the N-2 compatibility policy (docs/compatibility.md:1-35), and#333(open,refinement:ready) is accurately classified as binary release distribution rather than a binary floor increase for this slice.tbhb-dev/devtools#277(referenced by#329for.devtools/scripts/install-pre-push.sh):#277isopenand not yet Ready (norefinement:readylabel; its Round 1 review returnedNOT READY). Because#277concerns shared-worktree pre-push wrapper installation in.devtools/scripts/install-pre-push.sh:1-119and#816is strictly the--stagedcomparison slice of.devtools/scripts/check-leaks.sh,#277does not block#816.AC1throughAC12) to concrete behavioral checks that prove the criterion, includes the warm 20-run 100-changed-file staged benchmark forAC10, names existing repository tasks (mise run test-leaksatmise.toml:584,mise run checkatmise.toml:792,mise run cover-go-checkatmise.toml:685,mise run cover-py-checkatmise.toml:707, and conditional skill generation culminating inmise run check-generated-skillsatmise.toml:462-480), verifies#753protection and dispatcher registration coverage (internal/agentrepo/command.go:85), and states D1–D10 completion obligations.#753and must satisfy#753's exact-head owner-review requirements (covering.agents/agent-skills.conf:4,8,9,internal/agentrepo/command.go:85, andpackages/agents/source/skills/merge-pr/shared/scripts/merge-policy.py:528-534,576-590), while granting no gate-loosening authority.Gaps
None.
Split
Size
Mas a single pull request for the--stagedcomparison slice and its thin-wrapper/caller compatibility is well-bounded. Publication (--publish), whole-object/range/pre-push modes, andinstall-pre-push.shremain separate slices under#329and#588. No further split is needed.Definition of done
The definition of done for #816 (Feature). Tick each item and give its evidence.
A ticked box means planning coverage in the issue's acceptance criteria and verification plan, not completed work.
Evidence:
## Verify planmapsAC1–AC12to concrete checks and explicitly requires underDefinition of donethatD1 each AC is verified at the merged head, with the commands and results cited in the pull request's Verification.Evidence:
## Verify planrequiresD2 an independent review approves the exact merged head, and every finding has a recorded disposition, paired withD9for filing deferred review findings as follow-up issues.Evidence:
## Verify planrequiresD3 required checks pass with no gate loosened, and## Operator authoritystatesthis port grants no gate-loosening authorityand requires satisfying#753's exact-head owner-review requirements.check-leaks.shwith the repository's private-strings list, and the leak review of each post.Evidence:
## Verify planrequiresD4 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, which exercisesdevtools:lint-leaksanddevtools:gitleaks(packages/agents/source/skills/pr/shared/scripts/create-pr.sh:189-208) with exported*_PRIVATE_STRINGS(.devtools/scripts/check-leaks.sh:114-127).Evidence:
## Verify planrequiresD5 every commit is signed.docs/, CHANGELOG or help text), or the Verification section says "No doc impact" and why.Evidence:
## Verify planrequires checking adoption text underAC11and statesD6 the documentation matches, or the description says No doc impact with the reason.provenance:agent-assistedlabel.Evidence:
## Verify planrequiresD7 every commit carries an Assisted-by trailer and the pull request carries the provenance:agent-assisted label.Evidence:
## Sizescopes the work toM. One pull request, and## Verify planrequiresD8 the change stays within the pull request size limits.Evidence:
## Scope and non-goalsnotesFallback retirement is a separate N-2 follow-up under D9, and## Verify planrequiresD9 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.Status:comment names the merge commit.Evidence:
## Verify planrequiresD10 the merge closes this issue through a closing reference, the project board shows the state Done, and a final Status: comment names the merge commit.Round: 1 of 3