Repository navigation
Description
Problem
Three commit hooks remain as shell in scripts/: vale-commit-msg.sh, cspell-commit-msg.sh and clear-commit-agentmsg.sh. .pre-commit-hooks.yaml publishes each as a hook ID with an entry: path, a language: script and a stage, and consumer repositories pull the manifest by rev:, so the script they run is the one at that tag. This repository's own .pre-commit-config.yaml, tests/devtools/lint-commit-msg.bats and the merge tests (tests/skills/merge-pr/test_helper.bash) also run the scripts by path, and the squash-merge flow sets DEVTOOLS_CSPELL_CONFIG for the cspell hook. Porting the three follows the closed precedents that moved the commit-message linters to Go (#246, #257) and removes shell from the commit path (feature 10 of #588). Consumers must see no change in behaviour, including the behaviour that looks like a defect.
The scripts carry behaviour that a port can lose silently. All of it is read from scripts/ on origin/main and was run against stand-in linters:
- The vale hook runs under
set -euo pipefailandLC_ALL=C. It cuts the buffer at the first scissors line, strips git comment lines withgit stripspace --strip-comments, pipes the result to vale with--path=<basename>and--ext=.md, and adds--output=ai-tells-agent.tmplonly when.vale.ininames aStylesPaththat holds that template. The template probe reads.vale.iniinside a command substitution, so with no.vale.iniat all the hook exits 2 before vale runs, and prints nothing. With a.vale.inithat has noStylesPath, the hook runs vale without the flag. - The vale pipeline's status is that of the rightmost stage that failed, so vale's own non-zero status wins. When vale succeeds, an unreadable or missing buffer still makes the hook exit 2 (vale runs on empty input), and a failing git stage makes it exit with git's status. With no argument it exits 1 before anything runs.
- The cspell hook reads its config from
DEVTOOLS_CSPELL_CONFIG(default.cspell.jsonc) and labels the stdin textstdin://<dir>/<basename>, where<dir>follows the config's directory. It reads the whole buffer first, so an unreadable or missing buffer, or no argument, fails before cspell runs. It does not pin the locale. - The clear hook runs under
LC_ALL=C, deletesCOMMIT_AGENTMSGat the worktree root that git reports, and does nothing, successfully, outside a repository.
Acceptance criteria
- AC1: Given a commit-message buffer with comment lines, a scissors block (any number of dashes, optional spacing, a
#or;lead) and runs of blank lines, when the vale hook runs against a recording stand-in for vale, then the stand-in receives on standard input whatgit stripspace --strip-commentsyields for the buffer cut at its first scissors line, is invoked with--path=<basename of the buffer>and--ext=.md, and runs withLC_ALL=Cin its environment whatever locale the caller has, for a relative and for an absolute buffer path and for the default and a non-defaultcore.commentChar. - AC2: Given the current directory holds a
.vale.iniwith aStylesPathkey and that path holdsconfig/templates/ai-tells-agent.tmpl, when the vale hook runs, then vale is also invoked with--output=ai-tells-agent.tmpl; given a.vale.iniwithout aStylesPathkey, or aStylesPathwithout that template, then the flag is absent and vale still runs. - AC3: Given the current directory holds no
.vale.ini, when the vale hook runs, then it exits 2, prints nothing on either stream, and does not run vale, exactly as the shell script does today. - AC4: Given the vale hook runs vale, when it finishes, then vale's standard output and standard error pass through unchanged, a non-zero status of vale is the hook's status, and when vale succeeds the hook still exits non-zero (2 for a missing or unreadable buffer, git's own status for a failing
git stripspace) instead of reading as a clean lint. - AC5: Given a commit-message buffer, when the cspell hook runs against a recording stand-in for cspell, then the stand-in is invoked with
--config <config> --no-summary --no-progress --language-id commit-msg stdin://<dir>/<basename of the buffer>, receives the buffer with its trailing newlines collapsed to one, and inherits the caller's locale unchanged;<config>is.cspell.jsoncand<dir>is.whenDEVTOOLS_CSPELL_CONFIGis unset or empty, and when it is set<config>is its value and<dir>is that value's directory. - AC6: Given the cspell hook runs cspell, when it finishes, then cspell's standard output, standard error and exit status are the hook's, and a configuration file that does not exist is left to cspell to report.
- AC7: Given a preparation failure, then neither linter runs where the shell does not run it, and the hook never exits 0: the vale hook with no argument exits 1; the cspell hook with no argument or with a missing or unreadable buffer exits 1; and with the linter missing from
PATHeither hook exits 127 with a message on standard error naming the linter. - AC8: Given the post-commit stage with no arguments, when the clear hook runs inside a worktree under any caller locale, then
COMMIT_AGENTMSGat the root that git reports is gone and every other file, including aCOMMIT_AGENTMSGin another worktree, is untouched; it exits 0 when the file is absent and exits 0, deleting nothing, outside a repository. - AC9: Each hook ID in
.pre-commit-hooks.yamlkeeps itsentry,language,stages,always_runandpass_filenamesvalues. - AC10: Given a hook script path run where
agentrepois absent fromPATH, or where the installedagentrepopredates the hook subcommands, when the hook runs, then it exits non-zero and writes a message on standard error namingagentrepoand the hook subcommands, so a commit is never silently let through unlinted. - AC11: Non-functional: a hook run with a stand-in linter takes under 100 ms at the median over 50 runs on the CI runner, and the pull request reports the same measurement for the shell scripts.
- AC12: The consumer-facing documentation (the adoption documentation and the manifest's header comment) states that the three hooks need
agentrepofrom the same release as the hookrev:onPATHin the hook environment, names the pin update that moves both together, and no longer says the clear hook needs only shell utilities.
Scope and non-goals
In scope: the three scripts named above, their Go replacement, the tests, this repository's own hook entries for the three hooks, and the documentation named in AC12.
Non-goal: changing any behaviour of the shell scripts, including the exit 2 of AC3 when .vale.ini is absent; if that behaviour is wrong, a separate issue changes it and this port moves with it.
Non-goal: the commitlint and commit-trailers hooks, which already run the Go commit-lint command.
Non-goal: pre-push installation and the other .devtools/scripts/ hooks, which are later parts of feature 10 of #588.
Non-goal: renaming a hook ID, entry path or stage, or switching an entry to language: golang; that changes the published manifest and needs its own decision.
Out of scope: the linters' own configuration, and producing or installing the Go binary, which #333 and #544 own.
Approach
Add one group of subcommands for the three behaviours to the existing agentrepo command tree, which is registered in internal/agentrepo/command.go. Call git stripspace and git rev-parse as subprocesses rather than reimplementing them, so core.commentChar and worktree handling stay git's. Keep the shell's exit-status rules: vale's status first, then the rightmost failing upstream stage, as in AC4.
Record the characterization corpus first, as #719 does: run the shell scripts over the corpus with recording stand-ins for vale, cspell and git, and commit the recorded arguments, environment, input, output and statuses at a pinned commit of main. The corpus covers every case of AC1 to AC8, including an unreadable buffer, a failing git stage with vale succeeding, a non-default comment character and a non-C caller locale. Then write the Go tests against that corpus, replace each script body with a forwarding shim of at most 10 lines at the same path, and delete the shell logic in the same PR. The shim finds agentrepo on PATH, with no go run or build fallback, so there is no second implementation, and it fails closed as AC10 requires.
Release and version path. The published scripts are the ones at the consumer's rev:, so a consumer receives the shims with the first tag cut after this lands, and that tag's agentrepo is the first with the subcommands. A consumer that moves rev: and its agentrepo pin together, which devtools:update-pins does (it rewrites the rev: and the go: agentrepo pin to one tag), is unaffected. A consumer that moves only rev: hits AC10's refusal until its agentrepo pin reaches that tag, so AC9 keeps the manifest stable but the consumer step is the pin update, which AC12 documents in docs/agent-skills-migration.md. #333 and #544 can complete first; they ship and install whatever agentrepo the tag holds, so the subcommands reach consumers through the next tag either way.
Local hooks. This repository's own .pre-commit-config.yaml runs the three hooks directly from the working tree, like commitlint and commit-trailers do with go run ./cmd/commit-lint. Switch the three local entries to go run ./cmd/agentrepo <subcommand> with language: system, so a commit here is gated by the branch implementation and not by the pinned release. The published manifest keeps the script paths. The Bats suites run the real shims against the branch build: the test-hooks task builds bin/agentrepo from this tree and prepends bin/ to PATH for its Bats process (mise.toml), which covers tests/devtools/lint-commit-msg.bats and tests/skills/merge-pr. Port the cases of tests/scripts/clear-commit-agentmsg.bats into Go tests and keep one Bats case per hook that runs the real shim against the build, plus one per shim with the command absent and one with a stand-in agentrepo that lacks the subcommands.
Dependencies
Native blocked-by: #333 (binary release assets), #544 (consumer installation of those assets), #713 (gates) and #723 (the check judge migration, which applies the contract that the Spike #720 settles; #720 is reached through #723 and is not a separate blocker here). The shims run in consumer hook environments, where the Go command exists only once it is published and installed. #588 AC3 migrates gates and the merge path first and hooks second, and #713 and #723 are the issues that exist for that earlier work; the same ordering and hold apply as for #719: the shims are not switched, and this does not merge, until features 5 to 8 of #588 have shipped, and their issues are added as native blockers when they exist. The other ports (#714, #716 to #719, #721, #722) have no ordering with this one; #719 adds its own hook subcommands, so whichever lands second adjusts only the command registration.
Size
S. One PR.
Verify plan
- AC1: Go table tests over the corpus (comment lines, scissors variants, blank runs, relative and absolute paths, default and non-default
core.commentChar, a non-C caller locale) comparing the stand-in vale's recorded argv, stdin andLC_ALLwith the expected values from the corpus. - AC2: Go tests with a temporary working directory for the three
.vale.inistates of the criterion, asserting the presence or absence of--outputin the stand-in's argv. - AC3: a Go test with no
.vale.ini, asserting status 2, empty streams and that the stand-in vale was not run, against the recorded shell result. - AC4: Go tests with a stand-in vale that exits 0, 1 and 2 and prints on both streams, an unreadable buffer and a missing buffer with vale exiting 0 and 1, and a stand-in git whose
stripspacefails with vale exiting 0 and 1, asserting status and streams against the corpus. - AC5: Go tests with a stand-in cspell, with
DEVTOOLS_CSPELL_CONFIGunset, empty and set to a path in another directory, and a non-C caller locale, asserting argv, stdin and environment. - AC6: the same stand-in with exit statuses 0 and 1, output on both streams and a missing config, asserting streams and status.
- AC7: Go tests with no argument, a missing buffer, an unreadable buffer and each linter absent from
PATH, asserting the status, the message and that no stand-in ran. - AC8: Go tests ported from
tests/scripts/clear-commit-agentmsg.bats, plus a real two-worktree repository case, a non-C caller locale and a case outside a repository. - AC9: a test that parses
.pre-commit-hooks.yamlbefore and after and compares the five fields of each of the three hook IDs. - AC10: a Bats case per shim with
agentrepoabsent fromPATH, and one with a stand-inagentrepothat rejects the subcommands, asserting a non-zero status and the message on standard error; a grep showing nosed,stripspace,rmorbasenamelogic remains in the three scripts, which are at most 10 lines. - AC11: a timing script that runs each shim 50 times with stand-in linters, reports the median for the Go-backed and the recorded shell baseline, and fails above 100 ms.
- AC12: the documentation diff, and a grep that the old "needs only shell utilities" sentence is gone.
- Cross-check: the differential test over the recorded corpus, run against the Go-backed shims, plus the existing preview case (
tests/devtools/lint-commit-msg.bats) and the pinned-head dictionary case (tests/skills/merge-pr/scripts/merge-workflow.bats) against the branch binary; the corpus is committed with the PR.
Risks
A consumer's commit hook breaking at its next rev: bump, which AC9, AC10 and AC12 guard against. A missing or older binary making every commit fail, which AC10 turns into one clear message instead of a silent pass. Dropping the shell's pipefail behaviour so a failed stage reads as a clean lint, which AC4 and AC7 pin. Preserving a questionable behaviour (AC3) on purpose, because this port changes none. The undo is reverting the PR, which restores the shell scripts at the same paths.
Operator authority
None
Metadata
Metadata
Assignees
Labels
Type
Fields
Priority
Work type
Projects
- StatusShow more project fieldsBacklog
Activity
[-]Port the rebase conflict-marker scan to Go[/-][+]Port the commit-message hook scripts to Go[/+]tbhb-agent commentedon Oct 25, 2026
Refinement: NOT READY — #715 has no issue body
Checked
Read #715, its native parent #588, its native blockers, and siblings #713–#720. Both issue readers confirmed that #715’s body is empty. Its parent is correct; its blocked-by list is empty.
Read the published hook manifest, remaining commit-message scripts, preview adapter, shared shell library, Go commit-message and hook infrastructure, and relevant existing tests. No mechanical checks were run.
Gaps
In Definition of Ready order:
.pre-commit-hooks.yaml:63,.pre-commit-hooks.yaml:85).AC<n>:criteria, each with one observable outcome. Cover linter behavior, cleanup, public compatibility, failure handling, and applicable non-functional requirements.scripts/vale-commit-msg.sh:47,scripts/vale-commit-msg.sh:78); cspell’s worktree and explicit-config isolation (scripts/cspell-commit-msg.sh:35); and worktree-local draft deletion (scripts/clear-commit-agentmsg.sh:26). The existing Go parser is not equivalent to Git’s configurable comment cleanup (internal/commitlint/message.go:43).agenthookscurrently registers only a version command (cmd/agenthooks/main.go:32).tests/scripts/clear-commit-agentmsg.bats:32); existing merge tests exercise pinned-head dictionaries (tests/skills/merge-pr/scripts/merge-workflow.bats:286).Noneor an applicable reserved-phrase authority line.Split
No split is justified yet. A bounded migration of the three remaining public hook scripts plausibly fits one PR.
Explicitly exclude preview orchestration (
.devtools/scripts/lint-commit-msg.sh:65), shared review state (packages/agents/source/lib/lib.sh:482) and gate execution (packages/agents/source/lib/agent.sh:104) unless reassigned here.The proposed title fits #588. Sibling titles cover distinct workstreams, but #713–#719 also have empty bodies, preventing complete overlap assessment.
Definition of done
None can be ticked: #715 contains neither AC nor a Verify plan.
provenance:agent-assisted.mise run checkand both coverage-floor commands.Round: 1 of 3
tbhb-agent commentedon Oct 25, 2026
Refinement: NOT READY — compatibility evidence and binary rollout dependency remain incomplete
Checked
.pre-commit-hooks.yaml:90). Port commitlint and commit-trailers to one Go commit-message linter #246 and feat(lint): replace shell commit-message linters with Go #257 are closed precedents. The epic reference is inaccurate: public commit hooks are feature 10, not feature 9 of Replace complex shell with tested Go, starting with gates and merging #588.AC<n>:prefixes, within the limit. AC7 supplies a performance criterion. AC1–AC3 leave important compatibility behavior implicit; AC5 prescribes implementation, and AC6 specifies a test command rather than a product outcome.Nonemeets the required form.Gaps
Specify and verify the actual compatibility contract.
scripts/vale-commit-msg.sh:31,scripts/vale-commit-msg.sh:47,scripts/vale-commit-msg.sh:78). A stub checking only status/output does not prove these behaviors. Add assertions for subprocess arguments, stdin and configuration branches.pipefail, the hook can fail despite Vale succeeding (scripts/vale-commit-msg.sh:22,scripts/vale-commit-msg.sh:78). Missing.vale.inialso fails during template discovery before Vale runs (scripts/vale-commit-msg.sh:48). State whether these outcomes are preserved.DEVTOOLS_CSPELL_CONFIG, changes its virtual path with that override, and normalizes trailing newlines (scripts/cspell-commit-msg.sh:35). The override isolates squash linting from checkout configuration (packages/agents/source/skills/merge-pr/shared/scripts/merge-agent.sh:32). Add explicit compatibility evidence for these branches.tests/scripts/clear-commit-agentmsg.bats:32).Align acceptance and verification with Replace complex shell with tested Go, starting with gates and merging #588. Move implementation prescriptions and test commands into Approach/Verify, retaining observable outcomes as AC. Add Go behavioral tests alongside shim integration tests: Replace complex shell with tested Go, starting with gates and merging #588 explicitly requires Go tests, while this issue currently proposes new Bats cases only. Specify how integration tests receive the branch-built replacement binary;
test-hookscurrently builds onlyagentrepo(mise.toml:605). Define AC7’s timing baseline and measurement so it proves the stated overhead.Resolve the rollout contradiction. “None blocking” conflicts with switching only once Ship the Go binaries as release assets installed through mise's github backend #333 supplies binaries. Record the prerequisite as a native blocker, or define a separately enforceable deployment hold. Choose the command and lookup contract before coding.
agenthookscurrently exposes only version functionality (cmd/agenthooks/main.go:23);commit-lintis a separate executable (cmd/commit-lint/main.go:13). A shell fallback duplicating migrated behavior conflicts with Replace complex shell with tested Go, starting with gates and merging #588. Add missing-binary verification and consumer adoption/documentation evidence; Ship the Go binaries as release assets installed through mise's github backend #333 explicitly excludes consumer adoption work.Split
No split required. Keep the three related hooks together; binary distribution remains in #333.
Definition of done
All items below remain pending or uncovered by the current AC and Verify plan; none is established by this refinement review.
test-hooks, withoutcheckor either coverage-floor command.Round: 1 of 3
tbhb-agent commentedon Oct 25, 2026
Refinement: NOT READY — compatibility criteria still contradict the shell baseline
Checked
Read #715 and both round 1 verdicts, parent #588, native blockers #333 and #544, and siblings #713–#722. Read code only through
origin/mainat56543d2914814d0f7e47feb11b4679155a185ab1. No checks, edits, delegation or posts were performed.In Definition of Ready order:
agentrepoonPATH, subprocess Git operations, characterization fixtures and Go behavioral tests are specified. The branch-build integration claim is accurate (mise.toml:588).Nonemeets the required form.Round 1’s Go behavioral tests, branch-built integration binary, timing baseline, command lookup choice and missing-binary checks are now specified. Consumer documentation is also planned.
Gaps
Acceptance criteria: AC2 and AC9 require incompatible behavior.
Without
.vale.ini, the existing template-discovery pipeline fails underset -euo pipefail, before Vale runs (scripts/vale-commit-msg.sh:22,scripts/vale-commit-msg.sh:48). AC2 instead requires Vale to run, while AC9 requires identical recorded invocation, streams and status. Preserve the existing outcome, or explicitly declare this behavior change and exempt it from strict equivalence. The misleading shell comment does not establish the runtime contract.Acceptance criteria: qualify linter-status and stream preservation.
AC3 requires the linter’s status for “any” input while also requiring failure when upstream processing fails. The current Vale pipeline can return nonzero even when Vale returns 0 (
scripts/vale-commit-msg.sh:78). AC5 similarly promises cspell’s streams/status when a missing buffer or argument prevents cspell from running (scripts/cspell-commit-msg.sh:35,scripts/cspell-commit-msg.sh:45). Define successful invocation separately from preparation/startup failures, and specify the latter’s observable results consistently with AC9.The locale contract from round 1 is still missing: Vale and cleanup explicitly export
LC_ALL=C(scripts/vale-commit-msg.sh:31,scripts/clear-commit-agentmsg.sh:24). Include its preservation and evidence.Acceptance criteria: remove remaining implementation and test prescriptions.
AC8 still mandates line count and forwarding implementation alongside missing-command behavior. AC9 includes fixture-recording and retention requirements. Keep these instructions in Approach/Verify and state observable compatibility outcomes in the AC. AC11 also bundles adoption guidance, manifest commentary and inventory updates; regroup the criteria so each has one observable outcome, retaining the twelve-item limit.
Approach and dependencies: establish availability of these subcommands before switching callers.
Ship the Go binaries as release assets installed through mise's github backend #333 can publish an existing
agentrepo, and feat(distribution): migrate consumer tool pins to release assets #544 can install it, before this feature’s subcommands exist. Current main registers checks, review and config commands (internal/agentrepo/command.go:85). Completing those blockers therefore does not demonstrate that a consumer’s installed version can run the new hooks.Specify the release/version transition and verify the documented consumer hook environment with a binary containing these subcommands. Reconcile AC7’s “only bumps
rev:” promise with any required binary update. Also explain how repository-local hooks receive the branch implementation:test-hooksprependsbin/only for its Bats process (mise.toml:594), while local hooks execute the scripts directly (.pre-commit-config.yaml:95).Finally, reconcile “No dependency on the other ports” with Replace complex shell with tested Go, starting with gates and merging #588 AC3’s gates-and-merge-before-hooks order. Record the applicable prerequisite or an explicit rollout hold.
Verify plan: close the remaining behavioral coverage gaps.
AC3 and AC5 explicitly require unreadable-buffer handling, but their checks list missing buffers only. Add unreadable-buffer cases and an upstream Git failure with Vale succeeding, proving the pipeline contract. Include non-default Git comment-character and non-C locale cases. Keep the existing preview and pinned-head dictionary integration cases against the branch binary (
tests/devtools/lint-commit-msg.bats:113,tests/skills/merge-pr/scripts/merge-workflow.bats:285).Split
No split is required for the three-hook migration. Its file ownership is distinct from #713–#722; shared command registration is an integration point, not duplicated scope. Binary production and general consumer installation correctly remain in #333 and #544. Resolve the feature-specific release transition and sequencing before implementation.
Definition of done
Checked items indicate coverage already present in the AC and Verify plan, not completed implementation evidence.
check-leaks.shscans and post leak reviews are absent.provenance:agent-assistedare unspecified.Status:comment are unspecified.mise run check,mise run cover-go-checkandmise run cover-py-checkare absent.Round: 2 of 3
tbhb-agent commentedon Oct 25, 2026
Refinement: NOT READY — two declared native prerequisites are missing
Checked
Read the current #715 body, both round 1 verdicts, the round 2 verdict, parent #588, native dependencies, and siblings #713–#722.
In Definition of Ready order:
.pre-commit-hooks.yaml:90)..vale.ini. The latter fails during discovery before Vale runs (scripts/vale-commit-msg.sh:48).scripts/vale-commit-msg.sh:78).scripts/cspell-commit-msg.sh:35,scripts/cspell-commit-msg.sh:45).LC_ALL=C; cspell inherits its environment (scripts/vale-commit-msg.sh:31,scripts/clear-commit-agentmsg.sh:24).scripts/clear-commit-agentmsg.sh:26)..devtools/tasks/pins.toml:142,.devtools/tasks/pins.toml:171). Localgo runentries follow the existing commit-lint pattern (.pre-commit-config.yaml:79). Bats receives the branch-built binary throughbin/(mise.toml:588).Noneis explicit.Gaps
No further behavioral-contract or AC-verification gaps were found.
Split
No split required. Keep the three-hook migration together; binary production and consumer installation remain with #333 and #544.
Definition of done
Ticks indicate coverage in the AC and Verify plan, not completed implementation evidence.
check-leaks.shwith private strings, and post leak reviews are absent.provenance:agent-assistedlabel.Status:comment.mise run check,mise run cover-go-checkandmise run cover-py-checkare absent.Round: 3 of 3
tbhb-agent commentedon Oct 25, 2026
Status: redesigned after the three-round cap. Round 3 found one gap: the Dependencies prose named #713 and #720 as blockers, but the native blocked-by list held only #333 and #544. The split of #720 into the contract Spike #720 and the caller migration Feature #723 changed what the check-judge dependency means, so the redesign re-derived the list. The hook shims need the earlier gates and check-judge work to ship first, so the blockers are #713 (gates, itself ordered after #723) and #723 (the judge migration); #720 is reached through #723 and is not a separate blocker. The body prose now names #713 and #723, and the native links match: #333, #544, #713 and #723. No criterion, scope or size changed (AC1 to AC12 are stable). Refinement restarts at Round 1 of 3.
tbhb-agent commentedon Oct 25, 2026
Refinement: READY — redesigned dependencies agree and the hook port is implementable
Checked
scripts/vale-commit-msg.sh:22,scripts/vale-commit-msg.sh:31,scripts/vale-commit-msg.sh:48,scripts/vale-commit-msg.sh:78).scripts/cspell-commit-msg.sh:33,scripts/cspell-commit-msg.sh:45,scripts/cspell-commit-msg.sh:47).scripts/clear-commit-agentmsg.sh:24,scripts/clear-commit-agentmsg.sh:26)..devtools/tasks/pins.toml:142,.devtools/tasks/pins.toml:171). Local branch execution follows the existing Go-hook pattern (.pre-commit-config.yaml:79), andtest-hooksalready builds and exposes the branch binary (mise.toml:588).Gaps
None that require an implementer to guess or prevent the planned checks from proving their ACs.
Split
No further split required. #720 settles the contract; #723 implements the judge migration; #713 follows it; #715 retains the hook rollout hold.
Definition of done
Checked items indicate coverage in the issue’s plan, not completed implementation evidence.
checkand both coverage-floor commands are not explicitly included in Port the commit-message hook scripts to Go #715’s Verify plan.docs/agent-skills-migration.md.Round: 1 of 3
tbhb-agent commentedon Oct 26, 2026
Refinement amendment for the shell-to-Go epic (#588), covering compatibility and protection. The acceptance criteria stay as written, except where noted.
scripts/are consumer-visible byrev:. The shim and the Go command ship together, so a consumer that moves the hookrev:movesagentrepowith it. A consumer on an olderrev:keeps the script it already has. The step that replaces each script body with a forwarding shim applies only to the new release, and the older release's behaviour (including exit 2 with no.vale.ini) is untouched.