Expand description
git.commit / git.branch / git.push verb handlers (ADR-108, amended
by the ADR-108 Amendment).
Thin, 1:1 wrappers over system git, shelled via
std::process::Command::args (never a shell string) with every
caller-supplied value validated and assembled into an argv vector by
crate::write_argv before it reaches the process boundary. repo is an
ordinary verb argument like every other khive verb — the Gate (ADR-018)
still decides allow/deny before any of these functions run, but it is no
longer the only enforcement point: enforce_write_policy below is a
handler-level precondition, fail-closed independent of Gate
configuration, resolved by crate::write_policy against the operator’s
[git_write] allowlist (ADR-108 Amendment).
enforce_write_policy returns the canonical repo path on success, and
every git invocation for that call uses it from that point on — never the
raw caller-supplied repo (ADR-108 review r2 High finding: reusing the
raw path after only canonicalizing it for the comparison is a symlink
TOCTOU). The check and the mutation are additionally serialized per-repo
via the private repo_write_lock helper so a concurrent khive-mediated write to the same
repo cannot interleave between the policy check and the git command it
guards.
Every write attempt — allowed or denied, whether git itself then
succeeds or fails — appends exactly one git.write-shaped Event (kind
Audit, ADR-108 rule 2) via emit_write_audit, carrying
repo/branch/decision and, on success, sha. This is in addition
to, not a replacement for, the dispatch-level gate-check audit that
fires for every verb.