@ikon85/agent-workflow-kit 0.10.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 (273) hide show
  1. package/.agents/skills/ask-matt/SKILL.md +139 -0
  2. package/.agents/skills/ask-matt/THIRD-PARTY-NOTICES.md +29 -0
  3. package/.agents/skills/audit-skills/SKILL.md +145 -0
  4. package/.agents/skills/board-to-waves/SKILL.md +135 -0
  5. package/.agents/skills/code-review/SKILL.md +64 -0
  6. package/.agents/skills/codebase-design/DEEPENING.md +37 -0
  7. package/.agents/skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
  8. package/.agents/skills/codebase-design/SKILL.md +114 -0
  9. package/.agents/skills/codebase-design/THIRD-PARTY-NOTICES.md +29 -0
  10. package/.agents/skills/codex-adapter-sync/SKILL.md +151 -0
  11. package/.agents/skills/decision-gate/SKILL.md +67 -0
  12. package/.agents/skills/diagnose/SKILL.md +136 -0
  13. package/.agents/skills/diagnose/THIRD-PARTY-NOTICES.md +29 -0
  14. package/.agents/skills/diagnose/scripts/hitl-loop.template.sh +41 -0
  15. package/.agents/skills/domain-modeling/ADR-FORMAT.md +47 -0
  16. package/.agents/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  17. package/.agents/skills/domain-modeling/SKILL.md +76 -0
  18. package/.agents/skills/domain-modeling/THIRD-PARTY-NOTICES.md +29 -0
  19. package/.agents/skills/git-worktree-recover/SKILL.md +176 -0
  20. package/.agents/skills/grill-me/SKILL.md +54 -0
  21. package/.agents/skills/grill-me/THIRD-PARTY-NOTICES.md +29 -0
  22. package/.agents/skills/grill-with-docs/ADR-FORMAT.md +47 -0
  23. package/.agents/skills/grill-with-docs/CONTEXT-FORMAT.md +60 -0
  24. package/.agents/skills/grill-with-docs/SKILL.md +137 -0
  25. package/.agents/skills/grill-with-docs/THIRD-PARTY-NOTICES.md +29 -0
  26. package/.agents/skills/implement/SKILL.md +15 -0
  27. package/.agents/skills/implement/THIRD-PARTY-NOTICES.md +29 -0
  28. package/.agents/skills/improve-codebase-architecture/ADR-FORMAT.md +47 -0
  29. package/.agents/skills/improve-codebase-architecture/CONTEXT-FORMAT.md +60 -0
  30. package/.agents/skills/improve-codebase-architecture/DEEPENING.md +37 -0
  31. package/.agents/skills/improve-codebase-architecture/HTML-REPORT.md +123 -0
  32. package/.agents/skills/improve-codebase-architecture/INTERFACE-DESIGN.md +46 -0
  33. package/.agents/skills/improve-codebase-architecture/LANGUAGE.md +53 -0
  34. package/.agents/skills/improve-codebase-architecture/SKILL.md +88 -0
  35. package/.agents/skills/improve-codebase-architecture/THIRD-PARTY-NOTICES.md +29 -0
  36. package/.agents/skills/kit-release/SKILL.md +56 -0
  37. package/.agents/skills/local-ci/SKILL.md +94 -0
  38. package/.agents/skills/orchestrate-wave/SKILL.md +261 -0
  39. package/.agents/skills/orchestrate-wave/references/builder-contract.md +67 -0
  40. package/.agents/skills/prototype/LOGIC.md +79 -0
  41. package/.agents/skills/prototype/SKILL.md +30 -0
  42. package/.agents/skills/prototype/THIRD-PARTY-NOTICES.md +29 -0
  43. package/.agents/skills/prototype/UI.md +112 -0
  44. package/.agents/skills/research/SKILL.md +12 -0
  45. package/.agents/skills/research/THIRD-PARTY-NOTICES.md +29 -0
  46. package/.agents/skills/resolving-merge-conflicts/SKILL.md +14 -0
  47. package/.agents/skills/resolving-merge-conflicts/THIRD-PARTY-NOTICES.md +29 -0
  48. package/.agents/skills/retro/SKILL.md +209 -0
  49. package/.agents/skills/scale-check/SKILL.md +141 -0
  50. package/.agents/skills/security-audit/SKILL.md +67 -0
  51. package/.agents/skills/setup-workflow/SKILL.md +187 -0
  52. package/.agents/skills/setup-workflow/THIRD-PARTY-NOTICES.md +29 -0
  53. package/.agents/skills/setup-workflow/board-sync.md +111 -0
  54. package/.agents/skills/setup-workflow/code-review.md +26 -0
  55. package/.agents/skills/setup-workflow/domain.md +51 -0
  56. package/.agents/skills/setup-workflow/issue-tracker-github.md +35 -0
  57. package/.agents/skills/setup-workflow/issue-tracker-gitlab.md +34 -0
  58. package/.agents/skills/setup-workflow/issue-tracker-local.md +30 -0
  59. package/.agents/skills/setup-workflow/orchestrate-wave-seed.md +44 -0
  60. package/.agents/skills/setup-workflow/spec-completeness-seed.md +44 -0
  61. package/.agents/skills/setup-workflow/spec-self-critique-seed.md +43 -0
  62. package/.agents/skills/setup-workflow/triage-labels.md +18 -0
  63. package/.agents/skills/setup-workflow/workflow-overview.md +33 -0
  64. package/.agents/skills/spec-self-critique/SKILL.md +152 -0
  65. package/.agents/skills/spec-self-critique/scenarios.md +82 -0
  66. package/.agents/skills/tdd/SKILL.md +120 -0
  67. package/.agents/skills/tdd/THIRD-PARTY-NOTICES.md +29 -0
  68. package/.agents/skills/tdd/deep-modules.md +33 -0
  69. package/.agents/skills/tdd/interface-design.md +31 -0
  70. package/.agents/skills/tdd/mocking.md +59 -0
  71. package/.agents/skills/tdd/refactoring.md +10 -0
  72. package/.agents/skills/tdd/tests.md +61 -0
  73. package/.agents/skills/to-issues/SKILL.md +325 -0
  74. package/.agents/skills/to-issues/THIRD-PARTY-NOTICES.md +29 -0
  75. package/.agents/skills/to-prd/PROGRAM-PRD-FORMAT.md +162 -0
  76. package/.agents/skills/to-prd/SKILL.md +180 -0
  77. package/.agents/skills/to-prd/THIRD-PARTY-NOTICES.md +29 -0
  78. package/.agents/skills/to-waves/SKILL.md +260 -0
  79. package/.agents/skills/to-waves/SLICE-METADATA-FORMAT.md +74 -0
  80. package/.agents/skills/triage/AGENT-BRIEF.md +168 -0
  81. package/.agents/skills/triage/OUT-OF-SCOPE.md +101 -0
  82. package/.agents/skills/triage/SKILL.md +122 -0
  83. package/.agents/skills/triage/THIRD-PARTY-NOTICES.md +29 -0
  84. package/.agents/skills/verify-spike/SKILL.md +39 -0
  85. package/.agents/skills/wayfinder/SKILL.md +127 -0
  86. package/.agents/skills/wayfinder/THIRD-PARTY-NOTICES.md +29 -0
  87. package/.agents/skills/wrapup/SKILL.md +71 -0
  88. package/.agents/skills/wrapup/SOURCES.txt +6 -0
  89. package/.agents/skills/zoom-out/SKILL.md +7 -0
  90. package/.agents/skills/zoom-out/THIRD-PARTY-NOTICES.md +29 -0
  91. package/.claude/hooks/_hook_utils.py +184 -0
  92. package/.claude/hooks/drift-guard.py +176 -0
  93. package/.claude/hooks/skill-drift-hint.py +122 -0
  94. package/.claude/hooks/sync-board-status.py +191 -0
  95. package/.claude/skills/ask-matt/SKILL.md +139 -0
  96. package/.claude/skills/ask-matt/THIRD-PARTY-NOTICES.md +29 -0
  97. package/.claude/skills/audit-skills/SKILL.md +145 -0
  98. package/.claude/skills/board-to-waves/SKILL.md +148 -0
  99. package/.claude/skills/code-review/SKILL.md +64 -0
  100. package/.claude/skills/codebase-design/DEEPENING.md +37 -0
  101. package/.claude/skills/codebase-design/DESIGN-IT-TWICE.md +44 -0
  102. package/.claude/skills/codebase-design/SKILL.md +114 -0
  103. package/.claude/skills/codebase-design/THIRD-PARTY-NOTICES.md +29 -0
  104. package/.claude/skills/codex-build/SKILL.md +126 -0
  105. package/.claude/skills/codex-build/THIRD-PARTY-NOTICES.md +35 -0
  106. package/.claude/skills/codex-review/SKILL.md +145 -0
  107. package/.claude/skills/codex-review/THIRD-PARTY-NOTICES.md +31 -0
  108. package/.claude/skills/decision-gate/SKILL.md +67 -0
  109. package/.claude/skills/diagnose/SKILL.md +136 -0
  110. package/.claude/skills/diagnose/THIRD-PARTY-NOTICES.md +29 -0
  111. package/.claude/skills/diagnose/scripts/hitl-loop.template.sh +41 -0
  112. package/.claude/skills/domain-modeling/ADR-FORMAT.md +47 -0
  113. package/.claude/skills/domain-modeling/CONTEXT-FORMAT.md +60 -0
  114. package/.claude/skills/domain-modeling/SKILL.md +76 -0
  115. package/.claude/skills/domain-modeling/THIRD-PARTY-NOTICES.md +29 -0
  116. package/.claude/skills/git-guardrails-claude-code/SKILL.md +96 -0
  117. package/.claude/skills/git-guardrails-claude-code/THIRD-PARTY-NOTICES.md +29 -0
  118. package/.claude/skills/git-guardrails-claude-code/scripts/block-dangerous-git.sh +28 -0
  119. package/.claude/skills/git-worktree-recover/SKILL.md +182 -0
  120. package/.claude/skills/grill-me/SKILL.md +54 -0
  121. package/.claude/skills/grill-me/THIRD-PARTY-NOTICES.md +29 -0
  122. package/.claude/skills/grill-me-codex/SKILL.md +158 -0
  123. package/.claude/skills/grill-me-codex/THIRD-PARTY-NOTICES.md +32 -0
  124. package/.claude/skills/grill-with-docs/ADR-FORMAT.md +47 -0
  125. package/.claude/skills/grill-with-docs/CONTEXT-FORMAT.md +60 -0
  126. package/.claude/skills/grill-with-docs/SKILL.md +137 -0
  127. package/.claude/skills/grill-with-docs/THIRD-PARTY-NOTICES.md +29 -0
  128. package/.claude/skills/grill-with-docs-codex/ADR-FORMAT.md +47 -0
  129. package/.claude/skills/grill-with-docs-codex/CONTEXT-FORMAT.md +60 -0
  130. package/.claude/skills/grill-with-docs-codex/SKILL.md +233 -0
  131. package/.claude/skills/grill-with-docs-codex/THIRD-PARTY-NOTICES.md +33 -0
  132. package/.claude/skills/implement/SKILL.md +15 -0
  133. package/.claude/skills/implement/THIRD-PARTY-NOTICES.md +29 -0
  134. package/.claude/skills/improve-codebase-architecture/ADR-FORMAT.md +47 -0
  135. package/.claude/skills/improve-codebase-architecture/CONTEXT-FORMAT.md +60 -0
  136. package/.claude/skills/improve-codebase-architecture/DEEPENING.md +37 -0
  137. package/.claude/skills/improve-codebase-architecture/HTML-REPORT.md +123 -0
  138. package/.claude/skills/improve-codebase-architecture/INTERFACE-DESIGN.md +46 -0
  139. package/.claude/skills/improve-codebase-architecture/LANGUAGE.md +53 -0
  140. package/.claude/skills/improve-codebase-architecture/SKILL.md +88 -0
  141. package/.claude/skills/improve-codebase-architecture/THIRD-PARTY-NOTICES.md +29 -0
  142. package/.claude/skills/kit-release/SKILL.md +56 -0
  143. package/.claude/skills/local-ci/SKILL.md +94 -0
  144. package/.claude/skills/orchestrate-wave/SKILL.md +269 -0
  145. package/.claude/skills/orchestrate-wave/references/builder-contract.md +67 -0
  146. package/.claude/skills/prototype/LOGIC.md +79 -0
  147. package/.claude/skills/prototype/SKILL.md +30 -0
  148. package/.claude/skills/prototype/THIRD-PARTY-NOTICES.md +29 -0
  149. package/.claude/skills/prototype/UI.md +112 -0
  150. package/.claude/skills/research/SKILL.md +12 -0
  151. package/.claude/skills/research/THIRD-PARTY-NOTICES.md +29 -0
  152. package/.claude/skills/resolving-merge-conflicts/SKILL.md +14 -0
  153. package/.claude/skills/resolving-merge-conflicts/THIRD-PARTY-NOTICES.md +29 -0
  154. package/.claude/skills/retro/SKILL.md +209 -0
  155. package/.claude/skills/scale-check/SKILL.md +141 -0
  156. package/.claude/skills/security-audit/SKILL.md +67 -0
  157. package/.claude/skills/setup-pre-commit/SKILL.md +104 -0
  158. package/.claude/skills/setup-pre-commit/scripts/pre-commit.template.sh +35 -0
  159. package/.claude/skills/setup-workflow/SKILL.md +187 -0
  160. package/.claude/skills/setup-workflow/THIRD-PARTY-NOTICES.md +29 -0
  161. package/.claude/skills/setup-workflow/board-sync.md +111 -0
  162. package/.claude/skills/setup-workflow/code-review.md +26 -0
  163. package/.claude/skills/setup-workflow/domain.md +51 -0
  164. package/.claude/skills/setup-workflow/issue-tracker-github.md +35 -0
  165. package/.claude/skills/setup-workflow/issue-tracker-gitlab.md +34 -0
  166. package/.claude/skills/setup-workflow/issue-tracker-local.md +30 -0
  167. package/.claude/skills/setup-workflow/orchestrate-wave-seed.md +44 -0
  168. package/.claude/skills/setup-workflow/spec-completeness-seed.md +44 -0
  169. package/.claude/skills/setup-workflow/spec-self-critique-seed.md +43 -0
  170. package/.claude/skills/setup-workflow/triage-labels.md +18 -0
  171. package/.claude/skills/setup-workflow/workflow-overview.md +33 -0
  172. package/.claude/skills/skill-manifest.json +389 -0
  173. package/.claude/skills/spec-self-critique/SKILL.md +152 -0
  174. package/.claude/skills/spec-self-critique/scenarios.md +82 -0
  175. package/.claude/skills/tdd/SKILL.md +120 -0
  176. package/.claude/skills/tdd/THIRD-PARTY-NOTICES.md +29 -0
  177. package/.claude/skills/tdd/deep-modules.md +33 -0
  178. package/.claude/skills/tdd/interface-design.md +31 -0
  179. package/.claude/skills/tdd/mocking.md +59 -0
  180. package/.claude/skills/tdd/refactoring.md +10 -0
  181. package/.claude/skills/tdd/tests.md +61 -0
  182. package/.claude/skills/to-issues/SKILL.md +325 -0
  183. package/.claude/skills/to-issues/THIRD-PARTY-NOTICES.md +29 -0
  184. package/.claude/skills/to-prd/PROGRAM-PRD-FORMAT.md +162 -0
  185. package/.claude/skills/to-prd/SKILL.md +180 -0
  186. package/.claude/skills/to-prd/THIRD-PARTY-NOTICES.md +29 -0
  187. package/.claude/skills/to-waves/SKILL.md +260 -0
  188. package/.claude/skills/to-waves/SLICE-METADATA-FORMAT.md +74 -0
  189. package/.claude/skills/triage/AGENT-BRIEF.md +168 -0
  190. package/.claude/skills/triage/OUT-OF-SCOPE.md +101 -0
  191. package/.claude/skills/triage/SKILL.md +122 -0
  192. package/.claude/skills/triage/THIRD-PARTY-NOTICES.md +29 -0
  193. package/.claude/skills/verify-spike/SKILL.md +39 -0
  194. package/.claude/skills/wayfinder/SKILL.md +127 -0
  195. package/.claude/skills/wayfinder/THIRD-PARTY-NOTICES.md +29 -0
  196. package/.claude/skills/wrapup/SKILL.md +81 -0
  197. package/.claude/skills/wrapup/SOURCES.txt +6 -0
  198. package/.claude/skills/write-a-skill/GLOSSARY.md +201 -0
  199. package/.claude/skills/write-a-skill/SKILL.md +88 -0
  200. package/.claude/skills/write-a-skill/THIRD-PARTY-NOTICES.md +29 -0
  201. package/.claude/skills/zoom-out/SKILL.md +7 -0
  202. package/.claude/skills/zoom-out/THIRD-PARTY-NOTICES.md +29 -0
  203. package/LICENSE +28 -0
  204. package/PROVENANCE.md +39 -0
  205. package/README.md +619 -0
  206. package/agent-workflow-kit.package.json +1939 -0
  207. package/docs/agents/board-sync.md +71 -0
  208. package/docs/agents/code-review.md +14 -0
  209. package/docs/agents/domain.md +7 -0
  210. package/docs/agents/issue-tracker.md +12 -0
  211. package/docs/agents/security-audit-runbook-template.md +205 -0
  212. package/docs/agents/skills/orchestrate-wave.md +13 -0
  213. package/docs/agents/skills/spec-self-critique.md +18 -0
  214. package/docs/agents/triage-labels.md +10 -0
  215. package/docs/agents/wave-anchor-template.md +88 -0
  216. package/docs/conventions/spec-completeness.md +23 -0
  217. package/docs/index.html +56 -0
  218. package/docs/methodology.html +488 -0
  219. package/docs/methodology.svg +93 -0
  220. package/docs/workflow.png +0 -0
  221. package/package.json +40 -0
  222. package/scripts/anchor_table.py +343 -0
  223. package/scripts/board-sync.py +1232 -0
  224. package/scripts/board_config.py +147 -0
  225. package/scripts/board_fields.py +192 -0
  226. package/scripts/build-kit.mjs +116 -0
  227. package/scripts/build-kit.test.mjs +59 -0
  228. package/scripts/check-kit-staleness.mjs +45 -0
  229. package/scripts/check-kit-staleness.test.mjs +19 -0
  230. package/scripts/execute-ready-check.py +516 -0
  231. package/scripts/issue_deps.py +79 -0
  232. package/scripts/kit-release.mjs +100 -0
  233. package/scripts/kit-release.test.mjs +67 -0
  234. package/scripts/lib/audit-refs.mjs +146 -0
  235. package/scripts/lib/scrub.mjs +113 -0
  236. package/scripts/lib/scrub.test.mjs +187 -0
  237. package/scripts/loc_offender_core.py +196 -0
  238. package/scripts/loc_offender_gate.py +182 -0
  239. package/scripts/node_kind.py +68 -0
  240. package/scripts/portability_profile_scan.py +53 -0
  241. package/scripts/pr-body-check.py +263 -0
  242. package/scripts/program_graph.py +125 -0
  243. package/scripts/program_graph_parse.py +275 -0
  244. package/scripts/program_graph_validate.py +256 -0
  245. package/scripts/program_sync.py +160 -0
  246. package/scripts/release-delta-guard.mjs +96 -0
  247. package/scripts/release-delta-guard.test.mjs +53 -0
  248. package/scripts/test_board_sync_create_idempotency.py +104 -0
  249. package/scripts/test_dist_kit_smoke.py +199 -0
  250. package/scripts/test_kit_docs_language_census.py +178 -0
  251. package/scripts/test_skill_code_review_seed.py +89 -0
  252. package/scripts/test_skill_frontmatter_lint.py +226 -0
  253. package/scripts/test_skill_gh_lint.py +124 -0
  254. package/scripts/test_skill_language_census.py +254 -0
  255. package/scripts/test_skill_portability_lint.py +773 -0
  256. package/scripts/test_skill_publish_audit.py +300 -0
  257. package/scripts/test_skill_selfcontainment_lint.py +255 -0
  258. package/scripts/test_skill_setup_workflow_seeds.py +200 -0
  259. package/scripts/test_skill_stale_name_lint.py +126 -0
  260. package/scripts/test_skill_surface_refs.py +300 -0
  261. package/scripts/test_skill_trailing_artifact_lint.py +71 -0
  262. package/scripts/wrapup-land.py +573 -0
  263. package/src/cli.mjs +70 -0
  264. package/src/commands/diff.mjs +6 -0
  265. package/src/commands/init.mjs +59 -0
  266. package/src/commands/uninstall.mjs +43 -0
  267. package/src/commands/update.mjs +95 -0
  268. package/src/lib/atomicWrite.mjs +49 -0
  269. package/src/lib/bundle.mjs +133 -0
  270. package/src/lib/hash.mjs +13 -0
  271. package/src/lib/manifest.mjs +58 -0
  272. package/src/lib/sentinel.mjs +20 -0
  273. package/src/lib/settings.mjs +23 -0
@@ -0,0 +1,152 @@
1
+ ---
2
+ name: spec-self-critique
3
+ description: "Use AFTER writing or editing a spec (a `SPEC.md`/`PLAN.md` or any spec/design doc), BEFORE asking the user to review — runs a 12-point structural Self-Critique checklist, fixes issues inline, and emits a visible summary. Enriches each check from a project layer if one is present. Triggers right after a spec has been written. NOT for reviewing finished code/diffs (code-review) — this pass runs on the spec text itself."
4
+ ---
5
+
6
+ # Spec Self-Critique
7
+
8
+ A portable, structural self-review pass over a freshly written spec/plan. The **generic 12-point skeleton** below ships as-is; a **project layer** (if present) enriches each point with project-specific incidents, grep patterns, conventions, and extra sub-checks.
9
+
10
+ ## When to invoke
11
+
12
+ - After a spec was written/edited (a `SPEC.md` / `PLAN.md`, or a spec/design doc), BEFORE the user-review gate.
13
+
14
+ ## Step 0 — Project-layer probe
15
+
16
+ First, check whether a project layer exists: from the project root, look for `docs/agents/skills/spec-self-critique.md`.
17
+
18
+ - **Present** → **full pass**: run the 12 generic checks AND apply the per-point enrichment that file defines (incidents, grep patterns, extra sub-checks).
19
+ - **Absent** → **base pass**: run the 12 generic checks only, then add this one-line warning to the summary:
20
+ > ⚠ No project layer found (`docs/agents/skills/spec-self-critique.md`) — only the generic base checks ran. `/setup-workflow` creates the layer; it fills in project-specific content via `/retro`.
21
+
22
+ > **Routing — keep this skeleton clean.** Project-specific checks, incidents, and grep patterns belong in the project layer (`docs/agents/skills/spec-self-critique.md`), **NOT here**. `/retro` appends new project-specific lore to the project layer, never into this generic skeleton.
23
+
24
+ ## Altitude — a portable kit concept
25
+
26
+ The generic skeleton recognizes two spec altitudes: a **Feature-PRD** (the
27
+ default — every point above and below assumes this) and a **Program-PRD**
28
+ (marked `<!-- prd: program -->`, produced by the kit's `scale-check` →
29
+ `grill-with-docs` → `to-prd` program route — a native anchor over a
30
+ multi-wave `## Wellenplan`). This is a **portable kit concept**, not a
31
+ project-specific rule, so it stays **in this generic skeleton** — the
32
+ "project-specific → project layer" routing rule above is about *this
33
+ project's* incidents/grep patterns, not about a kit-wide spec shape the
34
+ skill itself already knows.
35
+
36
+ Two points read differently at Program-Altitude — both get a dedicated
37
+ fixture in `scenarios.md`:
38
+
39
+ - **Point 3 (Scope)** at `prd: program`: scope is not "small enough for one
40
+ plan" — it is "each wave holds 2–7 slices; the program splits via its wave
41
+ plan, the PRD itself is never split."
42
+ - **Point 12 (Vertical-slice completeness)** at `prd: program`: reads against
43
+ **Wellenplan rows**, not a slice/PR table — each wave is an outcome
44
+ cut/tracer, never a layer cut ("a backend wave" is the anti-pattern); an
45
+ enabler wave names the half it cuts off and the outcome wave that closes it.
46
+
47
+ Every other point runs unchanged at either altitude.
48
+
49
+ ## How to invoke
50
+
51
+ Read the most recently written/edited spec in full. Walk the 12-point checklist (points 1–12; **8b/8c are sub-checks of point 8**, not main points). Per point:
52
+
53
+ 1. Decide: does the spec trigger this rule?
54
+ 2. If yes: run the check.
55
+ 3. If violated: fix the spec inline (Edit tool, not "TODO later").
56
+ 4. Note the correction for the summary.
57
+
58
+ End with a visible summary in the chat:
59
+
60
+ ```
61
+ Self-Critique complete — <N> corrections:
62
+ - Point <X>: <short description>
63
+ - ...
64
+ ```
65
+
66
+ or, if none were needed: `Self-Critique complete — no corrections needed.` (append the Step-0 layer-absent warning if it applied). THEN ask the user-review question.
67
+
68
+ ## The 12-point checklist
69
+
70
+ **1. Placeholder scan + empirical re-check**
71
+ Scan for `TBD` / `TODO` / "später" / "fill in details" / vague requirements → fix inline. Plus, when applicable:
72
+ - **Cited counts** ("24 call-sites: 6 start, 8 succeed, …") → re-verify each empirically (`grep`); recon from the brainstorming phase can be stale, and wrong numbers mislead the effort estimate.
73
+ - **Folder move / rename** → broaden the caller-audit grep (search the path-segment without a `from …`-anchor, to catch mocks, dynamic imports, type-only imports) AND require a typecheck-backstop step right after the move (path-depth breaks inside the moved files aren't found by a caller grep).
74
+ - **Cited prior diagnosis** (issue body, investigation, memory snapshot, earlier plan) → verify each core claim empirically before finalizing. Such artifacts are hypotheses, not validated facts; drift compounds if left unchecked.
75
+ - **Risk mitigation** → it must name a concretely checkable **output string**, not just an action ("rowCount is 2307" is checkable; "rowCount > 1000" is a claim about a claim).
76
+ Skip only if none of these apply.
77
+
78
+ **2. Internal consistency**
79
+ Do sections contradict each other? Does the architecture match the feature description? Do numbers/orders agree between tables and prose?
80
+
81
+ **3. Scope check**
82
+ Small enough for **one** implementation plan, or must it split into sub-specs?
83
+ **At Program-Altitude** (`prd: program`) this reads differently — see
84
+ "Altitude" above: each wave holds 2–7 slices, the program splits via its wave
85
+ plan, and the PRD itself is never split.
86
+
87
+ **4. Ambiguity check**
88
+ Could a requirement be read two ways? If so, pick one interpretation and make it explicit.
89
+
90
+ **5. State transitions**
91
+ *Trigger:* the spec mentions "Live", "SSE", "WebSocket", "Polling", "EventSource", "Realtime", "Stream", or incoming updates.
92
+ *Check:* are all transitions played through — `idle → running → awaiting_decision → succeeded | failed` — plus `mid-flight reload`, `multi-tab parallel`, `connection-loss + reconnect`, `aborted`?
93
+
94
+ **6. Convention scope**
95
+ *Trigger:* the spec introduces a new pattern, convention, single-entry broker, wrapper, or consistency layer.
96
+ *Check:* is it explicitly scoped — applied app-wide vs only touched surfaces? Does the spec require a follow-up item for the untouched surfaces (in the spec body, not retroactively)?
97
+
98
+ **7. User walk-through**
99
+ *Trigger:* the spec has UI stages, wizards, or multi-step user interactions.
100
+ *Check:* are the sub-steps per UI stage walked through — what does the user see at each stage — not just the data model?
101
+
102
+ **8. Project-convention check**
103
+ *Trigger:* always.
104
+ *How:* iterate your project's documented conventions. Default location: from the project root, `docs/conventions/*.md`. For each convention file that carries a `## Self-Critique-Check` block (format: **Trigger / Check / Korrektur**):
105
+ 1. Evaluate its Trigger against the current spec.
106
+ 2. On match: run its Check. On violation: fix the spec inline + note it.
107
+ 3. A convention with no such block → skip it non-blocking + collect a warning ("convention `<file>` is missing a `## Self-Critique-Check` block").
108
+ No conventions directory / no blocks (e.g. a fresh project) → **soft skip** (non-blocking). Emit collected warnings at the end of the pass.
109
+
110
+ **8b. Marker-wording check**
111
+ *Trigger:* a convention mandates a header marker comment.
112
+ *Check:* the spec's marker must be copied **verbatim** from the convention, not paraphrased. Open the convention, compare the marker block 1:1, fix inline on any drift (drift makes the convention worthless as the single source of truth).
113
+
114
+ **8c. Structurally-trivial post-invariant**
115
+ *Trigger:* the spec has aggregation functions with post-invariants.
116
+ *Check:* for each post-invariant, can it ever fire under the current code path? Play the path through (all branches, all math ranges). If it is structurally impossible to violate under the current code, drop it or replace it with a property test (a property fires on every regression; a structurally-true post never does).
117
+
118
+ **9. Primitive recon (DRY)**
119
+ *Trigger:* the spec introduces a new UI primitive, hook, component, helper, repo function, or service — OR substantially touches (≥30 LOC) an existing file.
120
+ *Check:* did you `grep`/`ls` for an existing primitive/helper with overlapping responsibility (including in callers/pages, not just component dirs)? If one exists → switch the spec to reuse it. If a pattern is replicated 3+× → require a helper-extraction acceptance-criterion.
121
+
122
+ **10. User-action feedback**
123
+ *Trigger:* the spec describes a user action (click, submit, import, bulk op, setup run) that triggers a ≥2-step process.
124
+ *Check:* does the spec document, per sub-step, what the user sees on screen — progress, retry/throttle visibility (esp. external APIs or long waits), mode-switch visibility (e.g. bulk → per-item fallback), and a "why is this counter stalled" hint for per-resource paths?
125
+
126
+ **11. Live-verify bug-plausibility**
127
+ *Trigger:* the spec has a live-verify block with a bug-variant + an expected property failure.
128
+ *Check:* play the bug-variant through — does it actually change the target property (e.g. does it break the asserted ordering/monotonicity)? Is only one direction sharp? If the variant does NOT violate the property, pick a variant that does and fix the spec inline (a wrong variant yields a passing live-verify that catches no real regression).
129
+
130
+ **12. Vertical-slice completeness**
131
+ *Trigger:* the spec/PRD has a slice/phase table or splits into multiple PRs.
132
+ *Check:*
133
+ - (a) each *user-facing* slice = a tracer bullet "`<user action> → <visible result>`", **not** a layer name ("config UI", "backend resolver");
134
+ - (b) each byte-neutral/infra slice names its **omitted half** + the **closing follow-up slice** (otherwise the connecting path falls between two slices);
135
+ - (c) the first outcome slice after ≥1 prep slice is traced against the code with a concrete value (`grep`/Read), not trusted as "config-driven".
136
+ *Correction:* reword/split a layer-only slice; pull in a new slice for an uncovered half.
137
+ **At Program-Altitude** (`prd: program`), apply (a)–(c) analogously to
138
+ **Wellenplan rows** instead of a slice table — see "Altitude" above: each wave
139
+ is an outcome cut/tracer, never a layer cut, and an enabler wave names both
140
+ the half it omits and the outcome wave that closes it.
141
+
142
+ **Gate home.** This skill runs **automatically as the mandatory last step of `to-prd`** (on the Draft-PRD) — the visible two-line summary is required **before** the user-review question. The **slice-completeness gate (point 12)** additionally sits in `to-issues`. The skill stays **standalone-callable** for manual spec/PLAN reviews.
143
+
144
+ ## Anti-patterns of this skill
145
+
146
+ - **"Skipped self-critique because the spec is small"** — it runs on mini-specs too. Cost: 2–3 min; payoff: structural bugs caught in the spec phase.
147
+ - **"Made corrections silently inline, no summary"** — the visible summary is part of acceptance. A silent pass is indistinguishable from a skipped one.
148
+ - **"Improvised what a convention would say"** — if a convention file has no `## Self-Critique-Check` block, skip it non-blocking + collect a warning. Do not invent the rule.
149
+
150
+ ## Verification fixtures
151
+
152
+ See `scenarios.md` in this skill dir for project-neutral fixtures (one per check) — walk them when refactoring the checklist. If a project layer is present, it may carry richer, project-specific scenarios.
@@ -0,0 +1,82 @@
1
+ # Verification fixtures — spec-self-critique (generic)
2
+
3
+ **Fixtures only — no new rules here.** Each fragment is a synthetic, project-neutral spec snippet that violates **exactly one** check. When the skill works, it should trigger the named point and name it in the summary. Walk these when refactoring the checklist. New *project-specific* checks/scenarios go in the project layer (`docs/agents/skills/spec-self-critique.md`), never here.
4
+
5
+ ## Point 1 — placeholder / unverified count
6
+ > "Rename `oldUtil` → `newUtil` across the 9 call-sites and update imports."
7
+
8
+ Violates 1 (cited count not re-verified; rename = caller-audit + typecheck-backstop). Expected: *"Punkt 1: '9 call-sites' nicht empirisch belegt — grep + breiter Caller-Audit + Typecheck-Backstop nach dem Move ergänzt."*
9
+
10
+ ## Point 2 — internal consistency
11
+ > "Section A: the cache TTL is 60s. Section B's diagram labels the same cache 600s."
12
+
13
+ Violates 2. Expected: *"Punkt 2: widersprüchliche TTL (60s vs 600s) — vereinheitlicht."*
14
+
15
+ ## Point 3 — scope
16
+ > "This spec covers: new auth provider, a billing rewrite, a dashboard redesign, and a data migration."
17
+
18
+ Violates 3. Expected: *"Punkt 3: zu groß für einen Plan — in Sub-Specs zerlegen."*
19
+
20
+ ## Point 3 (Program-Altitude) — a wave outgrows the band
21
+ > "`<!-- prd: program -->` Program-PRD. Wellenplan: Welle 1 covers 9 slices
22
+ > across two subsystems; Welle 2 covers 3 slices."
23
+
24
+ Violates 3 at Program-Altitude (a wave over the 2–7 slice band needs
25
+ splitting into two waves; the PRD itself stays unsplit). Expected: *"Punkt 3
26
+ (Programm-Altitude): Welle 1 mit 9 Slices sprengt den 2–7-Rahmen — in zwei
27
+ Wellen aufgeteilt; das PRD selbst bleibt ungesplittet."*
28
+
29
+ ## Point 4 — ambiguity
30
+ > "When the request fails, retry it a few times before giving up."
31
+
32
+ Violates 4. Expected: *"Punkt 4: 'a few times' mehrdeutig — auf konkrete Zahl + Backoff festgelegt."*
33
+
34
+ ## Point 5 — state transitions
35
+ > "New live progress indicator: on start a spinner appears, on finish a green check."
36
+
37
+ Violates 5 (only `running → succeeded`). Expected: *"Punkt 5: Live-Feature, nur Erfolgs-Pfad — failed / reload / multi-tab / connection-loss / aborted ergänzt."*
38
+
39
+ ## Point 6 — convention scope
40
+ > "Introduce a `withRetry()` wrapper. Apply it in `serviceA.fetch()` and `serviceB.fetch()`."
41
+
42
+ Violates 6 (no app-wide-vs-touched scope, no follow-up). Expected: *"Punkt 6: Pattern-Scope nicht erklärt — explizit nur diese 2 + Followup für den Rest."*
43
+
44
+ ## Point 7 — user walk-through
45
+ > "New multi-step onboarding wizard at `/onboarding`. Data model: a 3-field form posted to `/api/onboard`."
46
+
47
+ Violates 7 (only data model). Expected: *"Punkt 7: kein User-Walk-Through der Wizard-Stufen — pro Stufe ergänzt, was der User sieht."*
48
+
49
+ ## Point 8 — project convention (+ 8b marker, 8c trivial post)
50
+ > "Refactor an aggregation module. Pre-invariant: `typeof rows[0]?.id === 'string'` (already guaranteed by the typed signature). Post-invariant: `out.length === rows.length` where the body is `for (const r of rows) out.push(...)`."
51
+
52
+ Violates 8c (post structurally guaranteed by the loop) + 8b-style trivial pre. Expected: *"Punkt 8c: Post strukturell durch den Loop garantiert — gestrichen / Property-Test; triviale Pre entfernt."* (With a project layer present, point 8 also iterates that project's `## Self-Critique-Check` convention blocks.)
53
+
54
+ ## Point 9 — primitive recon (DRY)
55
+ > "Build a new `FilterableList` component with sort + filter."
56
+
57
+ Violates 9 (no recon for an existing list/table primitive). Expected: *"Punkt 9: neues Primitiv ohne DRY-Recon — auf Wiederverwendung des Bestehenden geprüft/umgestellt."*
58
+
59
+ ## Point 10 — user-action feedback
60
+ > "A 'Rebuild caches' button kicks off a 4-stage backend job (~2 min). On error: a toast."
61
+
62
+ Violates 10 (no per-step feedback). Expected: *"Punkt 10: ≥2-Schritt-Prozess ohne Sub-Step-Feedback — Schritt-Labels / Progress / Retry- bzw. Modus-Sichtbarkeit ergänzt."*
63
+
64
+ ## Point 11 — live-verify bug-plausibility
65
+ > "Live-verify for percentile indices. Bug-variant: change `p80 = 0.8*n` to `0.6*n`. Expect the ordering check `p10 < p50 < p80 < p90` to fire."
66
+
67
+ Violates 11 (`0.5 < 0.6 < 0.9` stays monotone → property does NOT fire). Expected: *"Punkt 11: Variante erhält die Monotonie — Property feuert nicht; korrekte Variante (z.B. 0.8→0.95, bricht p80>p90) gewählt."*
68
+
69
+ ## Point 12 — vertical-slice completeness
70
+ > "Slices: 1) Config UI · 2) Backend resolver · 3) Wire-up."
71
+
72
+ Violates 12 (layer names, no tracer-bullet, no traced outcome slice). Expected: *"Punkt 12: Layer-Namen statt Tracer-Bullets — als '<Aktion> → <sichtbares Ergebnis>' umformuliert; erste Outcome-Slice gegen Code getrace't."*
73
+
74
+ ## Point 12 (Program-Altitude) — layer-cut waves
75
+ > "`<!-- prd: program -->` Program-PRD. Wellenplan: Welle 3 — 'Backend-Migration'. Welle 4 — 'Frontend-Rollout'."
76
+
77
+ Violates 12 at Program-Altitude (layer-cut waves, not outcome tracers; no
78
+ enabler/closing pairing named). Expected: *"Punkt 12 (Programm-Altitude):
79
+ 'Backend-Migration'/'Frontend-Rollout' sind Layer-Schnitte, keine
80
+ Outcome-Tracer — Welle 3 als Enabler benannt (abgeschnittene Hälfte:
81
+ sichtbares Frontend-Verhalten) mit Welle 4 als schließender Outcome-Welle,
82
+ oder zu echten Outcome-Wellen umgeschnitten."*
@@ -0,0 +1,120 @@
1
+ ---
2
+ name: tdd
3
+ description: Test-driven development with red-green-refactor loop. Use when user wants to build features or fix bugs using TDD, mentions "red-green-refactor", wants integration tests, or asks for test-first development.
4
+ ---
5
+
6
+ # Test-Driven Development
7
+
8
+ ## Philosophy
9
+
10
+ **Core principle**: Tests should verify behavior through public interfaces, not implementation details. Code can change entirely; tests shouldn't.
11
+
12
+ **Good tests** are integration-style: they exercise real code paths through public APIs. They describe _what_ the system does, not _how_ it does it. A good test reads like a specification - "user can checkout with valid cart" tells you exactly what capability exists. These tests survive refactors because they don't care about internal structure.
13
+
14
+ **Bad tests** are coupled to implementation. They mock internal collaborators, test private methods, or verify through external means (like querying a database directly instead of using the interface). The warning sign: your test breaks when you refactor, but behavior hasn't changed. If you rename an internal function and tests fail, those tests were testing implementation, not behavior.
15
+
16
+ See [tests.md](tests.md) for examples and [mocking.md](mocking.md) for mocking guidelines.
17
+
18
+ ## Anti-Pattern: Horizontal Slices
19
+
20
+ **DO NOT write all tests first, then all implementation.** This is "horizontal slicing" - treating RED as "write all tests" and GREEN as "write all code."
21
+
22
+ This produces **crap tests**:
23
+
24
+ - Tests written in bulk test _imagined_ behavior, not _actual_ behavior
25
+ - You end up testing the _shape_ of things (data structures, function signatures) rather than user-facing behavior
26
+ - Tests become insensitive to real changes - they pass when behavior breaks, fail when behavior is fine
27
+ - You outrun your headlights, committing to test structure before understanding the implementation
28
+
29
+ **Correct approach**: Vertical slices via tracer bullets. One test → one implementation → repeat. Each test responds to what you learned from the previous cycle. Because you just wrote the code, you know exactly what behavior matters and how to verify it.
30
+
31
+ ```
32
+ WRONG (horizontal):
33
+ RED: test1, test2, test3, test4, test5
34
+ GREEN: impl1, impl2, impl3, impl4, impl5
35
+
36
+ RIGHT (vertical):
37
+ RED→GREEN: test1→impl1
38
+ RED→GREEN: test2→impl2
39
+ RED→GREEN: test3→impl3
40
+ ...
41
+ ```
42
+
43
+ ## Workflow
44
+
45
+ ### 1. Planning
46
+
47
+ **First, mark the ticket active on the board.** When a ticket was provided (you're on a `feat/<#>-`/`fix/<#>-` branch), run once at TDD pickup:
48
+
49
+ <!-- mirror-xform:start codex-board-sync-command -->
50
+ ```
51
+ python3 "$CLAUDE_PROJECT_DIR/.claude/hooks/sync-board-status.py"
52
+ ```
53
+ <!-- mirror-xform:end -->
54
+
55
+ It parses the issue # from the current branch and moves the board item to the profile's in-progress status (`fields.status.roles.inProgress`; only from the idea/triaged/spec roles, idempotent). No ticket / no parseable branch → it's a silent no-op, so this is safe to run unconditionally. This closes the gap where the SessionStart sync already ran on `main` before the worktree existed, leaving the board stale.
56
+
57
+ When exploring the codebase, use the project's domain glossary so that test names and interface vocabulary match the project's language, and respect ADRs in the area you're touching.
58
+
59
+ Before writing any code:
60
+
61
+ - [ ] Confirm with user what interface changes are needed
62
+ - [ ] Confirm with user which behaviors to test (prioritize)
63
+ - [ ] Identify opportunities for [deep modules](deep-modules.md) (small interface, deep implementation)
64
+ - [ ] Design interfaces for [testability](interface-design.md)
65
+ - [ ] List the behaviors to test (not implementation steps)
66
+ - [ ] Get user approval on the plan
67
+
68
+ Ask: "What should the public interface look like? Which behaviors are most important to test?"
69
+
70
+ **You can't test everything.** Confirm with the user exactly which behaviors matter most. Focus testing effort on critical paths and complex logic, not every possible edge case.
71
+
72
+ ### 2. Tracer Bullet
73
+
74
+ Write ONE test that confirms ONE thing about the system:
75
+
76
+ ```
77
+ RED: Write test for first behavior → test fails
78
+ GREEN: Write minimal code to pass → test passes
79
+ ```
80
+
81
+ This is your tracer bullet - proves the path works end-to-end.
82
+
83
+ ### 3. Incremental Loop
84
+
85
+ For each remaining behavior:
86
+
87
+ ```
88
+ RED: Write next test → fails
89
+ GREEN: Minimal code to pass → passes
90
+ ```
91
+
92
+ Rules:
93
+
94
+ - One test at a time
95
+ - Only enough code to pass current test
96
+ - Don't anticipate future tests
97
+ - Keep tests focused on observable behavior
98
+
99
+ ### 4. Refactor
100
+
101
+ After all tests pass, look for [refactor candidates](refactoring.md):
102
+
103
+ - [ ] Extract duplication
104
+ - [ ] Deepen modules (move complexity behind simple interfaces)
105
+ - [ ] Apply SOLID principles where natural
106
+ - [ ] Consider what new code reveals about existing code
107
+ - [ ] Run tests after each refactor step
108
+
109
+ **Never refactor while RED.** Get to GREEN first.
110
+
111
+ ## Checklist Per Cycle
112
+
113
+ ```
114
+ [ ] Test describes behavior, not implementation
115
+ [ ] Test uses public interface only
116
+ [ ] Test would survive internal refactor
117
+ [ ] Code is minimal for this test
118
+ [ ] No speculative features added
119
+ [ ] Wave slice: a flipped/new assumption affecting an unbuilt sibling issue → log it to ANNAHMEN.md (worktree root; wrapup Step 0c reads it)
120
+ ```
@@ -0,0 +1,29 @@
1
+ # Third-Party Notices
2
+
3
+ This skill is adapted from **Matt Pocock's skills**
4
+ (https://github.com/mattpocock/skills), `skills/engineering/tdd` @ d574778, Copyright (c) 2026 Matt Pocock,
5
+ used under the MIT License. Locally adapted (fork-and-own); see PROVENANCE.md.
6
+
7
+ ```
8
+ MIT License
9
+
10
+ Copyright (c) 2026 Matt Pocock
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining a copy
13
+ of this software and associated documentation files (the "Software"), to deal
14
+ in the Software without restriction, including without limitation the rights
15
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16
+ copies of the Software, and to permit persons to whom the Software is
17
+ furnished to do so, subject to the following conditions:
18
+
19
+ The above copyright notice and this permission notice shall be included in all
20
+ copies or substantial portions of the Software.
21
+
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28
+ SOFTWARE.
29
+ ```
@@ -0,0 +1,33 @@
1
+ # Deep Modules
2
+
3
+ From "A Philosophy of Software Design":
4
+
5
+ **Deep module** = small interface + lots of implementation
6
+
7
+ ```
8
+ ┌─────────────────────┐
9
+ │ Small Interface │ ← Few methods, simple params
10
+ ├─────────────────────┤
11
+ │ │
12
+ │ │
13
+ │ Deep Implementation│ ← Complex logic hidden
14
+ │ │
15
+ │ │
16
+ └─────────────────────┘
17
+ ```
18
+
19
+ **Shallow module** = large interface + little implementation (avoid)
20
+
21
+ ```
22
+ ┌─────────────────────────────────┐
23
+ │ Large Interface │ ← Many methods, complex params
24
+ ├─────────────────────────────────┤
25
+ │ Thin Implementation │ ← Just passes through
26
+ └─────────────────────────────────┘
27
+ ```
28
+
29
+ When designing interfaces, ask:
30
+
31
+ - Can I reduce the number of methods?
32
+ - Can I simplify the parameters?
33
+ - Can I hide more complexity inside?
@@ -0,0 +1,31 @@
1
+ # Interface Design for Testability
2
+
3
+ Good interfaces make testing natural:
4
+
5
+ 1. **Accept dependencies, don't create them**
6
+
7
+ ```typescript
8
+ // Testable
9
+ function processOrder(order, paymentGateway) {}
10
+
11
+ // Hard to test
12
+ function processOrder(order) {
13
+ const gateway = new StripeGateway();
14
+ }
15
+ ```
16
+
17
+ 2. **Return results, don't produce side effects**
18
+
19
+ ```typescript
20
+ // Testable
21
+ function calculateDiscount(cart): Discount {}
22
+
23
+ // Hard to test
24
+ function applyDiscount(cart): void {
25
+ cart.total -= discount;
26
+ }
27
+ ```
28
+
29
+ 3. **Small surface area**
30
+ - Fewer methods = fewer tests needed
31
+ - Fewer params = simpler test setup
@@ -0,0 +1,59 @@
1
+ # When to Mock
2
+
3
+ Mock at **system boundaries** only:
4
+
5
+ - External APIs (payment, email, etc.)
6
+ - Databases (sometimes - prefer test DB)
7
+ - Time/randomness
8
+ - File system (sometimes)
9
+
10
+ Don't mock:
11
+
12
+ - Your own classes/modules
13
+ - Internal collaborators
14
+ - Anything you control
15
+
16
+ ## Designing for Mockability
17
+
18
+ At system boundaries, design interfaces that are easy to mock:
19
+
20
+ **1. Use dependency injection**
21
+
22
+ Pass external dependencies in rather than creating them internally:
23
+
24
+ ```typescript
25
+ // Easy to mock
26
+ function processPayment(order, paymentClient) {
27
+ return paymentClient.charge(order.total);
28
+ }
29
+
30
+ // Hard to mock
31
+ function processPayment(order) {
32
+ const client = new StripeClient(process.env.STRIPE_KEY);
33
+ return client.charge(order.total);
34
+ }
35
+ ```
36
+
37
+ **2. Prefer SDK-style interfaces over generic fetchers**
38
+
39
+ Create specific functions for each external operation instead of one generic function with conditional logic:
40
+
41
+ ```typescript
42
+ // GOOD: Each function is independently mockable
43
+ const api = {
44
+ getUser: (id) => fetch(`/users/${id}`),
45
+ getOrders: (userId) => fetch(`/users/${userId}/orders`),
46
+ createOrder: (data) => fetch('/orders', { method: 'POST', body: data }),
47
+ };
48
+
49
+ // BAD: Mocking requires conditional logic inside the mock
50
+ const api = {
51
+ fetch: (endpoint, options) => fetch(endpoint, options),
52
+ };
53
+ ```
54
+
55
+ The SDK approach means:
56
+ - Each mock returns one specific shape
57
+ - No conditional logic in test setup
58
+ - Easier to see which endpoints a test exercises
59
+ - Type safety per endpoint
@@ -0,0 +1,10 @@
1
+ # Refactor Candidates
2
+
3
+ After TDD cycle, look for:
4
+
5
+ - **Duplication** → Extract function/class
6
+ - **Long methods** → Break into private helpers (keep tests on public interface)
7
+ - **Shallow modules** → Combine or deepen
8
+ - **Feature envy** → Move logic to where data lives
9
+ - **Primitive obsession** → Introduce value objects
10
+ - **Existing code** the new code reveals as problematic
@@ -0,0 +1,61 @@
1
+ # Good and Bad Tests
2
+
3
+ ## Good Tests
4
+
5
+ **Integration-style**: Test through real interfaces, not mocks of internal parts.
6
+
7
+ ```typescript
8
+ // GOOD: Tests observable behavior
9
+ test("user can checkout with valid cart", async () => {
10
+ const cart = createCart();
11
+ cart.add(product);
12
+ const result = await checkout(cart, paymentMethod);
13
+ expect(result.status).toBe("confirmed");
14
+ });
15
+ ```
16
+
17
+ Characteristics:
18
+
19
+ - Tests behavior users/callers care about
20
+ - Uses public API only
21
+ - Survives internal refactors
22
+ - Describes WHAT, not HOW
23
+ - One logical assertion per test
24
+
25
+ ## Bad Tests
26
+
27
+ **Implementation-detail tests**: Coupled to internal structure.
28
+
29
+ ```typescript
30
+ // BAD: Tests implementation details
31
+ test("checkout calls paymentService.process", async () => {
32
+ const mockPayment = jest.mock(paymentService);
33
+ await checkout(cart, payment);
34
+ expect(mockPayment.process).toHaveBeenCalledWith(cart.total);
35
+ });
36
+ ```
37
+
38
+ Red flags:
39
+
40
+ - Mocking internal collaborators
41
+ - Testing private methods
42
+ - Asserting on call counts/order
43
+ - Test breaks when refactoring without behavior change
44
+ - Test name describes HOW not WHAT
45
+ - Verifying through external means instead of interface
46
+
47
+ ```typescript
48
+ // BAD: Bypasses interface to verify
49
+ test("createUser saves to database", async () => {
50
+ await createUser({ name: "Alice" });
51
+ const row = await db.query("SELECT * FROM users WHERE name = ?", ["Alice"]);
52
+ expect(row).toBeDefined();
53
+ });
54
+
55
+ // GOOD: Verifies through interface
56
+ test("createUser makes user retrievable", async () => {
57
+ const user = await createUser({ name: "Alice" });
58
+ const retrieved = await getUser(user.id);
59
+ expect(retrieved.name).toBe("Alice");
60
+ });
61
+ ```