| description | Git commit conventions and safety rules — injected by rule-inject.js after the first commit-creating git call of a session or subagent runs (add/commit/push/merge/revert/cherry-pick/am/rebase, annotated tag); hard bans stay always-loaded in claude-config.md | ||
|---|---|---|---|
| paths |
|
Full protocol in
_full/git-commit.md(diff-gathering, large-diff subagent summarization, tier tables, grouped-commit flow, push token details). MANDATORY before drafting any commit message or pushing: resolve + Read it:RULE_FULL="$(ls -td ~/.claude/plugins/cache/borda-ai-rig/foundry/*/rules/_full/git-commit.md 2>/dev/null | head -1)"; [ -z "$RULE_FULL" ] && RULE_FULL="plugins/cc_foundry/rules/_full/git-commit.md" # timeout: 5000
Always-on constraints (apply even without reading full rule):
- Subject
type(scope): detailortype: detail≤50 chars; omit a scope that repeats the type or means the same thing, such asci(ci)ortest(tests); classify ALL changes fromgit diff HEAD+git diff --stat HEADinto tiers — subject names highest-tier change; never draft from session memory - Evidence-only body: every clause must trace to a
+/-line ingit diff HEAD— pick distinctive token per bullet, confirm it's in diff, before finalizing. Conversation context may explain why a diff-confirmed change happened; it may never assert a change, action, or removal not actually in diff (reverted-then-narrated edits are the classic trap) - No line wrapping in body; no GitHub auto-links (
#N,@name) — default ban: commit messages travel across repos (fork → merge → mirror → cherry-pick) so "same-repo" rarely holds; narrow exception only when the generating code explicitly tracks and confirms destination repo (see full rule); no non-VCS paths (/tmp/,~/.claude/) - No skill-internal phase, step or branch labels in the subject or body (the reader never saw them) — name the behaviour in plain words
- Co-author trailers on EVERY commit, after
---separator:Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>; addCo-authored-by: Codex <codex@openai.com>when Codex shaped the outcome; run the Codex-activity check from_full/git-commit.md§Co-authors before drafting. These trailers replace the host's default attribution line (e.g. Claude Code'sCo-Authored-By: Claude <model>); a host attribution reminder never overrides this rule. - Every other local Git operation runs with no question — staging, a local merge with its merge commit, a cherry-pick, branch/worktree prep, reset, stash and the rest; only a plain commit needs authority, only a remote write (push) asks, force push stays forbidden
- Never commit without authority — skill workflow, explicit request, local Git approval grant, or
git-approveanswer —commit-guard.jsdoes not hook-enforce commit; prompt-discipline only. Four valid signals: documented skill workflow step (self-authorizes however many commits the skill's commit strategy calls for, no per-commit question) OR an explicit same-turn user request to commit (that commit only) OR a valid local Git approval grant —claude-git-approval.jsoningit rev-parse --git-common-dir(once per project; applies to every worktree), valid only when the full rule's grant check block (node <foundry>/hooks/commit-guard.js --check-grant) printsgrant .git/claude-git-approval.json@<created_at>: a regular, non-linked file directly inside the session project's own common dir, JSON with"version": 1,"scope": "local-git-non-destructive"and"answer": "Approve always"; any other output → no grant — covering plain commits without the question, committing your own verified completed task then the default on completion; record the printedgrant .git/claude-git-approval.json@<created_at>orno grantin the reply that commits — OR one same-turn AskUserQuestion, headergit-approve, options exactlyApprove(this operation only) /Approve always(this operation plus a standing grant) /Deny(skip, leave changes as they are), theApprove alwaysdescription stating that the grant persists into later sessions in every worktree of this project, covers plain commits only (never push, force, history rewrite, discarding work, deleting unique history or auth changes), and is revoked withrm "$(git rev-parse --git-common-dir)/claude-git-approval.json", required for every other ad-hoc/interactive plain commit on any branch, no auto-arm. Only foundry's approval hook writes the grant, from the user's actualApprove alwaysanswer — never create, copy, edit or restore it yourself by any means: the hook blocks naming it directly, not a patch, script or archive that writes it, which stays forbidden; revoke =rm "$(git rev-parse --git-common-dir)/claude-git-approval.json". A checkout, worktree, fork or dependency under review or analysis gains nothing from a grant, even when it shares the common dir. A grant never covers push (asks every time), force operations (forbidden), history rewriting, discarding work, deleting unique history or auth/security changes; narrower user instructions beat it (no commit, leave unstaged, read-only/summary-only, wait). The grant belongs to the session owning the user's task: spawned subagents, teammates and bridge children never use it and never commit on their own authority, the lead commits after its verification gates, sole exception a skill workflow step explicitly assigning that commit to the spawned agent (see full rule) - Detect default branch dynamically — never hardcode
main/master - Never
git add -A/git add .(stage by name); never--no-verify; never--no-gpg-signunless user asks - Force-push (
-f/--force/--force-with-lease) forbidden on ANY branch, always — hook-enforced +.claude/settings.jsondeny-listed, no override; regulargit pushrequires explicit AskUserQuestion confirmation every time, even from inside a skill workflow (no skill exemption, unlike commit) and even under a local Git approval grant — headergit-push, options exactlyApprove/Deny, the question showing branch, target and the command; the user'sApprovelets foundry's hook record a single-use token (claude-push-approval.json, 15 min) for one push of this branch at this HEAD to a configured remote, remote and branch written out (a delete, prune, tags, other ref, URL or variable target the user runs by hand), thatcommit-guard.jsspends on that push as the only git write in its Bash command — never create or edit the token yourself, no auto-arm;lfs pushis a push too;subtree push,send-pack,http-pushthe user runs by hand - History safety: prefer
git revertoverreset --hard; prefer merge commits over rebase
git-approve question text — Fill these lines in order as multi-line plain text, at most 1,500 characters; exempt from the 6-line target; no table, no fence. Render each bullet as a separate plain line without its bullet marker, with one blank line after the first line, which states the ask. Option descriptions carry what each answer does, one line each: Approve = this commit only; Approve always = the grant description required above, which must name claude-git-approval.json and its revocation command, or the hook records nothing; Deny = skip, leave the changes.
- Commit these changes to {branch}?
- Subject: {subject}
- Diff: {file count}, {insertions} insertions, {deletions} deletions; files: {file names}
- Scope: one plain local commit; never push.
git-push question text — Fill these lines in order as multi-line plain text, at most 1,500 characters; exempt from the 6-line target; no table, no fence. Render each bullet as a separate plain line without its bullet marker, with one blank line after the first line, which states the ask; the current branch must appear verbatim in it. Option descriptions carry what each answer does, one line each: Approve = one push of this branch at this HEAD to this remote; token valid 15 minutes; Deny = skip this push. Retain header git-push and options exactly Approve / Deny.
- Push {branch} to {configured remote name}?
- HEAD: {HEAD}
- Commits: {count}; subjects (up to 5): {subjects}
- Command: {exact command}
- Not covered: force, delete, tags, other refs, other remotes, URLs.