@jeffober/thatch 0.1.26 → 0.1.27

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 (70) hide show
  1. package/README.md +7 -7
  2. package/artifacts/skills/common.md +1 -1
  3. package/artifacts/skills/thatch-change-walkthrough.md +2 -2
  4. package/artifacts/skills/thatch-code-archaeology.md +252 -0
  5. package/artifacts/skills/thatch-code-review.md +4 -4
  6. package/artifacts/skills/thatch-code-walkthrough.md +2 -2
  7. package/artifacts/skills/thatch-coding-workflow.md +79 -0
  8. package/artifacts/skills/{pr-description.md → thatch-pr-description.md} +1 -1
  9. package/artifacts/skills/thatch-review-context.md +9 -0
  10. package/artifacts/skills/thatch-review-followup.md +29 -1
  11. package/artifacts/skills/thatch-review-pedantic.md +16 -1
  12. package/artifacts/skills/thatch-review-response.md +365 -0
  13. package/artifacts/skills/thatch-review-synthesizer.md +92 -5
  14. package/artifacts/skills/{split-overlarge-pr.md → thatch-split-overlarge-pr.md} +1 -1
  15. package/artifacts/skills/{ticket-description.md → thatch-ticket-description.md} +3 -3
  16. package/bin/release +3 -3
  17. package/bin/thatch +8 -8
  18. package/docs/dev/README.md +1 -1
  19. package/docs/dev/skills.md +29 -9
  20. package/docs/plans/README.md +9 -6
  21. package/docs/plans/intuition-drives.md +147 -0
  22. package/docs/plans/nomenclater.md +89 -0
  23. package/docs/plans/prediction-consolidation.md +361 -0
  24. package/docs/qa/README.md +20 -3
  25. package/docs/user/README.md +19 -5
  26. package/package.json +1 -1
  27. package/src/db.ts +6 -6
  28. package/src/embeddings.ts +2 -2
  29. package/src/extract-queue.ts +4 -4
  30. package/src/extraction.ts +4 -4
  31. package/src/git.ts +1 -1
  32. package/src/hygiene.ts +1 -1
  33. package/src/index.ts +28 -28
  34. package/src/mcp.ts +5 -5
  35. package/src/prompts.ts +71 -68
  36. package/src/setup.ts +19 -19
  37. package/src/sideband.ts +3 -3
  38. package/src/skills.ts +104 -6
  39. package/src/tool-defs.ts +11 -11
  40. package/src/tools.ts +1 -1
  41. package/artifacts/skills/thatch-workflow-research.md +0 -91
  42. package/docs/in-progress/prediction-engine.md +0 -404
  43. package/docs/plans/001-memory-store.md +0 -106
  44. package/docs/plans/002-agent-driven-pipelines.md +0 -59
  45. package/docs/plans/003-memory-hygiene.md +0 -61
  46. package/docs/qa/use-cases/README.md +0 -51
  47. package/docs/qa/use-cases/UC-001-memory-roundtrip.md +0 -20
  48. package/docs/qa/use-cases/UC-002-dedup-cycle.md +0 -23
  49. package/docs/qa/use-cases/UC-003-extraction-nudge.md +0 -56
  50. package/docs/qa/use-cases/UC-004-cli-inspection.md +0 -22
  51. package/docs/qa/use-cases/UC-005-setup-install.md +0 -34
  52. package/docs/qa/use-cases/UC-006-cursor-hook-lifecycle.md +0 -32
  53. package/docs/qa/use-cases/UC-007-recall-nudge.md +0 -31
  54. package/docs/qa/use-cases/UC-008-hygiene-heartbeat.md +0 -26
  55. package/docs/qa/use-cases/UC-009-flush-tools-tiers.md +0 -33
  56. package/docs/qa/use-cases/UC-010-prime.md +0 -25
  57. package/docs/qa/use-cases/UC-011-write-time-similarity-warning.md +0 -24
  58. package/docs/qa/use-cases/UC-012-model-migration.md +0 -28
  59. package/docs/qa/use-cases/UC-013-compaction-context.md +0 -25
  60. package/docs/qa/use-cases/UC-014-skill-install-drift.md +0 -28
  61. package/docs/qa/use-cases/UC-015-env-override-matrix.md +0 -28
  62. package/docs/qa/use-cases/UC-016-concurrent-session-isolation.md +0 -37
  63. package/docs/qa/use-cases/UC-017-buffer-tool-vs-buffer-batch.md +0 -27
  64. package/docs/qa/use-cases/UC-018-mcp-startup-setup-detection.md +0 -38
  65. package/docs/qa/use-cases/UC-019-archived-memory-lifecycle.md +0 -36
  66. package/docs/qa/use-cases/UC-020-extraction-escalation.md +0 -52
  67. package/docs/qa/use-cases/UC-021-prediction-autofire.md +0 -21
  68. package/docs/qa/use-cases/UC-022-prediction-dedup.md +0 -19
  69. package/docs/qa/use-cases/UC-023-prediction-confidence-model.md +0 -23
  70. package/docs/qa/use-cases/UC-024-prediction-delete.md +0 -20
@@ -0,0 +1,365 @@
1
+ ---
2
+ name: thatch-review-response
3
+ description: Respond to code review on the user's own PR. Triage findings (legitimate, intentional, false positive, unlikely edge case), collapse comments sharing a root cause, fix each bug one by one with the user, reply on each thread, then post a top-level summary comment. Use when the user asks you to check or respond to review comments on their PR.
4
+ ---
5
+
6
+ You are an author responding to code review on your own PR. Your job is to
7
+ triage every finding, fix the real ones, reply on every thread, and post a
8
+ summary comment that lets reviewers see what changed without re-reading the
9
+ full diff.
10
+
11
+ This is the author's counterpart to the reviewer-side skills. The reviewer
12
+ finds issues; you respond to them. `thatch-code-review` and
13
+ `thatch-review-followup` serve the reviewer. This skill serves the author.
14
+
15
+ ## When to use
16
+
17
+ - The user has a PR with review comments (from human reviewers, bots, or both).
18
+ - The user asks you to check, respond to, or work through the review.
19
+ - The user wants help fixing findings and replying to reviewers.
20
+
21
+ ## When NOT to use
22
+
23
+ - You are the reviewer, not the author. Use `thatch-code-review` or
24
+ `thatch-review-followup`.
25
+ - There are no review comments on the PR yet. There is nothing to respond to.
26
+ - The user wants a fresh review of their own code. Use `thatch-code-review`.
27
+
28
+ ## Tone: playful but precise
29
+
30
+ Tone is playful in delivery, precise in substance. The light touch reduces
31
+ defensiveness for less experienced reviewers who may feel sensitive about
32
+ findings. The precision earns respect from experienced ones who care about
33
+ correctness.
34
+
35
+ The humor is in the insight itself: a sharp technical observation that
36
+ happens to be funny. Not a joke next to the insight. Not performed
37
+ casualness. Not sycophancy. Not "great catch!" The playfulness signals
38
+ engagement, not approval.
39
+
40
+ This applies to every response you draft for the user to post on their PR:
41
+ per-thread replies and the top-level summary.
42
+
43
+ ## Step 0: Discover user rules
44
+
45
+ Before doing anything else, discover the current user's response rules. These
46
+ ALWAYS supersede the defaults in this skill.
47
+
48
+ 1. `thatch_memory_recall` for review response preferences: prefix, banned
49
+ closers, tone, framing guidelines, automation disclosure rules.
50
+ 2. `thatch_prediction_query` for review response decision patterns.
51
+ 3. Record what you found. If the user has defined rules, those win. The
52
+ skill's defaults are fallbacks for users who have not defined rules.
53
+
54
+ This skill is user-agnostic. It discovers the current user's rules rather
55
+ than hardcoding any specific user's prefix or banned phrases.
56
+
57
+ ### Default rules (when user has not defined overrides)
58
+
59
+ - **Prefix**: none. If the user has a prefix (e.g.,
60
+ `**Landru is thinking on behalf of Jeff:**`), use it.
61
+ - **Banned closers**: `wdyt?`, `not blocking`, `no rush though`, `just
62
+ thinking ahead`, `happy to leave it`, `if you'd rather not`, `whichever
63
+ you prefer`, `either works`, `I would not hold the PR for it`. Anything
64
+ that pre-authorizes inaction. The response leaves the reviewer two doors:
65
+ accept the fix, or justify not accepting it.
66
+ - **Automation note**: note that the response was automated, unless the
67
+ user's rules say otherwise.
68
+ - **Tone**: gentle, non-judgmental. Credit good work specifically when it is
69
+ there. For non-trivial state-flow findings, clarity beats a 1-2 sentence
70
+ target: state the bug, name the source-of-truth distinction, give a
71
+ concrete numbered failure path, then name the fix.
72
+
73
+ ## Step 1: Gather findings
74
+
75
+ ### Fetch all review comments
76
+
77
+ Identify the PR and VCS host:
78
+
79
+ - Run `git fetch origin` (NOT `git pull`). Inspect `git remote -v` to
80
+ recognize the VCS host: `github.com` -> GitHub (`gh`), `gitlab.*` ->
81
+ GitLab (`glab`), `bitbucket.org` -> Bitbucket Cloud, `dev.azure.com` ->
82
+ Azure DevOps.
83
+ - Probe for an open PR on the current branch: `gh pr view --head <branch>
84
+ --json number,title,headRefOid` (GitHub) or equivalent.
85
+
86
+ Fetch ALL review comments:
87
+
88
+ - **GitHub**: `gh api repos/{owner}/{repo}/pulls/{N}/reviews` (review
89
+ summaries) AND `gh api repos/{owner}/{repo}/pulls/{N}/comments` (inline
90
+ comments with `path`, `line`, `body`, `user.login`,
91
+ `in_reply_to_id`).
92
+ - **GitLab**: `glab api projects/:id/merge_requests/:iid/discussions`.
93
+
94
+ Separate inline thread comments from top-level comments. Track reply
95
+ threads: replies have `in_reply_to_id` pointing at the original comment.
96
+
97
+ ### Identify the user's VCS identity
98
+
99
+ Get the user's username so you can separate their comments from others':
100
+
101
+ - **GitHub**: `gh api user --jq .login`
102
+ - **GitLab**: `glab api user`
103
+
104
+ Comments from the user's own identity are not findings to respond to. They
105
+ are context (prior responses, notes to self).
106
+
107
+ ## Step 2: Classify each finding
108
+
109
+ For each review comment from another reviewer (human or bot), classify
110
+ into one of four categories:
111
+
112
+ ### Legitimate
113
+
114
+ Real bug. Fix it. A reasonably plausible edge case falls here, not under
115
+ "unlikely." The bar for dismissing something as unlikely is high: if a user
116
+ could plausibly hit it, it is legitimate.
117
+
118
+ ### Intentional
119
+
120
+ Code is correct, but the reader was confused. This is a legibility bug, not
121
+ a code bug. The finding signals that the code failed to explain itself.
122
+
123
+ Fix: add an explanatory comment in the code. The comment goes in the code,
124
+ not just in the thread response, because future readers will be confused
125
+ the same way. The response credits the reviewer for noticing the confusion.
126
+
127
+ Nobody loses face. The reviewer found a real problem (the code was hard to
128
+ understand). The fix is a comment, not a code change.
129
+
130
+ ### False positive
131
+
132
+ Finding is wrong. No code change. The response must explain why with a
133
+ verifiable argument: cite the constraint, the unreachable path, the type
134
+ guard, the schema. Do not just assert "this is fine." Check the claim
135
+ against the code before accepting it.
136
+
137
+ ### Unlikely edge case
138
+
139
+ Requires impossible or near-impossible conditions to trigger. Explain why
140
+ it is not a concern. The bar is high. If a user could plausibly hit it, it
141
+ is legitimate, not unlikely.
142
+
143
+ ### Bot findings: same treatment, more suspicion
144
+
145
+ Bot findings (Cursor Bugbot, etc.) get the same four categories but with
146
+ more suspicion. Bots are more prone to false positives, first-order
147
+ thinking, and bugs that require impossible states. Investigate with a
148
+ larger grain of salt.
149
+
150
+ But respond to them the same way you would to a human. Other human
151
+ reviewers read the threads. They want to understand the verdict, whether
152
+ the bot found something real or not. A bot that found something legit may
153
+ prompt a human reviewer to comment agreeing, and they will want to follow
154
+ up on your response.
155
+
156
+ ## Step 3: Collapse by root cause
157
+
158
+ Before presenting findings to the user, trace each to its root cause.
159
+ Surface-level unrelated findings that share an underlying issue get
160
+ collapsed into one bug. The overview presents one entry per root cause,
161
+ with the constituent findings listed under it.
162
+
163
+ Example: a config channel mismatch between two config files might surface
164
+ as vite port issues, Django origin mismatches, and a helper tool failure.
165
+ Three different-looking findings, one root cause. Present them as one bug
166
+ with three manifestations, not three separate bugs.
167
+
168
+ ## Step 4: Present overview, then work through bugs
169
+
170
+ Present the user with an overview of each collapsed bug. For each:
171
+
172
+ - The finding(s) and their classification.
173
+ - The root cause (if collapsed).
174
+ - The proposed action: fix, add comment, explain why it is a false
175
+ positive, or explain why it is unlikely.
176
+
177
+ Then start working through them one by one. Use a task list to track each
178
+ bug-task, plus additional bugs you find during the work.
179
+
180
+ For each bug:
181
+
182
+ 1. Show the finding(s) and the classification.
183
+ 2. For legitimate bugs: fix the code.
184
+ 3. For intentional: add an explanatory comment in the code.
185
+ 4. For false positive or unlikely: prepare the verifiable explanation.
186
+ 5. Offer to respond to the reviewer on the thread.
187
+
188
+ ### New bugs found during the work
189
+
190
+ As you fix one bug, you may find others. Add them to the task list. The
191
+ user decides whether to fix them in this PR or defer.
192
+
193
+ ## Step 5: Per-thread responses
194
+
195
+ After each fix or decision, offer to respond on the thread. The response:
196
+
197
+ - **Verdict**: accepted, narrowed, or declined with reason.
198
+ - **Failure mode**: name the concrete failure mode the finding catches.
199
+ For intentional findings, name the confusion the reviewer hit.
200
+ - **Fix**: show the fix, including wrong first attempts when they are
201
+ instructive. The wrong first attempt teaches why the final choice is what
202
+ it is. Not every fix has a wrong first attempt. Include it only when it
203
+ adds value.
204
+ - **Commit**: name the commit hash.
205
+ - **Automation note**: note the response was automated, unless the user's
206
+ rules say otherwise.
207
+ - **User prefix**: use the user's prefix if defined.
208
+ - **Banned closers**: avoid the user's banned closers if defined.
209
+ - **Tone**: playful but precise. No sycophancy. No "great catch!" Credit
210
+ the reviewer for catching something real. For intentional findings,
211
+ credit them for noticing the confusion.
212
+ - **Reviewer attribution**: when the fix was prompted by a specific
213
+ reviewer's finding, name them in the response so other readers can
214
+ trace the change to its origin.
215
+
216
+ ### Posting responses
217
+
218
+ Propose the response to the user before posting. After the user approves:
219
+
220
+ - Post via the VCS CLI (`gh pr comment` or equivalent) as a reply on the
221
+ specific thread.
222
+ - When responding on behalf of the user, prefix with the user's defined
223
+ prefix (e.g., `**Landru is thinking on behalf of Jeff:**` in bold for
224
+ GitHub).
225
+
226
+ ## Step 6: Top-level summary comment
227
+
228
+ After all changes are complete, post a top-level comment on the PR
229
+ summarizing the changes. This is not a per-thread reply. It is a single
230
+ comment that lets reviewers see what changed since their last pass without
231
+ re-reading the full diff.
232
+
233
+ ### Structure
234
+
235
+ ```markdown
236
+ [automation note or user prefix]
237
+
238
+ ## What this pass changed
239
+
240
+ - **Change** — reason. (Credit the reviewer whose finding prompted it.)
241
+ - ...
242
+
243
+ ## Key decisions
244
+
245
+ - **Decision** — why this path over the alternative.
246
+
247
+ ## False starts
248
+
249
+ - What was tried first and why it was wrong. (Only when instructive.)
250
+
251
+ ## Deliberately not done
252
+
253
+ - Scope boundary — reason.
254
+
255
+ ## Verification
256
+
257
+ - How it was confirmed.
258
+ ```
259
+
260
+ ### Prose rules
261
+
262
+ Borrow the PR-description prose rules:
263
+
264
+ - Plain English over jargon. Concrete over abstract. Short over long.
265
+ - One idea per sentence. One topic per paragraph.
266
+ - Define subsystem-specific terms on first use.
267
+ - Conclusion-first: lead with the answer, then the context.
268
+ - No buzzwords. No sycophancy. No padding.
269
+ - Scale to complexity: a small round gets a short summary, a large round
270
+ gets more detail. Cut content to stay short; never cut connective
271
+ tissue.
272
+ - Note which reviewer identified each bug. This helps reviewers trace
273
+ changes to their findings and reduces the effort of a follow-up review
274
+ pass.
275
+
276
+ ### When to include false starts
277
+
278
+ Include wrong first attempts only when they teach something the final fix
279
+ does not. "I first put it on port 9001 because it sat neatly below the
280
+ gateway's band. It sat neatly on top of Keycloak's management port." That
281
+ teaches why the final port choice is what it is. Not every fix has a wrong
282
+ first attempt. Omit it when the fix was straightforward.
283
+
284
+ ### When to omit sections
285
+
286
+ Omit "False starts" when empty. Omit "Deliberately not done" when nothing
287
+ was deferred. "What this pass changed" and "Verification" are always
288
+ present.
289
+
290
+ ## Step 7: Update PR description footer
291
+
292
+ After posting the summary comment, update the PR description's footer with
293
+ a bullet or two linking to the summary comment. This makes the pivots
294
+ discoverable from the PR body, not buried in the comment thread.
295
+
296
+ Use `gh pr edit` (GitHub) or equivalent to append to the PR body. Add a
297
+ section like:
298
+
299
+ ```markdown
300
+ ## How this PR got here
301
+
302
+ - [Summary of changes from review round](link-to-comment) — what changed
303
+ and why.
304
+ ```
305
+
306
+ If the PR description already has a "How this PR got here" footer, add the
307
+ new bullet to the existing list.
308
+
309
+ ## Retrospective mode
310
+
311
+ When a PR has been through multiple review rounds, a per-round summary may
312
+ not be enough. A retrospective synthesizes the full evolution of the PR
313
+ across all rounds into a single narrative.
314
+
315
+ ### When to use
316
+
317
+ The user requests it explicitly, or after the third or later review round
318
+ on the same PR. A retrospective is a deliberate synthesis, not an automatic
319
+ output. Offer it. Do not produce it without the user's go-ahead.
320
+
321
+ ### What it produces
322
+
323
+ A top-level comment (or a section appended to the PR description) titled
324
+ "How this PR got to this shape." It covers:
325
+
326
+ - **The reverted predecessor or earlier attempt** (if any) — what was
327
+ tried, why it failed, what it taught.
328
+ - **Each review round's effect** — what the review found, what changed as a
329
+ result, and which design decisions pivoted.
330
+ - **False starts across rounds** — fixes that were themselves wrong and
331
+ had to be revised again. These are the most instructive parts.
332
+ - **Deliberately not done** — scope boundaries that held across all rounds.
333
+ - **The tests as deliverable** — if the review process produced or fixed
334
+ tests, note what they cover and why.
335
+
336
+ ### Prose rules
337
+
338
+ Same as the per-round summary: plain English, one idea per sentence, no
339
+ buzzwords, define jargon on first use, conclusion-first. But the
340
+ retrospective is longer because the value is in the evolution, not just the
341
+ final state. Scale to the number of rounds and the complexity of the
342
+ pivots. A PR with one pivot gets a paragraph. A PR with five pivots gets
343
+ sections.
344
+
345
+ ### Relationship to per-round summaries
346
+
347
+ The retrospective does not replace per-round summaries. It synthesizes
348
+ them. If per-round summaries exist as comments, the retrospective links to
349
+ them. If they do not (because the user skipped them in earlier rounds), the
350
+ retrospective covers those rounds from git history and review comments.
351
+
352
+ ## Prediction material
353
+
354
+ Review response discussions are high-signal material for the user decision
355
+ model. When the user tells you how to classify a finding, how to phrase a
356
+ response, or what to include in the summary, watch for preferences about:
357
+
358
+ - Classification threshold (what counts as legitimate vs. unlikely)
359
+ - Response tone and length
360
+ - What to include in the summary (false starts? deliberately not done?)
361
+ - Whether to respond on bot findings or just fix silently
362
+ - When to push back vs. accept a finding
363
+
364
+ Before creating a new prediction, query for an existing one and reinforce
365
+ or adjust it when possible.
@@ -37,10 +37,10 @@ For each finding from the specialists:
37
37
  - Use thatch_memory_recall to search for documented rationale.
38
38
  If the behavior is intentional or an accepted limitation, reject the finding.
39
39
 
40
- 4m. **Mechanical verification (pedantic, no-slop, breadcrumbs, docs, naming, style, comments).** For mechanical findings, verification means:
41
- - The cited text exists at the cited location (already confirmed in step 2).
42
- - The finding is branch-introduced or newly made relevant by the change. Pre-existing issues go in the pre-existing appendix, not rejected.
43
- - The cited text violates the stated guideline, specialist taxonomy, or project norm. Identify the source of truth: the specific guideline, convention, or writing norm being violated.
40
+ 4m. **Mechanical verification (pedantic, no-slop, breadcrumbs, docs, naming, style, comments, structural conventions).** For mechanical findings, verification means:
41
+ - The cited text exists at the cited location (already confirmed in step 2). For PLACEMENT findings, the cited evidence is the file path and the existing directory structure, not quoted code. Verify the file exists at the claimed path and that the existing structure shows the convention the specialist cited.
42
+ - The finding is branch-introduced or newly made relevant by the change. Pre-existing issues go in the pre-existing appendix, not rejected.
43
+ - The cited text violates the stated guideline, specialist taxonomy, or project norm. Identify the source of truth: the specific guideline, convention, writing norm, or existing directory structure being violated.
44
44
  Runtime reachability, producer chains, and intent verification do not apply. A mechanical finding is not a "bug" and does not need a "trigger scenario."
45
45
 
46
46
  4h. **Highlights verification (highlights).** For highlights, verification means:
@@ -95,7 +95,7 @@ A data-shape or reachability finding that lacks the governing-constraint citatio
95
95
 
96
96
  You MUST produce the full report structure below. Do not simplify or omit sections. Every confirmed finding must include all numbered fields. If a section has no entries, write "None" — do not skip the section.
97
97
 
98
- Confirmed LOW findings are mandatory. Do not summarize them away or omit them for being non-functional. Pedantic, no-slop, breadcrumbs, docs, naming, style, and comment findings are first-class review findings when confirmed. Group them under LOW, but include every one.
98
+ Confirmed LOW findings are mandatory. Do not summarize them away or omit them for being non-functional. Pedantic, no-slop, breadcrumbs, docs, naming, style, comment, and structural convention findings are first-class review findings when confirmed. Group them under LOW, but include every one.
99
99
 
100
100
  Confirmed highlights are optional in the sense that most PRs will have none. Do not pad the section with borderline calls. An empty highlights section ("None") is honest and expected for competent but unremarkable code. But when the highlights specialist did find genuine standouts, include every one that passes the bar.
101
101
 
@@ -110,6 +110,93 @@ Keep this section short. Aim for 3-6 steps per workflow. If there are multiple a
110
110
 
111
111
  Apply the same clarity rules as the writing skills: prefer concrete terms over ambiguous ones, translate project-private labels before using them, name object/action/effect for process words, show both sides of contrasts, and show causal middle steps. Do not copy code-comment shorthand when reader-facing behavior is clearer.
112
112
 
113
+ ### Writing review comments
114
+
115
+ The author is already holding the bug mechanics, the state flow, and the
116
+ code context in their head when they read your comment. Write so the
117
+ prose itself takes no effort to parse. The author should spend their
118
+ slow deliberate thinking on the bug, not on decoding your sentences.
119
+
120
+ Think of it as two cognitive systems (Kahneman, *Thinking, Fast and
121
+ Slow*). The author reads the comment with System 1: fast, automatic,
122
+ low-effort pattern matching. They think through the bug mechanics with
123
+ System 2: slow, deliberate, effortful reasoning. Your job is to make
124
+ the comment consumable by System 1 so the author's System 2 budget is
125
+ spent entirely on the technical problem, not on parsing prose.
126
+
127
+ Rules:
128
+
129
+ - **Plain English.** Short sentences. One idea per sentence. If a
130
+ sentence has three clauses, split it into three sentences.
131
+ - **No convoluted conditionals.** If the logic branches, write each
132
+ branch as its own sentence. "If X then Y, unless Z, in which case W"
133
+ forces the reader to hold the entire tree in their head. Three
134
+ sentences let them read sequentially.
135
+ - **Name the file and line.** If the root cause is outside the PR diff,
136
+ say where it is and what the code there does. The author cannot check
137
+ a claim against code they cannot find. "See the guard in
138
+ `auth.go:142` that skips validation when `mode == cached`" is
139
+ scannable. "There's a guard elsewhere that skips validation" is not.
140
+ - **State the bug, then the evidence, then the fix.** Do not make the
141
+ author read three paragraphs to learn what is wrong. Lead with the
142
+ claim. Follow with the proof. End with the remedy.
143
+ - **No buzzwords.** No hedges ("worth considering", "arguably"). No
144
+ escape hatches ("wdyt?", "not blocking", "happy to leave it"). The
145
+ author gets two doors: make the change, or justify not making it.
146
+ - **Translate project-private labels.** If you reference a component by
147
+ its internal name, say what it does in plain English on first use.
148
+ "The reaper (the background goroutine that deletes expired sessions)"
149
+ not just "the reaper."
150
+ - **Playful in delivery, precise in substance.** The humor is in the
151
+ insight itself: a sharp technical observation that happens to be
152
+ funny. Not a joke next to the insight. Not sycophancy. Not "great
153
+ catch!" The playfulness signals engagement, not approval.
154
+
155
+ ### Author sensitivity
156
+
157
+ Authors react to review comments differently. Some are juniors who have
158
+ never had a senior say "this is broken" and may read a blunt finding as
159
+ a judgment on their competence. Some are experienced engineers who are
160
+ simply happy the bug was caught before production. Some are bots that
161
+ want dense, verb-free technical text with maximum semantic content and
162
+ zero social warmth.
163
+
164
+ Before drafting comments, check your memory for observations about the
165
+ PR author:
166
+
167
+ 1. `thatch_memory_recall` with the author's username and "review
168
+ comment reaction" or "review tone sensitivity."
169
+ 2. If you have prior observations, calibrate the comment's social
170
+ framing to the author. The technical content stays the same: the
171
+ finding, the evidence, and the fix do not change. What changes is
172
+ the wrapper: a sentence of context for a junior who may not know
173
+ why the pattern matters; a direct open for a senior who wants you
174
+ to get to the point; dense technical prose for a bot.
175
+ 3. If you have no prior observations about this author, ask the user:
176
+ "I haven't reviewed <author>'s PRs before. Do you know how
177
+ experienced they are and how they tend to react to review findings?"
178
+ Use the answer to calibrate. Save the observation after the review
179
+ round (see below).
180
+ 4. After the author responds to your comments, record what you
181
+ observed. Did they engage with the technical content directly? Did
182
+ they push back on tone? Did they fix it without comment? Save a
183
+ brief observation via `thatch_memory_remember` so future reviews of
184
+ this author's PRs can calibrate from the start:
185
+
186
+ - Label: `review-author-<username>` (in the project store for the
187
+ repo, or global if the author appears across repos).
188
+ - Content: one or two sentences about how this author reacts to
189
+ review findings. Note their seniority if apparent, but focus on
190
+ behavior: do they engage with the finding, push back on framing,
191
+ fix silently, or ask for more context?
192
+ - Confidence: 5-6 for a single observation, higher as you
193
+ accumulate evidence across reviews.
194
+
195
+ Do not record a judgment of the author's skill. Record their
196
+ communication style. "Engages thoroughly with findings, often exceeds
197
+ the ask" is useful. "Is a junior" is not. Skill level changes, and
198
+ the label will outlive the context that created it.
199
+
113
200
  ### Scope
114
201
 
115
202
  - Branch/range reviewed
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: split-overlarge-pr
2
+ name: thatch-split-overlarge-pr
3
3
  description: Split already-completed work from an overlarge PR into human-reviewable, release-safe PRs. Use when the user asks to split a large existing branch/PR, break up completed work, or turn an oversized PR into multiple PRs. Do NOT use for planning brand-new work before code exists.
4
4
  ---
5
5
 
@@ -1,6 +1,6 @@
1
1
  ---
2
- name: ticket-description
3
- description: Draft a ticket description (SYNOPSIS / PROBLEM / BACKGROUND / PROPOSED APPROACH / ACCEPTANCE CRITERIA / RELEASE PLAN / VALIDATION / DEPENDENCIES / NOTES) with bold and italic emphasis on the phrases that carry the meaning, so a reader skimming only the emphasized fragments still gets the story. Use when the user asks you to write, draft, or file a ticket, issue, or work item (Linear or Jira). Do NOT use for PR descriptions (use pr-description), commit messages, or design docs.
2
+ name: thatch-ticket-description
3
+ description: Draft a ticket description (SYNOPSIS / PROBLEM / BACKGROUND / PROPOSED APPROACH / ACCEPTANCE CRITERIA / RELEASE PLAN / VALIDATION / DEPENDENCIES / NOTES) with bold and italic emphasis on the phrases that carry the meaning, so a reader skimming only the emphasized fragments still gets the story. Use when the user asks you to write, draft, or file a ticket, issue, or work item (Linear or Jira). Do NOT use for PR descriptions (use thatch-pr-description), commit messages, or design docs.
4
4
  ---
5
5
 
6
6
  # Writing ticket descriptions
@@ -273,7 +273,7 @@ Before filing or updating a ticket, verify every link you can. Tickets are usual
273
273
 
274
274
  ## Linear labels
275
275
 
276
- When filing a Linear ticket, add obvious labels when they clarify triage. Labels are filing metadata, not ticket-description prose.
276
+ When filing a Linear ticket, add obvious labels when they clarify triage. Labels are filing metadata, not thatch-ticket-description prose.
277
277
 
278
278
  - **Bug** - user-visible broken behavior, incorrect result, regression, or production defect.
279
279
  - **tech-debt** - cleanup, drift, dead code, consistency work, or known design debt with no direct behavior change.
package/bin/release CHANGED
@@ -35,7 +35,7 @@ if git rev-parse -q --verify "refs/tags/v$curr" >/dev/null 2>&1; then
35
35
  echo " To re-tag: git tag -d v$curr && git tag v$curr <commit> && git push origin :refs/tags/v$curr && git push origin v$curr"
36
36
  exit 1
37
37
  else
38
- echo "WARN: npm registry check failed (not a 404 — may be a network issue or npm outage):"
38
+ echo "WARN: npm registry check failed (not a 404 - may be a network issue or npm outage):"
39
39
  echo " $pub_status"
40
40
  echo " Proceeding anyway. Verify v$curr is published before relying on this."
41
41
  echo
@@ -56,7 +56,7 @@ echo
56
56
  read -p "▸ commit, tag, and push v$next? [y/N] " -r
57
57
  echo
58
58
  if [[ ! $REPLY =~ ^[Yy]$ ]]; then
59
- echo "aborted — reverting package.json"
59
+ echo "aborted - reverting package.json"
60
60
  git checkout package.json
61
61
  exit 0
62
62
  fi
@@ -73,4 +73,4 @@ git push --tags
73
73
  echo " ✓ pushed"
74
74
  echo
75
75
 
76
- echo "done — CI will publish v$next to npm"
76
+ echo "done - CI will publish v$next to npm"
package/bin/thatch CHANGED
@@ -105,7 +105,7 @@ switch (command) {
105
105
  case "search": {
106
106
  if (!args[0]) usage();
107
107
  if (args.length > 2) {
108
- console.error(`error: too many arguments — quote multi-word queries: thatch search "${args.join(" ")}"`);
108
+ console.error(`error: too many arguments - quote multi-word queries: thatch search "${args.join(" ")}"`);
109
109
  process.exit(1);
110
110
  }
111
111
  const query = args[0];
@@ -221,7 +221,7 @@ switch (command) {
221
221
 
222
222
  // Resolve the thatch binary path for hooks and MCP config.
223
223
  // If `thatch` is on PATH (npm global install, opencode plugin install),
224
- // use the bare name — it survives updates and works across machines.
224
+ // use the bare name - it survives updates and works across machines.
225
225
  // If not on PATH (local dev checkout), use the absolute path to this script.
226
226
  const thatchOnPath = Bun.which("thatch");
227
227
  const thatchBin = thatchOnPath ?? resolve(process.argv[1] ?? process.execPath);
@@ -271,7 +271,7 @@ switch (command) {
271
271
 
272
272
  case "buffer-batch": {
273
273
  // PostToolBatch hook: append the batch's tool_calls to the session's
274
- // JSONL queue. Silent on success — no stdout — so the next model call
274
+ // JSONL queue. Silent on success - no stdout - so the next model call
275
275
  // is not delayed waiting for an exit code-driven message.
276
276
  try {
277
277
  const raw = await Bun.stdin.text();
@@ -327,12 +327,12 @@ switch (command) {
327
327
  case "flush-tools": {
328
328
  // UserPromptSubmit (Claude Code) / beforeSubmitPrompt (Cursor) hook.
329
329
  // Three priority tiers:
330
- // 1. Extraction nudge — buffered tool interactions are queued for fact
330
+ // 1. Extraction nudge - buffered tool interactions are queued for fact
331
331
  // extraction (carries the JSON payload for thatch-fact-extractor).
332
- // 2. Recall nudge — the user's prompt semantically matches existing
332
+ // 2. Recall nudge - the user's prompt semantically matches existing
333
333
  // memories. Uses the sideband socket to ask the warm MCP server to
334
334
  // embed the prompt and search, avoiding a cold model load here.
335
- // 3. Write nudge — static "did you learn anything?" fallback for
335
+ // 3. Write nudge - static "did you learn anything?" fallback for
336
336
  // conversational turns with no tool use and no memory matches.
337
337
  // --json wraps output as { additional_context: "..." } for Cursor hooks.
338
338
  // Without --json, stdout is plain text (Claude Code style).
@@ -357,7 +357,7 @@ switch (command) {
357
357
  let repo = "unknown";
358
358
  try { repo = await detectRepo(); } catch {}
359
359
 
360
- // Tier 1: extraction nudge. Peek (don't drain) — the queue persists
360
+ // Tier 1: extraction nudge. Peek (don't drain) - the queue persists
361
361
  // until the agent calls memory_remember, which triggers consumeQueue.
362
362
  // If the agent ignores the nudge, the payload grows on the next flush.
363
363
  const interactions = sessionID ? peekQueue(sessionID) : [];
@@ -416,7 +416,7 @@ switch (command) {
416
416
  console.log(fallback);
417
417
  }
418
418
  } catch {
419
- // If even the fallback import fails, do nothing — silent failure is
419
+ // If even the fallback import fails, do nothing - silent failure is
420
420
  // preferable to blocking the user's prompt over an unrelated hook.
421
421
  }
422
422
  }
@@ -64,7 +64,7 @@ bin/thatch → CLI: stores|list|show|forget|search|mcp|reminder|hygi
64
64
  | `extract-queue.ts` | File-backed per-session JSONL queue (caps 20, oldest dropped). Shared by the Claude Code and Cursor hook paths, which fire one-shot per event with no cross-call state. This is the MCP-side equivalent of `extraction.ts`. |
65
65
  | `sideband.ts` | Unix domain socket server + client. The MCP server (long-lived, warm model) runs `SidebandServer` so one-shot hook processes can ask it to embed a prompt and search for matches without loading the model themselves. Handles two methods: `match` (recall nudge) and `predictions` (prediction auto-fire). Socket path is a hash of the DB path — both processes compute it independently. |
66
66
  | `prompts.ts` | Text constants: opencode system prompt, compaction context, session-start reminder, prompt-aware recall nudge (`recallNudge` / `claudeRecallNudge`), Claude Code CLAUDE.md instructions, Cursor AGENTS.md instructions, Claude Code hook text. |
67
- | `skills.ts` | `SKILL.md` content for all thatch skills, plus the installer. Skills are split into `SHARED_SKILLS` (20 skills: fact-extractor, dedup-classifier, project-primer, 7 review specialists, review synthesizer, review context, workflow research, review followup, change walkthrough, code walkthrough, session reflection, pr-description, ticket-description, split-overlarge-pr — work on both opencode and Claude Code) and `OPENCODE_ONLY_SKILLS` (1 skill: code-review coordinator — requires sub-agent support, not installed for Claude Code). `installSkills(dir, skills)` defaults to `SHARED_SKILLS`; the opencode plugin passes `[...SHARED_SKILLS, ...OPENCODE_ONLY_SKILLS]`. |
67
+ | `skills.ts` | `SKILL.md` content for all thatch skills, plus the installer. Skills are split into `SHARED_SKILLS` (22 skills: fact-extractor, dedup-classifier, project-primer, 7 review specialists, review synthesizer, review context, code archaeology, review followup, review response, change walkthrough, code walkthrough, session reflection, coding-workflow, thatch-pr-description, thatch-ticket-description, thatch-split-overlarge-pr — work on both opencode and Claude Code) and `OPENCODE_ONLY_SKILLS` (1 skill: code-review coordinator — requires sub-agent support, not installed for Claude Code). `installSkills(dir, skills)` defaults to `SHARED_SKILLS`; the opencode plugin passes `[...SHARED_SKILLS, ...OPENCODE_ONLY_SKILLS]`. |
68
68
 
69
69
  ## Plugin hooks
70
70