Skip to content

feat(guard): find the commands that the guard watches - #32

Merged
Bakhomious merged 1 commit into
mainfrom
step/guard
Nov 3, 2026
Merged

Bakhomious merged 1 commit into
mainfrom
step/guard

Conversation

@Bakhomious

Copy link
Copy Markdown
Contributor

What

internal/guard: guard.Commands(script) reads a bash call with internal/bash (#31) and gives each command that the guard watches, with its kind and a name for a hook's reason (git push, gh pr merge, … push):

  • Outward: git's commands that send to another host (push, send-email, send-pack, http-push, imap-send), past git's options and the values of those that take one; git-push and the like; gh's commands but those that only read (so an alias counts too), and gh api; ssh, scp, sftp, acli, jira.
  • Control: tmux, osascript.
  • Agent: aider, claude, codex, copilot, cursor-agent, gemini, opencode.
  • Baton: baton with its command, so each pane's hook can let its own commands through.
  • Unknown: a program that only the run decides ("$GIT" push, eval "$X", bash -c "$X").

It fails closed on a git command or option, or gh's first two words, that only the run decides.

Nothing enforces it yet: guard-hook wires it into the role panes' preToolUse hook.

Split

The guard's rules came out at ~240 lines, so the step is now three, each near 150 lines:

  1. guard (this PR): watched commands by program.
  2. guard-http: curl, wget and gh api, watched only when they send data. Until then, gh api counts as a write and curl/wget aren't watched.
  3. guard-hook: baton hook guard and the plugin's preToolUse hook.

The docs' status table, decision 50's last sentence and the new decision 51 say so.

Docs

  • bash → Done (feat(bash): read the commands that a bash script runs #31); guard → In review (feat(guard): find the commands that the guard watches #32); new rows guard-http and guard-hook.
  • Fact 34: git's valued options and that git's and gh's commands match case (git 2.56.0, gh 2.103.2).
  • Decision 51 (lead's call, flagged): what the guard watches and why, and its known misses: git's aliases and the commands git runs itself, git lfs push, tools it doesn't know (npm publish, docker push, rsync to a host, cloud CLIs). Risk 2's second belt (belt) is for these.
  • Safety paragraph and risk 2 updated.

Checks

  • mise run check: green, total coverage 99.2%, internal/guard 100%.
  • Probes: 85 mutants (every entry of each list and map, each case and condition), all caught. Leftover check clean.
  • Smoke: an overlay-built main ran guard.Commands over 38 made-up role scripts in 0.3 s. The outward, control, agent, baton and dynamic cases were caught; reads (git status, gh pr view, gh pr checks, curl GET, go test, here-docs that mention git push) passed; an unterminated quote gave a parse error.

internal/guard reads a bash call with internal/bash and gives each command
that the guard watches, with its kind and name: outward (git's commands that
send to another host, gh's commands but its reads, gh api, ssh, scp, sftp,
acli, jira), control (tmux, osascript), another agent's CLI, baton with its
command, and a program that only the run decides. It fails closed on a git
command or option, or gh's first two words, that only the run decides.

Decision 51 and fact 34 record the rules and git's and gh's facts. The guard
now comes in three steps: guard, guard-http (curl, wget, gh api's reads) and
guard-hook.
@sonarqubecloud

sonarqubecloud Bot commented Nov 3, 2026

Copy link
Copy Markdown

@Bakhomious
Bakhomious merged commit fd39ba5 into main Nov 3, 2026
3 checks passed
@Bakhomious
Bakhomious deleted the step/guard branch November 3, 2026 20:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant