Conventional Commit Generator
Generate commit messages following the Conventional Commits specification.
Workflow
FIRST: Read .ai-factory/config.yaml if it exists to resolve:
- Paths:
paths.description, paths.architecture, paths.rules_file, paths.roadmap, paths.rules, paths.plan, and paths.plans
- Language:
language.ui for prompts and commit message conventions
- Workflow:
workflow.plan_id_format for read-only active plan discovery (slug default; sequential uses numbered full-plan lookup)
- Git preference:
git.enabled, git.create_branches, and git.skip_push_after_commit for active plan discovery and post-commit push behavior
- Rules hierarchy:
rules.base plus any named rules.<area> entries
If config.yaml doesn't exist, use defaults:
- Paths:
.ai-factory/ for context artifacts, .ai-factory/PLAN.md for paths.plan, .ai-factory/plans/ for paths.plans
- Language:
en (English)
- Workflow:
workflow.plan_id_format: slug
- Git:
git.enabled: true, git.create_branches: true
- Git preference:
skip_push_after_commit: false
Read .ai-factory/skill-context/aif-commit/SKILL.md — MANDATORY if the file exists.
This file contains project-specific rules accumulated by /aif-evolve from patches,
codebase conventions, and tech-stack analysis. These rules are tailored to the current project.
How to apply skill-context rules:
- Treat them as project-level overrides for this skill's general instructions
- When a skill-context rule conflicts with a general rule written in this SKILL.md,
the skill-context rule wins (more specific context takes priority — same principle as nested CLAUDE.md files)
- When there is no conflict, apply both: general rules from SKILL.md + project rules from skill-context
- Do NOT ignore skill-context rules even if they seem to contradict this skill's defaults —
they exist because the project's experience proved the default insufficient
- CRITICAL: skill-context rules apply to ALL outputs of this skill — including the commit
message format and conventions. If a skill-context rule says "commits MUST follow format X"
or "message MUST include Y" — you MUST comply. Generating a commit message that violates
skill-context rules is a bug.
Enforcement: After generating any output artifact, verify it against all skill-context rules.
If any rule is violated — fix the output before presenting it to the user.
Analyze Changes
- Run
git status to see staged files
- Run
git diff --cached to see staged changes
- If nothing staged, show warning and suggest staging
Resolve Active Plan Context (Read-Only, Optional)
- Resolve active plan using this read-only priority:
@<plan-file-or-directory> argument, when the argument starts with @
- branch-based full plan or ultra bundle in
paths.plans
- single full plan in
paths.plans, or a single ultra bundle there
- fast plan at
paths.plan
- If the argument does not start with
@, keep treating it as commit scope/context.
- Legacy
@<plan-file> syntax remains valid; the broader form additionally
accepts an ultra directory or its index.md.
- For branch-based full plan lookup:
- get current branch with
git branch --show-current when git.enabled = true
- replace every
/ with - to get <branch-stem>
- when
workflow.plan_id_format = sequential, use Glob for both
paths.plans/[0-9][0-9][0-9][0-9]_<branch-stem>.md and
paths.plans/[0-9][0-9][0-9][0-9]_<branch-stem>/index.md
- Read every directory candidate and retain it only when
index.md
contains exactly one <!-- aif:plan-mode:ultra -->
- use the highest-numbered valid artifact and emit
WARN [aif-commit] when
multiple valid candidates exist; if both shapes share the highest prefix,
prefer ultra
- if no valid sequential match exists, check
paths.plans/<branch-stem>/index.md then
paths.plans/<branch-stem>.md; Read the directory entrypoint before
selection, ignore it unless it contains exactly one ultra marker, and
warn and prefer ultra if both valid shapes exist
- If git mode is off, branch lookup cannot resolve, or no branch-based plan
exists, count root
*.md full plans plus direct child */index.md
entrypoints containing <!-- aif:plan-mode:ultra -->; exclude the resolved fast-plan
path and do not count phase files.
- Before normalizing an explicit ultra directory or treating an explicit
index.md as ultra, Read it and require exactly one
<!-- aif:plan-mode:ultra -->; otherwise STOP with a plan-integrity error.
- An automatically discovered directory entrypoint counts only when it
contains
<!-- aif:plan-mode:ultra -->; ignore unrelated */index.md files.
- If no active plan resolves or the active plan entrypoint has no
## Commit Plan, keep current staged-diff behavior unchanged.
- Never modify the active plan from this command.
Use Commit Plan Grouping When Available
If active plan contains ## Commit Plan, parse:
- commit group number/name
- task range, such as
after tasks 1-3 or tasks 4-6
- suggested conventional commit message
Read the plan's ## Tasks or ## Implementation Tasks section to map task ranges to task descriptions and any Files: hints.
For an ultra plan, resolve every task in the current commit group to its
Phase Index/details link, read each corresponding phase file, and build the
staged-path mapping from its ## Files to Change table plus the complete
## Task N specifications. Reading only index.md is insufficient.
If one phase contains tasks from multiple commit groups, use the individual
## Task N sections to distinguish file/hunk ownership; do not assign the
phase's entire file table to every group without task-level evidence.
Compare staged files/hunks with planned groups before changing staging:
- use staged file paths from
git diff --cached --name-only
- use staged hunk evidence from
git diff --cached when a file may span multiple groups
- task ranges and
Files: hints are guidance, not executable instructions
If files cannot be mapped to groups, stop and ask the user to adjust grouping.
Before using whole-file staging, compare grouped files with unstaged worktree paths from git diff --name-only.
Only use git add <files> when each planned group has a disjoint file set and no grouped file appears in git diff --name-only.
When one file spans multiple planned groups, use hunk-level staging (git add -p or git apply --cached) for each group.
If grouped files overlap unstaged worktree paths, preserve and apply the original cached patch per group (git diff --cached + git apply --cached), use hunk-level staging, or stop before changing staging.
If hunk-level staging cannot be applied confidently, stop before changing staging and ask the user to adjust grouping or commit everything together.
When a usable grouping exists, ask:
AskUserQuestion: Active plan contains a Commit Plan. How should these staged changes be committed?
Options:
1. Follow Commit Plan
2. Commit everything together
3. Adjust grouping
Follow Commit Plan → confirm the planned groups and messages, then proceed through user-confirmed multi-commit staging/commit flow.
Commit everything together → ignore plan grouping for this run and continue with the current single-message flow.
Adjust grouping → ask the user for the adjusted grouping, then validate it against staged files before committing.
Run Context Gates (Read-Only)
- Check the resolved architecture and description artifacts (use paths from config) to catch obvious scope/boundary drift
- Check the resolved RULES.md and roadmap artifacts (use paths from config) to catch rule and milestone alignment issues
- Check rules hierarchy (resolved
paths.rules_file + rules.base + named rules.<area>) for commit conventions
- Missing optional files (
ROADMAP.md, RULES.md) are WARN, not blockers
- Never modify context artifacts from this command
- If the user wants a standalone rules-only pass, suggest
/aif-rules-check; keep /aif-commit gate labels at WARN / ERROR
Determine Commit Type
feat: New feature
fix: Bug fix
docs: Documentation only
style: Code style (formatting, semicolons)
refactor: Code change that neither fixes a bug nor adds a feature
perf: Performance improvement
test: Adding or modifying tests
build: Build system or dependencies
ci: CI configuration
chore: Maintenance tasks
Identify Scope
- From file paths (e.g.,
src/auth/ → auth)
- From argument if provided
- Optional - omit if changes span multiple areas
Generate Message
- Keep subject line under 72 characters
- Use imperative mood ("add" not "added")
- Don't capitalize first letter after type
- No period at end of subject
Format
<type>(<scope>): <subject>
<body>
<footer>
Examples
Simple feature:
feat(auth): add password reset functionality
Bug fix with body:
fix(api): handle null response from payment gateway
The payment API can return null when the gateway times out.
Added null check and retry logic.
Fixes #123
Breaking change:
feat(api)!: change response format for user endpoint
BREAKING CHANGE: user endpoint now returns nested profile object
Behavior
When invoked:
Check for staged changes
Analyze the diff content
Resolve optional active plan context and use ## Commit Plan grouping when available
Run read-only context gates and summarize findings as WARN/ERROR
If commit type is feat/fix/perf and roadmap exists, check milestone linkage; if missing, warn and suggest adding linkage in commit body/footer
Propose a commit message
Confirm with the user before committing:
AskUserQuestion: Proposed commit message:
<type>(<scope>): <subject>
Options:
1. Commit as is
2. Edit message
3. Cancel
Handle user response:
- Commit as is → proceed to step 9
- Edit message → ask the user for the corrected message via
AskUserQuestion, then return to step 7 with the new message
- Cancel → stop, do NOT commit. End the workflow
Execute git commit with the confirmed message
Post-commit push handling:
If git.skip_push_after_commit = true in resolved config:
- Skip push prompt entirely
- End workflow after successful local commit
Otherwise (default behavior), offer to push:
- Show branch/ahead status:
git status -sb
- If the branch has no upstream, use:
git push -u origin <branch>
- Otherwise:
git push
AskUserQuestion: Push to remote?
Options:
1. Push now
2. Skip push
- Push now → execute push command based on upstream status:
- if branch has no upstream →
git push -u origin <branch>
- otherwise →
git push
- Skip push → end the workflow
If argument provided (e.g., /aif-commit auth):
- Use it as the scope
- Or as context for the commit message
Important
- Never commit secrets or credentials
- Review large diffs carefully before committing
/aif-commit has no implicit strict mode — context gates are warning-first unless user explicitly requests blocking behavior
- Treat the resolved architecture, roadmap, RULES.md, description, and plan artifacts as read-only context in this command
- If no active plan resolves or the active plan has no
## Commit Plan, keep current staged-diff behavior unchanged.
- If staged changes contain unrelated work (e.g., a feature + a bugfix, or changes to independent modules), suggest splitting into separate commits:
Show which files/hunks belong to which commit
Confirm split plan with the user:
AskUserQuestion: Split into separate commits?
Options:
1. Yes, split as suggested
2. No, commit everything together
3. Let me adjust the grouping
Handle user response:
- Yes, split as suggested → proceed to step 4
- No, commit everything together → proceed to step 5 (propose single commit message)
- Let me adjust the grouping → ask the user for the adjusted grouping via
AskUserQuestion, then return to step 2 with the new plan
Before changing staging, confirm whether each planned group has a disjoint file set, whether any file spans multiple groups, and whether grouped files overlap unstaged worktree paths from git diff --name-only.
If every group has a disjoint file set and no grouped file appears in git diff --name-only, unstage all with git reset HEAD, then stage and commit each group separately using git add <files> + git commit.
If grouped files overlap unstaged worktree paths, preserve each group's original cached patch before unstaging and re-apply only that patch with git apply --cached; otherwise use hunk-level staging or stop before changing staging.
If one file spans multiple groups, use hunk-level staging for each group: stage only that group's hunks with git add -p or git apply --cached, commit, then repeat for the next group.
If hunk-level staging or cached-patch application cannot be applied confidently, stop before changing staging and ask the user to adjust grouping or commit everything together.
Offer to push only after all commits are done
- NEVER add
Co-Authored-By or any other trailer attributing authorship to the AI. Commits must not contain AI co-author lines
1---2name: aif-commit3description: Create conventional commit messages by analyzing staged changes. Generates semantic commit messages following the Conventional Commits specification. Use when user says "commit", "save changes", or "create commit".4---56# Conventional Commit Generator78Generate commit messages following the [Conventional Commits](https://www.conventionalcommits.org/) specification.910## Workflow1112**FIRST:** Read `.ai-factory/config.yaml` if it exists to resolve:13- **Paths:** `paths.description`, `paths.architecture`, `paths.rules_file`, `paths.roadmap`, `paths.rules`, `paths.plan`, and `paths.plans`14- **Language:** `language.ui` for prompts and commit message conventions15- **Workflow:** `workflow.plan_id_format` for read-only active plan discovery (`slug` default; `sequential` uses numbered full-plan lookup)16- **Git preference:** `git.enabled`, `git.create_branches`, and `git.skip_push_after_commit` for active plan discovery and post-commit push behavior17- **Rules hierarchy:** `rules.base` plus any named `rules.<area>` entries1819If config.yaml doesn't exist, use defaults:20- Paths: `.ai-factory/` for context artifacts, `.ai-factory/PLAN.md` for `paths.plan`, `.ai-factory/plans/` for `paths.plans`21- Language: `en` (English)22- Workflow: `workflow.plan_id_format: slug`23- Git: `git.enabled: true`, `git.create_branches: true`24- Git preference: `skip_push_after_commit: false`2526**Read `.ai-factory/skill-context/aif-commit/SKILL.md`** — MANDATORY if the file exists.2728This file contains project-specific rules accumulated by `/aif-evolve` from patches,29codebase conventions, and tech-stack analysis. These rules are tailored to the current project.3031**How to apply skill-context rules:**32- Treat them as **project-level overrides** for this skill's general instructions33- When a skill-context rule conflicts with a general rule written in this SKILL.md,34 **the skill-context rule wins** (more specific context takes priority — same principle as nested CLAUDE.md files)35- When there is no conflict, apply both: general rules from SKILL.md + project rules from skill-context36- Do NOT ignore skill-context rules even if they seem to contradict this skill's defaults —37 they exist because the project's experience proved the default insufficient38- **CRITICAL:** skill-context rules apply to ALL outputs of this skill — including the commit39 message format and conventions. If a skill-context rule says "commits MUST follow format X"40 or "message MUST include Y" — you MUST comply. Generating a commit message that violates41 skill-context rules is a bug.4243**Enforcement:** After generating any output artifact, verify it against all skill-context rules.44If any rule is violated — fix the output before presenting it to the user.45461. **Analyze Changes**47 - Run `git status` to see staged files48 - Run `git diff --cached` to see staged changes49 - If nothing staged, show warning and suggest staging50512. **Resolve Active Plan Context (Read-Only, Optional)**52 - Resolve active plan using this read-only priority:53 1. `@<plan-file-or-directory>` argument, when the argument starts with `@`54 2. branch-based full plan or ultra bundle in `paths.plans`55 3. single full plan in `paths.plans`, or a single ultra bundle there56 4. fast plan at `paths.plan`57 - If the argument does not start with `@`, keep treating it as commit scope/context.58 - Legacy `@<plan-file>` syntax remains valid; the broader form additionally59 accepts an ultra directory or its `index.md`.60 - For branch-based full plan lookup:61 - get current branch with `git branch --show-current` when `git.enabled = true`62 - replace every `/` with `-` to get `<branch-stem>`63 - when `workflow.plan_id_format = sequential`, use `Glob` for both64 `paths.plans/[0-9][0-9][0-9][0-9]_<branch-stem>.md` and65 `paths.plans/[0-9][0-9][0-9][0-9]_<branch-stem>/index.md`66 - Read every directory candidate and retain it only when `index.md`67 contains exactly one `<!-- aif:plan-mode:ultra -->`68 - use the highest-numbered valid artifact and emit `WARN [aif-commit]` when69 multiple valid candidates exist; if both shapes share the highest prefix,70 prefer ultra71 - if no valid sequential match exists, check72 `paths.plans/<branch-stem>/index.md` then73 `paths.plans/<branch-stem>.md`; Read the directory entrypoint before74 selection, ignore it unless it contains exactly one ultra marker, and75 warn and prefer ultra if both valid shapes exist76 - If git mode is off, branch lookup cannot resolve, or no branch-based plan77 exists, count root `*.md` full plans plus direct child `*/index.md`78 entrypoints containing `<!-- aif:plan-mode:ultra -->`; exclude the resolved fast-plan79 path and do not count phase files.80 - Before normalizing an explicit ultra directory or treating an explicit81 `index.md` as ultra, Read it and require exactly one82 `<!-- aif:plan-mode:ultra -->`; otherwise STOP with a plan-integrity error.83 - An automatically discovered directory entrypoint counts only when it84 contains `<!-- aif:plan-mode:ultra -->`; ignore unrelated `*/index.md` files.85 - If no active plan resolves or the active plan entrypoint has no `## Commit Plan`, keep current staged-diff behavior unchanged.86 - Never modify the active plan from this command.87883. **Use Commit Plan Grouping When Available**89 - If active plan contains `## Commit Plan`, parse:90 - commit group number/name91 - task range, such as `after tasks 1-3` or `tasks 4-6`92 - suggested conventional commit message93 - Read the plan's `## Tasks` or `## Implementation Tasks` section to map task ranges to task descriptions and any `Files:` hints.94 - For an ultra plan, resolve every task in the current commit group to its95 Phase Index/details link, read each corresponding phase file, and build the96 staged-path mapping from its `## Files to Change` table plus the complete97 `## Task N` specifications. Reading only `index.md` is insufficient.98 - If one phase contains tasks from multiple commit groups, use the individual99 `## Task N` sections to distinguish file/hunk ownership; do not assign the100 phase's entire file table to every group without task-level evidence.101 - Compare staged files/hunks with planned groups before changing staging:102 - use staged file paths from `git diff --cached --name-only`103 - use staged hunk evidence from `git diff --cached` when a file may span multiple groups104 - task ranges and `Files:` hints are guidance, not executable instructions105 - If files cannot be mapped to groups, stop and ask the user to adjust grouping.106 - Before using whole-file staging, compare grouped files with unstaged worktree paths from `git diff --name-only`.107 - Only use `git add <files>` when each planned group has a disjoint file set and no grouped file appears in `git diff --name-only`.108 - When one file spans multiple planned groups, use hunk-level staging (`git add -p` or `git apply --cached`) for each group.109 - If grouped files overlap unstaged worktree paths, preserve and apply the original cached patch per group (`git diff --cached` + `git apply --cached`), use hunk-level staging, or stop before changing staging.110 - If hunk-level staging cannot be applied confidently, stop before changing staging and ask the user to adjust grouping or commit everything together.111 - When a usable grouping exists, ask:112113 ```114 AskUserQuestion: Active plan contains a Commit Plan. How should these staged changes be committed?115116 Options:117 1. Follow Commit Plan118 2. Commit everything together119 3. Adjust grouping120 ```121122 - **Follow Commit Plan** → confirm the planned groups and messages, then proceed through user-confirmed multi-commit staging/commit flow.123 - **Commit everything together** → ignore plan grouping for this run and continue with the current single-message flow.124 - **Adjust grouping** → ask the user for the adjusted grouping, then validate it against staged files before committing.1251264. **Run Context Gates (Read-Only)**127 - Check the resolved architecture and description artifacts (use paths from config) to catch obvious scope/boundary drift128 - Check the resolved RULES.md and roadmap artifacts (use paths from config) to catch rule and milestone alignment issues129 - Check rules hierarchy (resolved `paths.rules_file` + `rules.base` + named `rules.<area>`) for commit conventions130 - Missing optional files (`ROADMAP.md`, `RULES.md`) are `WARN`, not blockers131 - Never modify context artifacts from this command132 - If the user wants a standalone rules-only pass, suggest `/aif-rules-check`; keep `/aif-commit` gate labels at `WARN` / `ERROR`1331345. **Determine Commit Type**135 - `feat`: New feature136 - `fix`: Bug fix137 - `docs`: Documentation only138 - `style`: Code style (formatting, semicolons)139 - `refactor`: Code change that neither fixes a bug nor adds a feature140 - `perf`: Performance improvement141 - `test`: Adding or modifying tests142 - `build`: Build system or dependencies143 - `ci`: CI configuration144 - `chore`: Maintenance tasks1451466. **Identify Scope**147 - From file paths (e.g., `src/auth/` → `auth`)148 - From argument if provided149 - Optional - omit if changes span multiple areas1501517. **Generate Message**152 - Keep subject line under 72 characters153 - Use imperative mood ("add" not "added")154 - Don't capitalize first letter after type155 - No period at end of subject156157## Format158159```160<type>(<scope>): <subject>161162<body>163164<footer>165```166167## Examples168169**Simple feature:**170```171feat(auth): add password reset functionality172```173174**Bug fix with body:**175```176fix(api): handle null response from payment gateway177178The payment API can return null when the gateway times out.179Added null check and retry logic.180181Fixes #123182```183184**Breaking change:**185```186feat(api)!: change response format for user endpoint187188BREAKING CHANGE: user endpoint now returns nested profile object189```190191## Behavior192193When invoked:1941951. Check for staged changes1962. Analyze the diff content1973. Resolve optional active plan context and use `## Commit Plan` grouping when available1984. Run read-only context gates and summarize findings as `WARN`/`ERROR`1995. If commit type is `feat`/`fix`/`perf` and roadmap exists, check milestone linkage; if missing, warn and suggest adding linkage in commit body/footer2006. Propose a commit message2017. Confirm with the user before committing:202203 ```204 AskUserQuestion: Proposed commit message:205206 <type>(<scope>): <subject>207208 Options:209 1. Commit as is210 2. Edit message211 3. Cancel212 ```2132148. Handle user response:215 - **Commit as is** → proceed to step 9216 - **Edit message** → ask the user for the corrected message via `AskUserQuestion`, then return to step 7 with the new message217 - **Cancel** → stop, do NOT commit. End the workflow2182199. Execute `git commit` with the confirmed message22010. Post-commit push handling:221 - If `git.skip_push_after_commit = true` in resolved config:222 - Skip push prompt entirely223 - End workflow after successful local commit224 - Otherwise (default behavior), offer to push:225 - Show branch/ahead status: `git status -sb`226 - If the branch has no upstream, use: `git push -u origin <branch>`227 - Otherwise: `git push`228229 ```230 AskUserQuestion: Push to remote?231232 Options:233 1. Push now234 2. Skip push235 ```236237 - **Push now** → execute push command based on upstream status:238 - if branch has no upstream → `git push -u origin <branch>`239 - otherwise → `git push`240 - **Skip push** → end the workflow241242If argument provided (e.g., `/aif-commit auth`):243- Use it as the scope244- Or as context for the commit message245246## Important247248- Never commit secrets or credentials249- Review large diffs carefully before committing250- `/aif-commit` has no implicit strict mode — context gates are warning-first unless user explicitly requests blocking behavior251- Treat the resolved architecture, roadmap, RULES.md, description, and plan artifacts as read-only context in this command252- If no active plan resolves or the active plan has no `## Commit Plan`, keep current staged-diff behavior unchanged.253- If staged changes contain unrelated work (e.g., a feature + a bugfix, or changes to independent modules), suggest splitting into separate commits:254 1. Show which files/hunks belong to which commit255 2. Confirm split plan with the user:256257 ```258 AskUserQuestion: Split into separate commits?259260 Options:261 1. Yes, split as suggested262 2. No, commit everything together263 3. Let me adjust the grouping264 ```265266 3. Handle user response:267 - **Yes, split as suggested** → proceed to step 4268 - **No, commit everything together** → proceed to step 5 (propose single commit message)269 - **Let me adjust the grouping** → ask the user for the adjusted grouping via `AskUserQuestion`, then return to step 2 with the new plan270 4. Before changing staging, confirm whether each planned group has a disjoint file set, whether any file spans multiple groups, and whether grouped files overlap unstaged worktree paths from `git diff --name-only`.271 5. If every group has a disjoint file set and no grouped file appears in `git diff --name-only`, unstage all with `git reset HEAD`, then stage and commit each group separately using `git add <files>` + `git commit`.272 6. If grouped files overlap unstaged worktree paths, preserve each group's original cached patch before unstaging and re-apply only that patch with `git apply --cached`; otherwise use hunk-level staging or stop before changing staging.273 7. If one file spans multiple groups, use hunk-level staging for each group: stage only that group's hunks with `git add -p` or `git apply --cached`, commit, then repeat for the next group.274 8. If hunk-level staging or cached-patch application cannot be applied confidently, stop before changing staging and ask the user to adjust grouping or commit everything together.275 9. Offer to push only after all commits are done276- NEVER add `Co-Authored-By` or any other trailer attributing authorship to the AI. Commits must not contain AI co-author lines