@erclx/canon 5.41.0 → 5.42.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 (154) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/api-design/references/adopted.md +34 -14
  3. package/claude/skills/auto-ship/REQUIREMENT.md +1 -0
  4. package/claude/skills/auto-ship/SKILL.md +22 -2
  5. package/claude/skills/auto-ship/references/draft-mark.md +32 -6
  6. package/claude/skills/auto-ship/references/failure-recovery.md +15 -13
  7. package/claude/skills/auto-ship/references/tier-failures.md +31 -10
  8. package/claude/skills/auto-ship/references/ui-checklist.md +9 -4
  9. package/claude/skills/auto-ship/references/worktree-name.md +9 -3
  10. package/claude/skills/build-in-slices/references/adopted.md +35 -21
  11. package/claude/skills/canvas-board/references/canvas.md +17 -6
  12. package/claude/skills/canvas-board/references/design.md +26 -7
  13. package/claude/skills/code-craft/references/adopted.md +58 -20
  14. package/claude/skills/codebase-layout/references/adopted.md +49 -16
  15. package/claude/skills/codebase-layout/references/frontend.md +11 -4
  16. package/claude/skills/codebase-layout/references/tests.md +4 -2
  17. package/claude/skills/context-fold/references/classify.md +10 -15
  18. package/claude/skills/context-fold/references/completion-report.md +11 -9
  19. package/claude/skills/context-fold/references/context-refresh.md +26 -9
  20. package/claude/skills/context-fold/references/unusable-baseline.md +5 -3
  21. package/claude/skills/create-rule/REQUIREMENT.md +5 -0
  22. package/claude/skills/create-rule/SKILL.md +9 -1
  23. package/claude/skills/create-rule/references/checklist.md +26 -0
  24. package/claude/skills/create-rule/references/rule.md +98 -20
  25. package/claude/skills/create-skill/SKILL.md +1 -0
  26. package/claude/skills/create-skill/references/skill-disclosure.md +10 -2
  27. package/claude/skills/create-skill/references/skill-frontmatter.md +43 -0
  28. package/claude/skills/create-skill/references/skill-paths.md +7 -4
  29. package/claude/skills/create-skill/references/skill-practice.md +6 -3
  30. package/claude/skills/create-skill/references/skill-requirement.md +4 -2
  31. package/claude/skills/create-skill/references/skill.md +67 -44
  32. package/claude/skills/deploy-app/references/vercel.md +2 -1
  33. package/claude/skills/deprecation-migration/references/adopted.md +44 -25
  34. package/claude/skills/design-taste/references/adopted.md +9 -1
  35. package/claude/skills/design-taste/references/craft.md +3 -1
  36. package/claude/skills/design-taste/references/kinds.md +8 -7
  37. package/claude/skills/design-taste/references/preflight.md +12 -0
  38. package/claude/skills/design-taste/references/systems.md +7 -6
  39. package/claude/skills/design-taste/references/tells.md +24 -25
  40. package/claude/skills/design-taste/references/vocabulary.md +7 -5
  41. package/claude/skills/document-health/references/axes.md +54 -30
  42. package/claude/skills/draft-and-pick/references/live-arms.md +2 -2
  43. package/claude/skills/draft-doc/references/context.md +4 -3
  44. package/claude/skills/draft-doc/references/docs.md +6 -3
  45. package/claude/skills/draft-doc/references/readme/agent-facing.md +6 -0
  46. package/claude/skills/draft-doc/references/readme/application.md +8 -2
  47. package/claude/skills/draft-doc/references/readme/cli.md +5 -1
  48. package/claude/skills/draft-doc/references/readme/library.md +4 -0
  49. package/claude/skills/draft-doc/references/readme/plugin.md +9 -1
  50. package/claude/skills/draft-doc/references/readme.md +30 -13
  51. package/claude/skills/draft-doc/references/requirements.md +17 -4
  52. package/claude/skills/draft-doc/references/wiki-kind.md +20 -10
  53. package/claude/skills/draft-figure/references/architecture-set.md +7 -3
  54. package/claude/skills/draft-figure/references/figures.md +8 -6
  55. package/claude/skills/draft-figure/references/hand-drawn.md +3 -1
  56. package/claude/skills/draft-figure/references/mermaid-path.md +19 -9
  57. package/claude/skills/draft-figure/references/mermaid.md +10 -5
  58. package/claude/skills/draft-ready/references/ready.md +22 -15
  59. package/claude/skills/git-branch/references/branch.md +11 -1
  60. package/claude/skills/git-branch/references/slug.md +17 -5
  61. package/claude/skills/git-commit/references/commit.md +8 -0
  62. package/claude/skills/git-commit/references/versioning.md +23 -17
  63. package/claude/skills/git-followup/REQUIREMENT.md +1 -1
  64. package/claude/skills/git-followup/SKILL.md +5 -6
  65. package/claude/skills/git-issue/references/issue.md +29 -16
  66. package/claude/skills/git-pr/REQUIREMENT.md +1 -5
  67. package/claude/skills/git-pr/SKILL.md +11 -22
  68. package/claude/skills/git-pr/references/final-command.md +21 -8
  69. package/claude/skills/git-pr/references/labels.md +45 -28
  70. package/claude/skills/git-pr/references/pr.md +28 -9
  71. package/claude/skills/git-pr/references/publish.md +42 -28
  72. package/claude/skills/git-pr/references/task-number.md +20 -8
  73. package/claude/skills/git-ship/SKILL.md +1 -1
  74. package/claude/skills/plan-feature/references/plan-lifecycle.md +10 -3
  75. package/claude/skills/plan-feature/references/plan.md +57 -20
  76. package/claude/skills/plan-groundwork/references/groundwork-spikes.md +4 -1
  77. package/claude/skills/plan-groundwork/references/groundwork.md +14 -16
  78. package/claude/skills/plan-intake/references/intake.md +29 -24
  79. package/claude/skills/pr-evidence/REQUIREMENT.md +40 -0
  80. package/claude/skills/pr-evidence/SKILL.md +53 -0
  81. package/claude/skills/pr-evidence/references/evidence.md +150 -0
  82. package/claude/skills/review-address/references/post-review-findings.md +10 -3
  83. package/claude/skills/review-address/references/rebase-conflicts.md +15 -7
  84. package/claude/skills/review-address/references/rest-reads.md +3 -1
  85. package/claude/skills/review-craft/references/adopted.md +35 -18
  86. package/claude/skills/review-craft/references/security.md +42 -7
  87. package/claude/skills/review-craft/references/ui.md +23 -8
  88. package/claude/skills/review-pr/SKILL.md +6 -6
  89. package/claude/skills/review-pr/references/body-variants.md +29 -9
  90. package/claude/skills/review-pr/references/close-out.md +20 -5
  91. package/claude/skills/review-pr/references/key-changes.md +27 -3
  92. package/claude/skills/review-pr/references/post.md +83 -31
  93. package/claude/skills/review-pr/references/scope.md +54 -19
  94. package/claude/skills/review-ui/references/close-out.md +7 -5
  95. package/claude/skills/review-ui/references/driving.md +24 -4
  96. package/claude/skills/review-ui/references/post.md +43 -15
  97. package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +67 -17
  98. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +80 -40
  99. package/claude/skills/role-orchestrator/references/orchestrator-handback.md +52 -15
  100. package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +48 -26
  101. package/claude/skills/role-orchestrator/references/orchestrator-inbound.md +12 -13
  102. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +72 -36
  103. package/claude/skills/role-orchestrator/references/orchestrator-output.md +12 -4
  104. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +64 -24
  105. package/claude/skills/role-orchestrator/references/orchestrator-poll.md +80 -26
  106. package/claude/skills/role-orchestrator/references/orchestrator-refill.md +41 -18
  107. package/claude/skills/role-orchestrator/references/orchestrator-resume.md +19 -7
  108. package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +22 -12
  109. package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +15 -6
  110. package/claude/skills/role-orchestrator/references/orchestrator-sweep.md +25 -7
  111. package/claude/skills/role-orchestrator/references/orchestrator-watch.md +34 -8
  112. package/claude/skills/role-orchestrator/scripts/poll.ts +16 -24
  113. package/claude/skills/role-worker/REQUIREMENT.md +1 -0
  114. package/claude/skills/role-worker/SKILL.md +8 -0
  115. package/claude/skills/search-craft/references/adopted.md +18 -6
  116. package/claude/skills/session-map/references/session.md +26 -7
  117. package/claude/skills/session-worktree/references/main-root-writes.md +25 -8
  118. package/claude/skills/systematic-debugging/references/adopted.md +30 -16
  119. package/claude/skills/target-check/references/domains.md +39 -11
  120. package/claude/skills/target-setup/references/detect.md +80 -65
  121. package/claude/skills/target-setup/references/indexes.md +8 -6
  122. package/claude/skills/task-board/references/board.md +86 -30
  123. package/claude/skills/task-board/references/decline.md +29 -13
  124. package/claude/skills/task-board/references/tasks-decline.md +12 -5
  125. package/claude/skills/task-board/references/tasks.md +65 -33
  126. package/claude/skills/task-complete/references/archive.md +41 -17
  127. package/claude/skills/task-complete/references/receipt-sweep.md +23 -9
  128. package/claude/skills/task-complete/references/unusable-baseline.md +10 -3
  129. package/claude/skills/teach-workspace/references/glossary.md +6 -2
  130. package/claude/skills/teach-workspace/references/lesson-build.md +44 -16
  131. package/claude/skills/teach-workspace/references/lesson-craft.md +12 -7
  132. package/claude/skills/teach-workspace/references/pedagogy.md +6 -3
  133. package/claude/skills/teach-workspace/references/promotion-fold.md +17 -11
  134. package/claude/skills/teach-workspace/references/promotion.md +31 -8
  135. package/claude/skills/teach-workspace/references/revisit.md +8 -2
  136. package/claude/skills/teach-workspace/references/teach.md +17 -9
  137. package/claude/skills/test-craft/references/adopted.md +48 -14
  138. package/claude/skills/test-craft/references/component.md +7 -4
  139. package/claude/skills/test-craft/references/e2e.md +25 -7
  140. package/claude/skills/test-craft/references/unit.md +3 -1
  141. package/claude/skills/test-first/references/adopted.md +12 -4
  142. package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
  143. package/claude/skills/ui-checklist/SKILL.md +1 -1
  144. package/claude/skills/video-craft/references/adopted.md +62 -18
  145. package/claude/skills/write-human/references/adopted.md +21 -8
  146. package/docs/workflow/parallel-features.md +1 -1
  147. package/docs/workflow/skill-map.md +1 -0
  148. package/package.json +1 -1
  149. package/src/claude/cases/workflow.ts +5 -0
  150. package/src/commands/pr.ts +142 -28
  151. package/src/markdown/scope.ts +144 -0
  152. package/src/pr/lift.ts +6 -3
  153. package/src/pr/review-state.ts +182 -0
  154. package/claude/skills/git-pr/references/evidence.md +0 -124
@@ -7,23 +7,29 @@ description: How teach-workspace's fold mode lands each page a teach promotion h
7
7
 
8
8
  The fold mode of `teach-workspace`, run from a branch in a worktree. The session reads this file when the invocation asks to fold confirmed promotions in.
9
9
 
10
- Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`, falling back to `latest` on an empty result, and read `.canon/tmp/handoff/teach-promotion/<slug>.md` at the main worktree root. `teach-workspace` writes it, one H2 per destination naming the path, with a source line under the heading and the page body in a fenced block below that. Read the body out of the fence rather than off the heading level, since a reference page carries headings of its own and only the fence separates them from the next destination. Stop when the file is absent, reporting `❌ No promotion handoff at .canon/tmp/handoff/teach-promotion/<slug>.md. Run the promotion step from the workspace first.`
10
+ ## Read the handoff
11
11
 
12
- Each block is a page an operator already confirmed a destination for, so this step lands it rather than judging it again. Write to the destination the heading names, at `pwd` rather than at the main root, since every destination here is a tracked file that commits with the branch:
12
+ Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`, falling back to `latest` on an empty result, and read `.canon/tmp/handoff/teach-promotion/<slug>.md` at the main worktree root.
13
13
 
14
- - A wiki page and a public doc arrive as a whole file. Write it as the block gives it, and stop with the block unfolded when the destination path already holds a file, since overwriting a page someone else wrote is not a fold.
15
- - A context entry is merged into rather than created. Fold the body into the sections it belongs under, and never add an entry the catalog does not already carry.
14
+ - `teach-workspace` writes it, one H2 per destination naming the path, a source line under the heading, and the page body fenced below that
15
+ - Read the body out of the fence rather than off the heading level, since a reference page carries headings of its own and only the fence separates them from the next destination
16
+ - Stop when the file is absent, reporting `❌ No promotion handoff at .canon/tmp/handoff/teach-promotion/<slug>.md. Run the promotion step from the workspace first.`
16
17
 
17
- Then delete the handoff file so a later run does not fold it twice, and regenerate the index of any folder that carries one.
18
+ ## Land each block
18
19
 
19
- Output one line per page landed:
20
+ Each block is a page an operator already confirmed a destination for, so this step lands it rather than judging it again. Write to the destination the heading names at `pwd` rather than the main root, since every destination is a tracked file that commits with the branch.
20
21
 
21
- `✅ Promoted: <destination path>`
22
+ - A wiki page and a public doc arrive as a whole file. Write it as the block gives it, and leave the block unfolded when the destination holds a file, since overwriting another's page is not a fold.
23
+ - A context entry is merged into rather than created. Fold the body into the sections it belongs under, and never add an entry the catalog does not already carry.
22
24
 
23
- Add a line naming the handoff when one was consumed:
25
+ Then delete the handoff file so a later run does not fold it twice, and regenerate the index of any folder that carries one.
24
26
 
25
- `🧹 Folded: .canon/tmp/handoff/teach-promotion/<slug>.md`
27
+ ## Output
26
28
 
27
- Report a block left unfolded rather than dropping it:
29
+ One line per page landed, one naming the handoff when one was consumed, and one per block left unfolded rather than dropped.
28
30
 
29
- `⚠ Skipped: <destination path> already exists. Merge by hand.`
31
+ ```plaintext
32
+ ✅ Promoted: <destination path>
33
+ 🧹 Folded: .canon/tmp/handoff/teach-promotion/<slug>.md
34
+ ⚠ Skipped: <destination path> already exists. Merge by hand.
35
+ ```
@@ -6,9 +6,11 @@ Which surface a durable page from a learning workspace belongs to, and what to d
6
6
 
7
7
  Only the durable half. A reference page under `reference/` and `GLOSSARY.md` carry no learner and are ordinary reference prose about a subject, so they sort under the routing test like anything else.
8
8
 
9
- A lesson is never promoted, at any age and on any request. It is generated markup written to be worked through once, it carries a quiz and a second person, and nothing downstream cites it. Promoting one puts ungated markup into a corpus every other page passed a gate to enter.
9
+ A lesson is never promoted, at any age and on any request. It is generated markup worked through once, carrying a quiz and a second person, and nothing downstream cites it.
10
10
 
11
- A reference page that reads like a lesson is a lesson wearing the wrong extension. Where a page under `reference/` carries a quiz, a second person, or an instruction to the learner, say so and propose rewriting it in place before promotion rather than promoting it and repairing it at the destination.
11
+ - Promoting one puts ungated markup into a corpus every other page passed a gate to enter
12
+ - A reference page carrying a quiz, a second person, or an instruction to the learner is a lesson wearing the wrong extension
13
+ - Say so, and propose rewriting that page in place before promotion rather than repairing it at the destination
12
14
 
13
15
  ## The routing test
14
16
 
@@ -31,9 +33,13 @@ The folder has two spellings and a project carries whichever its scaffold wrote:
31
33
 
32
34
  Read which one exists rather than composing either. A project carrying both keeps its pages at the root, so propose the root spelling and say the other folder is there.
33
35
 
36
+ ### Neither spelling
37
+
34
38
  A project carrying neither gets a refusal rather than a scaffold:
35
39
 
36
- `❌ No wiki folder. Run canon wiki init to create one, then promote again.`
40
+ ```plaintext
41
+ ❌ No wiki folder. Run canon wiki init to create one, then promote again.
42
+ ```
37
43
 
38
44
  Creating the folder as a side effect of promoting one page hands the project a surface it never chose, and the refusal is one command from resolved.
39
45
 
@@ -63,7 +69,11 @@ Still owed: <what the destination expects that the page does not carry yet>
63
69
 
64
70
  Then stop and let the operator strike, redirect, or confirm each block.
65
71
 
66
- Write nothing to a destination here. One skill owns the durable writes, and two skills editing one file at one step is the failure that rule exists against. Record each confirmed block in `.canon/tmp/handoff/teach-promotion/<slug>.md` at the main worktree root instead, appending when the file exists, with one H2 per destination naming its path, the source page beneath it, and the page body fenced:
72
+ ### Record the handoff
73
+
74
+ Write nothing to a destination here. One skill owns the durable writes, and two skills editing one file at one step is the failure that rule exists against.
75
+
76
+ Record each confirmed block in `.canon/tmp/handoff/teach-promotion/<slug>.md` at the main worktree root instead, appending when the file exists. Each destination takes one H2 naming its path, the source page beneath it, and the page body fenced:
67
77
 
68
78
  ````markdown
69
79
  ## <destination path>
@@ -75,13 +85,26 @@ Source: .canon/teach/<nn>-<topic>/reference/<slug>.md
75
85
  ```
76
86
  ````
77
87
 
78
- The body is fenced rather than written bare because a reference page carries headings of its own, and the reader splits this file on its H2 lines. An unfenced body turns every section heading in the page into a destination naming no path. Open the body fence with four backticks so a page carrying a fenced code block of its own still closes where it should, and widen both fences together if it carries a four-backtick fence.
79
-
80
88
  Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`. Fall back to `latest` on an empty result.
81
89
 
82
- The handoff is its own file rather than a shared one. The routed-facts file another skill writes is deleted by whichever pass folds it, so a second producer's unread work goes with it, and a sibling path costs the folding skill one more read and removes the interaction.
90
+ ### Why the fence
91
+
92
+ A reference page carries headings of its own, and the reader splits this file on its H2 lines. An unfenced body turns every section heading in the page into a destination naming no path.
93
+
94
+ - Open the body fence with four backticks, so a page carrying a fenced code block still closes where it should
95
+ - Widen both fences together if the page carries a four-backtick fence
96
+
97
+ ### Why a file of its own
98
+
99
+ The routed-facts file another skill writes is deleted by whichever pass folds it, so a second producer's unread work would go with it. A sibling path costs the folding skill one more read and removes the interaction.
100
+
101
+ ### Sending and reporting
102
+
103
+ An append is a whole-file operation, so send it as a heredoc, per the skill's Step 0. Then tell the operator that `/teach-workspace fold` folds the file in from a branch.
104
+
105
+ The proposal costs nothing tracked and runs anywhere. The page it describes is a tracked file, so the fold is a worktree operation and the workspace it came from is not.
83
106
 
84
- An append is a whole-file operation, so send it as a heredoc, per the skill's Step 0. Then tell the operator that `/teach-workspace fold` folds the file in from a branch. The proposal costs nothing tracked and runs anywhere, while the page it describes is a tracked file, so the fold is a worktree operation and the workspace it came from is not.
107
+ ### Output
85
108
 
86
109
  A promotion pass reports this shape in place of the skill's Output block, one line per page the operator confirmed and one naming the handoff:
87
110
 
@@ -15,8 +15,14 @@ Then write `## Revisit`, one bullet per item, in the shape `${CLAUDE_SKILL_DIR}/
15
15
  - **<what comes back up>**: due <YYYY-MM-DD>, rung <n>
16
16
  ```
17
17
 
18
- Take both the date and the rung from the `due` entry Step 1 already read, copying `hit` for an item the learner retrieved unaided and `miss` for one they did not, with the rung stepped the same way. Do not compute a date from the ladder. A session told to widen a gap still picks the number by judgment, which is the reason the verb reports both dates at all.
18
+ ## Where the date comes from
19
19
 
20
- An item the records have never scheduled has no `due` entry to copy from. Open it at rung 1, dated the day after this session, which is the ladder's floor and the one number this body states. Every later date for it comes from the verb.
20
+ Take both the date and the rung from the `due` entry Step 1 already read. Copy `hit` for an item the learner retrieved unaided and `miss` for one they did not, with the rung stepped the same way.
21
+
22
+ - Do not compute a date from the ladder. A session told to widen a gap still picks the number by judgment, which is why the verb reports both dates.
23
+ - An item never scheduled has no `due` entry. Open it at rung 1, dated the day after this session, the ladder's floor and the one number this body states.
24
+ - Every later date for that item comes from the verb
25
+
26
+ ## Writing the shape exactly
21
27
 
22
28
  An entry outside this shape schedules nothing and nothing reports that it was skipped, so write the shape exactly. A later record naming the same item supersedes an earlier entry, so revise a schedule by writing the new bullet rather than editing the record it was set in.
@@ -73,7 +73,10 @@ A workspace failing these is non-conforming even when it satisfies every shape r
73
73
  | `lessons/` | Numbered lessons, generated and disposable | Optional |
74
74
  | `assets/` | Files several lessons share, including the stylesheet | Optional |
75
75
 
76
- Only the markdown half answers to a conformance check: `MISSION.md`, `RESOURCES.md`, `GLOSSARY.md`, `NOTES.md`, the markdown under `reference/`, and `learning-records/`. A lesson is generated markup that nothing downstream cites, so this standard fixes its filename and its location and says nothing about what it contains. A rendered reference page is the same kind of output, rewritten from its markdown on every `nav` run.
76
+ Only the markdown half answers to a conformance check: `MISSION.md`, `RESOURCES.md`, `GLOSSARY.md`, `NOTES.md`, the markdown under `reference/`, and `learning-records/`.
77
+
78
+ - A lesson is generated markup nothing downstream cites, so this standard fixes its filename and location and nothing about its contents
79
+ - A rendered reference page is the same kind of output, rewritten from its markdown on every `nav` run
77
80
 
78
81
  ## Frontmatter
79
82
 
@@ -125,15 +128,18 @@ Write one bullet per item, in this shape and no other:
125
128
  - **<what comes back up>**: due <YYYY-MM-DD>, rung <n>
126
129
  ```
127
130
 
128
- The rung is where the item sits on the spacing ladder, and it travels in the record rather than being counted from how many records name the item, since a miss drops it back and a count only climbs. A later record naming the same item supersedes an earlier one, so revise the schedule by writing the new entry rather than editing the old record.
131
+ The rung is the item's place on the spacing ladder. It travels in the record rather than being counted from records naming the item, since a miss drops it back and a count only climbs.
129
132
 
130
- Take the date and the rung from what the surface driving the workspace reports rather than picking either. An entry outside this shape schedules nothing, and nothing reports that it was skipped.
133
+ - A later record naming the item supersedes an earlier one, so revise by writing a new entry rather than editing the old record
134
+ - Take the date and rung from what the driving surface reports. An entry outside this shape schedules nothing, silently.
131
135
 
132
136
  ## GLOSSARY.md
133
137
 
134
- Required in every workspace, holding one entry per term the subject defines. The glossary reference the `canon:teach-workspace` skill carries fixes what an entry looks like, how the file orders and groups them, and which terms it carries, so this standard states only that the file exists and sits at the workspace root. That reference ships with the plugin rather than installing here, because a promoted glossary keeps its shape wherever it lands and no project folder covers every destination. Say so and stop rather than working the shape from memory when the project has no plugin to read it from.
138
+ Required at the root of every workspace, one entry per term the subject defines. The glossary reference the `canon:teach-workspace` skill carries fixes the entry shape, order, grouping, and which terms it holds.
135
139
 
136
- Name the lesson or reference page a term first appears in as that reference requires. A workspace is the case it was written for, so a glossary here has a first appearance to name.
140
+ - That reference ships with the plugin rather than installing here, since a promoted glossary keeps its shape wherever it lands
141
+ - With no plugin to read it from, say so and stop rather than working the shape from memory
142
+ - Name the lesson or reference page a term first appears in, which a workspace always has
137
143
 
138
144
  ## RESOURCES.md
139
145
 
@@ -143,7 +149,7 @@ Splits what was read from what was found.
143
149
  - List under a leads heading any source found and not opened, and never cite one
144
150
  - Say which claims in the workspace rest on which source
145
151
 
146
- A source found and not read is listed as a lead because a link attached to a page nobody opened is worse than no link. Listing it still pays, since it stops a later session searching for what this one already surfaced.
152
+ An unread source is a lead because a link to a page nobody opened is worse than none. Listing it stops a later session searching again.
147
153
 
148
154
  ### Choosing sources
149
155
 
@@ -155,6 +161,8 @@ Rest each general claim on the highest rung that covers it:
155
161
 
156
162
  A subject nobody owns, such as a mathematical topic or a craft, has no first rung, so its list starts at the second and is not missing anything. Record a third-rung source with the claim it covers and why no higher rung does, since that reason is what a later session checks the choice against.
157
163
 
164
+ ### What never counts
165
+
158
166
  The learner's own projects and material specific to one employer or organization are never a source for a general claim. Either may appear in the workspace as a worked application labeled with whose it is, and neither stands in `RESOURCES.md` as proof of what the subject says.
159
167
 
160
168
  A source reachable only through a paywall or a summary stays a lead until it is opened. A review or summary of a book is a different source from the book, so list the summary as read on its own rung and the book as a lead.
@@ -170,9 +178,9 @@ A source reachable only through a paywall or a summary stays a lead until it is
170
178
  - **The mission with no test.** Success stated as understanding rather than as a task leaves nothing able to say the mission is finished.
171
179
  - **The lesson filed as reference.** A page written to be worked through once sits in `lessons/`, and putting it in `reference/` puts disposable output in the half that gets promoted.
172
180
  - **The record that counts errors.** A tally of how many were missed carries none of the misconception, which is the only part a later session can act on.
173
- - **The revisit note with no date.** A line naming what to come back to and not when is read by nothing and schedules nothing, so the next session picks from the last record alone, which is the state the section exists to end.
174
- - **The date left in the body.** A frontmatter field and a sentence both claiming the opening date resolve to whichever a reader happens to hit, and only one of them is readable by a walker.
175
- - **The first search result as the source list.** A workspace resting on whatever a search returned first teaches the weakest account of the subject, and nothing in the folder says a stronger one was never looked for.
181
+ - **The revisit note with no date.** A line naming what to come back to and not when schedules nothing, so the next session picks from the last record alone, the state the section exists to end.
182
+ - **The date left in the body.** A frontmatter field and a sentence both claiming the opening date resolve to whichever a reader hits, and a walker reads only one.
183
+ - **The first search result as the source list.** A workspace resting on the first search hit teaches the weakest account of the subject, and nothing in the folder says a stronger one went unsought.
176
184
  - **The renumbered folder.** Closing a gap in the ordinals moves every name a reader or a record already cited.
177
185
 
178
186
  ## Template
@@ -11,36 +11,70 @@ External sources were read and filtered rather than imported. This file is the r
11
11
 
12
12
  ### Choosing the layer
13
13
 
14
- **The smallest-layer rule.** Fowler: "Push your tests as far down the test pyramid as you can", and write a lower test when a higher one catches what no lower one did ([Practical Test Pyramid](https://martinfowler.com/articles/practical-test-pyramid.html)). It is the body's layer rule and the reason for the decision table.
14
+ Three sources settle which layer a test belongs at and how the decision table reads.
15
15
 
16
- **Sizing by what a test touches.** Google's small, medium, and large sizes name what a test may touch rather than what it covers ([Software Engineering at Google, ch. 11](https://abseil.io/resources/swe-book/html/ch11.html)). The decision table reads the same way, keyed on what the behavior touches, so it transfers across stacks without naming a runner. The scope names unit, component, and end to end stay as the labels, since those are the names a reader and a file suffix already use.
16
+ | Adopted | Source |
17
+ | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
18
+ | The smallest-layer rule | Fowler, "push your tests as far down the test pyramid as you can" ([Practical Test Pyramid](https://martinfowler.com/articles/practical-test-pyramid.html)) |
19
+ | Sizing by what a test touches | Google's small, medium, and large sizes ([Software Engineering at Google, ch. 11](https://abseil.io/resources/swe-book/html/ch11.html)) |
20
+ | The component layer carrying UI weight | Kent C. Dodds's trophy ([Write tests](https://kentcdodds.com/blog/write-tests)) and Testing Library's [guiding principles](https://testing-library.com/docs/guiding-principles) |
17
21
 
18
- **The component layer carrying UI weight.** Kent C. Dodds's trophy ([Write tests](https://kentcdodds.com/blog/write-tests)) and Testing Library's principle that tests resembling use give more confidence ([guiding principles](https://testing-library.com/docs/guiding-principles)). The pyramid and the trophy are one rule applied to different code: a component's logic is its rendered behavior, so its lowest layer is a rendered test.
22
+ - Fowler writes a lower test when a higher one catches what no lower one did. It is the body's layer rule and the decision table's reason.
23
+ - Google's sizes name what a test may touch rather than cover. The table keys on the same, so it transfers across stacks without naming a runner.
24
+ - Testing Library holds that tests resembling use give more confidence
25
+
26
+ The scope names unit, component, and end to end stay as the labels, since a reader and a file suffix already use them. The pyramid and the trophy are one rule applied to different code, since a component's logic is its rendered behavior and its lowest layer is a rendered test.
19
27
 
20
28
  ### Judging a test
21
29
 
22
- **The opening question and the final filter.** From `obra/superpowers@5bf4e78`, `skills/test-driven-development/writing-good-tests.md`: name the production change that makes a test fail and whether it is a bug or a decision, then cut mirror assertions, change detectors, assertions on mocks, framework tests, and run the mutation check. Adopted as the body's opening question and final filter, with the fixed pause added from the end to end incidents.
30
+ The opening question and final filter come from `obra/superpowers@5bf4e78`, `skills/test-driven-development/writing-good-tests.md`. It names the production change that makes a test fail and whether it is a bug or a decision.
31
+
32
+ - It then cuts mirror assertions, change detectors, assertions on mocks, and framework tests, and runs the mutation check
33
+ - Adopted as the body's opening question and final filter, with the fixed pause added from the end to end incidents
34
+
35
+ ### Doubles in preference order and DAMP over DRY
36
+
37
+ From `addyosmani/agent-skills@c004a74`, `skills/test-driven-development/SKILL.md`, which orders real, fake, stub, then mock, and prefers descriptive test bodies over shared helpers. Adopted in `unit.md`.
38
+
39
+ ### Kent Beck's desiderata
40
+
41
+ The twelve properties at [testdesiderata.com](https://testdesiderata.com/) trade against each other and serve as background. "Behavioral" and "structure-insensitive" together are the whole of "test behavior, not implementation", which is why the body states that pair as asserting through the public surface.
23
42
 
24
- **Doubles in preference order and DAMP over DRY.** From `addyosmani/agent-skills@c004a74`, `skills/test-driven-development/SKILL.md`: real, fake, stub, mock, and descriptive test bodies over shared helpers. Adopted in `unit.md`.
43
+ ### Excuses, red flags, and a closing checklist
25
44
 
26
- **Kent Beck's desiderata as background.** The twelve properties at [testdesiderata.com](https://testdesiderata.com/) trade against each other. "Behavioral" and "structure-insensitive" together are the whole of "test behavior, not implementation", which is why the body states that pair as asserting through the public surface.
45
+ From `addyosmani/agent-skills@2686b620`, [`docs/skill-anatomy.md`](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/docs/skill-anatomy.md): Common Rationalizations, Red Flags, and Verification. Adopted as the three closing sections every practice skill carries, with the final filter as the closing checklist.
27
46
 
28
- **Excuses, red flags, and a closing checklist.** From `addyosmani/agent-skills@2686b620`, [`docs/skill-anatomy.md`](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/docs/skill-anatomy.md): Common Rationalizations, Red Flags, and Verification. Adopted as the three closing sections every practice skill carries, with the final filter as the closing checklist. This reverses an earlier decline of the excuses table. That decline objected to arguments against imagined objections, so each row here rebuts an excuse this skill's requirement records a session acting on, such as extending the open end to end spec or adding a pause for a run that flakes under load.
47
+ This reverses an earlier decline of the excuses table, which objected to arguments against imagined objections. Each row here rebuts an excuse this skill's requirement records a session acting on, such as extending the open end to end spec or adding a pause for a run that flakes under load.
29
48
 
30
49
  ### Per layer
31
50
 
32
- **Component query and wait rules.** Role queries first, user events over synthetic ones, one assertion per wait, no side effects inside a wait ([Common mistakes](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library)). Adopted in `component.md` with the library names removed from the rules.
51
+ Each layer reference takes its rules from the tool's own guidance.
33
52
 
34
- **Web-first assertions, actionability, config-wide reduced motion, sharding.** From Playwright's own pages ([best practices](https://playwright.dev/docs/best-practices), [actionability](https://playwright.dev/docs/actionability), [TestOptions](https://playwright.dev/docs/api/class-testoptions)). Adopted in `e2e.md`, where the runner is named because the reference is the per-layer home for runner specifics.
53
+ | Reference | Adopted | Source |
54
+ | -------------- | ---------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
55
+ | `component.md` | Role queries first, user events over synthetic ones, one assertion per wait, no side effects inside a wait | [Common mistakes](https://kentcdodds.com/blog/common-mistakes-with-react-testing-library) |
56
+ | `e2e.md` | Web-first assertions, actionability, config-wide reduced motion, sharding | Playwright's [best practices](https://playwright.dev/docs/best-practices), [actionability](https://playwright.dev/docs/actionability), and [TestOptions](https://playwright.dev/docs/api/class-testoptions) |
57
+
58
+ `component.md` states its rules with the library names removed. `e2e.md` names the runner, since the reference is the per-layer home for runner specifics.
35
59
 
36
60
  ## Declined
37
61
 
38
- **A numeric mix.** Google targets roughly 80% unit, 15% integration, 5% end to end ([same chapter](https://abseil.io/resources/swe-book/html/ch11.html)). A ratio is a codebase-wide target that a session writing one test cannot act on, and web.dev's point that the shape "should fit your architecture" ([Pyramid or Crab](https://web.dev/articles/ta-strategies)) is what a motion-heavy static site needs. The body states the rule and the budget in words instead.
62
+ Each item below stays out of the skill for the reason given.
63
+
64
+ ### A numeric mix
65
+
66
+ Google targets roughly 80% unit, 15% integration, 5% end to end ([same chapter](https://abseil.io/resources/swe-book/html/ch11.html)). A ratio is a codebase-wide target a session writing one test cannot act on.
67
+
68
+ web.dev's point that the shape "should fit your architecture" ([Pyramid or Crab](https://web.dev/articles/ta-strategies)) is what a motion-heavy static site needs, so the body states the rule and the budget in words instead.
69
+
70
+ ### Delete the code written before its test
39
71
 
40
- **Delete the code written before its test.** `superpowers`'s test-driven skill tells a session to delete implementation written ahead of a failing test. Declined: this toolkit audits the order after the fact with its test-order verb and reports rather than destroys, since deleting working code punishes the session without restoring the evidence the red run would have given.
72
+ `superpowers`'s test-driven skill tells a session to delete implementation written ahead of a failing test. This toolkit audits the order after the fact with its test-order verb and reports rather than destroys, since deleting working code punishes the session without restoring the evidence the red run would have given.
41
73
 
42
- **An iron law.** Both external test-driven skills carry an "Iron Law" stated as absolute. Declined for tone: this toolkit states a rule once with its reason.
74
+ ### Other declines
43
75
 
44
- **One skill per layer.** A unit skill, a component skill, and an end to end skill each loaded on its own trigger. Declined because the layer has to be chosen before the right skill can load, so the choice ends up restated in all three or in a fourth skill that is this one.
76
+ The remaining three were declined on tone or on shape.
45
77
 
46
- **A standard in place of a skill.** The guidance is judgment applied while writing, loaded on intent. A standard governs an artifact a reader checks afterwards, and nobody checks a test file against a layer rule after the fact.
78
+ - **An iron law.** Both external test-driven skills carry an "Iron Law" stated as absolute. Declined for tone, since this toolkit states a rule once with its reason.
79
+ - **One skill per layer.** The layer has to be chosen before the right skill can load, so the choice ends up restated in all three or in a fourth skill that is this one.
80
+ - **A standard in place of a skill.** The guidance is judgment applied while writing, loaded on intent. Nobody checks a test file against a layer rule after the fact, which is what a standard governs.
@@ -5,7 +5,9 @@ description: Render with real children, query by role, drive with user events, w
5
5
 
6
6
  # Component tests
7
7
 
8
- Read this before writing the first test at the component layer. A component's logic is its rendered behavior, so the lowest layer that catches a break in a loading state, an interaction, or a validation message is a rendered component test rather than a browser run across the whole site. Kent C. Dodds's testing trophy makes this the widest band for UI code ([Write tests](https://kentcdodds.com/blog/write-tests)), on the principle Testing Library states: "The more your tests resemble the way your software is used, the more confidence they can give you" ([guiding principles](https://testing-library.com/docs/guiding-principles)).
8
+ Read this before writing the first test at the component layer. A component's logic is its rendered behavior, so the lowest layer catching a break in a loading state, an interaction, or a validation message is a rendered component test rather than a whole-site browser run.
9
+
10
+ Kent C. Dodds's testing trophy makes this the widest band for UI code ([Write tests](https://kentcdodds.com/blog/write-tests)), on the principle Testing Library states: "The more your tests resemble the way your software is used, the more confidence they can give you" ([guiding principles](https://testing-library.com/docs/guiding-principles)).
9
11
 
10
12
  ## What belongs here
11
13
 
@@ -36,7 +38,8 @@ Read this before writing the first test at the component layer. A component's lo
36
38
 
37
39
  A simulated DOM computes no layout, no scroll position, and no animation frame. When the behavior under test is one of those, move to a runner that renders the component in a real browser rather than promoting the test to end to end.
38
40
 
39
- - Vitest browser mode runs tests "in the browser natively", with Playwright or WebdriverIO as the provider, and lists React, Vue, Svelte, Angular, Lit, Preact, and Qwik. Astro is not on the list ([Vitest browser mode](https://vitest.dev/guide/browser/)). For a static site, test the client module that drives the behavior against a fixture DOM here.
40
- - Playwright component testing is stable in plain `@playwright/test` through a mount fixture, and "if your dev server can render it, Playwright can test it" ([Playwright component testing](https://playwright.dev/docs/test-components)). The experimental `-ct-*` packages were removed after 1.62.
41
+ - Vitest browser mode runs tests "in the browser natively" through Playwright or WebdriverIO, for React, Vue, Svelte, Angular, Lit, Preact, and Qwik ([Vitest browser mode](https://vitest.dev/guide/browser/))
42
+ - Astro is not on that list. For a static site, test the client module driving the behavior against a fixture DOM in Vitest browser mode.
43
+ - Playwright component testing is stable in plain `@playwright/test` through a mount fixture ([Playwright component testing](https://playwright.dev/docs/test-components)). The experimental `-ct-*` packages were removed after 1.62.
41
44
 
42
- Either runs in a real browser without navigating the whole site, which keeps the test at the component's cost while observing what only a browser computes.
45
+ Playwright's own claim is that "if your dev server can render it, Playwright can test it". Either runs in a real browser without navigating the whole site, which keeps the test at the component's cost while observing what only a browser computes.
@@ -11,9 +11,9 @@ Read the settle, guard, and run-scope rules in the project's end to end reliabil
11
11
 
12
12
  ## What earns a browser run
13
13
 
14
- - A journey a user cannot lose without the product failing, crossing more than one route: sign up, check out, publish ([Practical Test Pyramid](https://martinfowler.com/articles/practical-test-pyramid.html)).
14
+ - A journey across routes a user cannot lose without the product failing, such as sign up or check out ([Practical Test Pyramid](https://martinfowler.com/articles/practical-test-pyramid.html)).
15
15
  - Behavior only a real browser computes across the whole page: layout at a breakpoint, scroll position, focus crossing a route, motion.
16
- - Not a state a component test can reach. Loading, empty, and error states, a toggle, and a validation message belong one layer down, even when the component sits on a page with other end to end coverage.
16
+ - Not a state a component test can reach. Loading, empty, and error states, a toggle, and a validation message belong one layer down, even on a page with other end to end coverage.
17
17
  - Not copy. Asserting exact wording in a browser run makes every copy edit a failure across every engine the gate runs.
18
18
 
19
19
  Suites dominated by end to end tests inflate both runtime and flake ([Google Testing Blog, 2015](https://testing.googleblog.com/2015/04/just-say-no-to-more-end-to-end-tests.html)). Nothing fixes a count ceiling, and the right shape depends on the architecture ([Pyramid or Crab](https://web.dev/articles/ta-strategies)). A site whose behavior is mostly layout and motion carries more browser tests than a form-heavy app, and each one still has to earn its place.
@@ -21,24 +21,42 @@ Suites dominated by end to end tests inflate both runtime and flake ([Google Tes
21
21
  ## Settle on conditions
22
22
 
23
23
  - Assert with a web-first assertion that retries until the condition holds. A manual visibility check reads once and does not retry ([best practices](https://playwright.dev/docs/best-practices)).
24
- - Lean on actionability for clicks and fills. An element counts as stable once it "has maintained the same bounding box for at least two consecutive animation frames", so an action waits out an animation on its own ([actionability](https://playwright.dev/docs/actionability)). A read does not wait, so poll it.
24
+ - Lean on actionability for clicks and fills, which wait out an animation on their own ([actionability](https://playwright.dev/docs/actionability)). A read does not wait, so poll it.
25
25
  - Never pause for a fixed duration to stand in for a condition. Reserve a fixed window for asserting that nothing happened across it.
26
26
  - Settle a smooth scroll on the `scrollend` event. Fall back to a stillness window only when the target was already in view.
27
27
 
28
+ An element counts as stable once it "has maintained the same bounding box for at least two consecutive animation frames", which is why an action needs no wait of its own.
29
+
28
30
  ## Motion off by default
29
31
 
30
32
  - Run with motion reduced unless the test asserts motion, and opt back in per test with `page.emulateMedia({ reducedMotion: 'no-preference' })`.
31
- - Set it once in the config's `use` block as `contextOptions: { reducedMotion: 'reduce' }` rather than per test, since the option defaults to `'no-preference'` ([BrowserContext options](https://playwright.dev/docs/api/class-browser#browser-new-context)). A top-level `use.reducedMotion` reaches no page and type-checks nowhere, so a spec asserting the media query is what catches it. A site honoring the reduced preference then has nothing to wait out in any test that does not opt back in.
33
+ - Set it once in the config's `use` block as `contextOptions: { reducedMotion: 'reduce' }`, since the option defaults to `'no-preference'` ([BrowserContext options](https://playwright.dev/docs/api/class-browser#browser-new-context)).
34
+ - A top-level `use.reducedMotion` reaches no page and type-checks nowhere, so a spec asserting the media query is what catches it
35
+
36
+ A site honoring the reduced preference then has nothing to wait out in any test that does not opt back in.
32
37
 
33
38
  ## Isolation and speed
34
39
 
35
40
  - Give every test its own state: a fresh context, its own account or seed, nothing left behind for the next test.
36
- - Speed a slow suite with parallel workers and sharding across machines rather than by cutting waits ([best practices](https://playwright.dev/docs/best-practices)). A suite that fails once workers rise carries timing-sensitive assertions, and those are the tests to move down a layer.
41
+ - Speed a slow suite with parallel workers and sharding rather than by cutting waits ([best practices](https://playwright.dev/docs/best-practices)).
42
+ - A suite that fails once workers rise carries timing-sensitive assertions, and those are the tests to move down a layer
37
43
  - Capture a trace on the first retry rather than a video on every run ([best practices](https://playwright.dev/docs/best-practices)).
38
44
  - Count the cost before adding a test: its runtime, times every engine in the matrix, times every push. That product is what the gate charges each later change.
39
45
 
40
46
  ## Two worked failures
41
47
 
42
- **A copy assertion in a browser run.** A portfolio site's home spec asserted the exact wording of its about section. A one-line copy edit then failed three engines in continuous integration, and the deploy waited on it. The production change that broke the test was a decision rather than a bug, which makes the assertion a change detector. The copy belonged in a unit test beside the module that holds it, and the browser run needed at most the section's presence.
48
+ Both failures were fixed by moving the assertion down a layer rather than by tuning the browser run.
49
+
50
+ ### A copy assertion in a browser run
51
+
52
+ A portfolio site's home spec asserted the exact wording of its about section. A one-line copy edit then failed three engines in continuous integration, and the deploy waited on it.
53
+
54
+ - The breaking change was a decision rather than a bug, which makes the assertion a change detector
55
+ - The copy belonged in a unit test beside the module holding it, and the browser run needed at most the section's presence
56
+
57
+ ### A settle that narrowed a failure without removing it
58
+
59
+ A focus-ring spec replaced a fixed pause with a condition wait on a scripted focus read. The next trunk push still failed one engine on every attempt with the condition timing out, and flaked a second test in the file, which skipped the deploy.
43
60
 
44
- **A settle that narrowed a failure without removing it.** A focus-ring spec waited on a scripted focus read with a condition wait, replacing a fixed pause. The next push to the trunk still failed one engine on every attempt with the condition timing out, and flaked a second test in the same file, which skipped the deploy. The settle was correct and the layer was wrong: an assertion whose result depends on how loaded the CI machine is keeps failing at the layer where load decides it. Moving the focus behavior to a real-browser component test takes it off the whole-site run.
61
+ - The settle was correct and the layer was wrong. An assertion whose result depends on how loaded the CI machine is keeps failing at the layer where load decides it.
62
+ - Moving the focus behavior to a real-browser component test takes it off the whole-site run
@@ -5,7 +5,9 @@ description: Doubles in preference order, descriptive over shared setup, table-d
5
5
 
6
6
  # Unit and integration tests
7
7
 
8
- Read this before writing the first test at the unit or integration layer. A unit test runs in one process with no network, no sleep, and no real I/O. An integration test may touch the local machine, such as a temporary directory or a local database, and nothing beyond it. Google's size vocabulary draws the same line by what a test may touch rather than what it covers ([Software Engineering at Google, ch. 11](https://abseil.io/resources/swe-book/html/ch11.html)).
8
+ Read this before writing the first test at the unit or integration layer. A unit test runs in one process with no network, no sleep, and no real I/O.
9
+
10
+ An integration test may touch the local machine, such as a temporary directory or a local database, and nothing beyond it. Google's size vocabulary draws the same line by what a test may touch rather than what it covers ([Software Engineering at Google, ch. 11](https://abseil.io/resources/swe-book/html/ch11.html)).
9
11
 
10
12
  ## Doubles
11
13
 
@@ -9,13 +9,21 @@ The loop predates this ledger, so this file records the sources it matches rathe
9
9
 
10
10
  ## Adopted
11
11
 
12
- **The loop itself.** Kent Beck's [Canon TDD](https://newsletter.kentbeck.com/p/canon-tdd) states it as turning one item into "an actual, concrete, runnable test", changing the code "to make the test (& all previous tests) pass", then refactoring. Adopted as steps 2, 4, 5, and 6, with the whole suite run after the pass rather than the new test alone.
12
+ ### The loop itself
13
13
 
14
- **Making it pass without designing.** The same post warns against "mixing refactoring into making the test pass", and keeps implementation design decisions for the refactor. Adopted as step 4's smallest change and step 6's cleanup of the shortcuts that change left.
14
+ Kent Beck's [Canon TDD](https://newsletter.kentbeck.com/p/canon-tdd) states it as turning one item into "an actual, concrete, runnable test", changing the code "to make the test (& all previous tests) pass", then refactoring. Adopted as steps 2, 4, 5, and 6, with the whole suite run after the pass rather than the new test alone.
15
15
 
16
- **Never faking the pass.** The same post lists deleting assertions "so the test pretends to pass" and "copying actual, computed values & pasting them into the expected values" as mistakes. Adopted as step 5's rule that a pass must be the one the test was written to prove.
16
+ ### Making it pass without designing
17
17
 
18
- **Refactoring is a step, not an option.** Martin Fowler's [TestDrivenDevelopment](https://martinfowler.com/bliki/TestDrivenDevelopment.html) names "neglecting the third step" as the most common way to get the practice wrong. Adopted as step 6 being mandatory where Canon TDD writes "optionally refactor".
18
+ The same post warns against "mixing refactoring into making the test pass", and keeps implementation design decisions for the refactor. Adopted as step 4's smallest change and step 6's cleanup of the shortcuts that change left.
19
+
20
+ ### Never faking the pass
21
+
22
+ The same post lists deleting assertions "so the test pretends to pass" and "copying actual, computed values & pasting them into the expected values" as mistakes. Adopted as step 5's rule that a pass must be the one the test was written to prove.
23
+
24
+ ### Refactoring is a step, not an option
25
+
26
+ Martin Fowler's [TestDrivenDevelopment](https://martinfowler.com/bliki/TestDrivenDevelopment.html) names "neglecting the third step" as the most common way to get the practice wrong. Adopted as step 6 being mandatory where Canon TDD writes "optionally refactor".
19
27
 
20
28
  ## Declined
21
29
 
@@ -33,7 +33,7 @@ The automatable half has its own gap, and it is no longer this skill's to close
33
33
  - Try to assert a visual property programmatically
34
34
  - Repeat the full checklist in chat, which is what made it evaporate
35
35
  - Stage or commit the checklist, which is gitignored scratch
36
- - Talk to GitHub directly. Posting the checklist belongs to `git-pr`, the sole consumer of the handoff file
36
+ - Talk to GitHub directly. Posting the checklist belongs to `pr-evidence`, the sole consumer of the handoff file
37
37
  - Move the handoff path to match this skill's name, which strands a checklist an older binary wrote
38
38
 
39
39
  ## Guards
@@ -69,7 +69,7 @@ Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`. Fall
69
69
 
70
70
  When a checklist is produced, write it to `.canon/tmp/handoff/ui-checklist/<slug>.md` at the main worktree root, resolved the way `session-worktree` does, creating the directory if needed and always overwriting.
71
71
 
72
- - It is a handoff file rather than a deliverable. `git-pr` renders it into the evidence comment once a pull request opens, then removes it, and nothing here calls `gh`.
72
+ - It is a handoff file rather than a deliverable. `pr-evidence` renders it into the evidence comment once a pull request opens, then removes it, and nothing here calls `gh`.
73
73
  - The path names the artifact rather than this skill, so a rename moves nothing and an older binary's checklist lands where the consumer looks
74
74
  - The checklist is a main-root write, so it goes out as a heredoc, routed the way `session-worktree` states
75
75
  - Skip the write when there is nothing to verify visually and nothing shipping untested