Quick Summary
Goal: Stage changes and create well-structured git commits following Conventional Commits format — and, when code changed, gate the commit on a user decision to verify (via /workflow-integration-test-green, which drives the suite to green), confirm already-verified, or explicitly skip (default: verify first). Every commit message body OPENS with a mandatory Estimate: line carrying the derived story points and AI man-days for that staged diff.
Summary: (read-this-if-nothing-else digest — purpose + ALL main steps + gates)
- PURPOSE — produce a commit whose message a future reader can act on WITHOUT opening the diff: conventional subject, an
Estimate: first body line, a purpose→what→how body, and a per-area Reviewers block. Three things are computed BEFORE the message exists (reviewers, estimate, doc triage) because they must live INSIDE it.
- STEP 0 — BYPASS MARKER. Create
tmp/claude-temp/.commit-skill-active before any git add/git commit, and ALWAYS remove it afterwards — success or failure.
- STEP 1-2 — ANALYZE + STAGE.
git status / git diff --cached / git diff / git log --oneline -5, then stage.
- STEP 2.5 — DOCS TRIAGE. Staged files matching doc-impact patterns → run
/docs-update, re-stage the doc changes.
- STEP 2.7 — IDENTIFY REVIEWERS (pre-commit, read-only): last author per staged file vs
HEAD, commit author EXCLUDED, grouped BY AREA with the focus each owns.
- STEP 2.9 — DERIVE THE ESTIMATE via the carried
SYNC:estimation-framework against the STAGED diff (or reuse the implemented plan/PBI/story frontmatter with (source: <path>)). SP is DERIVED from likely_days, never eyeballed; discount generated/lockfile/docs churn first.
- STEP 3 — GENERATE MESSAGE. Subject
type(scope): description; body OPENS with the Estimate line, then purpose/kind → what changed → how it works, then the Reviewers block.
- STEP 3.5 — TEST-VERIFY GATE (BLOCKING when code changed).
AskUserQuestion, default verify via /workflow-integration-test-green. Only an explicit Yes — already verified or Skip proceeds; NEVER choose skip on the user's behalf. If the gate mutates the staged set, re-stage AND re-derive the estimate.
- STEP 4 — COMMIT with the HEREDOC form (subject → blank → Estimate → body → Reviewers → footer).
- STEP 5 — VERIFY via
git status + git log; confirm the first body line IS the Estimate line, then re-present the reviewer assignment.
- STEP 6 — REFRESH THE CODE GRAPH (post-commit, BACKGROUND, non-blocking). Only when
.code-graph/ exists: fire /graph-build --scope=sync in the background so the commit that just moved HEAD is re-parsed AND the graph's last_synced_commit advances with it. NEVER blocks or gates the commit; a failure is reported, never retried inline.
- FLAG —
--push (a.k.a. "commit and push") stages + commits + pushes via git-manager. Without it: STOP after the commit; NEVER push unprompted.
Workflow:
- Analyze Changes — Run git status/diff to understand staged and unstaged changes
- Stage Changes — Add relevant files (specific or all)
- Identify Reviewers — from git history, list relevant reviewers (last author per touched file vs
HEAD, excluding the commit author) and the area each must focus on — computed BEFORE the commit so the block can be embedded in the message body
- Derive Estimate — Apply the carried
SYNC:estimation-framework to the staged diff (or reuse the frontmatter of the plan/PBI/story this commit implements) to derive story_points + man_days_ai — computed BEFORE the message so the numbers can head the body
- Generate Message — Detect type (feat/fix/refactor/etc.), extract scope from paths, write subject, open the body with the Estimate line from step 4, add a detailed body structured as purpose/kind → what changed → how it works, and append the Reviewers block from step 3
- Test-Verify Gate — When staged changes include code that might need tests, ask the user (
AskUserQuestion, default verify) to verify via /workflow-integration-test-green, confirm Yes — already verified, or explicitly Skip. Default = verify first, and verify means drive the suite to green, not merely report it
- Commit — Create commit with HEREDOC (title + Estimate line + detailed summary + Reviewers block + attribution footer)
- Verify — Confirm with git status and git log
Key Rules:
- Stamp the estimate on the FIRST body line — every commit message opens its body with
Estimate: <n> SP | man_days_ai: <x>d | man_days_traditional: <y>d. Story points and AI man-days are MANDATORY and DERIVED bottom-up per the carried SYNC:estimation-framework (or reused from the plan/PBI/story frontmatter this commit implements); the number describes THIS staged diff only
- Write a detailed body — purpose/kind → what changed → how it works — so the next human reading
git log/git blame understands the change without opening the diff. As detailed as the change needs (wrap ~72 chars); no title-only commits for non-trivial changes
- Embed a Reviewers block in the commit message — the per-area reviewers (last author per touched file vs
HEAD, commit author excluded) — computed BEFORE committing so it lives in the message body, not just as a side report
- When staged changes include code that might need tests, gate the commit on test verification — ask the user to verify via
/workflow-integration-test-green (default), confirm already-verified, or explicitly skip; only an explicit Yes or Skip proceeds straight to commit, and the agent NEVER chooses skip on the user's behalf
- Stop after the commit; push only when the user explicitly requests it (or passes
--push / says "commit and push" → stage + commit + push via git-manager)
- Never commit secrets, credentials, or .env files
- Never use
--amend or --no-verify unless explicitly requested
- Include
Generated with [Claude Code] attribution footer
Be skeptical. Apply critical thinking, sequential thinking. Every claim needs traced proof, confidence percentages (Idea should be more than 80%).
Git Commit Skill
Stage changes and create well-structured git commits following Conventional Commits format.
IMPORTANT: Bypass git-commit-block Hook
Before running any git add or git commit commands, create the marker file to bypass the git-commit-block hook:
PROJ=$(git rev-parse --show-toplevel) && mkdir -p "$PROJ/tmp/claude-temp" && touch "$PROJ/tmp/claude-temp/.commit-skill-active"
After committing (success or failure), always clean up the marker:
rm -f "$(git rev-parse --show-toplevel)/tmp/claude-temp/.commit-skill-active"
Workflow
Step 1: Analyze Changes
# Check current status (never use -uall flag)
git status
# See staged changes
git diff --cached
# See unstaged changes
git diff
# Check recent commit style
git log --oneline -5
Step 2: Stage Changes
# Stage all changes
git add .
# Or stage specific files
git add <file-path>
Step 2.5: Docs-Update Triage
Before committing, check if staged files impact documentation:
- Run
git diff --name-only --cached to list staged files
- Check if any staged file matches doc-impact patterns (resolve the concrete backend/frontend source paths from the project's structure reference /
docs/project-config.json):
- changes under the backend service source paths (per project config) → may impact
docs/specs/
.claude/skills/** → may impact .claude/docs/skills/
.claude/hooks/** → may impact .claude/docs/hooks/
.claude/workflows.json → may impact CLAUDE.md workflow table
- changes under the frontend app source paths (per project config) → may impact frontend pattern docs
- If matches found: invoke
/docs-update skill, then re-stage any doc changes with git add
- If no matches: skip (log "No doc-impacting files staged")
/docs-update's Phase 1 already runs /prompt-enhance <doc> on every docs/project-reference/** doc it PATCHES (see docs-update Step 1.3), keeping the doc concise yet AI-valuable before commit re-stages it — do not invoke /prompt-enhance again here.
Step 2.7: Identify Reviewers (pre-commit — feeds the message)
Runs BEFORE the commit so the result can be embedded in the commit message body (see Step 3). Read-only (git log/blame only) — it NEVER blocks the commit and never messages anyone.
For each staged file, find the LAST author who touched it (against HEAD, the soon-to-be parent) — that author is the natural reviewer for the area.
Rules:
- EXCLUDE the commit author from the "ask to review" list (you don't ask yourself to review) — but still surface files where the author is the only prior toucher as author-owned, no external reviewer.
- Brand-new files (no prior history) → mark
NEW FILE — reviewer = owner of its source/sibling file.
- GROUP reviewers by change AREA (which feature/subsystem each owns) and state WHICH AREA each must focus on — not a flat name list.
- Fetch each reviewer's email for tagging.
Collect the raw last-author-per-staged-file data:
# Staged files in this pending commit
git diff --cached --name-only \
| while read -r f; do
author=$(git log -1 --format='%an' HEAD -- "$f" 2>/dev/null)
email=$(git log -1 --format='%ae' HEAD -- "$f" 2>/dev/null)
date=$(git log -1 --format='%ad' --date=short HEAD -- "$f" 2>/dev/null)
[ -z "$author" ] && author="(NEW FILE — reviewer = source/sibling owner)" && date="-"
printf '%s\t%s\t%s\t%s\n' "$author" "$email" "$date" "$f"
done
Then: collapse by author, map each author's files to the change area, drop the commit author, and render the Reviewers block to embed in the commit message (Step 3) and to present to the user:
| Reviewer |
Email |
Focus area |
Files |
Follow the table with a short recommended review assignment by feature list (area → reviewer). The skill does NOT auto-message anyone — this is the user's deliverable.
Step 2.9: Derive the Estimate (pre-commit — feeds the message)
Runs BEFORE the commit so story_points and man_days_ai can head the message body (Step 3). Apply the SYNC:estimation-framework block this skill carries (see below) to the OBSERVED staged scope — post-hoc, with full diff visibility.
Source of the numbers — prefer an approved artifact over a fresh guess:
| Situation |
Source of story_points / man_days_ai |
| Commit implements a plan / PBI / story whose frontmatter already carries estimates |
REUSE its story_points + man_days_ai; append (source: <path>) to the Estimate line |
| Commit is a PARTIAL slice of such an artifact |
Derive the slice bottom-up — NEVER copy the whole artifact's number onto a partial commit |
| No estimate artifact exists |
Derive bottom-up from the staged diff per the framework |
Derivation (bottom-up — SP is DERIVED, never eyeballed):
- Blast-radius pass on
git diff --cached --stat — touched areas, complex files (>500 LOC / central / multi-handler), downstream consumers, shared/common code.
- Sum the Reuse-vs-Create tiers across UI + backend + tests →
bottom_up_hours.
likely_days = ceil(bottom_up_hours / 6) × productivity_factor.
story_points = closest SP→Days bucket. Disagreement >50% → trust bottom-up and downgrade SP.
man_days_ai = the AI likely column for that SP (1≈0.25d · 2≈0.35d · 3≈0.65d · 5≈1.0d · 8≈1.5d · 13≈2.0d), reconciled against the bottom-up result; it already includes the 30% review overhead.
man_days_traditional = the no-AI likely column (1≈0.5d · 2≈1d · 3≈2d · 5≈4d · 8≈6d · 13≈10d), same reconciliation.
Anti-inflation (discount BEFORE estimating — same guardrail /git-developer-performance applies): generated code, lockfiles, ORM/designer snapshots, i18n re-sorting, bulk reformatting, and pure docs/spec churn earn no story points. A 4 000-line lockfile bump is 1 SP, not 8.
Scope of the number: the estimate describes THIS commit's staged diff only — not the branch, not the whole feature it belongs to. A --push run does not change this.
Never block on the estimate. It is derived from evidence already on disk (the staged diff), so it never asks the user and never gates the commit. If the diff is genuinely unestimable (e.g. a pure merge commit with no resolved content), emit Estimate: 0 SP | man_days_ai: 0d — integration only, no authored change rather than omitting the line.
Step 3: Generate Commit Message
Analyze staged changes and generate message following Conventional Commits:
<type>(<scope>): <subject>
Estimate: <story_points> SP | man_days_ai: <x>d | man_days_traditional: <y>d
<detailed summary of changes>
Reviewers:
- <area>: <Reviewer Name> <email> — focus on <what they own>
Type Detection
| Change Pattern |
Type |
| New file/feature |
feat |
| Bug fix, error handling |
fix |
| Code restructure |
refactor |
| Documentation only |
docs |
| Tests only |
test |
| Dependencies, config |
chore |
| Performance improvement |
perf |
| Formatting only |
style |
Scope Rules
Extract from file paths:
{configured-source-root}/auth/ → auth
.claude/skills/ → claude-skills
libs/{shared-lib}/ → {shared-lib}
- Multiple unrelated areas → omit scope
Subject Rules
- Imperative mood ("add" not "added")
- Lowercase start
- No period at end
- Max 50 characters
Estimate Line (MANDATORY — the FIRST line of the body)
Estimate: <story_points> SP | man_days_ai: <x>d | man_days_traditional: <y>d
- Placed immediately after the blank line that follows the subject — above purpose/what/how. NEVER in the footer, NEVER folded into the subject (the subject stays imperative, lowercase, ≤50 chars per Conventional Commits), NEVER omitted.
story_points — Fibonacci 1 | 2 | 3 | 5 | 8 | 13 | 21, DERIVED per Step 2.9. Required. 0 is the ONE value outside that set, reserved for the unestimable case Step 2.9 names (a pure merge/integration commit with no authored content) — NEVER as a rounding-down of real work.
man_days_ai — AI-assisted man-days for this staged diff (Claude Code + project context, review overhead included). Required.
man_days_traditional — the no-AI baseline (3–5yr dev, 6 productive hrs/day). Recommended — include it whenever derived — why: alone, man_days_ai is an absolute figure nobody can calibrate, while the pair makes the AI leverage on THIS diff readable straight from git log. Written for a human reader: /git-developer-performance derives its own numbers from the diff rather than reading this line (its git log format stops at %s — .claude/skills/git-developer-performance/scripts/git-developer-performance.cjs:290), so the pair earns its place by what a person reads, not by what a tool consumes.
- Ranges are allowed and preferred once
likely_days ≥3: man_days_ai: 1.0-1.5d | man_days_traditional: 4-6d.
- Append
(source: <path>) when the numbers were REUSED from a plan/PBI/story frontmatter instead of derived from the diff.
- SP ≥13 on a single commit → the commit is doing too much; say so in the body ("SHOULD have been split") rather than quietly shipping the number.
Body Rules (MANDATORY) — write so a human understands fastest
Body is the deliverable. Optimize for the next person running git log / git blame — they understand the change without opening the diff. As detailed as the change needs; no artificial brevity limit — wrap ~72 chars, stop once nothing new said. Title-only commit FORBIDDEN for any non-trivial change. — why: the diff shows WHAT; the body must carry WHY + HOW, which the diff cannot.
Three parts (omit one only when genuinely empty):
- Purpose / kind — name the kind AND why it exists: feature · bug fix (state the symptom removed) · enhancement · refactor (state behaviour-preserving) · perf · security · chore. 1–2 sentences answering "what problem does this solve?".
- What changed — concrete edits grouped by behaviour, never by file. Each bullet specific — NEVER "update code", "fix stuff", "minor fixes".
- How it works / why this way — the part reviewers need: mechanism, key logic, invariants relied on, edge cases preserved, and any non-obvious decision ("did X instead of obvious Y because Z"). Focus the non-obvious; NEVER narrate boilerplate. Ordering/timing/security invariant or subtle failure mode → call it out explicitly.
Teach-the-reader mindset (from the understand skill): cover BOTH high-level motivation (why it matters) AND low-level logic (business rules, edge cases). Surface what a reader would NOT guess from the diff — write the explanation you would want to receive.
Detail dial — scale body to the change:
| Change size |
Body depth |
| Trivial (typo, rename, formatting) |
Purpose line + 1 bullet; skip "how it works" |
| Normal (feature/fix, single area) |
Purpose + 2–5 "what" bullets + a short "how it works" |
| Complex (cross-cutting, subtle bug) |
Purpose + grouped "what" + a full "how it works" that spells out the key invariant / edge case / why-this-over-that |
Step 3.5: Test-Verify Gate (blocking — only when code changed)
Decide whether the staged changes carry code that might need tests — why: this gate is the only thing standing between an untested behaviour change and permanent history.
Trigger detection — run git diff --cached --name-only and classify the staged files:
- Code that might need tests → any change to production/source code: backend service source, frontend app source, shared libraries, scripts, hooks (
.cjs), or other executable logic (resolve concrete source roots from docs/project-config.json / the project structure reference).
- NOT a trigger (skip the gate) → the staged set is only docs (
docs/**, *.md), specs (docs/specs/**), test-spec/config text, changelog, or other non-executable content with no source-code change.
If the gate is NOT triggered: log Test-Verify Gate: skipped (no code changes staged) and continue to Step 4.
If the gate IS triggered: STOP and ask the user with AskUserQuestion (default option is No):
Header: Test verify
Question: Staged code changes may need tests. Verify before committing, or skip?
Options (in order — first is the default):
Verify now — run /workflow-integration-test-green (Recommended) — do NOT commit yet; activate the workflow-integration-test-green workflow, which verifies the suite AND drives any failure to green (verify → adjudicate → fix → review → re-verify) before returning. Proceed to Step 4 only once the whole suite is green; if it escalates instead of converging, surface that and stop (no commit).
Yes — already verified — the user confirms the integration tests were run and passed; proceed directly to Step 4 (Commit).
Skip — commit without verifying — the user's explicit, recorded decision to commit unverified code; proceed to Step 4 and note Test-Verify Gate: skipped by user in the response (never in the commit message).
Rules:
- Default is option 1 (verify). If the user does not actively choose "Yes" or "Skip", treat it as verify-first — never commit unverified code on assumption.
- Verify routes to
workflow-integration-test-green, not to a bare verify run — why: a bare integration-test-verify only reports the failures, leaving the user to hand-carry each one; the workflow owns the converge-to-green loop, so choosing "verify" actually clears the suite instead of just describing it.
- Yes is an explicit user assertion that the integration tests were run and passed; honour it and commit.
- Skip is the user's call, and it is theirs alone to make. Offer it, never recommend it, and NEVER select it yourself — why: an agent that can skip its own gate has no gate.
- Re-run this gate only once per commit; after a
verify → green, proceed to commit without re-asking.
- If the verify branch changed ANY file, re-stage and RE-DERIVE before Step 4. Option 1 can land test or source fixes AFTER Step 2.9 already ran, so the diff the estimate described is no longer the diff being committed. Mirror Step 2.5: re-stage the new changes with
git add, then re-run Step 2.9 over the updated git diff --cached and put the fresh numbers in the message. Options 2 and 3 mutate nothing, so the original Step 2.9 numbers stand.
- This gate is independent of
--push: it runs before the commit in every mode.
Step 4: Commit
Use HEREDOC for proper formatting:
git commit -m "$(cat <<'EOF'
type(scope): subject
Estimate: 3 SP | man_days_ai: 0.65d | man_days_traditional: 2d
- summarize key change 1 with intent
- summarize key change 2 with impact
Reviewers:
- <area>: Reviewer Name <reviewer@email> — focus on <what they own>
Generated by AI
EOF
)"
The Estimate line comes from Step 2.9 — re-derived after Step 3.5 if that gate changed the staged set — and is ALWAYS the first line of the body.
The Reviewers block comes from Step 2.7 (last author per staged file vs HEAD, commit author excluded, grouped by area). Omit the block only when every staged file is brand-new or author-owned with no external reviewer — in that case state Reviewers: none (author-owned / new files).
Step 5: Verify
git status
git log -1
Confirm the committed body's FIRST line IS the Estimate line from Step 2.9 (Estimate: <n> SP | man_days_ai: <x>d …) — missing → the message is non-conformant; re-derive and record it, NEVER leave it out. Then confirm the body carries the Reviewers block from Step 2.7 (or the explicit Reviewers: none (author-owned / new files) line). Re-present the per-area reviewer assignment to the user as the final deliverable — why: they need it to request the right reviewers on the resulting PR.
Step 6: Refresh Code Graph (post-commit — background, non-blocking)
Skip entirely (silently) when .code-graph/ does not exist — the project has no knowledge graph and there is nothing to refresh.
When it does exist, fire /graph-build --scope=sync in the background immediately after Step 5 verifies the commit — one Bash call with run_in_background: true, so the commit never waits on it:
if [ -d ".code-graph" ]; then python .claude/scripts/code_graph sync --json; fi
- Why after the commit, not before: a commit MOVES
HEAD. sync diffs the graph's stored last_synced_commit against the current HEAD, so running it AFTER git commit re-parses exactly the files this commit introduced. Run it before and HEAD has not moved yet, so there is nothing for it to see.
- Why
sync and not update: sync is the HEAD-movement verb — it advances the stored last_synced_commit as well as the nodes. update only re-parses the working tree and leaves that bookkeeping pointing at the PRE-commit HEAD, which then reads as stale to graph-prompt-sync and forces a redundant re-sync on the next prompt. Committing is a HEAD move, so it takes the HEAD-move verb.
- Why background: the
graph-auto-update PostToolUse hook only fires on Edit|Write|MultiEdit, so a commit leaves the graph's node set stale for any file the session did not itself edit (merges, checkouts, externally-changed files) — but graph freshness is an accelerator, NEVER a commit gate. It MUST NOT block, delay, or fail the commit.
- Report the background result briefly when it returns (files synced/added/deleted, or
up_to_date). If it errors (Python/deps missing, lock held by a concurrent update), state the error in one line and stop — NEVER retry inline and NEVER treat it as a commit failure.
Safety net, not the only net. If this step is skipped or fails, the graph-prompt-sync UserPromptSubmit hook detects the moved HEAD on the next prompt and syncs then. Step 6 exists so the graph is already current for the rest of THIS session, not because the commit is the only chance to catch it.
The --push path pushes first, then refreshes the graph — the push is the user-visible operation and must not wait on graph work either.
Examples
feat(order): add warehouse filter to list
Estimate: 3 SP | man_days_ai: 0.65d | man_days_traditional: 2d
- add warehouse query parameter in order list endpoint
- wire frontend filter control to request payload
- update tests for filtered and unfiltered list behavior
Reviewers:
- order backend: Jane Doe <jane@acme.com> — focus on the list endpoint query change
- order UI: Bob Lee <bob@acme.com> — focus on the filter control wiring
Generated by AI
fix(validation): handle empty date range
Estimate: 1 SP | man_days_ai: 0.25d | man_days_traditional: 0.5d
- guard null/empty date inputs before parsing
- return validation message instead of throwing format exception
Reviewers: none (author-owned / new files)
Generated by AI
Critical Rules
- ALWAYS stage all unstaged changes before committing — run
git add . (or specific files) so nothing is left behind
- Test-Verify Gate (Step 3.5): when staged changes include code that might need tests, ask the user to verify via
/workflow-integration-test-green (default — it converges the suite to green), confirm already-verified, or explicitly skip; only an explicit Yes or user-chosen Skip commits without verifying, and the agent NEVER picks skip itself. Bypass the gate entirely only when the staged set is docs/specs/config with no source-code change
- Estimate line is MANDATORY and comes FIRST in the body —
Estimate: <n> SP | man_days_ai: <x>d | man_days_traditional: <y>d, derived bottom-up per the carried SYNC:estimation-framework against the STAGED diff (Step 2.9), or reused from the implemented plan/PBI/story frontmatter with (source: <path>). Story points and AI man-days are required; discount generated/lockfile/docs churn before estimating
- Stop after the commit; push to remote only when the user explicitly requests it
- Refresh the code graph after committing (Step 6) — when
.code-graph/ exists, fire /graph-build --scope=sync in the BACKGROUND (run_in_background: true) so the commit that moved HEAD is re-parsed and last_synced_commit advances with it; skip silently when the dir is absent. Non-blocking by design: it NEVER gates, delays, or fails the commit
- Review staged changes before committing
- Never commit secrets, credentials, or .env files
- Never use
git commit --amend unless explicitly requested AND the commit was created in this session AND not yet pushed
- Never skip hooks with
--no-verify unless explicitly requested
- Commit message MUST include a Conventional Commit title AND a detailed body — purpose/kind → what changed → how it works. As detailed as the change needs (wrap ~72 chars); title-only commit FORBIDDEN for non-trivial changes
- Optimize body for the next human reading
git log / git blame — surface the non-obvious (key logic, invariants, edge cases, why-this-over-that), not just a list of touched files
- Include attribution footer:
Generated by AI
- Embed reviewers in the commit message — BEFORE committing (Step 2.7), surface the last author per staged file vs
HEAD (exclude the commit author), grouped by focus area, and write it as a Reviewers: block in the message body so the right reviewers travel with the commit/PR. Read-only; never blocks the commit.
Push & PR Operations
Arg --push (a.k.a. "commit and push"): stage + commit + push in one shot — spawn git-manager immediately after committing. The former standalone stage-commit-push entry point, folded in; it adds no logic beyond the push delegation below.
This skill handles commit by default. Push-to-remote and PR creation delegate to the git-manager sub-agent (subagent_type: "git-manager"), which enforces conventional-commit validation, prevents --no-verify bypass, and creates PRs with structured summaries.
Spawn git-manager after committing when the user says "push", "create PR", or "open PR".
Sub-Agent Type Override
MANDATORY: Push and PR operations spawn git-manager sub-agent (subagent_type: "git-manager"), NOT the main agent.
Rationale: git-manager enforces conventional commits, prevents hook bypasses, and handles PR creation with structured summaries.
Related
changelog
branch-comparison
[IMPORTANT] Use TaskCreate to break ALL work into small tasks BEFORE starting — including tasks for each file read. This prevents context loss from long files. For simple tasks, AI MUST ATTENTION ask user whether to skip.
Sub-Agent Selection — Full routing contract: .claude/skills/shared/sub-agent-selection-guide.md
Rule: Route specialized domains (architecture, security, performance, DB, E2E, integration-test, git) to the matching specialist agent (see guide above) — NEVER use code-reviewer for these. — why: code-reviewer lacks each domain's checklist, so specialized issues slip through.
AI Mistake Prevention — Failure modes to avoid on every task:
Re-read files after context changes. Context compaction, resume, or long-running work can make memory stale; verify current files before acting.
Verify generated content against source evidence. AI hallucinates APIs, names, claims, and document facts. Check the relevant source before documenting or referencing.
Check downstream references before deleting or renaming. Removing an artifact can stale docs, generated mirrors, configs, and callers; map references first.
Trace the full impact chain after edits. Changing a definition can miss derived outputs and consumers. Follow the affected chain before declaring done.
Verify ALL affected outputs, not just the first. One green check is not all green checks; validate every output surface the change can affect.
Assume existing values are intentional — ask WHY before changing OR flagging one as a defect. Before changing or reporting a constant, limit, flag, cutoff, wording, or pattern, read nearby context and history, the CALLER's ordering, and 2+ sibling call sites of the same convention. A doc stating WHAT without WHY is missing rationale, not proof of a missing guard.
Surface ambiguity before acting — don't pick silently. Multiple valid interpretations require an explicit question or stated assumption with risk.
Assert the outcome your system owns, not the intermediate state your infrastructure owns. When verifying async work, assert the final business state — never the delivery/retry bookkeeping held in shared infrastructure that any co-running process can write. Such a check passes when run alone and flakes the moment anything else shares that infrastructure.
Keep shared guidance role-relevant. Universal guidance must help every receiving skill or agent; code-specific obligations belong only in code-specific protocols.
Estimation Framework — Bottom-up first; SP DERIVED; output min-max range when likely ≥3d. Stack-agnostic. Baseline: 3-5yr dev, 6 productive hrs/day. AI estimate assumes Claude Code + project context.
Method:
- Blast Radius pass (below) — drives code AND test cost
- Decompose phases → hours/phase →
bottom_up_hours = Σ phase_hours
likely_days = ceil(bottom_up_hours / 6) × productivity_factor
- Sum Risk Margin (base + add-ons) →
max_days = likely_days × (1 + margin)
min_days = likely_days × 0.9
- Output as range when
likely_days ≥3; single point allowed <3 (still record margin)
man_days_ai = same range × AI speedup
story_points DERIVED from likely_days via SP-Days — NEVER driver. Disagreement >50% → trust bottom-up
Productivity factor: 0.8 strong scaffolding+codegen+AI hooks · 1.0 mature default · 1.2 weak patterns · 1.5 greenfield
Cost Driver Heuristic (apply BEFORE work-type row):
- UI dominates in CRUD/business apps — 1.5-3x backend (states, validation, responsive, a11y, polish)
- Backend dominates ONLY: multi-aggregate invariants, cross-service contracts, schema migrations, heavy query/perf, new event flows
Reuse-vs-Create axis (PRIMARY lever, per layer):
| UI tier |
Cost |
| Reuse component on existing screen |
0.1-0.3d |
| Add control/column to existing screen |
0.3-0.8d |
| Compose components into NEW screen |
1-2d |
| NEW screen, custom layout/states/validation |
2-4d |
| NEW shared/common component (themed, tested) |
3-6d+ |
| Backend tier |
Cost |
| Reuse query/handler from new place |
0.1-0.3d |
| Small update existing handler/entity |
0.3-0.8d |
| NEW query on existing repo/model |
0.5-1d |
| NEW command/handler on existing aggregate (additive) |
1-2d |
| NEW aggregate/entity (repo, validation, events) |
2-4d |
| NEW cross-service contract OR schema migration |
2-4d each |
| Multi-aggregate invariant / heavy domain rule |
3-5d |
Rule: Sum tiers across UI+backend+tests, apply productivity factor. Reuse short-circuits tiers — call out.
Test-Scope drivers (compute test_count EXPLICITLY — "+tests" hand-wave is #1 failure):
| Driver |
Count |
| Happy-path journeys |
1 per story / AC main flow |
| State-machine transitions |
reachable transitions × allowed actors |
| Multi-entity state combos |
state(A) × state(B) — REACHABLE only, not Cartesian |
| Authorization matrix |
(owner, non-owner, elevated, unauth) × each mutation |
| Validation rules |
1 per required field / boundary / format / cross-field |
| UI states (per new screen/dialog) |
happy, loading, empty, error, partial — present only |
| Negative paths / invariants |
1 per violatable business rule |
| Test tier (Trad, incl. setup+assert+flake) |
Cost |
| 1-5 cases, fixtures reused |
0.3-0.5d |
| 6-12 cases, 1 new fixture |
0.5-1d |
| 13-25 cases, multi-entity setup |
1-2d |
| 26-50 cases OR new state-machine coverage |
2-3d |
| >50 cases OR full E2E journey |
3-5d |
Test multipliers: new fixture/seed harness +0.5d · cross-service/bus assertion +0.3d each · UI E2E ×1.5 · each new role +1-2 cases
Blast Radius (mandatory pre-pass — affects code AND test):
- Files/components directly modified — count
- Of those, "complex" (>500 LOC, multi-handler, central, frequently-modified) — count
- Downstream consumers (callers, event subscribers, cross-service) — list
- Shared/common code touched (multi-app blast) — yes/no
- Regression scope — areas needing re-test
Rule: Complex touch → add risk_factors. Each downstream consumer → +1-3 regression cases. Blast >5 areas OR >2 complex → re-evaluate SPLIT before estimating.
Risk Margin (drives max bound):
| likely_days |
Base margin |
| <1d trivial |
+10% |
| 1-2d small additive |
+20% |
| 3-4d real feature |
+35% |
| 5-7d large |
+50% |
| 8-10d very large |
+75% |
| >10d |
+100% AND flag SHOULD SPLIT |
Risk-factor add-ons (additive — enumerate in risk_factors):
| Factor |
+margin |
touches-complex-existing-feature (>500 LOC, multi-handler, central) |
+20% |
cross-service-contract change |
+25% |
schema-migration-on-populated-data |
+25% |
new-tech-or-unfamiliar-pattern |
+30% |
regression-fan-out (≥3 downstream areas re-test) |
+20% |
performance-or-latency-critical |
+20% |
concurrency-race-event-ordering |
+25% |
shared-common-code (multi-consumer/multi-app) |
+25% |
unclear-requirements-or-design |
+30% |
Collapse rule: total margin >100% → STOP, split (padding past 2x is dishonesty). Margin <15% on likely_days ≥5 → under-estimated, widen.
Work-Type Caps (hard ceilings on likely_days):
| Work type |
Max SP |
Max likely |
| Single field / config flag / style fix |
1 |
0.5d |
| Add property to existing model + bind to existing UI |
2 |
1d |
| Additive endpoint + minor UI control (button/menu/column), reuses fixtures |
3 |
2-3d |
| Additive endpoint + NEW UI surface OR additive multi-layer + new domain rule + 2+ test files |
5 |
3-5d |
| NEW model/aggregate OR migration OR cross-module contract OR heavy test (>1.5d) OR NEW UI + non-trivial backend |
8 |
5-7d |
| NEW UI surface + (NEW aggregate OR migration OR cross-service contract) |
13 |
SHOULD split |
| Cross-service contract + migration combined |
13 |
SHOULD split |
| Beyond |
21 |
MUST split |
SP→Days (validation only): 1=0.5d/0.25d · 2=1d/0.35d · 3=2d/0.65d · 5=4d/1.0d · 8=6d/1.5d · 13=10d/2.0d (Trad/AI likely)
AI speedup: SP 1≈2x · 2-3≈3x · 5-8≈4x · 13+≈5x. AI cost = (code_gen × 1.3) + (test_gen × 1.3) (30% review overhead).
MANDATORY frontmatter:
story_points: <n>
complexity: low | medium | high | critical
man_days_traditional: '<min>-<max>d' # range when likely ≥3d; '<N>d' when <3d
man_days_ai: '<min>-<max>d'
risk_margin_pct: <n> # base + add-ons
risk_factors: [touches-complex-existing-feature, regression-fan-out] # closed-list from add-ons; []
…(truncated)
1---2name: commit-33description: [Git] Use when asked to "commit", "stage and commit", "save changes", or after completing implementation tasks. Flag: --push (a.k.a. "commit and push") stages + commits + pushes to remote in one shot.4---56## Quick Summary78**Goal:** Stage changes and create well-structured git commits following Conventional Commits format — and, when code changed, gate the commit on a user decision to verify (via `/workflow-integration-test-green`, which drives the suite to green), confirm already-verified, or explicitly skip (default: verify first). Every commit message body OPENS with a mandatory `Estimate:` line carrying the derived story points and AI man-days for that staged diff.910**Summary:** (read-this-if-nothing-else digest — purpose + ALL main steps + gates)1112- **PURPOSE** — produce a commit whose message a future reader can act on WITHOUT opening the diff: conventional subject, an `Estimate:` first body line, a purpose→what→how body, and a per-area Reviewers block. Three things are computed BEFORE the message exists (reviewers, estimate, doc triage) because they must live INSIDE it.13- **STEP 0 — BYPASS MARKER.** Create `tmp/claude-temp/.commit-skill-active` before any `git add`/`git commit`, and **ALWAYS remove it afterwards** — success or failure.14- **STEP 1-2 — ANALYZE + STAGE.** `git status` / `git diff --cached` / `git diff` / `git log --oneline -5`, then stage.15- **STEP 2.5 — DOCS TRIAGE.** Staged files matching doc-impact patterns → run `/docs-update`, re-stage the doc changes.16- **STEP 2.7 — IDENTIFY REVIEWERS** (pre-commit, read-only): last author per staged file vs `HEAD`, commit author EXCLUDED, grouped BY AREA with the focus each owns.17- **STEP 2.9 — DERIVE THE ESTIMATE** via the carried `SYNC:estimation-framework` against the STAGED diff (or reuse the implemented plan/PBI/story frontmatter with `(source: <path>)`). SP is DERIVED from `likely_days`, never eyeballed; discount generated/lockfile/docs churn first.18- **STEP 3 — GENERATE MESSAGE.** Subject `type(scope): description`; body OPENS with the Estimate line, then purpose/kind → what changed → how it works, then the Reviewers block.19- **STEP 3.5 — TEST-VERIFY GATE (BLOCKING when code changed).** `AskUserQuestion`, default **verify** via `/workflow-integration-test-green`. Only an explicit **Yes — already verified** or **Skip** proceeds; NEVER choose skip on the user's behalf. If the gate mutates the staged set, **re-stage AND re-derive the estimate**.20- **STEP 4 — COMMIT** with the HEREDOC form (subject → blank → Estimate → body → Reviewers → footer).21- **STEP 5 — VERIFY** via `git status` + `git log`; confirm the first body line IS the Estimate line, then re-present the reviewer assignment.22- **STEP 6 — REFRESH THE CODE GRAPH (post-commit, BACKGROUND, non-blocking).** Only when `.code-graph/` exists: fire `/graph-build --scope=sync` in the background so the commit that just moved HEAD is re-parsed AND the graph's `last_synced_commit` advances with it. NEVER blocks or gates the commit; a failure is reported, never retried inline.23- **FLAG** — `--push` (a.k.a. "commit and push") stages + commits + pushes via `git-manager`. Without it: **STOP after the commit**; NEVER push unprompted.2425**Workflow:**26271. **Analyze Changes** — Run git status/diff to understand staged and unstaged changes282. **Stage Changes** — Add relevant files (specific or all)293. **Identify Reviewers** — from git history, list relevant reviewers (last author per touched file vs `HEAD`, excluding the commit author) and the area each must focus on — computed BEFORE the commit so the block can be embedded in the message body304. **Derive Estimate** — Apply the carried `SYNC:estimation-framework` to the staged diff (or reuse the frontmatter of the plan/PBI/story this commit implements) to derive `story_points` + `man_days_ai` — computed BEFORE the message so the numbers can head the body315. **Generate Message** — Detect type (feat/fix/refactor/etc.), extract scope from paths, write subject, open the body with the **Estimate** line from step 4, add a detailed body structured as **purpose/kind → what changed → how it works**, and append the **Reviewers** block from step 3326. **Test-Verify Gate** — When staged changes include code that might need tests, ask the user (`AskUserQuestion`, default **verify**) to verify via `/workflow-integration-test-green`, confirm **Yes — already verified**, or explicitly **Skip**. Default = verify first, and verify means drive the suite to green, not merely report it337. **Commit** — Create commit with HEREDOC (title + Estimate line + detailed summary + Reviewers block + attribution footer)348. **Verify** — Confirm with git status and git log3536**Key Rules:**3738- **Stamp the estimate on the FIRST body line** — every commit message opens its body with `Estimate: <n> SP | man_days_ai: <x>d | man_days_traditional: <y>d`. Story points and AI man-days are MANDATORY and DERIVED bottom-up per the carried `SYNC:estimation-framework` (or reused from the plan/PBI/story frontmatter this commit implements); the number describes THIS staged diff only39- Write a detailed body — **purpose/kind → what changed → how it works** — so the next human reading `git log`/`git blame` understands the change without opening the diff. As detailed as the change needs (wrap ~72 chars); no title-only commits for non-trivial changes40- Embed a **Reviewers** block in the commit message — the per-area reviewers (last author per touched file vs `HEAD`, commit author excluded) — computed BEFORE committing so it lives in the message body, not just as a side report41- When staged changes include code that might need tests, **gate the commit on test verification** — ask the user to verify via `/workflow-integration-test-green` (default), confirm already-verified, or explicitly skip; only an explicit **Yes** or **Skip** proceeds straight to commit, and the agent NEVER chooses skip on the user's behalf42- Stop after the commit; push only when the user explicitly requests it (or passes `--push` / says "commit and push" → stage + commit + push via `git-manager`)43- Never commit secrets, credentials, or .env files44- Never use `--amend` or `--no-verify` unless explicitly requested45- Include `Generated with [Claude Code]` attribution footer4647**Be skeptical. Apply critical thinking, sequential thinking. Every claim needs traced proof, confidence percentages (Idea should be more than 80%).**4849# Git Commit Skill5051Stage changes and create well-structured git commits following Conventional Commits format.5253## IMPORTANT: Bypass git-commit-block Hook5455Before running any `git add` or `git commit` commands, create the marker file to bypass the `git-commit-block` hook:5657```bash58PROJ=$(git rev-parse --show-toplevel) && mkdir -p "$PROJ/tmp/claude-temp" && touch "$PROJ/tmp/claude-temp/.commit-skill-active"59```6061After committing (success or failure), **always** clean up the marker:6263```bash64rm -f "$(git rev-parse --show-toplevel)/tmp/claude-temp/.commit-skill-active"65```6667## Workflow6869### Step 1: Analyze Changes7071```bash72# Check current status (never use -uall flag)73git status7475# See staged changes76git diff --cached7778# See unstaged changes79git diff8081# Check recent commit style82git log --oneline -583```8485### Step 2: Stage Changes8687```bash88# Stage all changes89git add .9091# Or stage specific files92git add <file-path>93```9495### Step 2.5: Docs-Update Triage9697Before committing, check if staged files impact documentation:98991. Run `git diff --name-only --cached` to list staged files1002. Check if any staged file matches doc-impact patterns (resolve the concrete backend/frontend source paths from the project's structure reference / `docs/project-config.json`):101 - changes under the backend service source paths (per project config) → may impact `docs/specs/`102 - `.claude/skills/**` → may impact `.claude/docs/skills/`103 - `.claude/hooks/**` → may impact `.claude/docs/hooks/`104 - `.claude/workflows.json` → may impact `CLAUDE.md` workflow table105 - changes under the frontend app source paths (per project config) → may impact frontend pattern docs1063. If matches found: invoke `/docs-update` skill, then re-stage any doc changes with `git add`1074. If no matches: skip (log "No doc-impacting files staged")108109> `/docs-update`'s Phase 1 already runs `/prompt-enhance <doc>` on every `docs/project-reference/**` doc it PATCHES (see `docs-update` Step 1.3), keeping the doc concise yet AI-valuable before commit re-stages it — do not invoke `/prompt-enhance` again here.110111### Step 2.7: Identify Reviewers (pre-commit — feeds the message)112113Runs **BEFORE** the commit so the result can be embedded in the commit message body (see Step 3). Read-only (git log/blame only) — it NEVER blocks the commit and never messages anyone.114115For each **staged** file, find the **LAST author who touched it** (against `HEAD`, the soon-to-be parent) — that author is the natural reviewer for the area.116117Rules:118119- **EXCLUDE the commit author** from the "ask to review" list (you don't ask yourself to review) — but still surface files where the author is the only prior toucher as **author-owned, no external reviewer**.120- **Brand-new files (no prior history)** → mark `NEW FILE — reviewer = owner of its source/sibling file`.121- **GROUP reviewers by change AREA** (which feature/subsystem each owns) and state WHICH AREA each must focus on — not a flat name list.122- Fetch each reviewer's email for tagging.123124Collect the raw last-author-per-staged-file data:125126```bash127# Staged files in this pending commit128git diff --cached --name-only \129 | while read -r f; do130 author=$(git log -1 --format='%an' HEAD -- "$f" 2>/dev/null)131 email=$(git log -1 --format='%ae' HEAD -- "$f" 2>/dev/null)132 date=$(git log -1 --format='%ad' --date=short HEAD -- "$f" 2>/dev/null)133 [ -z "$author" ] && author="(NEW FILE — reviewer = source/sibling owner)" && date="-"134 printf '%s\t%s\t%s\t%s\n' "$author" "$email" "$date" "$f"135 done136```137138Then: collapse by author, map each author's files to the change area, drop the commit author, and render the **Reviewers** block to embed in the commit message (Step 3) and to present to the user:139140| Reviewer | Email | Focus area | Files |141| -------- | ----- | ---------- | ----- |142143Follow the table with a short **recommended review assignment by feature** list (area → reviewer). The skill does NOT auto-message anyone — this is the user's deliverable.144145### Step 2.9: Derive the Estimate (pre-commit — feeds the message)146147Runs **BEFORE** the commit so `story_points` and `man_days_ai` can head the message body (Step 3). Apply the **`SYNC:estimation-framework`** block this skill carries (see below) to the **OBSERVED staged scope** — post-hoc, with full diff visibility.148149**Source of the numbers — prefer an approved artifact over a fresh guess:**150151| Situation | Source of `story_points` / `man_days_ai` |152| ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |153| Commit implements a plan / PBI / story whose frontmatter already carries estimates | REUSE its `story_points` + `man_days_ai`; append `(source: <path>)` to the Estimate line |154| Commit is a PARTIAL slice of such an artifact | Derive the slice bottom-up — NEVER copy the whole artifact's number onto a partial commit |155| No estimate artifact exists | Derive bottom-up from the staged diff per the framework |156157**Derivation (bottom-up — SP is DERIVED, never eyeballed):**1581591. **Blast-radius pass** on `git diff --cached --stat` — touched areas, complex files (>500 LOC / central / multi-handler), downstream consumers, shared/common code.1602. Sum the **Reuse-vs-Create** tiers across UI + backend + tests → `bottom_up_hours`.1613. `likely_days = ceil(bottom_up_hours / 6) × productivity_factor`.1624. `story_points` = closest **SP→Days** bucket. Disagreement >50% → trust bottom-up and downgrade SP.1635. `man_days_ai` = the AI likely column for that SP (1≈0.25d · 2≈0.35d · 3≈0.65d · 5≈1.0d · 8≈1.5d · 13≈2.0d), reconciled against the bottom-up result; it already includes the 30% review overhead.1646. `man_days_traditional` = the no-AI likely column (1≈0.5d · 2≈1d · 3≈2d · 5≈4d · 8≈6d · 13≈10d), same reconciliation.165166**Anti-inflation (discount BEFORE estimating — same guardrail `/git-developer-performance` applies):** generated code, lockfiles, ORM/designer snapshots, i18n re-sorting, bulk reformatting, and pure docs/spec churn earn **no** story points. A 4 000-line lockfile bump is 1 SP, not 8.167168**Scope of the number:** the estimate describes **THIS commit's staged diff only** — not the branch, not the whole feature it belongs to. A `--push` run does not change this.169170> **Never block on the estimate.** It is derived from evidence already on disk (the staged diff), so it never asks the user and never gates the commit. If the diff is genuinely unestimable (e.g. a pure merge commit with no resolved content), emit `Estimate: 0 SP | man_days_ai: 0d — integration only, no authored change` rather than omitting the line.171172### Step 3: Generate Commit Message173174Analyze staged changes and generate message following **Conventional Commits**:175176```177<type>(<scope>): <subject>178179Estimate: <story_points> SP | man_days_ai: <x>d | man_days_traditional: <y>d180181<detailed summary of changes>182183Reviewers:184- <area>: <Reviewer Name> <email> — focus on <what they own>185```186187#### Type Detection188189| Change Pattern | Type |190| ----------------------- | ---------- |191| New file/feature | `feat` |192| Bug fix, error handling | `fix` |193| Code restructure | `refactor` |194| Documentation only | `docs` |195| Tests only | `test` |196| Dependencies, config | `chore` |197| Performance improvement | `perf` |198| Formatting only | `style` |199200#### Scope Rules201202Extract from file paths:203204- `{configured-source-root}/auth/` → `auth`205- `.claude/skills/` → `claude-skills`206- `libs/{shared-lib}/` → `{shared-lib}`207- Multiple unrelated areas → omit scope208209#### Subject Rules210211- Imperative mood ("add" not "added")212- Lowercase start213- No period at end214- Max 50 characters215216#### Estimate Line (MANDATORY — the FIRST line of the body)217218```219Estimate: <story_points> SP | man_days_ai: <x>d | man_days_traditional: <y>d220```221222- Placed **immediately after the blank line that follows the subject** — above purpose/what/how. NEVER in the footer, NEVER folded into the subject (the subject stays imperative, lowercase, ≤50 chars per Conventional Commits), NEVER omitted.223- `story_points` — Fibonacci `1 | 2 | 3 | 5 | 8 | 13 | 21`, DERIVED per Step 2.9. **Required.** `0` is the ONE value outside that set, reserved for the unestimable case Step 2.9 names (a pure merge/integration commit with no authored content) — NEVER as a rounding-down of real work.224- `man_days_ai` — AI-assisted man-days for this staged diff (Claude Code + project context, review overhead included). **Required.**225- `man_days_traditional` — the no-AI baseline (3–5yr dev, 6 productive hrs/day). **Recommended** — include it whenever derived — why: alone, `man_days_ai` is an absolute figure nobody can calibrate, while the pair makes the AI leverage on THIS diff readable straight from `git log`. Written for a human reader: `/git-developer-performance` derives its own numbers from the diff rather than reading this line (its `git log` format stops at `%s` — `.claude/skills/git-developer-performance/scripts/git-developer-performance.cjs:290`), so the pair earns its place by what a person reads, not by what a tool consumes.226- **Ranges** are allowed and preferred once `likely_days ≥3`: `man_days_ai: 1.0-1.5d | man_days_traditional: 4-6d`.227- Append ` (source: <path>)` when the numbers were REUSED from a plan/PBI/story frontmatter instead of derived from the diff.228- SP ≥13 on a single commit → the commit is doing too much; say so in the body ("SHOULD have been split") rather than quietly shipping the number.229230#### Body Rules (MANDATORY) — write so a human understands fastest231232> Body is the deliverable. Optimize for the next person running `git log` / `git blame` — they understand the change **without opening the diff**. As detailed as the change needs; no artificial brevity limit — wrap ~72 chars, stop once nothing new said. Title-only commit FORBIDDEN for any non-trivial change. — why: the diff shows WHAT; the body must carry WHY + HOW, which the diff cannot.233234Three parts (omit one only when genuinely empty):2352361. **Purpose / kind** — name the kind AND why it exists: feature · bug fix (state the symptom removed) · enhancement · refactor (state behaviour-preserving) · perf · security · chore. 1–2 sentences answering _"what problem does this solve?"_.2372. **What changed** — concrete edits grouped by **behaviour**, never by file. Each bullet specific — NEVER "update code", "fix stuff", "minor fixes".2383. **How it works / why this way** — the part reviewers need: mechanism, key logic, invariants relied on, edge cases preserved, and any non-obvious decision ("did X instead of obvious Y because Z"). Focus the non-obvious; NEVER narrate boilerplate. Ordering/timing/security invariant or subtle failure mode → call it out explicitly.239240> **Teach-the-reader mindset (from the `understand` skill):** cover BOTH high-level motivation (why it matters) AND low-level logic (business rules, edge cases). Surface what a reader would NOT guess from the diff — write the explanation you would want to receive.241242**Detail dial — scale body to the change:**243244| Change size | Body depth |245| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------- |246| Trivial (typo, rename, formatting) | Purpose line + 1 bullet; skip "how it works" |247| Normal (feature/fix, single area) | Purpose + 2–5 "what" bullets + a short "how it works" |248| Complex (cross-cutting, subtle bug) | Purpose + grouped "what" + a full "how it works" that spells out the key invariant / edge case / why-this-over-that |249250### Step 3.5: Test-Verify Gate (blocking — only when code changed)251252Decide whether the staged changes carry **code that might need tests** — why: this gate is the only thing standing between an untested behaviour change and permanent history.253254**Trigger detection** — run `git diff --cached --name-only` and classify the staged files:255256- **Code that might need tests** → any change to production/source code: backend service source, frontend app source, shared libraries, scripts, hooks (`.cjs`), or other executable logic (resolve concrete source roots from `docs/project-config.json` / the project structure reference).257- **NOT a trigger (skip the gate)** → the staged set is _only_ docs (`docs/**`, `*.md`), specs (`docs/specs/**`), test-spec/config text, changelog, or other non-executable content with no source-code change.258259**If the gate is NOT triggered:** log `Test-Verify Gate: skipped (no code changes staged)` and continue to Step 4.260261**If the gate IS triggered:** STOP and ask the user with `AskUserQuestion` (default option is **No**):262263> Header: `Test verify`264> Question: `Staged code changes may need tests. Verify before committing, or skip?`265> Options (in order — first is the default):266>267> 1. `Verify now — run /workflow-integration-test-green` (Recommended) — do NOT commit yet; activate the `workflow-integration-test-green` workflow, which verifies the suite AND drives any failure to green (verify → adjudicate → fix → review → re-verify) before returning. Proceed to Step 4 only once the whole suite is green; if it escalates instead of converging, surface that and stop (no commit).268> 2. `Yes — already verified` — the user confirms the integration tests were run and passed; proceed directly to Step 4 (Commit).269> 3. `Skip — commit without verifying` — the user's explicit, recorded decision to commit unverified code; proceed to Step 4 and note `Test-Verify Gate: skipped by user` in the response (never in the commit message).270271Rules:272273- **Default is option 1 (verify).** If the user does not actively choose "Yes" or "Skip", treat it as verify-first — never commit unverified code on assumption.274- **Verify routes to `workflow-integration-test-green`, not to a bare verify run** — why: a bare `integration-test-verify` only reports the failures, leaving the user to hand-carry each one; the workflow owns the converge-to-green loop, so choosing "verify" actually clears the suite instead of just describing it.275- **Yes is an explicit user assertion** that the integration tests were run and passed; honour it and commit.276- **Skip is the user's call, and it is theirs alone to make.** Offer it, never recommend it, and NEVER select it yourself — why: an agent that can skip its own gate has no gate.277- Re-run this gate only once per commit; after a `verify → green`, proceed to commit without re-asking.278- **If the verify branch changed ANY file, re-stage and RE-DERIVE before Step 4.** Option 1 can land test or source fixes AFTER Step 2.9 already ran, so the diff the estimate described is no longer the diff being committed. Mirror Step 2.5: re-stage the new changes with `git add`, then re-run Step 2.9 over the updated `git diff --cached` and put the fresh numbers in the message. Options 2 and 3 mutate nothing, so the original Step 2.9 numbers stand.279- This gate is independent of `--push`: it runs before the commit in every mode.280281### Step 4: Commit282283Use HEREDOC for proper formatting:284285```bash286git commit -m "$(cat <<'EOF'287type(scope): subject288289Estimate: 3 SP | man_days_ai: 0.65d | man_days_traditional: 2d290291- summarize key change 1 with intent292- summarize key change 2 with impact293294Reviewers:295- <area>: Reviewer Name <reviewer@email> — focus on <what they own>296297Generated by AI298EOF299)"300```301302> The **Estimate** line comes from Step 2.9 — re-derived after Step 3.5 if that gate changed the staged set — and is ALWAYS the first line of the body.303> The **Reviewers** block comes from Step 2.7 (last author per staged file vs `HEAD`, commit author excluded, grouped by area). Omit the block only when every staged file is brand-new or author-owned with no external reviewer — in that case state `Reviewers: none (author-owned / new files)`.304305### Step 5: Verify306307```bash308git status309git log -1310```311312Confirm the committed body's FIRST line IS the **Estimate** line from Step 2.9 (`Estimate: <n> SP | man_days_ai: <x>d …`) — missing → the message is non-conformant; re-derive and record it, NEVER leave it out. Then confirm the body carries the **Reviewers** block from Step 2.7 (or the explicit `Reviewers: none (author-owned / new files)` line). Re-present the per-area reviewer assignment to the user as the final deliverable — why: they need it to request the right reviewers on the resulting PR.313314### Step 6: Refresh Code Graph (post-commit — background, non-blocking)315316**Skip entirely (silently) when `.code-graph/` does not exist** — the project has no knowledge graph and there is nothing to refresh.317318When it does exist, fire `/graph-build --scope=sync` **in the background** immediately after Step 5 verifies the commit — one Bash call with `run_in_background: true`, so the commit never waits on it:319320```bash321if [ -d ".code-graph" ]; then python .claude/scripts/code_graph sync --json; fi322```323324- **Why after the commit, not before:** a commit MOVES `HEAD`. `sync` diffs the graph's stored `last_synced_commit` against the current `HEAD`, so running it AFTER `git commit` re-parses exactly the files this commit introduced. Run it before and `HEAD` has not moved yet, so there is nothing for it to see.325- **Why `sync` and not `update`:** `sync` is the HEAD-movement verb — it advances the stored `last_synced_commit` as well as the nodes. `update` only re-parses the working tree and leaves that bookkeeping pointing at the PRE-commit HEAD, which then reads as stale to `graph-prompt-sync` and forces a redundant re-sync on the next prompt. Committing is a HEAD move, so it takes the HEAD-move verb.326- **Why background:** the `graph-auto-update` PostToolUse hook only fires on `Edit|Write|MultiEdit`, so a commit leaves the graph's node set stale for any file the session did not itself edit (merges, checkouts, externally-changed files) — but graph freshness is an accelerator, NEVER a commit gate. It MUST NOT block, delay, or fail the commit.327- **Report** the background result briefly when it returns (files synced/added/deleted, or `up_to_date`). If it errors (Python/deps missing, lock held by a concurrent update), state the error in one line and stop — NEVER retry inline and NEVER treat it as a commit failure.328329> **Safety net, not the only net.** If this step is skipped or fails, the `graph-prompt-sync` UserPromptSubmit hook detects the moved HEAD on the next prompt and syncs then. Step 6 exists so the graph is already current for the rest of THIS session, not because the commit is the only chance to catch it.330331> The `--push` path pushes first, then refreshes the graph — the push is the user-visible operation and must not wait on graph work either.332333## Examples334335```336feat(order): add warehouse filter to list337338Estimate: 3 SP | man_days_ai: 0.65d | man_days_traditional: 2d339340- add warehouse query parameter in order list endpoint341- wire frontend filter control to request payload342- update tests for filtered and unfiltered list behavior343344Reviewers:345- order backend: Jane Doe <jane@acme.com> — focus on the list endpoint query change346- order UI: Bob Lee <bob@acme.com> — focus on the filter control wiring347348Generated by AI349350fix(validation): handle empty date range351352Estimate: 1 SP | man_days_ai: 0.25d | man_days_traditional: 0.5d353354- guard null/empty date inputs before parsing355- return validation message instead of throwing format exception356357Reviewers: none (author-owned / new files)358359Generated by AI360```361362## Critical Rules363364- **ALWAYS stage all unstaged changes** before committing — run `git add .` (or specific files) so nothing is left behind365- **Test-Verify Gate (Step 3.5):** when staged changes include code that might need tests, ask the user to verify via `/workflow-integration-test-green` (default — it converges the suite to green), confirm already-verified, or explicitly skip; only an explicit **Yes** or user-chosen **Skip** commits without verifying, and the agent NEVER picks skip itself. Bypass the gate entirely only when the staged set is docs/specs/config with no source-code change366- **Estimate line is MANDATORY and comes FIRST in the body** — `Estimate: <n> SP | man_days_ai: <x>d | man_days_traditional: <y>d`, derived bottom-up per the carried `SYNC:estimation-framework` against the STAGED diff (Step 2.9), or reused from the implemented plan/PBI/story frontmatter with `(source: <path>)`. Story points and AI man-days are required; discount generated/lockfile/docs churn before estimating367- **Stop after the commit; push** to remote only when the user explicitly requests it368- **Refresh the code graph after committing (Step 6)** — when `.code-graph/` exists, fire `/graph-build --scope=sync` in the BACKGROUND (`run_in_background: true`) so the commit that moved HEAD is re-parsed and `last_synced_commit` advances with it; skip silently when the dir is absent. Non-blocking by design: it NEVER gates, delays, or fails the commit369- **Review staged changes** before committing370- **Never commit** secrets, credentials, or .env files371- **Never use** `git commit --amend` unless explicitly requested AND the commit was created in this session AND not yet pushed372- **Never skip** hooks with `--no-verify` unless explicitly requested373- Commit message MUST include a Conventional Commit title AND a detailed body — **purpose/kind → what changed → how it works**. As detailed as the change needs (wrap ~72 chars); title-only commit FORBIDDEN for non-trivial changes374- Optimize body for the next human reading `git log` / `git blame` — surface the non-obvious (key logic, invariants, edge cases, why-this-over-that), not just a list of touched files375- Include attribution footer: `Generated by AI`376- **Embed reviewers in the commit message** — BEFORE committing (Step 2.7), surface the last author per staged file vs `HEAD` (exclude the commit author), grouped by focus area, and write it as a `Reviewers:` block in the message body so the right reviewers travel with the commit/PR. Read-only; never blocks the commit.377378## Push & PR Operations379380**Arg `--push` (a.k.a. "commit and push"):** stage + commit + push in one shot — spawn `git-manager` immediately after committing. The former standalone stage-commit-push entry point, folded in; it adds no logic beyond the push delegation below.381382This skill handles **commit** by default. Push-to-remote and PR creation delegate to the `git-manager` sub-agent (`subagent_type: "git-manager"`), which enforces conventional-commit validation, prevents `--no-verify` bypass, and creates PRs with structured summaries.383384Spawn `git-manager` after committing when the user says "push", "create PR", or "open PR".385386## Sub-Agent Type Override387388> **MANDATORY:** Push and PR operations spawn `git-manager` sub-agent (`subagent_type: "git-manager"`), NOT the main agent.389> **Rationale:** `git-manager` enforces conventional commits, prevents hook bypasses, and handles PR creation with structured summaries.390391## Related392393- `changelog`394- `branch-comparison`395396---397398> **[IMPORTANT]** Use `TaskCreate` to break ALL work into small tasks BEFORE starting — including tasks for each file read. This prevents context loss from long files. For simple tasks, AI MUST ATTENTION ask user whether to skip.399400<!-- SYNC:sub-agent-selection -->401402> **Sub-Agent Selection** — Full routing contract: `.claude/skills/shared/sub-agent-selection-guide.md`403> **Rule:** Route specialized domains (architecture, security, performance, DB, E2E, integration-test, git) to the matching specialist agent (see guide above) — NEVER use `code-reviewer` for these. — why: `code-reviewer` lacks each domain's checklist, so specialized issues slip through.404405<!-- /SYNC:sub-agent-selection -->406407<!-- SYNC:ai-mistake-prevention -->408409> **AI Mistake Prevention** — Failure modes to avoid on every task:410>411> **Re-read files after context changes.** Context compaction, resume, or long-running work can make memory stale; verify current files before acting.412> **Verify generated content against source evidence.** AI hallucinates APIs, names, claims, and document facts. Check the relevant source before documenting or referencing.413> **Check downstream references before deleting or renaming.** Removing an artifact can stale docs, generated mirrors, configs, and callers; map references first.414> **Trace the full impact chain after edits.** Changing a definition can miss derived outputs and consumers. Follow the affected chain before declaring done.415> **Verify ALL affected outputs, not just the first.** One green check is not all green checks; validate every output surface the change can affect.416> **Assume existing values are intentional — ask WHY before changing OR flagging one as a defect.** Before changing or reporting a constant, limit, flag, cutoff, wording, or pattern, read nearby context and history, the CALLER's ordering, and 2+ sibling call sites of the same convention. A doc stating WHAT without WHY is missing rationale, not proof of a missing guard.417> **Surface ambiguity before acting — don't pick silently.** Multiple valid interpretations require an explicit question or stated assumption with risk.418> **Assert the outcome your system owns, not the intermediate state your infrastructure owns.** When verifying async work, assert the final business state — never the delivery/retry bookkeeping held in shared infrastructure that any co-running process can write. Such a check passes when run alone and flakes the moment anything else shares that infrastructure.419> **Keep shared guidance role-relevant.** Universal guidance must help every receiving skill or agent; code-specific obligations belong only in code-specific protocols.420421<!-- /SYNC:ai-mistake-prevention -->422423<!-- SYNC:estimation-framework -->424425> **Estimation Framework** — Bottom-up first; SP DERIVED; output min-max range when likely ≥3d. Stack-agnostic. Baseline: 3-5yr dev, 6 productive hrs/day. AI estimate assumes Claude Code + project context.426>427> **Method:**428>429> 1. **Blast Radius pass** (below) — drives code AND test cost430> 2. Decompose phases → hours/phase → `bottom_up_hours = Σ phase_hours`431> 3. `likely_days = ceil(bottom_up_hours / 6) × productivity_factor`432> 4. Sum **Risk Margin** (base + add-ons) → `max_days = likely_days × (1 + margin)`433> 5. `min_days = likely_days × 0.9`434> 6. Output as range when `likely_days ≥3`; single point allowed `<3` (still record margin)435> 7. `man_days_ai` = same range × AI speedup436> 8. `story_points` DERIVED from `likely_days` via SP-Days — NEVER driver. Disagreement >50% → trust bottom-up437>438> **Productivity factor:** 0.8 strong scaffolding+codegen+AI hooks · 1.0 mature default · 1.2 weak patterns · 1.5 greenfield439>440> **Cost Driver Heuristic (apply BEFORE work-type row):**441>442> - **UI dominates** in CRUD/business apps — 1.5-3x backend (states, validation, responsive, a11y, polish)443> - **Backend dominates ONLY:** multi-aggregate invariants, cross-service contracts, schema migrations, heavy query/perf, new event flows444>445> **Reuse-vs-Create axis (PRIMARY lever, per layer):**446>447> | UI tier | Cost |448> | -------------------------------------------- | -------- |449> | Reuse component on existing screen | 0.1-0.3d |450> | Add control/column to existing screen | 0.3-0.8d |451> | Compose components into NEW screen | 1-2d |452> | NEW screen, custom layout/states/validation | 2-4d |453> | NEW shared/common component (themed, tested) | 3-6d+ |454>455> | Backend tier | Cost |456> | ---------------------------------------------------- | --------- |457> | Reuse query/handler from new place | 0.1-0.3d |458> | Small update existing handler/entity | 0.3-0.8d |459> | NEW query on existing repo/model | 0.5-1d |460> | NEW command/handler on existing aggregate (additive) | 1-2d |461> | NEW aggregate/entity (repo, validation, events) | 2-4d |462> | NEW cross-service contract OR schema migration | 2-4d each |463> | Multi-aggregate invariant / heavy domain rule | 3-5d |464>465> **Rule:** Sum tiers across UI+backend+tests, apply productivity factor. Reuse short-circuits tiers — call out.466>467> **Test-Scope drivers (compute test_count EXPLICITLY — "+tests" hand-wave is #1 failure):**468>469> | Driver | Count |470> | --------------------------------- | ------------------------------------------------------ |471> | Happy-path journeys | 1 per story / AC main flow |472> | State-machine transitions | reachable transitions × allowed actors |473> | Multi-entity state combos | state(A) × state(B) — REACHABLE only, not Cartesian |474> | Authorization matrix | (owner, non-owner, elevated, unauth) × each mutation |475> | Validation rules | 1 per required field / boundary / format / cross-field |476> | UI states (per new screen/dialog) | happy, loading, empty, error, partial — present only |477> | Negative paths / invariants | 1 per violatable business rule |478>479> | Test tier (Trad, incl. setup+assert+flake) | Cost |480> | ------------------------------------------ | -------- |481> | 1-5 cases, fixtures reused | 0.3-0.5d |482> | 6-12 cases, 1 new fixture | 0.5-1d |483> | 13-25 cases, multi-entity setup | 1-2d |484> | 26-50 cases OR new state-machine coverage | 2-3d |485> | >50 cases OR full E2E journey | 3-5d |486>487> **Test multipliers:** new fixture/seed harness +0.5d · cross-service/bus assertion +0.3d each · UI E2E ×1.5 · each new role +1-2 cases488>489> **Blast Radius (mandatory pre-pass — affects code AND test):**490>491> 1. Files/components directly modified — count492> 2. Of those, "complex" (>500 LOC, multi-handler, central, frequently-modified) — count493> 3. Downstream consumers (callers, event subscribers, cross-service) — list494> 4. Shared/common code touched (multi-app blast) — yes/no495> 5. Regression scope — areas needing re-test496>497> **Rule:** Complex touch → add `risk_factors`. Each downstream consumer → +1-3 regression cases. Blast >5 areas OR >2 complex → re-evaluate SPLIT before estimating.498>499> **Risk Margin (drives max bound):**500>501> | likely_days | Base margin |502> | ------------------- | ------------------------------- |503> | <1d trivial | +10% |504> | 1-2d small additive | +20% |505> | 3-4d real feature | +35% |506> | 5-7d large | +50% |507> | 8-10d very large | +75% |508> | >10d | +100% AND **flag SHOULD SPLIT** |509>510> **Risk-factor add-ons (additive — enumerate in `risk_factors`):**511>512> | Factor | +margin |513> | --------------------------------------------------------------------- | ------- |514> | `touches-complex-existing-feature` (>500 LOC, multi-handler, central) | +20% |515> | `cross-service-contract` change | +25% |516> | `schema-migration-on-populated-data` | +25% |517> | `new-tech-or-unfamiliar-pattern` | +30% |518> | `regression-fan-out` (≥3 downstream areas re-test) | +20% |519> | `performance-or-latency-critical` | +20% |520> | `concurrency-race-event-ordering` | +25% |521> | `shared-common-code` (multi-consumer/multi-app) | +25% |522> | `unclear-requirements-or-design` | +30% |523>524> **Collapse rule:** total margin >100% → STOP, split (padding past 2x is dishonesty). Margin <15% on `likely_days ≥5` → under-estimated, widen.525>526> **Work-Type Caps (hard ceilings on `likely_days`):**527> | Work type | Max SP | Max likely |528> | --- | --- | --- |529> | Single field / config flag / style fix | 1 | 0.5d |530> | Add property to existing model + bind to existing UI | 2 | 1d |531> | **Additive endpoint + minor UI control** (button/menu/column), reuses fixtures | **3** | **2-3d** |532> | Additive endpoint + **NEW UI surface** OR additive multi-layer + new domain rule + 2+ test files | 5 | 3-5d |533> | NEW model/aggregate OR migration OR cross-module contract OR heavy test (>1.5d) OR NEW UI + non-trivial backend | 8 | 5-7d |534> | NEW UI surface + (NEW aggregate OR migration OR cross-service contract) | 13 | SHOULD split |535> | Cross-service contract + migration combined | 13 | SHOULD split |536> | Beyond | 21 | MUST split |537>538> **SP→Days (validation only):** 1=0.5d/0.25d · 2=1d/0.35d · 3=2d/0.65d · 5=4d/1.0d · 8=6d/1.5d · 13=10d/2.0d (Trad/AI likely)539> **AI speedup:** SP 1≈2x · 2-3≈3x · 5-8≈4x · 13+≈5x. AI cost = `(code_gen × 1.3) + (test_gen × 1.3)` (30% review overhead).540>541> **MANDATORY frontmatter:**542>543> ```yaml544> story_points: <n>545> complexity: low | medium | high | critical546> man_days_traditional: '<min>-<max>d' # range when likely ≥3d; '<N>d' when <3d547> man_days_ai: '<min>-<max>d'548> risk_margin_pct: <n> # base + add-ons549> risk_factors: [touches-complex-existing-feature, regression-fan-out] # closed-list from add-ons; []550551…(truncated)