Vibe Commit
Overview
A vague "commit please" is a request to turn a messy working tree into one
clean, correctly scoped commit — not a request to run git add -A && git commit. The instruction is underspecified on purpose: the user trusts the agent
to decide what belongs in the commit, keep junk out, and leave a message and
history a future maintainer can use.
This skill governs the execution of that: which files to stage, what to keep
out, how to re-verify the staged set before committing, how to transport a
multi-line message without corruption, and how to amend or repair a commit while
keeping authorship trailers intact. The guidance here is distilled from real
agent sessions where these exact steps prevented — or, when skipped, caused —
commit mistakes.
When a request calls for a commit and no blocking condition remains, the
deliverable carries every applicable gate whether it is executed or, for a
"command only" ask or a response-only decision over represented repository
state, shown as the command sequence: tree inspection, the staged-set gate
with the staged diff read, the commit command, and verification of the stored
message against the exact committed patch and of the remaining working-tree
state. A bare commit invocation is not a commit answer. For an inspection-only
request or a blocked decision, stop at the applicable boundary and say what
remains unresolved; add no commit command or post-commit check for an
operation that will not occur.
Message content vs. commit execution
Commit work splits cleanly between message content and execution:
- The commit message content must stand on its own: an outcome-focused
Conventional Commit subject, body only for durable context the diff cannot
recover, medium-density body wording that names durable contract surfaces
without becoming a feature walkthrough, a compact
Verification: section that
explains what durable proof covers instead of replaying session commands, no
prompt/session/plan labels, and no Markdown wrappers in message bytes. A
Verification: bullet is that pair, not one half of it: keep the exact
command as the rerun anchor and add what its proof covers, so neither deleting
the command nor leaving it bare counts as a compact verification section.
vibe-commit owns the execution: staging, exclusion, the pre-commit
verification gate, command safety, history mutation, message transport, and
trailers as a transport mechanism.
Apply the compact message rules in references/history-and-trailers.md whenever
this skill prepares, inspects, amends, or repairs a commit message. The commit's
bytes — file set, message transport, trailer footer, and stored message — are
this skill's responsibility, and you verify them after committing.
Authority and safety boundary
Committing locally is reversible; publishing is not. Stay on the reversible side
of that line unless the user says otherwise.
Effect And Write Boundaries
For every consolidation block this package carries, here and in its references: where this package declares a stricter or narrower rule in its own text, that declaration controls.
For every gate and schema block this package carries, here and in its references: this package may state which of its phases the block applies to; it may not change the block's inputs, outcomes, or fields.
Write nothing beyond what the phase's own effect class and its declared boundary permit.
- Declare exactly one effect class for every workflow phase, in that phase's own text.
- In a read-only phase, read and report; make chat the deliverable — findings, alignment, or direction.
- In a read-only phase, edit no source, test, config, doc, or other file, and run no command that mutates runtime or repository state.
- In a read-only phase, never stage, commit, tag, push, change versions, delete data, or start services.
- In a read-only phase, write a file only when the current user explicitly asks for a saved artifact.
- In an artifact-only phase, create or update the artifact it owns: the requirements spec, the plan, the plan-review state, the instruction files, or the text artifacts the request names.
- In an artifact-only phase, write the supporting paths its own text declares:
- the text it was asked to revise (comments, docstrings, docs);
- a confirmed reflection into the bound plan;
- an ignore file it previewed and the user confirmed;
- a narrowly confirmed configuration edit its text names;
- a decision record or findings report its own text declares.
- In an artifact-only phase, leave those verified changes in the working tree.
- In an artifact-only phase, never implement executable behavior, never edit application code or tests as implementation, never produce an artifact another phase owns, and never perform release work.
- Never let an artifact-only phase's artifact authorize same-turn implementation.
- In a state-changing phase, edit files and run commands inside the scope its own text declares — the unit it implements, the repair it proves, the fixes it applies, the round it integrates, or the commit it executes.
- In a state-changing phase, keep its edits to the smallest verified unit of that scope.
- In a state-changing phase, leave paths outside the scope, pre-existing working-tree changes the phase did not make, and runtime or external state beyond the scope unwritten unless the current user selects them.
- Keep every irreversible or outward-facing operation under its own consent.
The scope this workflow declares is the commit it executes — the index and
history of that commit and the message it transports — and it makes no source
edits.
Honor .gitignore and the agreed scope. Never git add -f an ignored
path, and never stage files outside the change being committed, unless the
user explicitly asks to include that ignored path after you have surfaced why
it is ignored and what risk that creates. Decide scope by the user-visible
change, not by whatever happens to be dirty.
No surprise side effects. Do not bump versions, cut releases, or trigger
hooks the repo did not ask for as a byproduct of committing.
Durable Records
Before recording a settled decision, deferring a finding, or closing a unit,
read references/durable-records.md. This phase ordinarily writes neither
docs/decisions/ nor docs/reports/findings/; it hands a decision or finding
forward as the carry-forward packet that reference defines, and a saved
artifact the user explicitly requests stays within this phase's own boundary.
Commit Selection
Only an explicit user request, a bound plan item, or a workflow's own verified checkpoint selects a commit.
- Select a commit from exactly three sources: an explicit current-user request; a bound approved plan item requiring that checkpoint; or a state-changing workflow closing its own verified, reviewed, in-scope unit under its checkpoint default.
- Never let routing or invocation, edit permission, a convenient stopping point, tracked changes in the working tree, or an available commit-execution workflow select a commit.
- Never treat an unverified unit as a handoff.
- Execute in commit-execution only the commits those sources select; that phase has no checkpoint default of its own.
- Close a self-contained unit of the workflow's own work with a local commit of exactly that unit once it is implemented, verified, reviewed, and its material findings dispositioned.
- Commit that unit without waiting for a separate commit instruction.
- Never let a multi-unit run accumulate as one undifferentiated working tree.
- When the default is suspended, leave the verified changes in the working tree and report the reason.
- Let the checkpoint default reach only local commits of the unit's own verified changes.
- Select no commit from discovery-only, blocked, unchanged, failing, unverified, or work-in-progress state.
- Never widen the staged set beyond the verified unit.
- Exclude pre-existing working-tree changes the workflow did not make, an artifact whose tracked status would itself be new, and paths outside the unit.
- Never treat an available commit-execution workflow or ambient tracked status as a reason to include them.
- When the unit's changes cannot be separated from unrelated working-tree state, report the mixed state and ask instead of committing.
- Route every selected commit through the commit-execution workflow with the verified scope, its test and review evidence, its unrelated-path exclusions, and any proposed message.
- Leave staging, file-set and exact-diff review, message transport, history safety, and post-commit verification to that workflow.
- Never read a request to commit as a request to push.
- Keep push, release preparation, version changes, tags, amend, rebase, reset, stash, squash, destructive actions including cleanup, force-adds, tracking a newly created artifact, external side effects, and unrelated or ambiguous paths separately consent-bound even when a checkpoint was selected.
- Never let a route, checkpoint, or handoff implicitly authorize them.
Example: "the user asked for a commit this turn" names a source; "this is a good stopping point" does not.
Exception: a current no-commit instruction, a bound plan that forbids commits, or project policy against commits suspends the checkpoint default.
This workflow is that commit-execution phase: it executes the commits those
three sources select, keeps no checkpoint default of its own, and runs no
git push unless the current user explicitly asks. Scoped checkpoint handoffs
reach it as commit requests for their named paths.
Every handoff still passes this skill's file-set, verification, message,
and history-safety gates, and none of them authorizes broad staging, empty
commits, push, release work, version changes, or history rewriting.
Separate discovery from lifecycle authority. Status, diff, path
existence, same-session creation, logical relevance, conventional repository
placement, and commit permission make a path a candidate; they do not by
themselves authorize tracking, staging, or commit membership. A newly
selected untracked artifact needs explicit tracking intent or an applicable
mandatory repository/owning-workflow coupling. Already tracked coupled tests,
docs, specs, README, and changelog changes may remain part of the selected
logical change when their owning contract requires them.
Commit-Selection Gate
Never run a plain git commit without naming the selection source it rests on.
- With no user-installed hook enforcing this gate, this wording is the whole gate: apply it yourself before the command runs.
- Name one recorded source before committing: the current user's request (
user-turn), the bound plan item (bound-plan-item), or the workflow's own checkpoint of a verified unit (specialist-checkpoint).
- Treat
agent-proposed as a recorded proposal, never a selection.
- When the workflow is router-bound, have the router record that source as a
commit-selection event before the command runs.
- For a standalone commit with no router active, name the direct current-user request or the verified checkpoint handoff and follow the phase's ordinary confirmation policy.
- When no source can be named, do not commit; ask the user whether a commit is wanted.
- Return
allow when the command is not a commit.
- Return
ask on every plain commit, quoting from the session record under .plans/vibe-sessions/ the recorded phase and the most recent recorded commit-selection event's source, at, and note.
- Or state that no
commit-selection event is recorded, or that the record is absent, malformed, stale, foreign, session-unbound, or conflicting.
- Never return
deny from this gate.
- Never allow a plain commit silently: surface the recorded
source at the prompt so a self-attested selection is caught there.
- Answer
ask, never deny, for a record in any invalid state.
Exception: an amend or other history rewrite belongs to the history-mutation gate, not this one.
This gate applies to every plain commit the commit-execution phase runs.
History-Mutation Gate
Never rewrite git history without stopping and asking the user first.
- With no user-installed hook enforcing this gate, this wording is the whole gate.
- Before running a matched command, stop and ask the user with that reason, and proceed only on the user's answer.
- Match
git commit --amend, git rebase, git filter-branch or another filter-* rewrite, git reset --hard, git push, or a scripted or looped replay that rewrites more than one commit.
- Return
allow when the command is not a history mutation.
- Return
ask for every matched history mutation, naming the matched operation.
- Quote from the session record under
.plans/vibe-sessions/ the recorded phase, effect_mode, and the kind and source of every recorded event bearing on it.
- Or state that the record is absent, malformed, stale, foreign, session-unbound, or conflicting, or that no such event is recorded.
- Never return
deny from this gate.
- Never allow a matched history mutation silently, whatever the record says: surface the recorded values at the prompt so a self-attested record is caught there rather than trusted.
- Treat history that has left this machine — pushed, fetched by another clone, or otherwise published — as shared; no recorded value makes rewriting it silent.
- Let the record decide only the wording of the reason, never the outcome.
- Answer
ask, never deny, for an absent, malformed, stale, foreign, session-unbound, conflicting, or identity-mismatched record.
Exception: a plain git commit belongs to the commit-selection gate, not this one, and a read-only git command is not a history mutation.
This gate applies to the history mutations the commit-execution phase runs.
History Safety
Do not rewrite shared history. Amending or rebasing an already-pushed
commit rewrites history other clones depend on. Only amend/rebase commits that
have not left this machine, and never force-push a shared branch without an
explicit, informed request. When you stop for that consent, say in the same
answer what the rewrite would cost — other clones diverge and collaborators may
have to rebase, reset, or reconcile duplicated commits — and name the correction
paths you are offering, including whether a later commit can reach the defect at
all.
Never let a scripted rewrite delete live files without a separate confirmed
stop. When a scripted or looped multi-commit rewrite drops paths from
history, derive each step's target list from that commit's own tree (e.g.
git ls-tree), never from an ambient whole-worktree snapshot (git status,
-uall, or similar) — the two are different states, and conflating them
deletes files unrelated to the commit being rewritten. Print the full
resolved list first and require an explicit confirmed stop before any
deletion executes; a preview a script can run straight past is not a gate. A
backup limits damage if something goes wrong — it never substitutes for that
per-path confirmation, and it does not by itself authorize deleting a live
working-tree file. See references/history-and-trailers.md.
Core workflow: "commit please" → one clean commit
Follow this spine. Each step names the load-bearing command; the references go
deeper on the judgment calls.
- Discover everything.
git status --short --branch --untracked-files=all
and git status --ignored show every modified, staged, untracked, and
ignored path in one view. Add git log -1 --oneline and git branch --show-current so you know the branch and the commit you might extend.
- Inspect intent. Read the actual changes —
git diff --stat, then git diff -- <file> for specific files and git diff -- <newfile> (or open it)
for untracked ones. Decide what each path is before deciding whether it
belongs.
- Classify and select. Sort every changed path into (a) the core
deliverable that forms ONE logical change — implementation plus its tests and
the docs/CHANGELOG/spec it fulfills — versus (b) out-of-scope edits or
generated artifacts. For every newly selected untracked artifact, verify
tracking intent or mandatory coupling before staging it. Split unrelated
concerns into separate commits. See
references/file-selection.md.
- Exclude deliberately. Leave generated, scratch, unowned plan/spec, build,
unrelated lock, agent-state (
.agents/, .claude/, .codex/), and secret
paths unstaged. A verified requirements or plan artifact named by an owning
workflow's scoped checkpoint handoff is owned content, not generic scratch.
A lockfile that records a dependency change needed by the selected commit is
in-scope with the manifest; do not drop it just because it is a lockfile.
When unsure whether a path is ignored, git check-ignore -v <path>. See
references/file-selection.md.
- Stage explicitly.
git add -- <path1> <path2> … by full name. Avoid git add . / -A / globs in a dirty tree — they silently sweep in strays. For a
file with mixed in-scope and out-of-scope hunks, git add -p <file>.
- Re-verify the staged set (mandatory gate). Before committing, confirm
what you are about to commit:
git diff --cached --name-only (exact files),
git diff --cached --stat (volume sanity), git diff --cached (read the
hunks), git diff --cached --check (whitespace/line-ending errors). In-scope
files present, out-of-scope/ignored files absent, diff matches intent. This
2–3 second gate is the single highest-leverage habit; see
references/staging-and-recovery.md.
- Reconcile message to the exact target diff (mandatory internal gate). Read
the complete final staged patch and map every material concern to the proposed
type, scope, outcome, body coverage, and one-commit or split decision. Bind
the decision to the current staged bytes; source drift invalidates it. Show a
detailed public receipt only for complex or multi-package changes,
reword/amend work, a supplied-message conflict, or a user-requested audit. In
those cases, keep the receipt compact but explicit about the source target,
peer concerns and shared contract, type/scope/outcome bases, subject/body
coverage, one-commit or split decision, supplied-message disposition, and the
rule that source-patch drift requires reconciliation again. When the diff
touches an accepted decision record's
paths, check conformance or the
superseding record in the same commit, else report the conflict. Report that
conflict and ask: name the record id, its binding paths, and the exact
non-conformance, then ask whether to stop or proceed instead of closing that
question yourself. See references/history-and-trailers.md.
- Decide amend vs. new. Create a NEW commit by default. Only
--amend to
fix the immediately preceding, unpushed commit. See
references/history-and-trailers.md.
- Compose the message. Conventional Commits
type(scope): summary
(imperative, ≤72 chars) naming the outcome, blank line, then a body only when
it preserves durable context the diff cannot recover. For body-worthy
commits, use a medium-density shape: one to three short paragraphs or a few
labeled bullets that group changes by durable surface, constraint, non-goal,
or risk. If the message wants a long feature walkthrough, file inventory, or
manual-test transcript, summarize or split the commit. Detect the repo's
trailer convention first: git log -5 --format='%H%n%B'. A new repository
convention this phase adopts, and any defect it discovers, go to the closing
workflow's carry-forward packet.
- Transport the message safely. For any multi-line body, use a heredoc
(
git commit -F - <<'EOF' … EOF, single-quoted delimiter) or `git commit -F
. Add or repair authorship trailers with a git commit ... --trailer
'Key: value'command — includinggit commit --amend ... --trailerorgit
commit -C --trailer ...for local rewrites — not by typing them into the body or a synthesized message payload. Never embed raw newlines in a single-m. See references/history-and-trailers.md. 11. **Post-verify the stored commit.** git show -s --format=%B HEADconfirms subject/body/trailer landed byte-correct and the trailer parsed as a footer; for newly added or repaired authorship trailers, also confirm the command path usedgit commit ... --trailer. For body messages, inspect the stored message for low-signal verification dumps, bullets that only list session commands without review meaning, and local-only proof-source leakage such as git-unmanaged local generated artifacts, ignored result files, local-only run IDs, or private tool-session records. Compare the stored message with the exact committed patch and the internal pre-commit reconciliation; git show --stat HEADis only an auxiliary file-set check. A semantic mismatch remains incomplete and is repaired only within existing unpushed-history authority.git status --shortconfirms only intentionally-left files remain and nothing leaked. 12. **Recover reversibly if wrong.** Prefer the least-destructive fix: git restore --staged to unstage,git reset --soft HEAD~1to undo a commit while keeping changes,git commit --amend --no-edit --trailer … to fix a just-made local commit. Seereferences/staging-and-recovery.md`.
When the request is narrower
Not every invocation is a full "commit please." Jump to the relevant reference:
- a response-only task supplies represented repository state and says not to
inspect or mutate the ambient checkout → treat the supplied staged, dirty,
verification, permission, and history facts as the target state. Show the
complete decision and command gates that would apply without executing them;
do not replace represented changes with an empty eval sandbox or claim that
represented commands actually ran.
- "did I stage the right things?", "check what's staged", split a commit, drop a
stray file →
references/staging-and-recovery.md
- "this got committed and shouldn't have", undo/unstage, fix a wrong file set,
recover lost work →
references/staging-and-recovery.md
- fix the last commit, amend, reword, add/fix a
Co-Authored-By, multi-line
message corruption → references/history-and-trailers.md
- a rewrite must drop or delete paths across multiple commits (not just a
trailer repair) →
references/history-and-trailers.md
- "what should I commit / leave out?", excluding generated or secret files →
references/file-selection.md
- "commit the staged changes" → do not invent extra staging, but still run the
mandatory staged-set gate before committing and the stored-commit verification
after committing.
- "show the exact commit command" or "commit command only" → include the exact
git commit ... invocation, but do not collapse the answer to that one line.
The safe artifact is the command sequence: staged-set verification, commit
command, then stored-message/file-set verification. Simple docs commits and
trailer-only commits are not exempt.
- the user supplies
git status, git diff, or git log excerpts → treat them
as evidence, but still run or show the corresponding inspection commands in
the sequence. Do not jump from supplied excerpts straight to staging,
committing, amending, or splitting.
- a commit subject needs evidence → choose a concrete Conventional Commit
subject before showing an executable
git commit, or stop before the commit
command. Use supplied user intent even when it is broad: a named feature, bug
fix, module, or behavior change is enough for a conservative subject. Do not
defer a usable broad subject to future diff output merely to make it more
precise. If paths/status are the only evidence and no behavior or fix class is
supplied, inspect git diff or git diff --cached first; in a response-only
command plan, show that inspection step and omit git commit until a concrete
subject can be written. A commit command block whose subject contains
angle-bracket text, unresolved-marker words, or instructions to fill the
subject later is still an invalid shown command even if prose says not to run
it.
- partial staging is needed → verify both sides with file-specific diffs:
git diff --cached <file> for the committed hunk and git diff <file> for
the intentionally-left local hunk. Show both as explicit verification
commands before committing; a prose note or git status is not a substitute.
- an amend/rebase would touch pushed history → name the concrete collaboration
risk: other clones can diverge and collaborators may have to rebase, reset, or
reconcile duplicated commits.
- a user-named path is absent from
git status → check git check-ignore -v <path> before deciding. If it is ignored, especially local config or
secret-like data, do not force-add it merely because the path was named; state
that the requested scope cannot be fully committed without an explicit
override after the ignore rule is known.
Common mistakes
git add . / -A / a glob in a dirty tree, sweeping in unrelated edits,
generated output, lock files, or secrets.
- Committing immediately after
git add without re-reading the staged diff.
- Force-adding or accidentally committing ignored/scratch content (eval
workspaces,
plans/, .codex/, .env).
- Committing a whole generated directory instead of just its durable spec
(
evals/<name>/ vs. evals/<name>/evals.json).
- Multi-line message corruption from a single
-m with embedded newlines, or a
double-quoted heredoc that lets the shell expand $/backticks.
- Trailer corruption: trailers typed into the body, added through
git interpret-trailers --trailer plus plumbing or a synthesized message
file, dropped when rewording with --amend -m (re-add with --trailer),
wrong capitalization, or a stray Key: value body line folding into the
footer.
- Mixing unrelated concerns into one commit so blame, bisect, and revert get
messy.
- Destructive recovery without a plan (
git reset --hard, force-push) that
loses work or rewrites shared history.
- A scripted rewrite deriving its deletion targets from a global
git status
snapshot, or deleting right after printing a preview with no confirmed stop
in between — see references/history-and-trailers.md.
Self-check
Before reporting the commit done:
- Does the staged set match the user-visible change, with no out-of-scope,
generated, ignored, or secret files?
- Did every newly selected untracked artifact have explicit tracking intent or
mandatory coupling, rather than only relevance, path placement, or commit
permission?
- Did you read
git diff --cached (not just the file list) and run --check?
- Did internal message-to-diff reconciliation cover every material concern and
invalidate on source drift? When the change is complex, multi-package,
reword/amend, conflicted with a supplied message, or audit-requested, did the
public receipt expose that decision clearly?
- Is the subject a Conventional Commit naming the outcome, with the body kept to
context the diff cannot recover?
- Did you verify the stored commit (
git show -s --format=%B HEAD and
the exact committed patch, with git show --stat HEAD as auxiliary), not just
the command you ran?
- If a trailer was required, did it land as a parsed footer in the exact
authorship form for the agent that wrote the commit and the repo's existing
convention?
- If an authorship trailer was newly added or repaired, did the transport path
use
git commit --trailer, git commit --amend ... --trailer, or git commit -C ... --trailer, never a hand-edited footer, raw append, or plumbing-created
message?
- Did anything outside the agreed scope get committed, pushed, or rewritten?
- If the rewrite deleted any path, did it pass the commit-scoped, confirmed-stop
gate in
references/history-and-trailers.md rather than an ambient snapshot
or an unconfirmed preview?
1---2name: vibe-commit3description: Use when the user asks to commit, stage, or "save" agent-assisted coding changes — including vague requests like "commit this", "commit please", "コミットして", or "/commit" — and the real work is deciding which files belong in the commit, excluding unwanted or generated files, splitting unrelated changes, or fixing a commit's file set, multi-line message transport, history (amend/rebase), or authorship trailers. This skill owns commit execution, message transport, and git safety.4---56# Vibe Commit78## Overview910A vague "commit please" is a request to turn a messy working tree into one11clean, correctly scoped commit — not a request to run `git add -A && git12commit`. The instruction is underspecified on purpose: the user trusts the agent13to decide what belongs in the commit, keep junk out, and leave a message and14history a future maintainer can use.1516This skill governs the *execution* of that: which files to stage, what to keep17out, how to re-verify the staged set before committing, how to transport a18multi-line message without corruption, and how to amend or repair a commit while19keeping authorship trailers intact. The guidance here is distilled from real20agent sessions where these exact steps prevented — or, when skipped, caused —21commit mistakes.2223When a request calls for a commit and no blocking condition remains, the24deliverable carries every applicable gate whether it is executed or, for a25"command only" ask or a response-only decision over represented repository26state, shown as the command sequence: tree inspection, the staged-set gate27with the staged diff read, the commit command, and verification of the stored28message against the exact committed patch and of the remaining working-tree29state. A bare commit invocation is not a commit answer. For an inspection-only30request or a blocked decision, stop at the applicable boundary and say what31remains unresolved; add no commit command or post-commit check for an32operation that will not occur.3334## Message content vs. commit execution3536Commit work splits cleanly between message content and execution:3738- The commit message content must stand on its own: an outcome-focused39 Conventional Commit subject, body only for durable context the diff cannot40 recover, medium-density body wording that names durable contract surfaces41 without becoming a feature walkthrough, a compact `Verification:` section that42 explains what durable proof covers instead of replaying session commands, no43 prompt/session/plan labels, and no Markdown wrappers in message bytes. A44 `Verification:` bullet is that pair, not one half of it: keep the exact45 command as the rerun anchor and add what its proof covers, so neither deleting46 the command nor leaving it bare counts as a compact verification section.47- `vibe-commit` owns the **execution**: staging, exclusion, the pre-commit48 verification gate, command safety, history mutation, message transport, and49 trailers as a transport mechanism.5051Apply the compact message rules in `references/history-and-trailers.md` whenever52this skill prepares, inspects, amends, or repairs a commit message. The commit's53*bytes* — file set, message transport, trailer footer, and stored message — are54this skill's responsibility, and you verify them after committing.5556## Authority and safety boundary5758Committing locally is reversible; publishing is not. Stay on the reversible side59of that line unless the user says otherwise.6061### Effect And Write Boundaries6263<!-- shared-contract:class language=none commit=state-changing effect=state-changing -->64<!-- shared-contract:begin closing source=shared/vibe-contract.md -->65For every consolidation block this package carries, here and in its references: where this package declares a stricter or narrower rule in its own text, that declaration controls.66For every gate and schema block this package carries, here and in its references: this package may state which of its phases the block applies to; it may not change the block's inputs, outcomes, or fields.67<!-- shared-contract:end closing -->68<!-- shared-contract:begin effect-write-boundaries source=shared/vibe-contract.md -->69**Write nothing beyond what the phase's own effect class and its declared boundary permit.**7071- Declare exactly one effect class for every workflow phase, in that phase's own text.72- In a read-only phase, read and report; make chat the deliverable — findings, alignment, or direction.73- In a read-only phase, edit no source, test, config, doc, or other file, and run no command that mutates runtime or repository state.74- In a read-only phase, never stage, commit, tag, push, change versions, delete data, or start services.75- In a read-only phase, write a file only when the current user explicitly asks for a saved artifact.76- In an artifact-only phase, create or update the artifact it owns: the requirements spec, the plan, the plan-review state, the instruction files, or the text artifacts the request names.77- In an artifact-only phase, write the supporting paths its own text declares:78 - the text it was asked to revise (comments, docstrings, docs);79 - a confirmed reflection into the bound plan;80 - an ignore file it previewed and the user confirmed;81 - a narrowly confirmed configuration edit its text names;82 - a decision record or findings report its own text declares.83- In an artifact-only phase, leave those verified changes in the working tree.84- In an artifact-only phase, never implement executable behavior, never edit application code or tests as implementation, never produce an artifact another phase owns, and never perform release work.85- Never let an artifact-only phase's artifact authorize same-turn implementation.86- In a state-changing phase, edit files and run commands inside the scope its own text declares — the unit it implements, the repair it proves, the fixes it applies, the round it integrates, or the commit it executes.87- In a state-changing phase, keep its edits to the smallest verified unit of that scope.88- In a state-changing phase, leave paths outside the scope, pre-existing working-tree changes the phase did not make, and runtime or external state beyond the scope unwritten unless the current user selects them.89- Keep every irreversible or outward-facing operation under its own consent.90<!-- shared-contract:end effect-write-boundaries -->9192The scope this workflow declares is the commit it executes — the index and93history of that commit and the message it transports — and it makes no source94edits.9596**Honor `.gitignore` and the agreed scope.** Never `git add -f` an ignored97path, and never stage files outside the change being committed, unless the98user explicitly asks to include that ignored path after you have surfaced why99it is ignored and what risk that creates. Decide scope by the user-visible100change, not by whatever happens to be dirty.101102**No surprise side effects.** Do not bump versions, cut releases, or trigger103hooks the repo did not ask for as a byproduct of committing.104105### Durable Records106107Before recording a settled decision, deferring a finding, or closing a unit,108read `references/durable-records.md`. This phase ordinarily writes neither109`docs/decisions/` nor `docs/reports/findings/`; it hands a decision or finding110forward as the carry-forward packet that reference defines, and a saved111artifact the user explicitly requests stays within this phase's own boundary.112113### Commit Selection114115<!-- shared-contract:begin commit-selection-state-changing source=shared/vibe-contract.md -->116**Only an explicit user request, a bound plan item, or a workflow's own verified checkpoint selects a commit.**117118- Select a commit from exactly three sources: an explicit current-user request; a bound approved plan item requiring that checkpoint; or a state-changing workflow closing its own verified, reviewed, in-scope unit under its checkpoint default.119- Never let routing or invocation, edit permission, a convenient stopping point, tracked changes in the working tree, or an available commit-execution workflow select a commit.120- Never treat an unverified unit as a handoff.121- Execute in commit-execution only the commits those sources select; that phase has no checkpoint default of its own.122- Close a self-contained unit of the workflow's own work with a local commit of exactly that unit once it is implemented, verified, reviewed, and its material findings dispositioned.123- Commit that unit without waiting for a separate commit instruction.124- Never let a multi-unit run accumulate as one undifferentiated working tree.125- When the default is suspended, leave the verified changes in the working tree and report the reason.126- Let the checkpoint default reach only local commits of the unit's own verified changes.127- Select no commit from discovery-only, blocked, unchanged, failing, unverified, or work-in-progress state.128- Never widen the staged set beyond the verified unit.129- Exclude pre-existing working-tree changes the workflow did not make, an artifact whose tracked status would itself be new, and paths outside the unit.130- Never treat an available commit-execution workflow or ambient tracked status as a reason to include them.131- When the unit's changes cannot be separated from unrelated working-tree state, report the mixed state and ask instead of committing.132- Route every selected commit through the commit-execution workflow with the verified scope, its test and review evidence, its unrelated-path exclusions, and any proposed message.133- Leave staging, file-set and exact-diff review, message transport, history safety, and post-commit verification to that workflow.134- Never read a request to commit as a request to push.135- Keep push, release preparation, version changes, tags, amend, rebase, reset, stash, squash, destructive actions including cleanup, force-adds, tracking a newly created artifact, external side effects, and unrelated or ambiguous paths separately consent-bound even when a checkpoint was selected.136- Never let a route, checkpoint, or handoff implicitly authorize them.137138Example: "the user asked for a commit this turn" names a source; "this is a good stopping point" does not.139140Exception: a current no-commit instruction, a bound plan that forbids commits, or project policy against commits suspends the checkpoint default.141<!-- shared-contract:end commit-selection-state-changing -->142143This workflow is that commit-execution phase: it executes the commits those144three sources select, keeps no checkpoint default of its own, and runs no145`git push` unless the current user explicitly asks. Scoped checkpoint handoffs146reach it as commit requests for their named paths.147148Every handoff still passes this skill's file-set, verification, message,149and history-safety gates, and none of them authorizes broad staging, empty150commits, push, release work, version changes, or history rewriting.151152**Separate discovery from lifecycle authority.** Status, diff, path153existence, same-session creation, logical relevance, conventional repository154placement, and commit permission make a path a candidate; they do not by155themselves authorize tracking, staging, or commit membership. A newly156selected untracked artifact needs explicit tracking intent or an applicable157mandatory repository/owning-workflow coupling. Already tracked coupled tests,158docs, specs, README, and changelog changes may remain part of the selected159logical change when their owning contract requires them.160161### Commit-Selection Gate162163<!-- shared-contract:begin commit-selection-gate source=shared/vibe-contract.md -->164**Never run a plain `git commit` without naming the selection source it rests on.**165166- With no user-installed hook enforcing this gate, this wording is the whole gate: apply it yourself before the command runs.167- Name one recorded source before committing: the current user's request (`user-turn`), the bound plan item (`bound-plan-item`), or the workflow's own checkpoint of a verified unit (`specialist-checkpoint`).168- Treat `agent-proposed` as a recorded proposal, never a selection.169- When the workflow is router-bound, have the router record that source as a `commit-selection` event before the command runs.170- For a standalone commit with no router active, name the direct current-user request or the verified checkpoint handoff and follow the phase's ordinary confirmation policy.171- When no source can be named, do not commit; ask the user whether a commit is wanted.172- Return `allow` when the command is not a commit.173- Return `ask` on every plain commit, quoting from the session record under `.plans/vibe-sessions/` the recorded `phase` and the most recent recorded `commit-selection` event's `source`, `at`, and `note`.174- Or state that no `commit-selection` event is recorded, or that the record is absent, malformed, stale, foreign, session-unbound, or conflicting.175- Never return `deny` from this gate.176- Never allow a plain commit silently: surface the recorded `source` at the prompt so a self-attested selection is caught there.177- Answer `ask`, never `deny`, for a record in any invalid state.178179Exception: an amend or other history rewrite belongs to the history-mutation gate, not this one.180<!-- shared-contract:end commit-selection-gate -->181182This gate applies to every plain commit the commit-execution phase runs.183184### History-Mutation Gate185186<!-- shared-contract:begin history-mutation-gate source=shared/vibe-contract.md -->187**Never rewrite git history without stopping and asking the user first.**188189- With no user-installed hook enforcing this gate, this wording is the whole gate.190- Before running a matched command, stop and ask the user with that reason, and proceed only on the user's answer.191- Match `git commit --amend`, `git rebase`, `git filter-branch` or another `filter-*` rewrite, `git reset --hard`, `git push`, or a scripted or looped replay that rewrites more than one commit.192- Return `allow` when the command is not a history mutation.193- Return `ask` for every matched history mutation, naming the matched operation.194- Quote from the session record under `.plans/vibe-sessions/` the recorded `phase`, `effect_mode`, and the `kind` and `source` of every recorded event bearing on it.195- Or state that the record is absent, malformed, stale, foreign, session-unbound, or conflicting, or that no such event is recorded.196- Never return `deny` from this gate.197- Never allow a matched history mutation silently, whatever the record says: surface the recorded values at the prompt so a self-attested record is caught there rather than trusted.198- Treat history that has left this machine — pushed, fetched by another clone, or otherwise published — as shared; no recorded value makes rewriting it silent.199- Let the record decide only the wording of the reason, never the outcome.200- Answer `ask`, never `deny`, for an absent, malformed, stale, foreign, session-unbound, conflicting, or identity-mismatched record.201202Exception: a plain `git commit` belongs to the commit-selection gate, not this one, and a read-only git command is not a history mutation.203<!-- shared-contract:end history-mutation-gate -->204205This gate applies to the history mutations the commit-execution phase runs.206207### History Safety208209**Do not rewrite shared history.** Amending or rebasing an already-pushed210commit rewrites history other clones depend on. Only amend/rebase commits that211have not left this machine, and never force-push a shared branch without an212explicit, informed request. When you stop for that consent, say in the same213answer what the rewrite would cost — other clones diverge and collaborators may214have to rebase, reset, or reconcile duplicated commits — and name the correction215paths you are offering, including whether a later commit can reach the defect at216all.217218**Never let a scripted rewrite delete live files without a separate confirmed219stop.** When a scripted or looped multi-commit rewrite drops paths from220history, derive each step's target list from that commit's own tree (e.g.221`git ls-tree`), never from an ambient whole-worktree snapshot (`git status`,222`-uall`, or similar) — the two are different states, and conflating them223deletes files unrelated to the commit being rewritten. Print the full224resolved list first and require an explicit confirmed stop before any225deletion executes; a preview a script can run straight past is not a gate. A226backup limits damage if something goes wrong — it never substitutes for that227per-path confirmation, and it does not by itself authorize deleting a live228working-tree file. See `references/history-and-trailers.md`.229230## Core workflow: "commit please" → one clean commit231232Follow this spine. Each step names the load-bearing command; the references go233deeper on the judgment calls.2342351. **Discover everything.** `git status --short --branch --untracked-files=all`236 and `git status --ignored` show every modified, staged, untracked, and237 ignored path in one view. Add `git log -1 --oneline` and `git branch238 --show-current` so you know the branch and the commit you might extend.2392. **Inspect intent.** Read the actual changes — `git diff --stat`, then `git240 diff -- <file>` for specific files and `git diff -- <newfile>` (or open it)241 for untracked ones. Decide what each path *is* before deciding whether it242 belongs.2433. **Classify and select.** Sort every changed path into (a) the core244 deliverable that forms ONE logical change — implementation plus its tests and245 the docs/CHANGELOG/spec it fulfills — versus (b) out-of-scope edits or246 generated artifacts. For every newly selected untracked artifact, verify247 tracking intent or mandatory coupling before staging it. Split unrelated248 concerns into separate commits. See `references/file-selection.md`.2494. **Exclude deliberately.** Leave generated, scratch, unowned plan/spec, build,250 unrelated lock, agent-state (`.agents/`, `.claude/`, `.codex/`), and secret251 paths unstaged. A verified requirements or plan artifact named by an owning252 workflow's scoped checkpoint handoff is owned content, not generic scratch.253 A lockfile that records a dependency change needed by the selected commit is254 in-scope with the manifest; do not drop it just because it is a lockfile.255 When unsure whether a path is ignored, `git check-ignore -v <path>`. See256 `references/file-selection.md`.2575. **Stage explicitly.** `git add -- <path1> <path2> …` by full name. Avoid `git258 add .` / `-A` / globs in a dirty tree — they silently sweep in strays. For a259 file with mixed in-scope and out-of-scope hunks, `git add -p <file>`.2606. **Re-verify the staged set (mandatory gate).** Before committing, confirm261 what you are about to commit: `git diff --cached --name-only` (exact files),262 `git diff --cached --stat` (volume sanity), `git diff --cached` (read the263 hunks), `git diff --cached --check` (whitespace/line-ending errors). In-scope264 files present, out-of-scope/ignored files absent, diff matches intent. This265 2–3 second gate is the single highest-leverage habit; see266 `references/staging-and-recovery.md`.2677. **Reconcile message to the exact target diff (mandatory internal gate).** Read268 the complete final staged patch and map every material concern to the proposed269 type, scope, outcome, body coverage, and one-commit or split decision. Bind270 the decision to the current staged bytes; source drift invalidates it. Show a271 detailed public receipt only for complex or multi-package changes,272 reword/amend work, a supplied-message conflict, or a user-requested audit. In273 those cases, keep the receipt compact but explicit about the source target,274 peer concerns and shared contract, type/scope/outcome bases, subject/body275 coverage, one-commit or split decision, supplied-message disposition, and the276 rule that source-patch drift requires reconciliation again. When the diff277 touches an accepted decision record's `paths`, check conformance or the278 superseding record in the same commit, else report the conflict. Report that279 conflict and ask: name the record id, its binding `paths`, and the exact280 non-conformance, then ask whether to stop or proceed instead of closing that281 question yourself. See `references/history-and-trailers.md`.2828. **Decide amend vs. new.** Create a NEW commit by default. Only `--amend` to283 fix the immediately preceding, unpushed commit. See284 `references/history-and-trailers.md`.2859. **Compose the message.** Conventional Commits `type(scope): summary`286 (imperative, ≤72 chars) naming the outcome, blank line, then a body only when287 it preserves durable context the diff cannot recover. For body-worthy288 commits, use a medium-density shape: one to three short paragraphs or a few289 labeled bullets that group changes by durable surface, constraint, non-goal,290 or risk. If the message wants a long feature walkthrough, file inventory, or291 manual-test transcript, summarize or split the commit. Detect the repo's292 trailer convention first: `git log -5 --format='%H%n%B'`. A new repository293 convention this phase adopts, and any defect it discovers, go to the closing294 workflow's carry-forward packet.29510. **Transport the message safely.** For any multi-line body, use a heredoc296 (`git commit -F - <<'EOF' … EOF`, single-quoted delimiter) or `git commit -F297 <file>`. Add or repair authorship trailers with a `git commit ... --trailer298 'Key: value'` command — including `git commit --amend ... --trailer` or `git299 commit -C <ref> --trailer ...` for local rewrites — not by typing them into300 the body or a synthesized message payload. Never embed raw newlines in a301 single `-m`. See `references/history-and-trailers.md`.30211. **Post-verify the stored commit.** `git show -s --format=%B HEAD` confirms303 subject/body/trailer landed byte-correct and the trailer parsed as a footer;304 for newly added or repaired authorship trailers, also confirm the command305 path used `git commit ... --trailer`. For body messages, inspect the stored306 message for low-signal verification dumps, bullets that only list session307 commands without review meaning, and local-only proof-source leakage such as308 git-unmanaged local generated artifacts, ignored result files, local-only309 run IDs, or private tool-session records. Compare the stored message with310 the exact committed patch and the internal pre-commit reconciliation;311 `git show --stat HEAD` is only an auxiliary file-set check. A semantic312 mismatch remains incomplete and is repaired only within existing313 unpushed-history authority. `git status --short` confirms only314 intentionally-left files remain and nothing leaked.31512. **Recover reversibly if wrong.** Prefer the least-destructive fix:316 `git restore --staged <file>` to unstage, `git reset --soft HEAD~1` to undo317 a commit while keeping changes, `git commit --amend --no-edit --trailer …`318 to fix a just-made local commit. See `references/staging-and-recovery.md`.319320## When the request is narrower321322Not every invocation is a full "commit please." Jump to the relevant reference:323324- a response-only task supplies represented repository state and says not to325 inspect or mutate the ambient checkout → treat the supplied staged, dirty,326 verification, permission, and history facts as the target state. Show the327 complete decision and command gates that would apply without executing them;328 do not replace represented changes with an empty eval sandbox or claim that329 represented commands actually ran.330- "did I stage the right things?", "check what's staged", split a commit, drop a331 stray file → `references/staging-and-recovery.md`332- "this got committed and shouldn't have", undo/unstage, fix a wrong file set,333 recover lost work → `references/staging-and-recovery.md`334- fix the last commit, amend, reword, add/fix a `Co-Authored-By`, multi-line335 message corruption → `references/history-and-trailers.md`336- a rewrite must drop or delete paths across multiple commits (not just a337 trailer repair) → `references/history-and-trailers.md`338- "what should I commit / leave out?", excluding generated or secret files →339 `references/file-selection.md`340- "commit the staged changes" → do not invent extra staging, but still run the341 mandatory staged-set gate before committing and the stored-commit verification342 after committing.343- "show the exact commit command" or "commit command only" → include the exact344 `git commit ...` invocation, but do not collapse the answer to that one line.345 The safe artifact is the command sequence: staged-set verification, commit346 command, then stored-message/file-set verification. Simple docs commits and347 trailer-only commits are not exempt.348- the user supplies `git status`, `git diff`, or `git log` excerpts → treat them349 as evidence, but still run or show the corresponding inspection commands in350 the sequence. Do not jump from supplied excerpts straight to staging,351 committing, amending, or splitting.352- a commit subject needs evidence → choose a concrete Conventional Commit353 subject before showing an executable `git commit`, or stop before the commit354 command. Use supplied user intent even when it is broad: a named feature, bug355 fix, module, or behavior change is enough for a conservative subject. Do not356 defer a usable broad subject to future diff output merely to make it more357 precise. If paths/status are the only evidence and no behavior or fix class is358 supplied, inspect `git diff` or `git diff --cached` first; in a response-only359 command plan, show that inspection step and omit `git commit` until a concrete360 subject can be written. A commit command block whose subject contains361 angle-bracket text, unresolved-marker words, or instructions to fill the362 subject later is still an invalid shown command even if prose says not to run363 it.364- partial staging is needed → verify both sides with file-specific diffs:365 `git diff --cached <file>` for the committed hunk and `git diff <file>` for366 the intentionally-left local hunk. Show both as explicit verification367 commands before committing; a prose note or `git status` is not a substitute.368- an amend/rebase would touch pushed history → name the concrete collaboration369 risk: other clones can diverge and collaborators may have to rebase, reset, or370 reconcile duplicated commits.371- a user-named path is absent from `git status` → check `git check-ignore -v372 <path>` before deciding. If it is ignored, especially local config or373 secret-like data, do not force-add it merely because the path was named; state374 that the requested scope cannot be fully committed without an explicit375 override after the ignore rule is known.376377## Common mistakes378379- `git add .` / `-A` / a glob in a dirty tree, sweeping in unrelated edits,380 generated output, lock files, or secrets.381- Committing immediately after `git add` without re-reading the staged diff.382- Force-adding or accidentally committing ignored/scratch content (eval383 workspaces, `plans/`, `.codex/`, `.env`).384- Committing a whole generated directory instead of just its durable spec385 (`evals/<name>/` vs. `evals/<name>/evals.json`).386- Multi-line message corruption from a single `-m` with embedded newlines, or a387 double-quoted heredoc that lets the shell expand `$`/backticks.388- Trailer corruption: trailers typed into the body, added through389 `git interpret-trailers --trailer` plus plumbing or a synthesized message390 file, dropped when rewording with `--amend -m` (re-add with `--trailer`),391 wrong capitalization, or a stray `Key: value` body line folding into the392 footer.393- Mixing unrelated concerns into one commit so blame, bisect, and revert get394 messy.395- Destructive recovery without a plan (`git reset --hard`, force-push) that396 loses work or rewrites shared history.397- A scripted rewrite deriving its deletion targets from a global `git status`398 snapshot, or deleting right after printing a preview with no confirmed stop399 in between — see `references/history-and-trailers.md`.400401## Self-check402403Before reporting the commit done:404405- Does the staged set match the user-visible change, with no out-of-scope,406 generated, ignored, or secret files?407- Did every newly selected untracked artifact have explicit tracking intent or408 mandatory coupling, rather than only relevance, path placement, or commit409 permission?410- Did you read `git diff --cached` (not just the file list) and run `--check`?411- Did internal message-to-diff reconciliation cover every material concern and412 invalidate on source drift? When the change is complex, multi-package,413 reword/amend, conflicted with a supplied message, or audit-requested, did the414 public receipt expose that decision clearly?415- Is the subject a Conventional Commit naming the outcome, with the body kept to416 context the diff cannot recover?417- Did you verify the **stored** commit (`git show -s --format=%B HEAD` and418 the exact committed patch, with `git show --stat HEAD` as auxiliary), not just419 the command you ran?420- If a trailer was required, did it land as a parsed footer in the exact421 authorship form for the agent that wrote the commit and the repo's existing422 convention?423- If an authorship trailer was newly added or repaired, did the transport path424 use `git commit --trailer`, `git commit --amend ... --trailer`, or `git commit425 -C ... --trailer`, never a hand-edited footer, raw append, or plumbing-created426 message?427- Did anything outside the agreed scope get committed, pushed, or rewritten?428- If the rewrite deleted any path, did it pass the commit-scoped, confirmed-stop429 gate in `references/history-and-trailers.md` rather than an ambient snapshot430 or an unconfirmed preview?