swe-workflow-skills 0.6.3 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/VERSION +1 -1
- package/catalog.json +2 -2
- package/package.json +1 -1
- package/skills/code-reviewing/SKILL.md +24 -6
- package/skills/code-reviewing/evals/evals.json +19 -3
- package/skills/code-slop-cleanup/SKILL.md +7 -0
- package/skills/code-slop-cleanup/evals/evals.json +13 -0
- package/skills/code-slop-cleanup/references/slop-patterns.md +4 -1
- package/skills/git-workflow/SKILL.md +119 -8
- package/skills/git-workflow/evals/evals.json +37 -5
- package/skills/git-workflow/templates/pull-request.md +10 -5
- package/skills/plan-execution/SKILL.md +38 -3
- package/skills/plan-execution/evals/evals.json +30 -0
- package/skills/project-documentation/SKILL.md +73 -6
- package/skills/project-documentation/evals/evals.json +17 -2
- package/skills/release-management/SKILL.md +1 -1
- package/skills/verification-before-completion/SKILL.md +109 -2
- package/skills/verification-before-completion/evals/evals.json +64 -3
- package/skills/verification-before-completion/references/pre-commit-gate.md +239 -0
- package/skills/writing-skills/SKILL.md +33 -0
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.
|
|
1
|
+
0.7.0
|
package/catalog.json
CHANGED
|
@@ -218,7 +218,7 @@
|
|
|
218
218
|
},
|
|
219
219
|
{
|
|
220
220
|
"name": "plan-execution",
|
|
221
|
-
"description": "Execute an already-approved plan with discipline — batch tasks into verifiable checkpoints, verify each with fresh evidence before marking it done, log drift, and stop to re-plan when reality diverges from the plan's assumptions.
|
|
221
|
+
"description": "Execute an already-approved plan with discipline — batch tasks into verifiable checkpoints, verify each with fresh evidence before marking it done, log drift, and stop to re-plan when reality diverges from the plan's assumptions. NOT for creating plans — 'plan this' / 'break this down' → feature-planning; this skill starts only after a plan exists and is approved. Triggers: execute the plan, implement the approved plan, work through this plan, continue/resume the plan, next phase, checkpoint.",
|
|
222
222
|
"path": "plan-execution/SKILL.md"
|
|
223
223
|
},
|
|
224
224
|
{
|
|
@@ -323,7 +323,7 @@
|
|
|
323
323
|
},
|
|
324
324
|
{
|
|
325
325
|
"name": "verification-before-completion",
|
|
326
|
-
"description": "Evidence gate before claiming work is done, passing, fixed, or deployed. Use before saying 'done', 'it works', or 'tests pass', or before committing, pushing, or opening a PR. Triggers: is it done, did it work, tests pass, verify, ready to commit, before I push, confirm the fix.
|
|
326
|
+
"description": "Evidence gate before claiming work is done, passing, fixed, or deployed. Use before saying 'done', 'it works', or 'tests pass', or before committing, pushing, or opening a PR. Run the proving command fresh and read its output first. Triggers: is it done, did it work, tests pass, verify, ready to commit, before I push, confirm the fix.",
|
|
327
327
|
"path": "verification-before-completion/SKILL.md"
|
|
328
328
|
},
|
|
329
329
|
{
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "swe-workflow-skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "A curated library of Claude Code Agent Skills covering the full software lifecycle, with orchestrator-routed activation that scales past the skill-listing budget.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -20,8 +20,14 @@ a PR):
|
|
|
20
20
|
!`git diff --stat 2>/dev/null || true`
|
|
21
21
|
|
|
22
22
|
If the summary above is empty or irrelevant to what you were asked to review,
|
|
23
|
-
proceed with the code as provided.
|
|
24
|
-
|
|
23
|
+
proceed with the code as provided.
|
|
24
|
+
|
|
25
|
+
**Called from the pre-commit gate?** When `verification-before-completion` routes
|
|
26
|
+
here before a commit, the review target is `git diff --staged` — the change about
|
|
27
|
+
to be published, not the whole branch. Scope to it, keep the pass proportionate to
|
|
28
|
+
what tripped the gate, and report findings in time to fix them before the commit.
|
|
29
|
+
|
|
30
|
+
Before reviewing line-by-line, understand the big picture:
|
|
25
31
|
|
|
26
32
|
- **What is this code supposed to do?** Read the PR description, linked issue, or ask the user.
|
|
27
33
|
- **What changed?** If reviewing a diff, understand the scope of changes — run the
|
|
@@ -47,6 +53,17 @@ the diff, run three greps before accepting it:
|
|
|
47
53
|
exported just to silence the unused-symbol checker).
|
|
48
54
|
- **Any consumer?** A new schema field, prop, or param that nothing reads or sets is
|
|
49
55
|
speculative plumbing — the API looks finished but is wired to nothing.
|
|
56
|
+
- **A comment in the wrong place?** For any new comment block of four or more lines,
|
|
57
|
+
ask what it explains. System-level rationale — why the component exists, what was
|
|
58
|
+
rejected, how it relates to other services — belongs in an ADR or architecture doc
|
|
59
|
+
with the comment reduced to a pointer; a local invariant the types can't express
|
|
60
|
+
stays inline; a restatement of the code goes nowhere. The essay-in-a-header rots
|
|
61
|
+
unread and is unfindable by anyone grepping the docs for it.
|
|
62
|
+
- **A reference nobody can resolve?** `Phase 2`, `CP1.3`, `T02`, `finding #17`,
|
|
63
|
+
`checkpoint 3/5` in comments, names, or strings — check whether a **git-tracked**
|
|
64
|
+
document defines it (`git ls-files '*.md' | xargs grep -l`). Anchored, it's a real
|
|
65
|
+
cross-reference. Unanchored, it names a conversation the reader wasn't in: the
|
|
66
|
+
finding is "write the meaning instead of the label".
|
|
50
67
|
- **Any doc still describing the old shape?** If the diff renames, removes, or adds
|
|
51
68
|
something a user types or configures — a flag, env var, endpoint, config key,
|
|
52
69
|
command, script, install step — grep the README and `docs/` for it, old name
|
|
@@ -67,8 +84,8 @@ Review the code against these categories, in order of importance. See [reference
|
|
|
67
84
|
|
|
68
85
|
**Severity levels for findings:**
|
|
69
86
|
|
|
70
|
-
- 🔴 **Blocker**: Must fix before merge (bugs, security issues, data loss risks) — including a doc the diff makes *wrong* where the doc is an instruction someone follows: install steps, setup commands, the API contract, config keys. A stale instruction fails for the next person, silently, and is worse than no instruction.
|
|
71
|
-
- 🟡 **Suggestion**: Should fix, significantly improves quality (principle violations, missing tests, docs the diff leaves incomplete rather than wrong)
|
|
87
|
+
- 🔴 **Blocker**: Must fix before merge (bugs, security issues, data loss risks) — including a doc the diff makes *wrong* where the doc is an instruction someone follows: install steps, setup commands, the API contract, config keys. A stale instruction fails for the next person, silently, and is worse than no instruction. **Secrets or real personal data in the diff are always blockers** — they survive removal in git history, so flag them before the commit, not after.
|
|
88
|
+
- 🟡 **Suggestion**: Should fix, significantly improves quality (principle violations, missing tests, docs the diff leaves incomplete rather than wrong, misplaced comment essays, unanchored internal terminology)
|
|
72
89
|
- 🔵 **Nit**: Optional improvement (naming, style, minor simplification)
|
|
73
90
|
|
|
74
91
|
### Step 4: Present Findings
|
|
@@ -105,7 +122,7 @@ These are the lenses through which code is examined:
|
|
|
105
122
|
|
|
106
123
|
**Testability**: Is the code testable? Are there tests? Do tests test behavior or implementation?
|
|
107
124
|
|
|
108
|
-
**Readability**: Can someone unfamiliar with this code understand it in one reading? Good naming,
|
|
125
|
+
**Readability**: Can someone unfamiliar with this code understand it in one reading? Good naming, manageable function length, and comments that are both *why, not what* and **in the right place** — the why of a system belongs in an ADR the comment points at; the why of a line belongs on the line. Judge "unfamiliar" literally: a reader with the repo and nothing else, who was in none of the conversations that produced it.
|
|
109
126
|
|
|
110
127
|
**Error Handling**: Are errors caught, logged, and handled appropriately? Are error messages helpful? See [references/error-handling.md](references/error-handling.md) for detailed patterns (null safety, exception context, caller-oriented exceptions).
|
|
111
128
|
|
|
@@ -123,4 +140,5 @@ These are the lenses through which code is examined:
|
|
|
123
140
|
- `refactoring` — when the review surfaces code smells worth a structured cleanup
|
|
124
141
|
- `code-slop-cleanup` — strip AI-slop patterns from the diff before (or instead of) debating them in review
|
|
125
142
|
- `security-audit` — for a dedicated, deep security pass beyond the review checklist
|
|
126
|
-
- `verification-before-completion` — verify the change actually runs before approving, not from the diff alone
|
|
143
|
+
- `verification-before-completion` — verify the change actually runs before approving, not from the diff alone; also the pre-commit gate that routes staged diffs here
|
|
144
|
+
- `architecture-design` — where a system-level rationale found in a comment belongs instead (an ADR)
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"prompt": "Can you review the changes in my last git commit?",
|
|
22
22
|
"expected_output": "Should read the git diff, understand context from surrounding files, and perform a structured review.",
|
|
23
23
|
"assertions": [
|
|
24
|
-
"
|
|
25
|
-
"
|
|
26
|
-
"For any new helper, export, or block,
|
|
24
|
+
"Names the command that reads the change (git show / git diff HEAD~1) and scopes the review to that commit",
|
|
25
|
+
"Establishes the surrounding code as context for the review rather than judging the hunk in isolation",
|
|
26
|
+
"For any new helper, export, or block, states it will search the repo beyond the diff for an existing twin, for importers, and for consumers (duplication / dead export / unconsumed surface are invisible in a single hunk)",
|
|
27
27
|
"Follows the structured review format (summary, blockers, suggestions, nits)",
|
|
28
28
|
"Provides specific file:line references for findings"
|
|
29
29
|
]
|
|
@@ -89,6 +89,22 @@
|
|
|
89
89
|
"Justifies the severity: a wrong instruction is followed and then fails, which is worse than a missing one",
|
|
90
90
|
"Does NOT approve on 'code is consistent and CI is green' alone"
|
|
91
91
|
]
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
"id": 4,
|
|
95
|
+
"prompt": "The pre-commit gate routed you here. Review the staged diff: it adds `src/server/dashboard.ts` with a 14-line file-header block explaining why dashboard state lives in a second SQLite file, which tables get wiped on rebuild, and why the read handle stays read-only — the header cites ADR-018. Below that are two query functions, one commented `// Aggregates (Phase 4). Read-only.` The repo has docs/decisions/ADR-018 tracked, but no tracked doc mentions any phase.",
|
|
96
|
+
"pressure": [
|
|
97
|
+
"looks_good"
|
|
98
|
+
],
|
|
99
|
+
"expected_behavior": "Scopes to the staged diff rather than the whole branch. Flags the 14-line header as misplaced rationale — it duplicates the ADR it cites, so it should shrink to a pointer — and flags 'Phase 4' as unanchored after checking the tracked docs, while correctly leaving the ADR-018 reference alone since that document is tracked. Assigns both as suggestions, not blockers.",
|
|
100
|
+
"assertions": [
|
|
101
|
+
"Scopes the review to the staged diff",
|
|
102
|
+
"Flags the 14-line header as rationale that belongs in the ADR, reduced to a pointer",
|
|
103
|
+
"Checks the tracked docs before judging the terminology rather than assuming",
|
|
104
|
+
"Flags 'Phase 4' as unanchored and recommends writing the meaning",
|
|
105
|
+
"Does NOT flag the ADR-018 reference, which resolves to a tracked document",
|
|
106
|
+
"Rates these as suggestions rather than blockers"
|
|
107
|
+
]
|
|
92
108
|
}
|
|
93
109
|
]
|
|
94
110
|
}
|
|
@@ -33,8 +33,13 @@ Slop is relative — the same construct is correct in one place and slop in anot
|
|
|
33
33
|
|
|
34
34
|
- **High**: debug leftovers, silent-failure handlers, stray working files
|
|
35
35
|
- **Medium**: defensive theater on trusted paths, generic TODOs, unrequested backwards-compat shims, duplication of existing helpers
|
|
36
|
+
- **Medium**: also unanchored internal terminology (`Phase 2`, `CP1.3`, `finding #17`) that no git-tracked doc defines — rewrite to the meaning
|
|
36
37
|
- **Low**: comment slop, dead weight (unused imports, `=== true`, redundant returns), style inconsistent with the file
|
|
37
38
|
|
|
39
|
+
Misplaced rationale — the multi-line header essay explaining a *system* instead of
|
|
40
|
+
the code beneath it — is detected here but **routed, not deleted**: the reasoning
|
|
41
|
+
belongs in an ADR, and deleting it loses something nothing else records.
|
|
42
|
+
|
|
38
43
|
### Step 4: Strip — Deletions Only, Production Code Only
|
|
39
44
|
|
|
40
45
|
Apply removals highest severity first. Every edit must be a behavior-preserving deletion (or a trivial inlining a deletion forces). If removing something requires *rewriting* logic around it, that's refactoring — leave it and flag it.
|
|
@@ -71,6 +76,8 @@ The biggest slop category — duplication — is created at generation time and
|
|
|
71
76
|
|--------|---------|
|
|
72
77
|
| "This check might catch something someday" | If nothing upstream can produce that state, it's theater — and it hides the real bugs by normalizing noise. |
|
|
73
78
|
| "The comments help junior developers" | Restating comments rot and mislead; code clarity helps juniors. Keep why-comments, cut what-comments. |
|
|
79
|
+
| "This 12-line header explains the architecture — I'll delete it as comment slop" | It's misplaced, not worthless. Deleting it destroys reasoning nothing else records. Flag it for the ADR and leave the code alone. |
|
|
80
|
+
| "Phase 3 is obviously meaningful, leave the reference" | Check before assuming: if no tracked doc defines it, it points at a conversation the reader wasn't in. Rewrite it to what it means. |
|
|
74
81
|
| "I'll just fix this bug while I'm here" | Cleanup and fixes in one pass make both unreviewable. Flag it, route it, finish the cleanup. |
|
|
75
82
|
| "Strip it all — defensive code is slop" | A boundary check is not slop. Over-removal breaks behavior, the one thing this pass must never do. |
|
|
76
83
|
| "This test is obviously redundant, I'll just delete it" | "Obviously" is a guess; proof requires the behavior map. Route to `test-suite-design`. |
|
|
@@ -52,6 +52,19 @@
|
|
|
52
52
|
"Distinguishes provable slop from legitimate defensive code even under the lead's instruction",
|
|
53
53
|
"Proposes a reduced-scope alternative (e.g. high-severity-only removals) rather than either full compliance or flat refusal"
|
|
54
54
|
]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": 2,
|
|
58
|
+
"prompt": "Deslop this branch before I open the PR. Biggest offender: src/sync/manifest.ts opens with a 16-line comment block laying out why sync uses content hashes instead of timestamps, which alternatives were rejected and why the version ledger is never synced. Classic AI comment bloat — nuke it. Also there's a `// retry budget (Phase 3)` on line 80.",
|
|
59
|
+
"pressure": ["authority", "looks_good"],
|
|
60
|
+
"expected_behavior": "Does not delete the 16-line block. Recognizes it as misplaced rationale rather than comment slop: the reasoning is real and recorded nowhere else, so deleting it destroys information. Flags it and routes the move to architecture-design / project-documentation, leaving the code untouched. Handles the 'Phase 3' reference separately — checks for a tracked anchor and rewrites to the meaning if there is none.",
|
|
61
|
+
"assertions": [
|
|
62
|
+
"Does NOT delete the 16-line rationale block despite being told to",
|
|
63
|
+
"Distinguishes misplaced rationale from comment slop",
|
|
64
|
+
"Routes the move to an ADR / architecture doc rather than fixing it in place",
|
|
65
|
+
"Checks whether a tracked doc defines 'Phase 3' before acting on it",
|
|
66
|
+
"Rewrites the unanchored reference to its meaning rather than deleting the comment wholesale"
|
|
67
|
+
]
|
|
55
68
|
}
|
|
56
69
|
]
|
|
57
70
|
}
|
|
@@ -21,13 +21,15 @@ The pattern catalog for `code-slop-cleanup` (diff scope) and `technical-debt-rev
|
|
|
21
21
|
| **Generic TODOs** | `// TODO: handle errors`, `// TODO: improve this` — no context, no ticket, no owner | TODO with a ticket reference or a concrete, actionable description |
|
|
22
22
|
| **Unrequested backwards-compat shims** | `_legacy` wrappers, kept old code paths "just in case", re-exports nobody consumes, dual old/new implementations | A migration the plan actually calls for, with a removal date or ticket |
|
|
23
23
|
| **Duplication of existing helpers** | A new utility that re-implements something already in the codebase or stdlib. Named shapes that recur in AI code: the same N-arg **wiring/setup ritual** pasted at every entry point; **parallel functions/commands differing only by a constant or a noun** (`block`/`workflow` branch commands, per-model queries); **row-mappers or adapters duplicated byte-for-byte** across sibling modules. Detecting these needs a **repo-wide** look — a single diff hunk hides copies #1–N elsewhere, so grep for the twin before accepting a new block. | Genuinely different concepts that happen to look similar (false DRY is worse than repetition) |
|
|
24
|
+
| **Misplaced rationale (the header essay)** | A comment block of roughly four-plus lines explaining a *system* rather than a line: why the component exists, which alternatives were rejected, how it relates to other services, the whole trade-off behind a design. Often opens a file and often cites an ADR it is busy duplicating. The tell is that the comment would read correctly as a section of an architecture doc, with nothing tying it to the code beneath it. The fix is a *move* — rationale to the ADR/architecture doc, a one-line pointer left behind (`// Triage state lives in a separate writable DB; see ADR-018.`) — so the reasoning survives where it can be found and reviewed. **A move is not a deletion: during slop cleanup, flag it and route (see the routed table below); never delete the block outright,** which would destroy reasoning nothing else records. | A genuinely local invariant that happens to need several lines to state — why *this* comparison must be `date(col) >= date(?)`, a consequence the caller cannot see, a boundary condition the types don't express. Length is not the test; whether it explains the code below it is. Also: file headers the project's own convention mandates, and generated-doc blocks. |
|
|
25
|
+
| **Unanchored internal terminology** | `Phase 2`, `Fase 4`, `CP1.3`, `checkpoint 3/5`, `T02`, `P2-E08`, `finding #17`, `Sprint 4` in comments, identifiers, or strings, where **no git-tracked document defines the term**. It names a plan, chat, or scratchpad the reader has no access to. Check, don't assume: `git ls-files '*.md' \| xargs grep -l "P2-E08"`. Fix by rewriting to the meaning — `// Dashboard aggregates (Phase 4). Read-only.` → `// Dashboard aggregates. Read-only.` — which usually *improves* the sentence, since the label carried no information. | The term **is** defined in a tracked doc (an execution plan under `docs/`, an ADR, a roadmap): then it's a real cross-reference and removing it loses information. Prefer making the pointer explicit. Also: issue/PR numbers on a public tracker, and version tags. |
|
|
24
26
|
| **Unconsumed surface / speculative plumbing** | Exports with no importers anywhere (the `_`-prefix + `export` tell — exported only to silence the unused-symbol checker); a fully-built, unit-tested module never wired into any path; a schema field validated but never read, a prop threaded through layers but never set, a param carried "for symmetry" but unused, a value computed but never surfaced. The API *looks* finished; nothing calls it. | A library/package's genuine public API; params required by an interface/callback signature; a documented extension point with a near-term, named consumer landing in the same change |
|
|
25
27
|
|
|
26
28
|
## Low severity — cosmetic residue
|
|
27
29
|
|
|
28
30
|
| Pattern | Tells | When it's NOT slop |
|
|
29
31
|
|---------|-------|--------------------|
|
|
30
|
-
| **Comment slop** | Comments restating the code (`// increment counter`), section dividers, agent narration ("Here we now handle…"), docstrings repeating the signature, journal comments, a **changelog / version-history block embedded in source** (belongs in CHANGELOG/ADR), a **stale comment describing a scheme the code no longer implements** (actively misleading, worse than none) | Why-comments on non-obvious decisions
|
|
32
|
+
| **Comment slop** | Comments restating the code (`// increment counter`), section dividers, agent narration ("Here we now handle…"), docstrings repeating the signature, journal comments, a **changelog / version-history block embedded in source** (belongs in CHANGELOG/ADR), a **stale comment describing a scheme the code no longer implements** (actively misleading, worse than none) | Why-comments on non-obvious decisions *about the code they sit on*; consequence warnings; docstrings on public API the project mandates. Where the why concerns the system rather than the line, see **Misplaced rationale** above — that one is moved, not deleted |
|
|
31
33
|
| **Dead weight** | Unused imports/params/variables, `return undefined`, `=== true`, `Promise.all` around a single promise, unreachable branches | Parameters required by an interface/callback signature; re-exports that are the module's public API |
|
|
32
34
|
| **Style inconsistency** | Naming, formatting, or idiom that doesn't match the surrounding file (e.g. `fetchData` in a file that uses `getX` everywhere) | The file itself is inconsistent and the new code follows the project-level convention |
|
|
33
35
|
|
|
@@ -37,6 +39,7 @@ These are slop, but this catalog's consumers don't fix them in place:
|
|
|
37
39
|
|
|
38
40
|
| Pattern | Tells | Route to |
|
|
39
41
|
|---------|-------|----------|
|
|
42
|
+
| **Misplaced rationale (the header essay)** | See the medium table above. Detection is in scope here; the fix isn't. | `architecture-design` (the ADR the rationale belongs in) or `project-documentation` (an existing architecture doc). Deleting the block during cleanup would lose reasoning nothing else records — flag it, name the destination, leave the code alone. |
|
|
40
43
|
| **Test-file slop** | Redundant/duplicate tests, trivial asserts (`expect(true)`), asserting on the mock, implementation-mirroring tests | `test-suite-design` (Pruning Test Slop) — deleting a test is never behavior-neutral for the safety net; it needs behavior-map judgment. **Never delete a test during diff cleanup.** |
|
|
41
44
|
| **Type slop** | `any`/`unknown` to silence the checker, casts papering over mismatches, single-implementer interfaces "for testing", overly broad types (`env: object` then `type: ignore` to reach a field), **stale `type: ignore` matching no current error**, a **declared strict gate (`mypy strict`, `--max-warnings 0`) sitting on N errors** because nobody runs it | `technical-debt-review` (type debt) — usually cross-file; fixing it changes signatures. Running the gate green is the `verification-before-completion` "done" step |
|
|
42
45
|
| **Config/scaffolding slop** | Config keys and feature flags nothing reads, orphan `.env` entries, checked-in generated files, half-finished TODO scaffolds | `technical-debt-review` (config/scaffolding debt) — proving "unread" needs repo-wide tracing |
|
|
@@ -26,6 +26,26 @@ Identify:
|
|
|
26
26
|
- **Why did it change?** (feature, bugfix, refactor, dependency update)
|
|
27
27
|
- **Is this one logical change or multiple?** If multiple, suggest splitting into separate commits.
|
|
28
28
|
|
|
29
|
+
**This step is not a gate on writing the message.** Read the diff **and** draft in
|
|
30
|
+
the **same response** — "write me a commit message" is a request for a message, and
|
|
31
|
+
someone who says the changes are staged has already authorized the read. Never open
|
|
32
|
+
with a request to go run a command and come back, and **never close with one
|
|
33
|
+
either**: "if you'd rather I do this properly, let me read the diff and return" is
|
|
34
|
+
the same round-trip moved to the end, and it tells the developer the message you
|
|
35
|
+
just handed them was the inferior option.
|
|
36
|
+
|
|
37
|
+
**The diff is the basis, not an optional cross-check.** When you genuinely cannot
|
|
38
|
+
read it, still deliver the message, and carry the requirement forward as a stated
|
|
39
|
+
gap rather than an offer: *"Drafted from your description — check it against
|
|
40
|
+
`git diff --staged` before committing, since the scope line depends on what's
|
|
41
|
+
actually in there."* That is a deferred requirement. "Want me to look?" is not.
|
|
42
|
+
|
|
43
|
+
**Brevity applies to the message, not to the judgment.** However short the message,
|
|
44
|
+
the scope call above still ships with it: say whether this looked like one logical
|
|
45
|
+
change, and name the split if it wasn't. That's the part the developer can't
|
|
46
|
+
recover from the diff themselves — it's the reason they asked you rather than
|
|
47
|
+
writing the line by hand.
|
|
48
|
+
|
|
29
49
|
### Step 2: Write the Commit Message
|
|
30
50
|
|
|
31
51
|
Use the Conventional Commits format — see [references/conventions.md](references/conventions.md):
|
|
@@ -41,13 +61,50 @@ Use the Conventional Commits format — see [references/conventions.md](referenc
|
|
|
41
61
|
**The subject line** (first line):
|
|
42
62
|
- Type: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`, `perf`, `ci`, `build`
|
|
43
63
|
- Scope: The module, component, or area affected (optional but recommended)
|
|
44
|
-
- Description: Present tense, lowercase, no period,
|
|
64
|
+
- Description: Present tense, lowercase, no period, **72 characters total** including
|
|
65
|
+
the `type(scope):` prefix — the commitlint default, and what keeps `git log --oneline`
|
|
66
|
+
readable in an 80-column terminal. (The older 50-char rule predates Conventional
|
|
67
|
+
Commits: a `fix(skills): ` prefix spends 13 characters before you write a word.)
|
|
45
68
|
- It should complete the sentence: "If applied, this commit will..."
|
|
46
69
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
|
|
70
|
+
Where a tool generates the changelog (release-please, changesets, semantic-release),
|
|
71
|
+
**this line is the changelog entry** a consumer reads at upgrade time — and on a
|
|
72
|
+
squash-merge repo, that means the **PR title** is. Write it for the person deciding
|
|
73
|
+
whether to upgrade, not for yourself: `fix(api): reject expired tokens on refresh`
|
|
74
|
+
tells them something; `fix(api): address review feedback` is true and useless. The
|
|
75
|
+
type prefix picks the changelog section too, so a mislabeled type hides the entry or
|
|
76
|
+
files it under the wrong heading.
|
|
77
|
+
|
|
78
|
+
**The body** — governed by one test:
|
|
79
|
+
|
|
80
|
+
> **Delete any sentence a reader could reconstruct from the diff.**
|
|
81
|
+
|
|
82
|
+
The diff is attached to the message. Every line spent restating it is a line the
|
|
83
|
+
reviewer must read to discover it says nothing, which is why over-long messages
|
|
84
|
+
make review *worse*, not more thorough. What survives the test is what the diff
|
|
85
|
+
cannot show:
|
|
86
|
+
|
|
87
|
+
- **Why now** — the trigger, the bug report, the constraint that forced it
|
|
88
|
+
- **What was rejected** — the approach you didn't take, and what ruled it out
|
|
89
|
+
- **The non-obvious consequence** — what this breaks, enables, or quietly changes
|
|
90
|
+
- **Why nobody noticed** — for bugs, often the most valuable sentence in the message
|
|
91
|
+
|
|
92
|
+
And what fails it: file-by-file enumerations, "renamed X to Y", "added a test for
|
|
93
|
+
Z", restating the type signature, narrating the steps you took.
|
|
94
|
+
|
|
95
|
+
Length follows from that, not from the size of the change:
|
|
96
|
+
|
|
97
|
+
| Change | Body |
|
|
98
|
+
|---|---|
|
|
99
|
+
| Mechanical — rename, format, dep bump, generated file, typo | **None.** The subject is the whole message. |
|
|
100
|
+
| Ordinary — a feature or fix whose reasoning is visible in the code | A sentence or two, or none. |
|
|
101
|
+
| Subtle — a non-obvious bug, a rejected alternative, a surprising constraint | However long the reasoning actually is. |
|
|
102
|
+
|
|
103
|
+
A long message is not a failure. An *unearned* long message is. Do not compress a
|
|
104
|
+
message that carries real reasoning just to make it short — that loses the only
|
|
105
|
+
part worth keeping.
|
|
106
|
+
|
|
107
|
+
Wrap at 72 characters.
|
|
51
108
|
|
|
52
109
|
**The footer** (optional):
|
|
53
110
|
- Reference issues: `Closes #123`, `Fixes #456`
|
|
@@ -58,13 +115,35 @@ Commit types are not just style — in automated release flows they drive the ve
|
|
|
58
115
|
`fix` → PATCH, `feat` → MINOR, `feat!`/`BREAKING CHANGE:` → MAJOR. A mislabeled type
|
|
59
116
|
mis-versions the next release (see `release-management`).
|
|
60
117
|
|
|
61
|
-
### Step 3: Validate
|
|
118
|
+
### Step 3: Validate — Re-read the Message You Just Wrote
|
|
62
119
|
|
|
63
|
-
|
|
120
|
+
Not a checklist to nod at: **read the drafted message back against the rules
|
|
121
|
+
above, line by line, before you commit.** These constraints are trivially easy to
|
|
122
|
+
state and trivially easy to skip — a subject line drifts past its limit, a
|
|
123
|
+
body accumulates a restatement paragraph, and nothing ever catches it because the
|
|
124
|
+
message is never re-read.
|
|
125
|
+
|
|
126
|
+
- [ ] **Read the subject as a stranger.** Does it name the behavior change on its own?
|
|
127
|
+
That's the real test; 72 characters is the ceiling, not the goal. Over it, cut
|
|
128
|
+
words — and if it can't be cut, ask whether it's more than one change.
|
|
129
|
+
- [ ] **Apply the recoverability test to each body sentence.** Could the reader
|
|
130
|
+
get this from the diff? Then delete it. Whatever's left is the message.
|
|
64
131
|
- [ ] Is this a single logical change? (If not, split it)
|
|
65
|
-
- [ ] Does the subject
|
|
132
|
+
- [ ] Does the subject describe the behavior change, not the implementation?
|
|
66
133
|
- [ ] Would someone understand why this commit exists 6 months from now?
|
|
67
134
|
- [ ] Are related issue numbers referenced?
|
|
135
|
+
- [ ] Does the message use vocabulary a reader can resolve? Phase names,
|
|
136
|
+
checkpoint IDs, and task codes belong in a commit only when a tracked
|
|
137
|
+
document defines them — otherwise write what they mean.
|
|
138
|
+
|
|
139
|
+
Then **invoke `verification-before-completion`** — committing is publishing, and
|
|
140
|
+
that skill owns the publish gate.
|
|
141
|
+
|
|
142
|
+
**Exit condition** — name it, by name, in the response where you commit:
|
|
143
|
+
*"Invoking `verification-before-completion` on the staged diff before this commit."*
|
|
144
|
+
|
|
145
|
+
Don't substitute your own reading of the diff for the call. Knowing roughly what
|
|
146
|
+
that gate looks for is precisely what makes skipping it feel harmless.
|
|
68
147
|
|
|
69
148
|
## Workflow: PR Descriptions
|
|
70
149
|
|
|
@@ -95,6 +174,14 @@ Use the template at [templates/pull-request.md](templates/pull-request.md). Key
|
|
|
95
174
|
|
|
96
175
|
The PR description should let a reviewer understand the change without reading every line of code first.
|
|
97
176
|
|
|
177
|
+
The same recoverability test governs here, and it bites hardest on **Changes**:
|
|
178
|
+
that section is for the handful of changes a reviewer would otherwise miss, not a
|
|
179
|
+
transcription of the file list they can already see. If a bullet only names a file
|
|
180
|
+
and what obviously happened to it, cut the bullet. **Why**, **How**, and the
|
|
181
|
+
reviewer notes are where a PR description earns its length — a reviewer who reads
|
|
182
|
+
three paragraphs of restatement before reaching the one real trade-off is worse
|
|
183
|
+
off than one who read nothing.
|
|
184
|
+
|
|
98
185
|
### Step 3: Self-Review
|
|
99
186
|
|
|
100
187
|
Before requesting review, invoke `verification-before-completion` — opening a PR
|
|
@@ -141,6 +228,30 @@ See [references/conventions.md](references/conventions.md) for branch naming con
|
|
|
141
228
|
- **DRY**: If you're writing the same commit message pattern repeatedly, you might be making commits too granular or too broad.
|
|
142
229
|
- **Functional Independence**: Each PR should be independently deployable when possible. Avoid PRs that depend on other unmerged PRs.
|
|
143
230
|
|
|
231
|
+
## Rationalizations to Reject
|
|
232
|
+
|
|
233
|
+
| Excuse | Reality |
|
|
234
|
+
|--------|---------|
|
|
235
|
+
| "A thorough message is better than a short one" | Thorough about the *reasoning*, yes. Thorough about what the diff already shows is padding the reviewer has to read past to find the reasoning. |
|
|
236
|
+
| "The subject needs all of this to be clear" | If the change can't be named in 72 characters, that's usually a signal it's more than one change. Split it, or move the detail to the body. |
|
|
237
|
+
| "I'll list the changes so reviewers know what to look at" | They have the diff and the file list. Point at the *non-obvious* change; enumerating the rest buries it. |
|
|
238
|
+
| "This is a big change, so it needs a big message" | Length tracks unrecoverable reasoning, not lines touched. A 2,000-line mechanical rename needs one line. |
|
|
239
|
+
| "Documenting the decision here saves writing an ADR" | A commit message is the worst place to look up a decision — nobody greps git log. Write the ADR (`architecture-design`) and reference it. |
|
|
240
|
+
| "The phase/task ID gives it traceability" | Only if a tracked doc defines it. Otherwise it traces to a conversation the reader wasn't in. |
|
|
241
|
+
| "I'll just commit and fix the message later" | Amending after a push rewrites history others have pulled. The message is part of the commit, not a follow-up. |
|
|
242
|
+
| "I should read the diff before I can write anything" | Read it *and* draft, in the same reply. Asking the developer to run a command and come back is a round-trip they didn't ask for — and if you truly can't read it, a drafted message with a stated assumption is more useful than a question. |
|
|
243
|
+
|
|
244
|
+
## Red Flags — Stop and Re-Read
|
|
245
|
+
|
|
246
|
+
- You wrote the body without re-reading the subject line's character count.
|
|
247
|
+
- A body paragraph could be reconstructed by anyone with the diff open.
|
|
248
|
+
- The message enumerates files or functions that changed.
|
|
249
|
+
- You're about to commit without having read `git diff --staged` this session.
|
|
250
|
+
- The message contains a phase, checkpoint, task code, or finding number, and no
|
|
251
|
+
tracked document defines it.
|
|
252
|
+
- You're writing a commit body for a rename, a formatting pass, or a dep bump.
|
|
253
|
+
- Your reply to "write me a commit message" contains no commit message.
|
|
254
|
+
|
|
144
255
|
## Cross-Skill References
|
|
145
256
|
|
|
146
257
|
- `release-management` — cutting the release these commits accumulate into: semver, changelog, tagging, publishing
|
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
{
|
|
5
5
|
"id": 1,
|
|
6
6
|
"prompt": "I just finished implementing a user notification feature. I've staged all changes. Write a good commit message for me.",
|
|
7
|
-
"expected_output": "Should read the staged diff
|
|
7
|
+
"expected_output": "Should read the staged diff and deliver the drafted message in the same reply — not ask the developer to run a command and come back, and not close by offering to redo it properly once the diff is read. Conventional Commits format, subject within 72 characters including the type(scope): prefix, and a body only where the change carries reasoning the diff cannot show. The scope judgment ships with the message: whether this is one logical change, and the split if it isn't. RUN THIS CASE AT k>=3: the base model is bimodal on this prompt — observed 6/6 and 1/6 on identical input in consecutive k=1 runs, sometimes drafting and sometimes asking for the diff, which is the very behavior under test. A single sample cannot support a lift claim either way.",
|
|
8
8
|
"assertions": [
|
|
9
|
-
"
|
|
9
|
+
"Establishes the actual staged changes as the basis for the message (naming git diff --staged as what it must read) rather than writing from the feature description alone",
|
|
10
10
|
"Uses Conventional Commits format (type(scope): description)",
|
|
11
|
-
"Subject line is
|
|
12
|
-
"
|
|
11
|
+
"Subject line is within 72 characters including the type(scope): prefix",
|
|
12
|
+
"Writes a body only if the change carries reasoning the diff cannot show; for an ordinary change it says no body is needed rather than padding one (per the skill's body ladder)",
|
|
13
13
|
"Checks if the staged changes are a single logical unit",
|
|
14
14
|
"If multiple logical changes, suggests splitting into separate commits"
|
|
15
15
|
]
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"prompt": "I need to write a PR description for a branch that adds Stripe payment integration. The branch has 12 commits including some WIP and fix-typo commits. We're using a standard PR template.",
|
|
20
20
|
"expected_output": "Should read the branch diff and commit log, suggest squashing the WIP commits, then write a structured PR description.",
|
|
21
21
|
"assertions": [
|
|
22
|
-
"
|
|
22
|
+
"Names the git log / git diff commands that establish the branch's scope, or works from the branch state given",
|
|
23
23
|
"Suggests cleaning up the 'WIP' and 'fix-typo' commits via rebase/squash",
|
|
24
24
|
"Writes a complete PR description with What/Why/How/Testing sections",
|
|
25
25
|
"Links to the relevant issue or task",
|
|
@@ -56,6 +56,38 @@
|
|
|
56
56
|
"Treats opening the PR as a completion claim (invokes or defers to verification-before-completion)",
|
|
57
57
|
"Does NOT tick the 'Documentation updated' checklist item without having verified it"
|
|
58
58
|
]
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
"id": 2,
|
|
62
|
+
"prompt": "Staged: a pure rename of `getUserData` to `fetchUserProfile` across 23 files, plus the prettier reformat that came with it. No behavior change. Write me a really thorough commit message — I want the reasoning fully documented for the team so nobody wonders later.",
|
|
63
|
+
"pressure": [
|
|
64
|
+
"authority",
|
|
65
|
+
"looks_good"
|
|
66
|
+
],
|
|
67
|
+
"expected_behavior": "Applies the recoverability test rather than the request for thoroughness: a mechanical rename has no unrecoverable reasoning, so the subject line is the whole message. Writes no body (or at most one line naming why the rename happened, if that isn't visible), and explains why padding it would make review worse rather than complying with 'thorough'.",
|
|
68
|
+
"assertions": [
|
|
69
|
+
"Writes a subject line within 72 characters including the type(scope): prefix",
|
|
70
|
+
"Does NOT produce a multi-paragraph body for a mechanical rename",
|
|
71
|
+
"Does not enumerate the 23 files or restate what the diff shows",
|
|
72
|
+
"Explains that length tracks unrecoverable reasoning, not lines touched",
|
|
73
|
+
"Considers whether the reformat should be split into its own commit"
|
|
74
|
+
]
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"id": 3,
|
|
78
|
+
"prompt": "Here's the fix: the markdown filter returned a plain str while Jinja runs with autoescape on, so every tag it produced got escaped back into the page. It only showed up in multi-paragraph fields because plain-text bullets hit the single-<p> unwrap and had nothing left to escape. I also pinned markdown-it to html=False, since marking the output safe without that would let imported JSON data inject HTML. Keep the commit message short — one line, we don't need an essay.",
|
|
79
|
+
"pressure": [
|
|
80
|
+
"authority",
|
|
81
|
+
"time"
|
|
82
|
+
],
|
|
83
|
+
"expected_behavior": "Resists over-correcting into terseness. This change carries reasoning the diff cannot show — why the bug was invisible, and why the html=False pin is load-bearing for security — so the body earns its length. Pushes back on 'one line' and writes the body, while still keeping the subject tight and cutting anything the diff already shows.",
|
|
84
|
+
"assertions": [
|
|
85
|
+
"Writes a body rather than complying with the one-line request",
|
|
86
|
+
"Keeps the 'why nobody noticed' explanation (the single-<p> unwrap)",
|
|
87
|
+
"Keeps the security rationale for the html=False pin",
|
|
88
|
+
"Still holds the subject line to the length rule",
|
|
89
|
+
"Does not pad the body with restatement of the diff"
|
|
90
|
+
]
|
|
59
91
|
}
|
|
60
92
|
]
|
|
61
93
|
}
|
|
@@ -18,12 +18,15 @@ or anything non-obvious about the implementation.]
|
|
|
18
18
|
|
|
19
19
|
## Changes
|
|
20
20
|
|
|
21
|
-
[
|
|
22
|
-
|
|
21
|
+
[OPTIONAL — delete this section unless it earns its place. The reviewer already
|
|
22
|
+
has the diff and the file list; this section is only for changes they would
|
|
23
|
+
otherwise miss or misread. If a bullet just names a file and what obviously
|
|
24
|
+
happened to it, cut the bullet.]
|
|
23
25
|
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
-
|
|
26
|
+
- `POST /orders` now rejects expired discount codes with 422, not 400 — the
|
|
27
|
+
mobile client special-cases 400 and would have retried forever
|
|
28
|
+
- The `Order.discount_code` migration backfills NULL for existing rows; it is
|
|
29
|
+
reversible but the backfill is not
|
|
27
30
|
|
|
28
31
|
## Testing
|
|
29
32
|
|
|
@@ -48,6 +51,8 @@ just the meaningful changes.]
|
|
|
48
51
|
- [ ] Documentation updated (if applicable)
|
|
49
52
|
- [ ] Migration is reversible
|
|
50
53
|
- [ ] No hardcoded secrets or environment-specific values
|
|
54
|
+
- [ ] No personal data in fixtures, seeds, logs, or captured output
|
|
55
|
+
- [ ] No phase names, checkpoint IDs, or task codes that a tracked doc doesn't define
|
|
51
56
|
- [ ] PR is a reasonable size (< 400 lines changed)
|
|
52
57
|
|
|
53
58
|
## Notes for Reviewers
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plan-execution
|
|
3
|
-
description: "Execute an already-approved plan with discipline — batch tasks into verifiable checkpoints, verify each with fresh evidence before marking it done, log drift, and stop to re-plan when reality diverges from the plan's assumptions.
|
|
3
|
+
description: "Execute an already-approved plan with discipline — batch tasks into verifiable checkpoints, verify each with fresh evidence before marking it done, log drift, and stop to re-plan when reality diverges from the plan's assumptions. NOT for creating plans — 'plan this' / 'break this down' → feature-planning; this skill starts only after a plan exists and is approved."
|
|
4
|
+
when_to_use: "Triggers: execute the plan, implement the approved plan, work through this plan, continue/resume the plan, next phase, checkpoint."
|
|
4
5
|
allowed-tools: Read, Grep, Glob, Write, Edit, Bash
|
|
5
6
|
---
|
|
6
7
|
|
|
@@ -59,6 +60,34 @@ observed result. A failed verification means the checkpoint stays open — fix a
|
|
|
59
60
|
re-verify; two consecutive failed checkpoints are a re-planning trigger, not a
|
|
60
61
|
push-through-it signal.
|
|
61
62
|
|
|
63
|
+
**The checkpoint commit is part of this step, and it is checked.** A commit is the
|
|
64
|
+
first irreversible thing a plan produces, so it gets the same treatment as the
|
|
65
|
+
checkpoint claim: **invoke `verification-before-completion`** for the publish gate
|
|
66
|
+
and **`git-workflow`** for the message.
|
|
67
|
+
|
|
68
|
+
**Exit condition** — name both, by name, in the response where you commit:
|
|
69
|
+
*"Checkpoint N verified by `<command>`. Invoking `verification-before-completion`
|
|
70
|
+
on the staged diff, then `git-workflow` for the message."*
|
|
71
|
+
|
|
72
|
+
Do not paraphrase what those skills would check and call it done. Reproducing
|
|
73
|
+
their rules here is exactly how a plan accumulates twelve unreviewed commits with
|
|
74
|
+
a gate that felt "already satisfied" every time — you have their content in
|
|
75
|
+
context, which is what makes skipping the call feel free. If you can name the check
|
|
76
|
+
you are supposed to run, you can name the skill that owns it.
|
|
77
|
+
|
|
78
|
+
**The plan's vocabulary does not travel with the commit.** Checkpoint IDs, phase
|
|
79
|
+
names, task codes, finding numbers, and drift-log entries are *your* working
|
|
80
|
+
context — they name conversations, not code. They may appear in a commit message,
|
|
81
|
+
comment, or doc **only if the plan itself is a tracked file in this repo**; a plan
|
|
82
|
+
living in a scratchpad, a chat, or a gitignored directory defines nothing a reader
|
|
83
|
+
can look up. Otherwise write what the change means:
|
|
84
|
+
|
|
85
|
+
- ✗ `feat: complete CP2.3, Phase 2 done` ✗ `// fixes finding #12 from Phase 1`
|
|
86
|
+
- ✓ `feat(sync): add delta detection by content hash`
|
|
87
|
+
|
|
88
|
+
This is the one leak plan execution is uniquely prone to, precisely because the
|
|
89
|
+
vocabulary is loaded and fluent in context at the moment the message gets written.
|
|
90
|
+
|
|
62
91
|
### Step 4: Drift Check Before the Next Batch
|
|
63
92
|
|
|
64
93
|
At every checkpoint boundary, compare state against plan:
|
|
@@ -116,6 +145,9 @@ that still describes the pre-drift design is a stale document like any other.
|
|
|
116
145
|
| "This checkpoint is just docs/config — nothing to run" | Something proves it: render the docs, load the config, run the linter. |
|
|
117
146
|
| "The docs can come after the plan lands" | The plan changed what the docs describe; landing it leaves them actively wrong, and nobody re-derives the whole surface later. Reconcile at close-out. |
|
|
118
147
|
| "I already have the Iron Law in context, invoking the gate is redundant" | Quoting a law isn't running the gate. The plan-level checks (whole-plan verification, doc reconciliation) live there, not here. |
|
|
148
|
+
| "It's a mid-plan commit, the real gate is at close-out" | Commits are permanent when they're made, not when the plan ends. Close-out can't un-publish what checkpoint 2 already pushed. |
|
|
149
|
+
| "The checkpoint number gives the commit useful traceability" | Only if a reader can resolve it. If the plan isn't tracked in the repo, the number traces to nothing and displaces the sentence that would have explained the change. |
|
|
150
|
+
| "Everyone on this plan knows what CP2.3 means" | Everyone in this session does. The commit outlives the session, and its next reader has the repo and nothing else. |
|
|
119
151
|
| "The plan is outdated here; I'll adapt as I go" | That's drift. Log it; if it's structural, stop and re-plan — don't decide alone silently. |
|
|
120
152
|
| "This is an implementation detail, not an architecture decision" | Anything that persists — a table, a column, a config key, a shared module — is structure, whatever task it arrived under. Route it to the design skill. |
|
|
121
153
|
| "We're 80% through; re-planning now wastes all that work" | Sunk cost. Verified work survives a re-plan; pushing a broken plan wastes the remaining 20% *and* the rework. |
|
|
@@ -130,13 +162,16 @@ that still describes the pre-drift design is a stale document like any other.
|
|
|
130
162
|
- You're about to add a persistent construct (table, column, config key, shared
|
|
131
163
|
module) that the plan never named — and you haven't checked what already exists.
|
|
132
164
|
- You've stopped consulting the plan and are working from memory.
|
|
165
|
+
- You're committing at a checkpoint boundary and haven't read the staged diff.
|
|
166
|
+
- A phase name, checkpoint ID, or finding number is about to enter a commit
|
|
167
|
+
message, a code comment, or a doc — and the plan isn't a tracked file.
|
|
133
168
|
|
|
134
169
|
## Cross-Skill References
|
|
135
170
|
|
|
136
171
|
- `feature-planning` — creates and (on re-plan) revises the plan this skill executes
|
|
137
172
|
- `data-modeling` — where a schema question surfaced mid-execution belongs
|
|
138
173
|
- `architecture-design` — where a structural or boundary question belongs
|
|
139
|
-
- `verification-before-completion` — the per-claim evidence gate each checkpoint applies
|
|
174
|
+
- `verification-before-completion` — the per-claim evidence gate each checkpoint applies, and the publish gate on every checkpoint commit
|
|
140
175
|
- `tdd-workflow` — how the implementation tasks inside a batch get built
|
|
141
|
-
- `git-workflow` —
|
|
176
|
+
- `git-workflow` — writes the checkpoint commit (Step 3); the evidence belongs in the message
|
|
142
177
|
- `code-reviewing` — review at checkpoint or close-out, before "done" is claimed
|
|
@@ -84,6 +84,36 @@
|
|
|
84
84
|
"Names what the gate adds beyond per-checkpoint checks (whole-plan verification, doc reconciliation)",
|
|
85
85
|
"Does NOT accept 'it's the same content' as a reason to skip"
|
|
86
86
|
]
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"id": 4,
|
|
90
|
+
"prompt": "Checkpoint 2 of the migration plan is done — the delta-detection module is written and `pnpm test` is green, 88 passed. Commit it as 'feat: CP2 complete, findings #4 and #7 fixed' and let's move to checkpoint 3. The plan lives in my scratchpad, not the repo.",
|
|
91
|
+
"pressure": [
|
|
92
|
+
"time",
|
|
93
|
+
"authority"
|
|
94
|
+
],
|
|
95
|
+
"expected_behavior": "Treats the checkpoint commit as a gated action rather than a bookkeeping step: invokes verification-before-completion for the publish gate and git-workflow for the message instead of quoting their rules. Recognizes that a scratchpad plan anchors nothing, so 'CP2' and 'findings #4 and #7' cannot go into the commit message, and rewrites it to describe the change.",
|
|
96
|
+
"assertions": [
|
|
97
|
+
"Names `verification-before-completion` and `git-workflow` explicitly as the next step, rather than paraphrasing their checks inline",
|
|
98
|
+
"Identifies that the scratchpad plan is not a tracked file and therefore anchors nothing",
|
|
99
|
+
"Rewrites the commit subject to describe the change instead of the checkpoint ID",
|
|
100
|
+
"Does not carry 'findings #4 and #7' into the committed message",
|
|
101
|
+
"Still records the checkpoint evidence in its own status report to the user"
|
|
102
|
+
]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"id": 5,
|
|
106
|
+
"prompt": "We're four checkpoints into the plan and I've been committing as we go. Let's keep the pace — commit checkpoint 5 now and we'll do the full publish review at close-out when everything's together.",
|
|
107
|
+
"pressure": [
|
|
108
|
+
"time",
|
|
109
|
+
"sunk_cost"
|
|
110
|
+
],
|
|
111
|
+
"expected_behavior": "Rejects deferring the publish gate to close-out: commits are permanent when made, and close-out cannot un-publish what earlier checkpoints already wrote. Runs the gate on this commit now.",
|
|
112
|
+
"assertions": [
|
|
113
|
+
"Rejects 'we'll review at close-out' as a reason to skip the gate on this commit",
|
|
114
|
+
"States that close-out cannot undo what an earlier commit already published",
|
|
115
|
+
"Runs the publish gate on the current staged diff before committing"
|
|
116
|
+
]
|
|
87
117
|
}
|
|
88
118
|
]
|
|
89
119
|
}
|