swe-workflow-skills 0.6.3 → 0.8.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.
Files changed (38) hide show
  1. package/README.md +11 -4
  2. package/VERSION +1 -1
  3. package/catalog.json +2 -2
  4. package/package.json +1 -1
  5. package/skills/architecture-design/evals/evals.json +2 -3
  6. package/skills/architecture-documentation/evals/evals.json +47 -44
  7. package/skills/cicd-pipeline/evals/evals.json +13 -0
  8. package/skills/code-reviewing/SKILL.md +24 -6
  9. package/skills/code-reviewing/evals/evals.json +19 -3
  10. package/skills/code-slop-cleanup/SKILL.md +7 -0
  11. package/skills/code-slop-cleanup/evals/evals.json +13 -0
  12. package/skills/code-slop-cleanup/references/slop-patterns.md +4 -1
  13. package/skills/containerization/evals/evals.json +12 -0
  14. package/skills/effort-estimation/evals/evals.json +13 -0
  15. package/skills/feature-planning/evals/evals.json +2 -3
  16. package/skills/frontend-architecture/evals/evals.json +12 -0
  17. package/skills/git-workflow/SKILL.md +119 -8
  18. package/skills/git-workflow/evals/evals.json +37 -5
  19. package/skills/git-workflow/templates/pull-request.md +10 -5
  20. package/skills/infrastructure-as-code/evals/evals.json +12 -0
  21. package/skills/metrics-and-okrs/evals/evals.json +12 -0
  22. package/skills/ml-experiment-tracking/evals/evals.json +12 -0
  23. package/skills/ml-model-deployment/evals/evals.json +12 -0
  24. package/skills/plan-execution/SKILL.md +38 -3
  25. package/skills/plan-execution/evals/evals.json +30 -0
  26. package/skills/prd-writing/evals/evals.json +13 -0
  27. package/skills/project-documentation/SKILL.md +73 -6
  28. package/skills/project-documentation/evals/evals.json +17 -2
  29. package/skills/project-proposal/evals/evals.json +12 -0
  30. package/skills/release-management/SKILL.md +23 -1
  31. package/skills/retrospective/evals/evals.json +13 -0
  32. package/skills/strategic-review/evals/evals.json +7 -7
  33. package/skills/ui-ux-design/SKILL.md +12 -0
  34. package/skills/ui-ux-design/evals/evals.json +12 -0
  35. package/skills/verification-before-completion/SKILL.md +109 -2
  36. package/skills/verification-before-completion/evals/evals.json +66 -7
  37. package/skills/verification-before-completion/references/pre-commit-gate.md +239 -0
  38. package/skills/writing-skills/SKILL.md +43 -7
@@ -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, under 50 characters
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
- **The body** (optional but valuable for non-trivial changes):
48
- - Explain WHY this change was made, not WHAT changed (the diff shows what)
49
- - Include context that isn't obvious from the code
50
- - Wrap at 72 characters
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
- Before committing, check:
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 line describe the behavior change, not the implementation?
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 first, then write a Conventional Commits formatted message with type, scope, subject, and body explaining why.",
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
- "Runs git diff --staged to read the actual changes",
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 under 50 characters",
12
- "Body explains WHY, not just WHAT",
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
- "Reads git log and diff for the branch",
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
- [Bullet list of the main changes, grouped logically. Not every file —
22
- just the meaningful changes.]
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
- - Added `OrderService.calculateDiscount()` for percentage-based discounts
25
- - Updated `Order` model with `discount_code` field and migration
26
- - Added validation for discount codes in `POST /orders` endpoint
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
@@ -28,6 +28,18 @@
28
28
  "Flags missing tags",
29
29
  "Provides corrected Terraform with restricted policy"
30
30
  ]
31
+ },
32
+ {
33
+ "id": 3,
34
+ "prompt": "Our Terraform is in good shape. The problem is the AWS bill jumped 40% last month and finance wants it back down before the quarter closes. Work out what's driving it and cut it.",
35
+ "expected_output": "Scope boundary — attributing and reducing cloud spend is finops-cost-optimization work. Should hand off rather than starting a Terraform refactor, while noting that IaC is where any agreed change eventually lands.",
36
+ "assertions": [
37
+ "Recognizes that cost attribution and spend reduction are finops-cost-optimization concerns",
38
+ "Hands off to or invokes the finops-cost-optimization skill",
39
+ "Does not begin refactoring or reviewing Terraform modules as the answer",
40
+ "Distinguishes whether infrastructure is correctly provisioned from what it costs to run",
41
+ "Notes that IaC is where the agreed rightsizing or teardown gets implemented once the driver is identified"
42
+ ]
31
43
  }
32
44
  ]
33
45
  }
@@ -28,6 +28,18 @@
28
28
  "Suggests a timeframe for evaluation (not 'check once and declare victory')",
29
29
  "Warns against vanity metrics (total searches without context is meaningless)"
30
30
  ]
31
+ },
32
+ {
33
+ "id": 3,
34
+ "prompt": "We defined the KR already. Here's the data: the A/B test on the new onboarding shows a 3.1% lift in activation, p = 0.06, n = 800 split across both arms. Is that a real effect? Do we ship it?",
35
+ "expected_output": "Scope boundary — judging whether an observed lift is real (significance, power, sample size, stopping rules) is statistical-analysis work. Should hand off rather than re-running an OKR-definition workflow or ruling on the p-value inline.",
36
+ "assertions": [
37
+ "Recognizes this as an inference question about experiment results, not a metric-definition question",
38
+ "Hands off to or invokes the statistical-analysis skill",
39
+ "Does not declare the result significant or issue a ship/no-ship verdict from the p-value alone",
40
+ "Does not restart an OKR or success-metric definition exercise the user has already completed",
41
+ "May note how the established result would feed the existing key result once the inference is settled"
42
+ ]
31
43
  }
32
44
  ]
33
45
  }
@@ -27,6 +27,18 @@
27
27
  "Suggests data versioning to prevent future dataset ambiguity",
28
28
  "Provides a practical migration path, not an all-or-nothing approach"
29
29
  ]
30
+ },
31
+ {
32
+ "id": 3,
33
+ "prompt": "Before I wire up MLflow — I don't actually know how to tell whether our RAG support chatbot is answering well. What should the golden dataset look like, and how do I build a judge that says whether an answer is faithful to the retrieved context?",
34
+ "expected_output": "Scope boundary — deciding WHAT to measure (golden datasets, faithfulness metrics, LLM-as-judge design) is ai-evaluation work; this skill records and compares runs once those are defined. Should hand off rather than answering with run-logging setup.",
35
+ "assertions": [
36
+ "Recognizes that defining the golden dataset and judge is ai-evaluation work, not experiment tracking",
37
+ "Hands off to or invokes the ai-evaluation skill",
38
+ "Does not answer primarily with MLflow/W&B run-logging or model-registry setup",
39
+ "Distinguishes deciding what to measure from recording and comparing the runs",
40
+ "Offers to set up tracking once the evaluation metrics are defined"
41
+ ]
30
42
  }
31
43
  ]
32
44
  }
@@ -29,6 +29,18 @@
29
29
  "Suggests a retraining pipeline with fresh data",
30
30
  "Does NOT just say 'retrain the model' without diagnosing the cause"
31
31
  ]
32
+ },
33
+ {
34
+ "id": 3,
35
+ "prompt": "Hold off on the serving setup. We've found the training job computes the account-age feature from the full table while serving computes it at request time, so they disagree. I need the feature pipeline redesigned so training and serving can't drift apart.",
36
+ "expected_output": "Scope boundary — training/serving skew and point-in-time-correct feature computation are ml-pipeline-design concerns. Should hand off rather than answering with serving infrastructure, canary or rollout strategy.",
37
+ "assertions": [
38
+ "Names the problem as training/serving skew rather than a deployment or rollout issue",
39
+ "Hands off to or invokes the ml-pipeline-design skill for the feature pipeline redesign",
40
+ "Does not answer with serving infrastructure, canary strategy, or inference endpoint design",
41
+ "Recognizes point-in-time correctness as the underlying requirement",
42
+ "Notes that deployment work resumes once the feature computation is unified"
43
+ ]
32
44
  }
33
45
  ]
34
46
  }
@@ -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. Triggers: execute the plan, implement the approved plan, work through this plan, continue/resume the plan, next phase, checkpoint. NOT for creating plans — 'plan this' / 'break this down' → feature-planning; this skill starts only after a plan exists and is approved."
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` — commit at checkpoint boundaries; the evidence belongs in the message
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
  }
@@ -28,6 +28,19 @@
28
28
  "Has open questions that invite reviewer input",
29
29
  "Links to feature-planning for implementation task breakdown"
30
30
  ]
31
+ },
32
+ {
33
+ "id": 3,
34
+ "prompt": "The PRD is signed off by product and design. Now turn it into the actual sprint backlog — tickets sized in points, ordered by dependency, with acceptance criteria on each one.",
35
+ "expected_output": "Scope boundary — the PRD owns the WHAT and WHY; decomposing it into ordered, sized tickets is feature-planning (with effort-estimation for the sizing). Should hand off rather than producing another requirements document.",
36
+ "assertions": [
37
+ "Recognizes that task breakdown and dependency ordering are feature-planning work",
38
+ "Hands off to or invokes the feature-planning skill",
39
+ "Routes the point sizing to effort-estimation rather than producing estimates inline",
40
+ "Does not produce another PRD, RFC, or requirements document",
41
+ "Articulates the WHAT/WHY versus HOW boundary explicitly",
42
+ "Confirms the approved PRD is the input the breakdown should be derived from"
43
+ ]
31
44
  }
32
45
  ]
33
46
  }
@@ -29,6 +29,47 @@ Two modes use this skill. **Authoring** creates a document that doesn't exist ye
29
29
  because a change made them wrong — that's the next section, and it's the mode you
30
30
  want when someone says "I changed X" rather than "write me a Y".
31
31
 
32
+ ## The Documentation Strategy — What Ships and What Doesn't
33
+
34
+ Establish once with the user: **which artifacts are git-versioned, and which stay
35
+ internal.** Most projects accumulate both, and only one of them is readable by
36
+ someone who has the repo and nothing else.
37
+
38
+ | Typically versioned | Typically internal |
39
+ |---|---|
40
+ | README, contributing guide, API docs, changelog | Execution plans and phase breakdowns |
41
+ | ADRs and architecture docs | Findings/bug logs kept during a work session |
42
+ | Roadmaps the project chooses to publish | Scratchpads, handoff prompts, session notes |
43
+ | Runbooks and operational docs | Anything under a gitignored directory |
44
+
45
+ This boundary is not bureaucracy — it decides what vocabulary the project's own
46
+ artifacts are allowed to use. **A term is usable in a versioned file only if a
47
+ versioned file defines it.** When a plan lives outside the repo, its phases,
48
+ checkpoints, and task codes name a conversation, and a reader hitting `Phase 2` or
49
+ `CP1.3` in a comment or commit has nothing to resolve it against. Write what the
50
+ term means instead.
51
+
52
+ The reverse also holds and matters just as much: when a project *does* ship its
53
+ plan or roadmap, referencing it is good practice, not a leak. Check which case
54
+ you're in rather than assuming either — `git ls-files` answers it.
55
+
56
+ **On a greenfield project** nothing is tracked yet, so this is a decision to make,
57
+ not a fact to look up.
58
+
59
+ **Exit condition** — one line, then write the document in the same response:
60
+ *"Nothing is tracked yet, so `<term>` resolves to nothing for a reader; I've
61
+ written the meaning instead. Worth deciding whether the plan itself ships."*
62
+
63
+ **This is not a gate on authoring.** Raise the boundary, apply the safe default —
64
+ meanings rather than labels, which is never wrong and costs nothing to change — and
65
+ deliver the document. Never answer a request for docs with the boundary question
66
+ alone: the user asked for a README, and a README that avoids unresolvable
67
+ vocabulary is strictly better than a question. Ask when the answer would change
68
+ what you write; otherwise state the assumption and write.
69
+
70
+ `verification-before-completion`'s publish gate reads this boundary as its baseline
71
+ when checking a staged diff.
72
+
32
73
  ## Workflow: Sync After a Change
33
74
 
34
75
  Docs don't rot evenly. They rot where a change moved something a document names,
@@ -135,11 +176,19 @@ Follow Keep a Changelog conventions:
135
176
 
136
177
  See [templates/changelog.md](templates/changelog.md) for the format.
137
178
 
138
- Accumulate entries under `[Unreleased]` as changes land. Writing the entries is this
139
- skill's work even when they must be reconstructed from git history — read the log
140
- since the last tag, drop trivial commits (merges, typo fixes), and translate the rest
141
- into user-perspective entries under the sections above. Hand off only the release
142
- mechanics (version choice, tagging, publish automation) to `release-management`.
179
+ **First check whether the project generates this file.** A `release-please-config.json`,
180
+ `.changeset/`, `.releaserc*`, or `cliff.toml` means the changelog is derived from commit
181
+ history, and hand-editing it — including keeping an `[Unreleased]` section alongside —
182
+ throws away the guarantee the tool exists to provide and reintroduces drift. There, the
183
+ entry is the **commit subject** (for squash-merges, the PR title) and the work is writing
184
+ that well; the reasoning goes in the commit body, not the changelog. Say so and stop.
185
+
186
+ When the changelog *is* hand-maintained, accumulate entries under `[Unreleased]` as
187
+ changes land. Writing them is this skill's work even when they must be reconstructed from
188
+ git history — read the log since the last tag, drop trivial commits (merges, typo fixes),
189
+ and translate the rest into user-perspective entries under the sections above. Hand off
190
+ only the release mechanics (version choice, tagging, publish automation) to
191
+ `release-management`.
143
192
 
144
193
  ## Workflow: Inline Documentation
145
194
 
@@ -147,12 +196,30 @@ For code-level documentation (JSDoc, Python docstrings, Go doc comments):
147
196
 
148
197
  - **Document public APIs**: Every exported function, class, and type
149
198
  - **Skip obvious code**: Don't document `getName()` returning a name
150
- - **Document the why**: Why this approach, why this parameter exists, why this edge case matters
199
+ - **Document the why — at the altitude it belongs**: this is where inline docs go
200
+ wrong most often. The why of a *line* belongs on the line: why this parameter
201
+ exists, why this comparison is written the strange way it is, what the caller
202
+ can't see. The why of a *system* — why the component exists, which alternatives
203
+ were rejected, how it relates to other services — belongs in an ADR or
204
+ architecture doc, and the code carries a pointer to it:
205
+ `// Triage state lives in a separate writable DB; see ADR-018.`
206
+ A design rationale pasted into a file header is unfindable (nobody greps source
207
+ for "why two databases"), unreviewable (it never gets the scrutiny an ADR gets),
208
+ and rots first — nobody re-reads a file header while editing line 300.
151
209
  - **Include examples** for non-obvious usage
152
210
  - **Document exceptions/errors**: What can go wrong and under what conditions
211
+ - **Use vocabulary the reader can resolve**: no phase names, checkpoint IDs, or
212
+ task codes that no versioned document defines (see The Documentation Strategy)
153
213
 
154
214
  ## Principles Applied
155
215
 
156
216
  - **KISS**: Write the minimum documentation that makes the project usable. Don't over-document internals.
157
217
  - **DRY**: Don't duplicate information across docs. Link between documents instead.
158
218
  - **YAGNI**: Don't write architecture docs for a 200-line script. Match documentation depth to project complexity. And don't create docs nobody asked for — a doc that merely restates the code is doc-slop: it goes stale immediately and buries the docs that answer real questions. Every document must answer a question someone actually has.
219
+
220
+ ## Cross-Skill References
221
+
222
+ - `architecture-design` — the ADR a system-level rationale belongs in, rather than a source-file header
223
+ - `architecture-documentation` — C4 diagrams and docs-as-code for the architecture docs this skill points at
224
+ - `verification-before-completion` — the doc-drift and publish gates that read the versioned/internal boundary above
225
+ - `technical-debt-review` — a repo-wide doc-rot audit, as opposed to the drift from the change in front of you
@@ -6,7 +6,7 @@
6
6
  "prompt": "Write a README for my project. It's a Node.js REST API for a task management app built with Express, Prisma, and PostgreSQL. It has authentication with JWT, CRUD for tasks and projects, and runs in Docker for local dev.",
7
7
  "expected_output": "Should read the codebase first if available, then produce a complete README with all essential sections. Should include working setup instructions and actual environment variables from the project.",
8
8
  "assertions": [
9
- "Reads codebase/package.json before writing if available",
9
+ "Grounds the README in the project's actual manifest/codebase, or states which files it must read to do so",
10
10
  "Starts with a clear one-line description of what the project does",
11
11
  "Includes prerequisites with specific versions",
12
12
  "Setup instructions go from git clone to running server",
@@ -14,7 +14,7 @@
14
14
  "Lists environment variables needed with descriptions",
15
15
  "Includes verification step (e.g., 'visit localhost:3000/health')",
16
16
  "Code examples are copy-pasteable",
17
- "Saves the README.md file to the project root"
17
+ "Delivers the complete README content, ready to be written to README.md at the project root"
18
18
  ]
19
19
  },
20
20
  {
@@ -85,6 +85,21 @@
85
85
  "Redirects to reconciling what the refactor actually made wrong",
86
86
  "Asks what question a proposed document answers / who its reader is before writing it"
87
87
  ]
88
+ },
89
+ {
90
+ "id": 4,
91
+ "prompt": "Starting a new repo — nothing committed yet beyond the source. Write the README and an architecture doc. We're working from a five-phase build plan I keep in my notes app, so reference the phases throughout so the docs line up with how we're actually building it.",
92
+ "pressure": [
93
+ "authority"
94
+ ],
95
+ "expected_behavior": "Establishes the versioned-vs-internal boundary before authoring rather than after, and declines to build the docs around phase references that no versioned document defines — a reader with only the repo cannot resolve them. Offers the alternatives: publish the plan into the repo so the references anchor, or write what each phase means. Does not refuse to write the docs.",
96
+ "assertions": [
97
+ "Raises the versioned-vs-internal boundary before writing",
98
+ "Identifies that a notes-app plan does not anchor phase references in the repo",
99
+ "Offers either tracking the plan or writing the meanings instead of the labels",
100
+ "Still delivers the README and architecture doc",
101
+ "Does not scatter unresolvable phase references through the docs"
102
+ ]
88
103
  }
89
104
  ]
90
105
  }