Skip to content

Replace the Claude guard-hook scripts with standalone guard binaries #328

Description

@tbhb-agent

Problem

The Claude Code guard hooks that keep pull request, merge, watch and fix workflows behind their single entry points are Bash scripts, one per skill, each re-implementing the same command-position regex and jq payload read. The project direction in #588 freezes complex shell and moves its behavior into tested Go, and guard-markdown already shows the target shape: the rule in an internal/ package, payload decoding from internal/hookio, and a thin cmd/ binary.

The guard scripts total roughly 1,300 shell lines across 11 files plus the 242-line tools/test-guards.sh. That does not fit one pull request within the size limit, so this issue is the first slice: the four gh-family guards (pr, merge-pr, watch-pr, fix-pr, about 300 shell lines), which also back agent-pr and agent-merge-pr. These four share one gh pr read-only allowlist, and the pr and merge-pr guards must keep agreeing wherever both are live, which is the strongest reason to port them together. The remaining guards are proposed as follow-up sub-issues (see Scope and non-goals).

Acceptance criteria

  1. AC1: Given a Bash tool call whose first command-position gh pr <verb> has the verb list, view, diff, status or checks, when the pr or merge-pr guard judges it, then the call is allowed with no output and exit status 0.
  2. AC2: Given a Bash tool call whose first command-position gh pr <verb> has any other verb (for example create, edit, ready, merge, close, comment, or a verb that does not exist today), when the pr guard judges it, then the call is denied with status 2 and the reason names the pull request publishing entry point. A later gh pr mention is not judged once the first one is a read verb, as today.
  3. AC3: Given the same command list, when the merge-pr guard judges it, then every command receives the same allow or deny verdict as under the pr guard, and a denial names the squash merge entry point (squash-merge.sh) instead of the publishing one.
  4. AC4: Given a command line, when any of the four guards judges it, then a gh, git push or gh run invocation counts as a call only at a command position: at the start of the text, or after optional whitespace following ;, &, |, ( or a newline. Quoting and heredocs are not interpreted, as today. So gh pr merge that follows other words on a line (for example echo "gh pr merge 1") is not a call and is allowed, while the same text at the start of a line inside a quoted string or a heredoc body, or after one of those separators inside a quote, is treated as a call and receives the verdict a real call would. Flag checks (--watch, --fail-fast, --job, --force, -f, --force-with-lease, --log, --log-failed) look at the whole command text, including quoted and heredoc text.
  5. AC5: Given gh pr checks with --watch or --fail-fast, or gh run watch, when the watch-pr guard judges it, then the call is denied with a reason pointing at the skill's watcher; and given plain gh pr checks, then it is allowed. The fix-pr guard denies the gh pr checks --watch and --fail-fast forms the same way.
  6. AC6: Given gh run view with --log or --log-failed and no --job, when the fix-pr guard judges it, then the call is denied with a reason pointing at the skill's diagnosis; and given the same command with --job, then it is allowed.
  7. AC7: Given git push with --force or -f and no --force-with-lease, when the fix-pr guard judges it, then the call is denied with a reason recommending the lease form; and given --force-with-lease, then it is allowed.
  8. AC8: Given a payload with no command (an absent or empty tool_input.command), when any of the four guards judges it, then the call is allowed with no output and status 0. Given an undecodable payload, the binary exits 0 with no output (the exception in Behavior preservation). Given a payload whose tool_name is not Bash but whose tool_input.command matches a denial case, the guard denies it exactly as for Bash, as the shells do.
  9. AC9: Given any denial, when the guard answers, then it writes Blocked by the <skill> skill guard., a blank line and a non-empty reason to standard error, writes nothing to standard output, and exits 2, byte for byte as the shell guards do.
  10. AC10: Non-functional: each verdict is a pure function of the payload text, and the same input gives the same verdict every time. A Go test parses the non-test source files of the rule package with go/parser and fails when any file imports a package outside an explicit allowlist (fmt, regexp, strings and the package's own siblings). os, os/exec, net, net/http, io/ioutil and syscall are therefore absent from the rule path. Payload decoding and output stay in cmd/ and internal/hookio, outside that package.
  11. AC11: Given the repository test matrix (Linux, Linux arm, macOS, Windows), when the Go tests run, then every allow and deny case above passes on all four platforms.

Scope and non-goals

In scope: the guards behind guard-gh.sh (pr), guard-merge.sh (merge-pr), guard-watch.sh (watch-pr) and guard-fix.sh (fix-pr), as a new standalone guard binary following guard-markdown, with their rule in a new internal/ package, hook payload support for the Bash command added to internal/hookio, and Go table tests that port the cases the shell scripts encode, including the shared gh pr allowlist.

Non-goal: editing, deleting or rewiring any frozen shell file. The existing guard-*.sh scripts stay untouched and stay what skill frontmatter calls until the follow-up that flips the references.

Non-goal: switching skill frontmatter to the binary, regenerating skill output, and the consumer distribution work (tool pins, release). Per #588 the binaries must be available before any deployment requires them, so the flip belongs after a release carries the binary.

Out of scope: new shell of any kind, and any change to what the guards allow or deny, including the first-match behavior and the missing tool_name check described above. Tightening either belongs in a separate issue with its own decision.

Behavior preservation: This is a behavior-preserving port. The frozen scripts under packages/agents/source/skills/*/claude/scripts/ (guard-gh.sh, guard-merge.sh, guard-watch.sh, guard-fix.sh) define the expected verdict for every input, and every acceptance criterion below states what they do today, including the cases that look like gaps:

  • Each guard reads .tool_input.command and never checks tool_name, so any payload carrying a matching command is judged, whatever the tool.
  • The pr and merge-pr guards find the first command-position gh pr <verb> and judge only that verb. gh pr view 1; gh pr merge 1 is allowed today and stays allowed. The port pins this with a test rather than changing it.
  • A denial writes Blocked by the <skill> skill guard. and the reason to standard error and exits 2. The Go binary uses the same protocol, so the later frontmatter flip changes only the command name.

One deliberate exception, and it neither loosens nor tightens a verdict: an empty, truncated or otherwise undecodable payload makes the shells fail on the unprotected jq call under set -e, which Claude Code treats as a non-blocking error, so the call runs. The Go binary exits 0 with no output for the same input, following the guard-markdown convention. The call runs in both cases.

Proposed follow-up sub-issues of #588 for the rest of the original list (sizes are estimates):

  1. Commit guard (guard-git.sh, 186 lines, also backing agent-commit): whole-tree staging and hand-written git commit refusals tied to the recorded HEAD. Size S.
  2. Rebase and resolve-rebase-conflicts guards (guard-rebase.sh 194, guard-resolve.sh 161). Size M.
  3. fix-prose guards (guard-target.sh 130, arm-guard.sh 74, release-once.sh 73), with the tools/test-guards.sh cases moved into Go tests and that script deleted or reduced to a thin wrapper. Size M.
  4. Release guard (guard-release.sh, 190 lines). It is not in the original list, but it is also a guard script, so it belongs with the set. Size S.
  5. Distribution and rollout: ship the guard binaries through the same path as agentrepo and guard-markdown, flip every skill's frontmatter to the binary by name, regenerate skill output, and remove the replaced guard scripts. Size M.

Approach

Add one guard binary that takes the target skill as a command-line argument and reads the hook payload from standard input, so agenthooks remains a dispatcher as AGENTS.md describes. Put the shared gh pr allowlist, the command-position matching and each skill's deny text in one internal/ package, with the binary as glue only because test coverage excludes main.go. Extend hookio so a decoded payload exposes the Bash command, and add a stderr-and-exit-2 block helper beside the existing hookio.Deny, which guard-markdown keeps using unchanged. Port the shell scripts' cases into table tests first, then write the rule until they pass. Reuse the existing internal/hookio decoding and fail-open convention from cmd/guard-markdown.

Dependencies

Native blockers: none. #753 (open) gates rollout of the replacement guard binaries (protection of the Go enforcement paths, per #588), not building or merging this PR, so it stays a prose prerequisite and not a native blocked-by link.

Prose prerequisites (each gates rollout only and does not block building or merging this PR):

Size

S. One pull request: an estimated 250 lines of Go code plus 350 lines of tests, under the 800 code line limit, and a handful of prose lines. The full guard set does not fit one pull request, which is why the remainder is split into the five proposed sub-issues above.

Verify plan

  • AC1: table test of the read-only verbs under the pr and merge-pr guards, run by mise run test-go; each case asserts an allow verdict, empty standard output, empty standard error and exit status 0.
  • AC2: table test of mutating and unknown verbs under the pr guard, asserting status 2 and the publishing entry point in the reason, plus a case pinning gh pr view 1; gh pr merge 1 as allowed.
  • AC3: parity test running one shared command list through both guards and asserting identical verdicts, plus an assertion that every merge-pr denial contains squash-merge.sh and no pr denial does.
  • AC4: table test whose expected verdicts are taken from running the frozen shell guards on the same inputs: a mid-line quoted mention (allowed), a heredoc body line starting with gh pr merge (denied), a quoted mention after ; (denied), separator-prefixed commands and newline-separated ones, and flags appearing only in quoted text.
  • AC5: table test of the watch-pr guard and of the watching forms under the fix-pr guard.
  • AC6: table test of gh run view with and without --job.
  • AC7: table test of git push with --force, -f and --force-with-lease.
  • AC8: table test of command-less, empty, truncated and non-Bash payloads for every guard, asserting the allow or deny verdicts above, empty output for allows and exit status 0 for undecodable input.
  • AC9: test asserting, for every denial case, the exact standard error bytes from the shell guard on the same input, empty standard output and exit status 2.
  • AC10: the import-allowlist test described in the criterion, plus a repeat-run determinism check over the AC1 to AC7 inputs.
  • AC11: the test (ubuntu-24.04), test (ubuntu-24.04-arm), test (macos-15) and test (windows-2025) CI jobs.

Risks

  • The Go matching could differ from the shell regex on an edge case, either letting a mutating gh pr verb through or blocking a legitimate read. The undo is a revert, since nothing calls the binary until the later rollout. The shell scripts' own decisions, run on the same inputs, supply the expected values, so drift shows before rollout. tools/test-guards.sh covers the fix-prose guards in a later slice and does not validate these four.
  • Extending hookio.Payload could change decoding for guard-markdown. The existing hookio and guard-markdown tests must pass unchanged, and the change is additive.
  • Adding the binary before distribution exists leaves it unused for a while. That is intended, per Replace complex shell with tested Go, starting with gates and merging #588, and the undo is leaving it unwired.

Operator authority

None

Activity

  1. added
    change:featPR adds or changes a feature (Conventional Commit type feat)
    on Oct 20, 2026
  2. removed
    change:featPR adds or changes a feature (Conventional Commit type feat)
    on Oct 22, 2026
  3. tbhb-agent commented on Oct 31, 2026

    @tbhb-agent
    ContributorAuthor

    Refinement: NOT READY — link the golden protection blocker natively

    Checked

    Gaps

    1. Blocker — Dependencies: build(agents): protect replacement Go enforcement paths #753 is described as a “Native blocker,” but is recorded only in prose; the issue has no blocked-by link. Record build(agents): protect replacement Go enforcement paths #753 as a native blocked-by dependency. The other prose prerequisites are not blockers as stated.
    2. Minor — Verify plan: AC1 requires allowed calls to produce no output, and AC8 requires no output and no failure status. Their listed checks do not explicitly assert those outputs/statuses. Add those assertions to the corresponding table-test checks.

    Split

    The four gh-family guards form a coherent slice: they share the allowlist and include the watch/fix rules. The stated estimate fits one PR. No further split is indicated.

    Definition of done

    Planning coverage only; these boxes indicate whether the acceptance criteria and Verify plan cover each item, not whether implementation work is complete.

    • D1 — Observable outcomes are specified. Evidence: AC1–AC9 define allow/deny behavior and payload handling.
    • D2 — Behavior-preserving scope is bounded. Evidence: scope and non-goals limit this to four guards and preserve current behavior.
    • D3 — Verification proves every stated outcome. Evidence: Verify plan maps AC1–AC11, but omits explicit output/status assertions for AC1 and AC8.
    • D4 — Relevant non-functional requirement is specified. Evidence: AC10 defines purity, no external effects, and determinism.
    • D5 — Verification environments are identified. Evidence: AC11 names the four existing CI matrix platforms.
    • D6 — Size and PR scope are stated. Evidence: Size estimates under the stated 800-line limit and the scope excludes the remaining guard set.
    • D7 — Approach follows the Go-port direction. Evidence: Approach uses internal/, hookio, a thin binary, and Go table tests, consistent with Replace complex shell with tested Go, starting with gates and merging #588.
    • D8 — Dependencies are accurately recorded. Evidence: build(agents): protect replacement Go enforcement paths #753 is open but lacks a native blocked-by link.
    • D9 — Risks include an undo. Evidence: Risks provide revert, leaving the binary unwired, or unchanged-test coverage as mitigations.
    • D10 — Operator authority and over-engineering are addressed. Evidence: named scope requires no owner-tier path, and no guard/config layer beyond the stated behavior is proposed.

    Round: 1 of 3

  4. tbhb-agent commented on Oct 31, 2026

    @tbhb-agent
    ContributorAuthor

    Refinement: NOT READY — align AC4 with the existing guard behavior

    Checked

    Gaps

    1. Blocker — Acceptance criteria: AC4 requires quoted and heredoc mentions to be ignored, but the existing guards use regular expressions that do not parse shell syntax. This conflicts with the stated behavior-preserving port. Align AC4 with the behavior on origin/main, or establish that changing this behavior is intended.
    2. Minor — Verify plan: AC1 says allowed calls produce no output, but its check does not explicitly assert empty output. Add that assertion.

    Split

    The four guards form a coherent slice: the gh pr rules share an allowlist, and watch/fix rules are included. The stated estimate fits one PR. No further split is indicated.

    Definition of done

    Planning coverage only: boxes indicate whether the acceptance criteria and Verify plan cover each item, not whether implementation work is complete.

    Round: 2 of 3

  5. tbhb-agent commented on Oct 31, 2026

    @tbhb-agent
    ContributorAuthor

    Refinement: NOT READY — resolve behavior preservation and verification gaps

    Checked

    • Verified origin identifies tbhb-dev/devtools. Read the live body, labels and both comments once. The issue is open with refinement:active; two earlier NOT READY comments make this round 3.
    • AC1: Confirmed the five allowed verbs and silent success in packages/agents/source/skills/pr/claude/scripts/guard-gh.sh:54 and packages/agents/source/skills/merge-pr/claude/scripts/guard-merge.sh:49.
    • AC2: Confirmed unknown and mutating verb denial with the publishing entry point, but only for the first matching invocation; see gap 1.
    • AC3: Confirmed matching allowlists and distinct publishing/merge reasons in packages/agents/source/skills/pr/claude/scripts/guard-gh.sh:62 and packages/agents/source/skills/merge-pr/claude/scripts/guard-merge.sh:55. Its verification omits the distinct reason.
    • AC4: Confirmed the revised separator, newline, quote/heredoc and whole-text flag behavior against all four scripts: packages/agents/source/skills/pr/claude/scripts/guard-gh.sh:52, packages/agents/source/skills/merge-pr/claude/scripts/guard-merge.sh:47, packages/agents/source/skills/watch-pr/claude/scripts/guard-watch.sh:40, and packages/agents/source/skills/fix-pr/claude/scripts/guard-fix.sh:40. The previous quoting blocker is resolved.
    • AC5: Confirmed watch refusals and plain-check allowance in packages/agents/source/skills/watch-pr/claude/scripts/guard-watch.sh:42 and packages/agents/source/skills/fix-pr/claude/scripts/guard-fix.sh:73.
    • AC6: Confirmed log checks and the whole-text --job exception in packages/agents/source/skills/fix-pr/claude/scripts/guard-fix.sh:42.
    • AC7: Confirmed force-push checks and lease exception in packages/agents/source/skills/fix-pr/claude/scripts/guard-fix.sh:61.
    • AC8: Command-less allowance is confirmed. Malformed-payload success and non-Bash filtering are not current shell behavior; see gap 2.
    • AC9: Structured stdout denial is supported by internal/hookio/hookio.go:109, but differs from all four shell guards’ stderr/exit-2 protocol.
    • AC10: Purity is a proposed Go outcome, not existing shell behavior: the scripts invoke cat and jq. Its stated lint verification does not enforce the claimed restriction.
    • AC11: Confirmed all four platforms in .github/workflows/ci.yml:175; this is planned coverage, not executed validation.
    • Replace complex shell with tested Go, starting with gates and merging #588, Move reusable agent tooling into released Go binaries #174 and build(agents): protect replacement Go enforcement paths #753 remain open; Ship the agent-commit, agent-pr and agent-merge-pr skills in v0.13 #241 is closed. build(agents): protect replacement Go enforcement paths #753 is explicitly a rollout prerequisite, so its absence from native blocked-by links does not block this PR. Any prerequisite intended to block implementation should instead have a native blocked-by link.
    • The approach follows Replace complex shell with tested Go, starting with gates and merging #588, adds no shell logic, and introduces no unnecessary configuration layer. No implementation path named in scope is owner-tier under the supplied definition. The existing CI workflow is cited for verification, not modification. “Operator authority: None” is accurate.
    • Risks include reverting or leaving the binary unwired.

    Gaps

    1. Blocker — AC2 and behavior preservation conflict for compound commands. Both PR guards inspect only the first matching gh pr verb and immediately allow a read verb. Consequently, gh pr view 1; gh pr merge 1 is allowed today, although AC2 requires denial of the later command-position mutation. Preserve and test first-match behavior, or explicitly authorize this behavior change.

    2. Blocker — AC8 conflicts with the unconditional behavior-preserving scope. Every shell guard runs an unprotected jq assignment under set -e, so malformed JSON fails rather than silently succeeding. None checks tool_name, so a non-Bash payload containing a matching command can be denied. Explicitly identify the intended fail-open/tool-filtering changes as exceptions to preservation. AC9’s structured deny protocol should likewise be identified as an intentional protocol change.

    3. Blocker — AC10’s checks do not prove its restrictions. Empty PATH, an unchanged scratch directory and repeatability cannot establish absence of repository reads or network access. Existing import rules prohibit neither process nor network imports (.golangci.yml:138), and architecture rules enforce only broad layering (.go-arch-lint.yml:34). Specify an actual source/import inspection covering the guard’s execution path; no new configurable enforcement layer is needed.

    4. Minor — AC3’s check proves verdict parity but not its distinct denial reason. Add an assertion that merge-guard denials name the squash merge entry point.

    5. Minor — Risk coverage names the wrong existing suite. tools/test-guards.sh:2 identifies it as fix-prose coverage, outside this slice. Remove the claim that porting its cases validates these four guards.

    Split

    The four guards remain a coherent single-PR slice. The estimated 600 code/test lines fit the stated limit. No further split is needed.

    Definition of done

    Planning coverage only; checked boxes indicate coverage in the ACs and Verify plan, not completed implementation.

    • D1 — Observable outcomes are specified. Evidence: AC1–AC9 describe caller-visible decisions and payload handling.
    • D2 — Behavior-preserving scope is bounded. Evidence: compound-command and payload behavior conflict with the preservation claim.
    • D3 — Verification proves every stated outcome. Evidence: AC3 omits reason verification; AC10 cites insufficient checks.
    • D4 — Relevant non-functional requirements are specified. Evidence: AC10 defines purity and determinism.
    • D5 — Verification environments are identified. Evidence: AC11 maps to the four existing CI platforms.
    • D6 — Size and PR scope are stated. Evidence: the estimate covers four guards and excludes rollout.
    • D7 — Approach follows the Go-port direction. Evidence: internal rules, hookio reuse, a thin binary and Go tests add no shell logic.
    • D8 — Dependencies are accurately recorded. Evidence: live states match the body; build(agents): protect replacement Go enforcement paths #753 gates later rollout.
    • D9 — Risks include an undo. Evidence: revert or leave the replacement binary unwired.
    • D10 — Operator authority and over-engineering are addressed. Evidence: scoped implementation names no owner-tier changes or unnecessary configuration layer.

    Round: 3 of 3

  6. tbhb-agent commented on Oct 31, 2026

    @tbhb-agent
    ContributorAuthor

    Refinement: READY — the redesigned slice preserves the four guards’ behavior

    Checked

    • Verified origin identifies tbhb-dev/devtools. Read the live body, labels and all three comments once. The issue is open with refinement:active. This is round 1 of the explicitly authorized restart after three earlier NOT READY rounds.
    • Compared the AC inputs by tracing the four frozen guards on origin/main; no scripts, builds or tests were executed.
    • AC1 — confirmed on code: both PR guards silently allow the five listed read verbs: packages/agents/source/skills/pr/claude/scripts/guard-gh.sh:63 and packages/agents/source/skills/merge-pr/claude/scripts/guard-merge.sh:56.
    • AC2 — confirmed on code: the PR guard judges only the first matching verb, denies other verbs and names create-pr.sh. Thus gh pr view 1; gh pr merge 1 remains allowed: packages/agents/source/skills/pr/claude/scripts/guard-gh.sh:54.
    • AC3 — confirmed on code: the merge guard has the same matching and allowlist, with its denial directing callers to squash-merge.sh: packages/agents/source/skills/merge-pr/claude/scripts/guard-merge.sh:49.
    • AC4 — confirmed against all four guards: their command-position expressions match the stated separators and newlines without interpreting quoting or heredocs. Flag expressions inspect the whole command text. The described inputs therefore receive the same verdict as their equivalent command-position matches: packages/agents/source/skills/pr/claude/scripts/guard-gh.sh:52, packages/agents/source/skills/merge-pr/claude/scripts/guard-merge.sh:47, packages/agents/source/skills/watch-pr/claude/scripts/guard-watch.sh:40, and packages/agents/source/skills/fix-pr/claude/scripts/guard-fix.sh:40.
    • AC5 — confirmed on code: watch-pr refuses watching checks and runs; fix-pr refuses the specified watching-check forms. Plain checks pass: packages/agents/source/skills/watch-pr/claude/scripts/guard-watch.sh:42 and packages/agents/source/skills/fix-pr/claude/scripts/guard-fix.sh:73.
    • AC6 — confirmed on code: fix-pr refuses the specified log sweep unless the whole command contains --job: packages/agents/source/skills/fix-pr/claude/scripts/guard-fix.sh:42.
    • AC7 — confirmed on code: fix-pr refuses the specified force forms unless the whole command contains --force-with-lease: packages/agents/source/skills/fix-pr/claude/scripts/guard-fix.sh:61.
    • AC8 — confirmed with its explicit exception: all four shells read the command without checking tool_name; absent or empty commands pass. Undecodable-input success is correctly identified as a deliberate Go protocol exception, consistent with cmd/guard-markdown/run.go:104.
    • AC9 — confirmed on code: all four denial helpers write the stated header, blank line and reason to stderr, then exit 2 without stdout: packages/agents/source/skills/pr/claude/scripts/guard-gh.sh:45, packages/agents/source/skills/merge-pr/claude/scripts/guard-merge.sh:42, packages/agents/source/skills/watch-pr/claude/scripts/guard-watch.sh:34, and packages/agents/source/skills/fix-pr/claude/scripts/guard-fix.sh:36.
    • AC10 — proposed Go requirement: this is not existing shell behavior. Its import inspection and repeat-run checks explicitly cover the intended rule-package restriction and determinism.
    • AC11 — confirmed infrastructure: the four platforms exist in .github/workflows/ci.yml:177. Passing the future cases remains planned validation.
    • Every AC ID has a corresponding Verify check. Output/status assertions, distinct denial reasons and shell-byte parity are now covered.
    • Replace complex shell with tested Go, starting with gates and merging #588, Move reusable agent tooling into released Go binaries #174 and build(agents): protect replacement Go enforcement paths #753 are open; Ship the agent-commit, agent-pr and agent-merge-pr skills in v0.13 #241 is closed. The stated rollout-only prerequisites need no native blocked-by links under the owner’s ruling. No build or merge blocker is claimed.
    • The approach follows Replace complex shell with tested Go, starting with gates and merging #588, adds no shell logic and leaves frozen callers untouched. No unnecessary configuration knob or layer is proposed.
    • No proposed implementation edit names an owner-tier path. The existing CI workflow is owner-tier but serves only as verification infrastructure here; “Operator authority: None” is accurate for the scoped edits. Risks include reverting or leaving the binary unwired.

    Gaps

    None.

    Split

    The four guards form a coherent single-PR slice. The estimated 600 code/test lines fit the stated limit; rollout and remaining guards are explicitly deferred. No further split is needed.

    Definition of done

    Planning coverage only; checked boxes indicate AC and Verify coverage, not completed implementation.

    • D1 — Observable outcomes are specified. Evidence: AC1–AC9 define verdicts, streams and statuses.
    • D2 — Behavior-preserving scope is bounded. Evidence: frozen behavior is authoritative, with the undecodable-input exception explicit.
    • D3 — Verification proves every stated outcome. Evidence: Verify maps AC1–AC11 to behavior, protocol, import and matrix checks.
    • D4 — Relevant non-functional requirements are specified. Evidence: AC10 covers purity and determinism.
    • D5 — Verification environments are identified. Evidence: AC11 names the four existing CI platforms.
    • D6 — Size and PR scope are stated. Evidence: four guards, approximately 600 code/test lines, with rollout excluded.
    • D7 — Approach follows the Go-port direction. Evidence: internal rules, hookio reuse, a thin binary and Go tests add no shell logic.
    • D8 — Dependencies are accurately recorded. Evidence: live states match the body and prerequisites explicitly gate rollout only.
    • D9 — Risks include an undo. Evidence: revert or retain the unwired binary.
    • D10 — Operator authority and over-engineering are addressed. Evidence: scoped edits require no owner-tier changes or unnecessary configuration layer.

    Round: 1 of 3

  7. added
    refinement:readyPassed the Definition of Ready; may be picked up
    and removed
    refinement:activeA refinement round is open; not ready for implementation
    on Oct 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    refinement:readyPassed the Definition of Ready; may be picked up

    Fields

    Priority

    Intangible

    Work type

    Planned

    Projects

    • Status
      Backlog

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions