Skip to content

Architecture

src/gitvow/
  cli.py          argument parsing; every subcommand is one function; exit codes 0/1/2
  hooks/          the four Claude Code hook handlers; pure functions (payload, home) → (exit code, stderr text)
  policy.py       load (with precedence + validation) and evaluate; Decision(outcome, reason, detail)
  redact.py       layered redaction; the only place text is scrubbed
  transcript.py   read Claude Code JSONL; produce counts, tool list, files written, last plan
  state.py        git helpers; .git/gitvow-session.json; .git/gitvow-hooks.log
  install.py      settings merge/unmerge; git hook script; user/repo install and uninstall
  collect.py      gather ledger + logs + trailers + notes for a trial; summarize
  selftest.py     end-to-end self-check in a temporary repo and home
  default_policy.json

Invariants the tests enforce: - Hooks never raise to the caller; any exception in the decision path becomes exit 2. - Nothing from transcript.py reaches state.py, hooks/ or collect.py without passing redact.redact. - install twice equals install once; install then uninstall restores the settings file byte-for-byte except gitvow's entries. - The package imports only the standard library.