---
name: tt-conventional-commit
description: Stage and commit TimeTrak changes using a Conventional Commits message that matches the repo's existing style. Critical - never include a Co-Authored-By Claude trailer or any Claude Code attribution. Use when the user asks to commit completed work.
license: MIT
compatibility: TimeTrak. git only.
metadata:
  author: timetrak
  version: "1.0"
---

Create a single, focused commit using a Conventional Commits message that matches the existing TimeTrak history. This skill is the only sanctioned commit path for TimeTrak work — it enforces the repo-specific rules below.

**HARD RULE — no Claude attribution**

The commit message MUST NOT contain:
- `Co-Authored-By: Claude ...`
- `🤖 Generated with [Claude Code]`
- `Generated with Claude` / `Generated by Claude`
- Any reference to Claude, Anthropic, or any AI assistant.

Plain Conventional Commits only. The repo history (e.g. `feat(authz): harden workspace authorization boundaries`, `docs(openspec): archive ...`) does not carry an AI trailer; new commits must not introduce one.

**Steps**

1. **Confirm there is something to commit**
   ```bash
   git status
   git diff --stat
   git diff --cached --stat
   ```
   If both diffs are empty, stop — do not create an empty commit.

2. **Inspect history for tone**
   ```bash
   git log --oneline -20
   ```
   Match the existing format. Observed prefixes in TimeTrak:
   - `feat(<scope>): <subject>` — new behavior
   - `fix(<scope>): <subject>` — bug fix
   - `docs(<scope>): <subject>` — docs / OpenSpec archives / spec updates
   - `chore: <subject>` — tooling, scaffolding
   - `test: <subject>` — test-only changes
   - `refactor(<scope>): <subject>` — internal restructuring without behavior change

   Common scopes: `authz`, `web`, `domain`, `db`, `shared`, `openspec`, `tracking`, `clients`, `projects`, `rates`, `reporting`. Pick the narrowest accurate scope. Omit the scope only when no domain fits (e.g. plain `chore:` or `docs:`).

3. **Stage deliberately (never `git add -A`)**

   Stage by explicit path or by hunk:
   ```bash
   git add internal/<domain>/service.go internal/<domain>/handler.go
   git add migrations/0013_invoices.up.sql migrations/0013_invoices.down.sql
   git add web/templates/<domain>/index.html
   ```

   Forbidden:
   - `git add -A` / `git add .` / `git add -u` — too broad, drags in unrelated work and risks secrets.
   - Staging anything matching `.env*`, `*.pem`, `*.key`, `id_rsa*`, `secrets*`, `credentials*`, or anything inside a `secrets/` directory. If the working tree contains such a file, **stop and tell the user** — do not stage, do not commit.

   After staging, re-run:
   ```bash
   git diff --cached --stat
   git diff --cached
   ```
   Sanity-check that only the intended files and hunks are staged.

4. **Write the message**

   - Subject: `<type>(<scope>): <imperative summary>` — lowercase, no trailing period, ≤ 72 chars.
   - Imperative voice: `add`, `fix`, `harden`, `archive`, not `added`/`adds`.
   - Body (optional): wrap at 72; explain *why* if it isn't obvious from the diff. Reference the OpenSpec change name if applicable (e.g. "Implements `harden-workspace-authorization-boundaries`.").
   - Footer (optional): `Refs #N` or `Closes #N` for issue links.
   - **No `Co-Authored-By` trailer of any kind.**

5. **One change per commit (binding)**

   If the staged diff spans multiple meaningful units (e.g. a migration + an unrelated UI fix), split into separate commits. The repo follows one-change-per-unit; commits should mirror that. Reset and re-stage by path if needed:
   ```bash
   git reset HEAD <path>
   ```

6. **Commit (HEREDOC for multiline messages)**
   ```bash
   git commit -m "$(cat <<'EOF'
   feat(<scope>): <imperative subject>

   Optional body explaining the why. Reference the OpenSpec change if relevant.
   EOF
   )"
   ```
   For a one-line commit, just:
   ```bash
   git commit -m "docs(openspec): archive add-csv-export and update specs"
   ```

7. **Verify**
   ```bash
   git log -1 --format=full
   git status
   ```
   Confirm:
   - The subject matches the conventional format.
   - There is **no** `Co-Authored-By` trailer.
   - Working tree is clean (or holds only intentionally-deferred work).

8. **Do not push**
   Do not run `git push` unless the user explicitly asks. Never force-push to `main`.

**Guardrails**
- Never include any AI / Claude / Anthropic attribution in the commit message.
- Never use `git add -A` / `git add .` / `git add -u`.
- Never stage `.env*` or other secret-bearing files.
- Never amend an existing commit unless the user explicitly asks; create a new commit instead.
- Never bypass hooks (`--no-verify`, `--no-gpg-sign`) unless the user explicitly asks. If a hook fails, fix the underlying issue and create a new commit.
- Never commit unless the user has asked you to.

**Fluid Workflow Integration**
Invoke at the end of an `openspec-apply-change` session, after `tt-run-tests` confirms green and the user explicitly asks to commit. Typical sequence: `tt-run-tests` → user says "commit" → this skill stages by path and writes a single conventional commit per logical unit of work.
