---
name: commit
description: Analyze staged changes and auto-generate a Conventional Commits message, then execute the commit.
---

# Commit Workflow (/commit)

## Step 1: Load Project Context

Before generating anything, read the following files (if they exist):

- `.agent/rules/commit-standards.md` — commit format rules and prohibited content
- `.agent/rules/tech-stack.md` — confirm the project's **language preference** (English / 中文)
- `.agent/plans/task-progress.md` — find the current `in-progress` task for issue linking

## Step 1.5: main branch protection

**Direct commits on the default branch are forbidden.** Verify the current branch before generating any commit message:

```bash
current_branch=$(git rev-parse --abbrev-ref HEAD)
if [[ "$current_branch" == "main" || "$current_branch" == "master" ]]; then
  echo "[commit] refusing to commit on $current_branch" >&2
  echo "[commit] create a feature branch first: cortex-agent branch create --from <proposal>" >&2
  exit 2
fi
```

- `main` / `master` commit → immediately `exit 2` + stderr explanation, never reaches Step 2
- **Does not block amend / fixup**: `git commit --amend` modifies an existing commit and is not a "new" commit; Step 1.5 only fires on fresh-commit entry points
- **Does not block worktree branches**: any commit on `feat/*` / `fix/*` / `wt/*` / `release/*` / `hotfix/*` / `chore/*` passes through
- **Failure handling**: after `exit 2`, the user should either:
  1. Switch to an existing feature branch (`git switch feat/<slug>`), or
  2. Create a binding branch: `cortex-agent branch create --from <proposal> --base main`

> Naming conventions: see `.agent/rules/branch-management.md`. Registry schema: see `.agent/branches/registry.json`.

## Step 2: Analyze Changes

```bash
git status
git diff --staged          # Staged changes (preferred)
git diff HEAD              # Fall back if staging area is empty
```

Understand each changed file:
- What changed? Why? Which module does it affect?
- Are there any breaking changes (signature changes, removed public APIs, etc.)?
- Do all changes belong to the same logical unit? (If not, prompt the user to split the commit.)

## Step 3: Generate the Commit Message

Follow the format in `.agent/rules/commit-standards.md`:

```
<type>(<scope>): <subject>

[body — optional: motivation and key details]

[footer — optional: Closes #42 or BREAKING CHANGE: ...]
```

**Language rule**: subject and body must use the project's configured language (read from tech-stack.md).

**Scope rule**: use only a stable module, domain, or directory name as the scope. Do not use task,
proposal, Mission, Milestone, or batch identifiers such as `T-001`, `P-004`, `M-010`, `MS-002`, or
`batch-a`; put them in the body or footer when traceability is useful. Omit the scope when no stable
module or domain name applies.

**Commit boundary**: commit at an independently verifiable Milestone, stage, or coherent batch boundary.
Do not commit merely because one proposal or control contract is complete, and do not wait until an entire
multi-Milestone project is complete. A short-lived batch checkpoint may record progress evidence only;
commit it when interruption, handoff, or branch switching is likely. Include only files related to the task.

**Strictly forbidden** anywhere in the commit message:
- `Co-authored-by: Claude` or any AI tool attribution
- `Generated by AI`, `AI-assisted`, `Powered by Claude`, or any AI-related attribution

After generating, display the full message for user review and explain the choice of type/scope.

## Step 4: User Confirmation

Display for confirmation:

```
📝 Generated commit message:

feat(auth): add OAuth2 login support

Supports GitHub and Google as third-party providers; adds /auth/callback route.

Closes #42

---
Execute this commit? (y / edit / cancel)
```

If the user requests changes, adjust and re-display before proceeding.

## Step 5: Execute the Commit

After confirmation, **record the commit intent before executing** and **record the result only after Git returns a real identity**.

```bash
# Stage any unstaged files if needed:
git add <files>

# 5a. Freeze commit_intent receipt — git tree state, scope, language, dedupe key
node .agent/skills/activity-recording/scripts/index.js receipt append --payload-json "$(cat <<'EOF'
{
  "schema_version": 1,
  "receipt_id": "AR-commit-intent-<utc timestamp>",
  "receipt_kind": "commit_intent",
  "source": "/commit",
  "source_revision": "HEAD",
  "capture_mode": "workflow_required",
  "observed_at": "<UTC RFC 3339 timestamp>",
  "activity_refs": [],
  "gaps": [],
  "evidence_refs": [],
  "availability": "available",
  "redaction": { "status": "not_applicable" },
  "dedupe_key": "commit:intent:<scope>:<subject-hash>",
  "commit_identity": null,
  "intent_receipt_ref": null
}
EOF
)"

# 5b. Execute the commit (HEREDOC handles special characters safely)
git commit -m "$(cat <<'EOF'
<full commit message>
EOF
)"

# 5c. Record commit_result receipt only after Git returns a real commit identity
COMMIT_SHA=$(git rev-parse HEAD)
node .agent/skills/activity-recording/scripts/index.js receipt append --payload-json "$(cat <<'EOF'
{
  "schema_version": 1,
  "receipt_id": "AR-commit-result-<utc timestamp>",
  "receipt_kind": "commit_result",
  "source": "/commit",
  "source_revision": "<COMMIT_SHA>",
  "capture_mode": "workflow_required",
  "observed_at": "<UTC RFC 3339 timestamp>",
  "activity_refs": [],
  "gaps": [],
  "evidence_refs": [".git/refs/heads/<branch>"],
  "availability": "available",
  "redaction": { "status": "not_applicable" },
  "dedupe_key": "commit:result:<COMMIT_SHA>",
  "commit_identity": "<COMMIT_SHA>",
  "intent_receipt_ref": "AR-commit-intent-..."
}
EOF
)"
```

If the commit fails (non-zero exit from `git commit`), record a `commit_result` with `availability: "failed"` and `commit_identity: null`. **Never fabricate a sha for a failed commit.**

On success, output the commit hash and summary.

## Step 6: Follow-up

Ask if the user wants to push:

```bash
git push
# For a new branch:
git push -u origin HEAD
```

---

## 💡 Tips

- **Split commits**: If changes span unrelated concerns, use `git add -p` and run `/commit` multiple times to maintain atomicity.
- **Breaking changes**: Use `feat(scope)!:` format and explain the migration path in the footer.
- **Task linking**: Read the current task ID from `task-progress.md` and auto-append `Closes #<id>` or `refs #<id>` to the footer.
- **Scope selection**: Prefer a stable module or domain name; never use task, proposal, Mission, Milestone, or batch identifiers as the scope.
