Skip to content

feat(checks): let the ADR guard allow appends and cover Bash writes - #59

Merged
chrispezza merged 1 commit into
mainfrom
feat/adr-guard-appends
Oct 12, 2026
Merged

chrispezza merged 1 commit into
mainfrom
feat/adr-guard-appends

Conversation

@chrispezza

Copy link
Copy Markdown
Collaborator

Summary

  • The PreToolUse guard blocked every edit to an existing ADR and named a kill-switch as the legal move. That switch is an environment variable of the Claude Code process, so an agent could never take it. The repo's own required appends (amendments, graduation-log entries) had no reachable path except a tool the guard did not watch.
  • The guard now allows a pure append to an existing ADR and still blocks rewrites, mid-file inserts and Status-line changes.
  • The matcher now includes MultiEdit and Bash. Shell writes to an existing protected file are blocked; reads and new ADR files pass. This is a heuristic guard rail, not a security boundary.
  • Only numbered ADR files are protected, which leaves docs/adrs/README.md free for a generated index.
  • Rejections now name moves the agent can take, and say that anything else means asking the owner.

Attack surface

None added. This narrows what an agent session can do to ADR files through the shell.

Cost

One new CI step in the existing enforcement job: stdlib unittest, about one second. No new dependency.

Test plan

  • python -m unittest discover -s checks/tests — 15 tests pass
  • python checks/run_checks.py --ci — 0 findings
  • The ADR 0012 amendment in this PR was written through the new guard as an append
  • CI green

ADR impact

  • Existing ADR updated: ADR 0012, appended amendment dated 2026-10-12

Notes for reviewers

The hook matcher change takes effect in new sessions. Running sessions keep the matcher they started with.

🤖 Generated with Claude Code

The PreToolUse guard blocked every edit to an existing ADR and pointed at a
kill-switch only the session's launcher can set, so the repo's own required
appends (amendments, graduation-log entries) had no move an agent could
take. It also watched only Edit and Write, so a shell command rewrote an ADR
without touching the hook.

- Allow Edit/Write/MultiEdit on an existing ADR when the result keeps all
  existing text and only adds after it; keep blocking everything else
- Extend the matcher to MultiEdit and Bash; block shell writes to existing
  protected files (heuristic guard rail, not a security boundary)
- Protect only numbered ADR files, leaving docs/adrs/README.md free for a
  generated index
- Reword rejections to name moves the agent can take
- Add stdlib unittest coverage and run it in the enforcement CI job
- Record the change as an appended amendment to ADR 0012

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@chrispezza
chrispezza merged commit 11d0e1e into main Oct 12, 2026
2 checks passed
@chrispezza
chrispezza deleted the feat/adr-guard-appends branch October 12, 2026 17:57
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