Skip to main content

Git Agent Identity Policy — MC #105779

Agent Git Identity Policy

MC #105779. Author: Kelsey Hightower (FlowForge), maintainer of ~/.claude/hooks/git-author-guard.sh (MC #101291).

The rule

Any builder running inside a Claude Code session that will git commit on an ALAI repo MUST set a worktree-local git identity matching its company persona BEFORE the first commit:

git -C <worktree-dir> config user.email "<slug>@<company>.alai.no"
git -C <worktree-dir> config user.name  "<Persona Name> (<Company>)"

<worktree-dir> is the actual working-tree directory checked out for this task (the one the push will run from) — not the main repo clone, not ~.

This satisfies the git-author-guard.sh ALLOWLIST so the push proceeds without triggering the CEO override path.

Why

The global git identity on this machine is user.email = [email protected] (CEO's real address, used for the CEO's own manual commits). If a builder session commits without setting a local override, every commit is stamped [email protected] — a BLOCKLIST match — and git-author-guard.sh blocks the push on every single CC-session push, not just genuine CEO-direct-commit violations (HC#1, MC #101291 genesis: Bilko UAT 2026-05-16, 5 direct john@ commits to main). Global override was never enacted (never --global) because it would corrupt the CEO's own manual-commit provenance system-wide.

Persona -> email table (must match ALLOWLIST_PATTERNS in the guard)

Company Domain Example personas Worktree-local email pattern
CodeCraft backend/architecture/db Petter Graff, Martin Kleppmann, Hadi Hariri, Lee Robinson, Bruce Momjian *@codecraft.alai.no
Vizu frontend/design systems Brad Frost, Lea Verou *@vizu.alai.no
Securion security Parisa Tabriz, sentinel-architect *@securion.alai.no
FlowForge devops/infra Kelsey Hightower *@flowforge.alai.no
Proveo QA/testing Angie Jones, James Bach, Lisa Crispin, Dorota Huizinga *@proveo.alai.no
AgentForge AI/ML/RAG Chip Huyen, Georgi Gerganov *@agentforge.alai.no
Finverge fintech/payments Markos Zachariadis *@finverge.alai.no
Skybound mobile/BA Paul Hudson, sentinel-ba *@skybound.alai.no
Lexicon linguistic QA Dževad Jahić *@lexicon.alai.no
Skillforge docs/BookStack *@skillforge.alai.no
Resolver *@resolver.alai.no

Use a short task-scoped local part when useful for audit trail, e.g. [email protected] — the guard matches on domain suffix only (@codecraft\.alai\.no$), so the local part is free-form.

Full up-to-date routing table (source of truth, not this file): ~/system/agents/specialist-mapping.json.

Hard rules

  1. NEVER git config --global for a persona identity. Worktree-local (git config without --global, run inside the worktree dir) only. A global persona email would corrupt the CEO's own commit provenance and defeat the guard for every repo on the machine.
  2. NEVER request/use the CEO override token (/tmp/git-author-override-<sha>) as a substitute for setting the identity correctly. The override exists for genuine CEO emergency pushes (MC #101291 design), not routine builder workflow friction. Requesting it to skip identity setup is a ZAKON #2.5-class shortcut and will be treated as such.
  3. If a commit was already made under the wrong (blocklisted) identity before this was caught: fix with git commit --amend --reset-author (after setting the correct local user.email/user.name) rather than requesting override — this rewrites the author on the existing commit instead of bypassing the check.
  4. Always run git push from the worktree directory being pushed, not from the main repo checkout with a different branch checked out elsewhere. The guard resolves the commit range from the local ref of the pushed branch (MC #105779 fix), but if that local ref isn't reachable from the invoking $CWD at all, the guard fails closed rather than guessing.

When the guard's fetch fails with an auth error

If push-time verification needs to fetch the target branch and fails with could not read Username/authentication failed/403 (no PAT configured for the git remote in this shell), that is an auth gap in this session, not a signal to abandon identity setup or reach for the override token. Fix: configure the Azure DevOps PAT as an http.extraHeader on the remote —

git -C <worktree-dir> config http.https://dev.azure.com/.extraHeader \
  "Authorization: Basic $(printf 'PAT:%s' "$PAT" | base64)"

— pulling $PAT from Vaultwarden item 776a5d5e-7222-4843-9c76-212122f65e62 ("Azure DevOps PAT - alai-holding"): bw get item 776a5d5e --session $(cat /tmp/bw-session). The guard will fall back to a broader (but still correctly-scoped, post MC #105779 fix) local scan if the fetch can't be fixed in time; it does not fail open on an auth error.

Reference

  • Guard implementation: ~/.claude/hooks/git-author-guard.sh
  • Guard genesis: MC #101291 (Bilko UAT 2026-05-16 incident)
  • This policy: MC #105779 (2026-07-15), triggered by false-flag on commit 78108536 during MC #105776 and the identity-friction pattern it exposed