commit — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited commit (Agent Skill) and scored it 96/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 1 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 1 flagged
The text {match} tells the agent to skip the normal "ask the user first" gate. Used adversarially it removes the human-in-the-loop check before destructive or sensitive actions, turning a normally-gated agent into a fire-and-forget executor.
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
You are generating a commit message for the user's staged changes. Work in phases. Never run git commit until the user has confirmed the message.
Run bash bin/session-check.sh --flow=commit. If it produces output, surface the line to the user verbatim. Do not block the flow.
Run bin/commit.sh --target <cwd>. The script emits a JSON context object (target, branch, on_main, convention, staged_files, summary, diff, truncated).
Exit code handling:
0 → JSON context emitted. Check the nothing_staged field:nothing_staged: true → ask the user what they want to stage(git add <paths>, git add -p, or "everything"), then re-run.
2 → not a git repo. Tell the user, stop.If on_main: true, warn the user that the block-main hook will reject the commit. Suggest they create a feature branch via the new-branch skill before continuing.
Run both of these before generating the message — they inform scope choice and prevent obvious mistakes from reaching the commit message step:
bash bin/pre-action-guard.sh --flow commit --target <cwd> [--profile <resolved-profile.json>]
bash bin/commit-hygiene.sh --target <cwd> [--profile <resolved-profile.json>]| Exit | Meaning | Action |
|---|---|---|
| 0 | All guards passed (or only advisory warnings) | Surface any advisory message lines, continue |
| 3 | One or more critical guards failed | Surface the failing guard messages. Refuse to proceed unless the user passes --skip-guards explicitly (re-ask via AskUserQuestion). |
| 4 | One or more confirm-severity guards failed | Surface the failures. Call AskUserQuestion: "Proceed despite the warnings?" Only continue on explicit confirm. |
Don't silently pass critical failures. The merge-conflict-markers guard catching <<<<<<< in the staged diff is exactly the case where "warn and continue" would let a broken merge into a commit.
commit-hygiene.sh emits {scope_suggestion, incomplete_staging, debug_artifacts, dead_code, summary}. Surface them inline:
scope_suggestion.primary (when non-null) — pre-fill the CC scope in§3 with this value unless the user objects.
incomplete_staging[] — surface each entry as a short warning("package.json staged but lockfile is modified-but-unstaged"). Don't block; the user may genuinely intend a partial commit.
debug_artifacts[] — show file:line:match. Ask the user viaAskUserQuestion whether to abort + clean up, or continue.
dead_code[] — show file:line:name. Same prompt as debug artifacts.If summary.warnings == 0, skip the hygiene surface entirely — quiet when there's nothing to say.
Read context.convention:
| value | meaning | reference |
|---|---|---|
conventional-commits | commitlint.config.* present; CC format enforced | references/conventional-commits.md |
commitizen | .pre-commit-config.yaml has commitizen; CC format with stricter body/footer rules | references/conventional-commits.md + commitizen notes |
default | no framework configured; core commit-msg hook regex applies (CC format too) | references/conventional-commits.md |
In every case you are writing Conventional Commits. Load references/conventional-commits.md for the authoritative rules and examples before generating.
Using the diff + file summary + convention, write a message with this shape:
<type>[(<scope>)][!]: <description>
[optional body — wrap at 72 chars, use imperative mood]
[optional footers: "Closes #N", "BREAKING CHANGE: ..."]Rules you must respect (full rationale in the reference):
<type> ∈ {feat, fix, chore, docs, refactor, test, perf, ci, build, style, revert}.! before the : ONLY when the change is a breaking public-API change.Pair with a BREAKING CHANGE: footer if so.
split. Don't invent a catch-all subject.
Closes #N / Fixes #N go in the footer block only — never in the subject.Show the user the generated message plus:
You MUST call the `AskUserQuestion` tool (not plain text) to confirm:
{
"questions": [
{
"question": "Proceed with this commit message?",
"header": "Commit",
"multiSelect": false,
"options": [
{ "label": "Commit", "description": "Create the commit with this message" },
{ "label": "Edit", "description": "Let me revise the message first" },
{ "label": "Abort", "description": "Cancel, don't commit anything" }
]
}
]
}Invoke bin/try-commit.sh --target <target> --subject <subject> [--body <body>]. It attempts git commit and emits a structured JSON result instead of failing the tool call, so you can branch on result:
{"result":"committed","sha":"abc123","subject":"feat: ...","stage":null,"reason":null,"exit_code":0}
{"result":"rejected","sha":null,"subject":"...","stage":"commit-msg","reason":"<hook stderr>","exit_code":1}
{"result":"error","sha":null,"subject":"...","stage":null,"reason":"<stderr>","exit_code":N}Never pass --no-verify. The commit-msg hook is a safety net, not noise.
If result == "rejected" and stage == "commit-msg":
reason for the hook's failure line (typically the regex itwanted or the specific rule that rejected the subject).
original user-facing scope/intent; only adjust the form.
try-commit.sh again with the corrected subject.user the last rejection's reason + the message you tried, and ask for manual input. Do not loop further. Do not suggest --no-verify.
For result == "rejected" on pre-commit stage, the user usually needs to fix their working tree (formatter / linter / block-main). Surface the reason verbatim and stop — don't try to auto-fix code.
For result == "error" (non-hook failure, e.g. identity missing), pass the reason verbatim to the user. They fix their environment.
On success, end with:
git rev-parse HEAD).nothing_staged: true in the JSON → ask what to stage, then re-run§1. Don't assume "everything".
ask the user to rewrite. Don't loop further.
git commit errors for non-hook reasons (e.g. author missing) → surfacethe git error verbatim; the user fixes their environment.
pr skill (PR only) or ship skill(PR + merge in one step).
sync skill.new-branch skill.undo skill.Details: references/conventional-commits.md.
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.