---
name: commit
description:
  "Inspect local staged, unstaged, deleted, renamed, and untracked changes; propose semantic
  Conventional Commit boundaries; and, with authorization, stage exact files or hunks and create
  local commits. Use for staged-only commits, dirty-tree commit planning, rename-aware grouping, or
  hunk-level staging. Does not push, open pull requests, or review on GitHub; use pr for that."
allowed-tools:
  Bash(git-hunk:*), Bash(command -v git-hunk), Bash(git add:*), Bash(git commit:*), Bash(git
  status:*), Bash(git diff:*), Bash(git log:*), Bash(git show:*), Bash(git branch:*), Bash(git
  rev-parse:*), Bash(git symbolic-ref:*), Bash(git ls-files:*), Bash(fd:*), Bash(rg:*), Read, Grep,
  Glob, Agent
argument-hint: "[plan | stage | staged] [path-or-scope]"
metadata:
  short-description: Local Conventional Commit grouping and commits
---

# Commit

Treat this as the local commit boundary. Planning is read-only. Preview every index or commit
mutation before running it and mutate only with authorization; authorization to review or propose
groups is not authorization to mutate. Authorization is either explicit (the user names the action)
or standing from an approved delivery plan (`delivery`), which grants staging and atomic semantic
commits within its planned lanes. A worker holding an autonomous lane lease inherits that
authorization only inside its assigned worktree and scope; it must preserve every change outside the
lease. Do not infer authorization to amend, rebase, squash, merge, push, open a PR, bypass hooks, or
discard changes.

## Routing

An explicit `commit` invocation authorizes the selected route within the named scope:

- No mode: inspect the selected scope, propose semantic boundaries, then stage and commit them.
- `plan`: return the commit plan without mutating the index.
- `stage`: stage the selected planned group and leave it uncommitted.
- `staged`: verify and commit exactly the existing index.

A trailing path or scope limits the selected changes. Natural-language equivalents route to the same
workflow.

## Inventory exact state

Use porcelain status for the complete index/worktree/untracked split, then inspect each surface:

```bash
git status --porcelain=v2 --branch --untracked-files=all
git diff --name-status --find-renames
git diff --cached --name-status --find-renames
git ls-files --others --exclude-standard
git diff
git diff --cached
git log --oneline --decorate -8
```

Do not include ignored files or `.scratchpad` by default. Stop on unmerged paths or an in-progress
merge/rebase instead of guessing intent.

`git diff` omits untracked file content, and `git-hunk` only sees worktree-vs-index and
index-vs-HEAD, so untracked files are invisible to both. Read each relevant untracked file
explicitly before assigning it to a semantic boundary.

Capture the initial staged paths and status so later verification can prove what changed in the
index.

## Plan semantic boundaries

Group by one coherent outcome, not directory, file type, or an arbitrary commit count:

- implementation with its focused tests and directly coupled docs;
- schema/type/API change with required producer and consumer updates;
- dependency/config change with its lockfile or generated artifact;
- mechanical rename with every required reference update;
- formatting or generated churn separately only when it is intentional and meaningful.

Keep a rename's old path, new path, and reference updates together. Treat a tracked deletion plus a
similar untracked path as a rename candidate and compare contents/history without mutating the real
index. Final rename identity is verified after explicit staging with Git's rename detection.

Use hunk-level staging only when one file contains changes belonging to different semantic outcomes.
Do not split inseparable hunks merely to force an idealized history.

Each commit should be independently understandable and, when practical, build/test at its boundary.
Order prerequisite contract/schema changes before dependent consumers.

## Preview before mutation

Present this plan before staging or committing:

```text
Group 1: type(scope): subject
Outcome: <one coherent change>
Paths:
  - <path>: <reason>
Staging: whole-file | hunk-level (<identified hunks>)
Depends on: none | Group N
Verification: <exact command or existing evidence>
```

If mutation authorization is not already explicit, stop after the plan. If it is explicit, state the
exact next staging operation before running it.

## Conventional Commit messages

Use `type(scope): concise imperative subject`. Reserve `!` and a `BREAKING CHANGE:` footer for a
real breaking public contract. Keep scope narrow and optional. Add a body when the reason,
constraint, migration, or non-obvious consequence matters. Do not add AI attribution or unrelated
issue references.

## Stage authorized groups

### Whole paths

Stage only explicit paths:

```bash
: "${TARGET_PATH:?set the exact path}"
git add -- "$TARGET_PATH"
```

Never use `git add .`, `git add -A`, `git add -u`, or `git commit -a` for semantic grouping. Stage
both sides of a rename together.

### Hunks

Use the installed non-interactive `git-hunk` workflow. Scan is read-only; dry-run the selection
before applying it:

```bash
git-hunk scan --mode stage --compact --json
git-hunk show --mode stage "$CHANGE_KEY" --json
git-hunk stage --snapshot "$SNAPSHOT_ID" --change-key "$CHANGE_KEY" --dry-run --json
git-hunk stage --snapshot "$SNAPSHOT_ID" --change-key "$CHANGE_KEY" --json
```

Repeat `--change-key` for multiple selections. Do not pass comma-separated keys. Any index or
worktree mutation can stale the snapshot; rescan after each stage, unstage, commit, formatter, or
hook change. Do not run `git add` on a partially staged file afterward because that stages its
remaining hunks.

Do not use intent-to-add on the real index merely to detect renames. Do not unstage pre-existing
changes to improve grouping without explicit approval for that index rewrite.

## Verify the index before commit

After every staging operation, inspect the exact prospective commit:

```bash
git status --porcelain=v2 --branch --untracked-files=all
git diff --cached --name-status --find-renames
git diff --cached --check
git diff --cached
git commit --dry-run --short
```

Confirm:

- only the planned paths/hunks are staged;
- rename pairs remain together and Git's detected rename is plausible;
- secrets, credentials, local state, and `.scratchpad` are absent;
- no unresolved conflict marker or whitespace error remains;
- relevant repository-native checks passed, or the user explicitly accepted a known WIP boundary.

If verification differs from the plan, stop and inspect. Do not commit first and repair history
afterward.

## Commit only when authorized

Run staging and commit as separate operations. Preserve hooks and signing configuration:

```bash
git commit -m "type(scope): subject" -m "optional explanatory body"
```

Do not use `--no-verify`, `--amend`, `--allow-empty`, or author/date overrides unless explicitly
requested and justified. If a hook fails or changes files, inspect status and the cached diff again;
do not retry blindly.

Never use `git reset --hard`, `git checkout -- <path>`, `git clean`, or another destructive command,
and never clean, reset, or discard the remaining worktree to make the status look tidy. Leftover
changes after a commit are the expected outcome, not a defect to be swept up.

For multiple groups, verify that the index is empty after each commit before staging the next group.

## Verify resulting boundaries

After each commit:

```bash
git show --stat --name-status --find-renames HEAD
git status --porcelain=v2 --branch --untracked-files=all
```

Check that the commit contains one planned outcome, its message matches the diff, rename detection
is sensible, hooks did not add unrelated content, and remaining staged/unstaged/untracked changes
still belong to the user.

Path-specific unstaging is an index mutation and still requires authorization; it must not alter the
worktree.

## Report

For plan-only review, report groups, exact paths/hunks, ordering, messages, and verification needed.

After authorized mutations, report:

- commit hash, Conventional Commit message, and semantic outcome per commit;
- exact files/hunks left staged, unstaged, and untracked;
- checks run and results;
- hooks or staging changes that affected the plan;
- confirmation that nothing was pushed and no PR was created.

## Completion gate

Stop when:

- the original and final staged/unstaged/untracked state are accounted for;
- every commit boundary is semantic and rename/hunk aware;
- each created commit matches its planned paths, message, and verification evidence.
