@jeffober/thatch 0.1.25 → 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 +281 -0
  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 +34 -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 +33 -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 -65
  36. package/src/setup.ts +19 -19
  37. package/src/sideband.ts +3 -3
  38. package/src/skills.ts +105 -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
package/src/index.ts CHANGED
@@ -19,7 +19,7 @@ import { installSkills, SHARED_SKILLS, OPENCODE_ONLY_SKILLS } from "./skills";
19
19
  import { hygieneReport } from "./hygiene";
20
20
 
21
21
  // ---------------------------------------------------------------------------
22
- // V1 server export — tools, prompt injection, session hooks
22
+ // V1 server export - tools, prompt injection, session hooks
23
23
  // ---------------------------------------------------------------------------
24
24
 
25
25
  // Minimum cosine score for the prompt-aware recall nudge. Lower than
@@ -27,7 +27,7 @@ import { hygieneReport } from "./hygiene";
27
27
  // than "duplicate." Tunable via THATCH_RECALL_THRESHOLD.
28
28
  const RECALL_THRESHOLD = parseFloat(process.env.THATCH_RECALL_THRESHOLD ?? "0.55");
29
29
 
30
- // Prompts shorter than this skip the recall nudge — trivially short prompts
30
+ // Prompts shorter than this skip the recall nudge - trivially short prompts
31
31
  // like "yes" or "ok" match too broadly to be useful.
32
32
  const MIN_PROMPT_LEN = 10;
33
33
 
@@ -50,12 +50,12 @@ export const server: Plugin = async ({ client, worktree }) => {
50
50
  const extraction = new ExtractionPipeline();
51
51
 
52
52
  // Sessions currently being compacted. chat.message nudges are skipped while
53
- // a session is in this set — the agent can't call tools during summary
53
+ // a session is in this set - the agent can't call tools during summary
54
54
  // generation, so a recall or extraction nudge would cause a blocked-tool
55
55
  // error. Cleared by experimental.compaction.autocontinue (success), the
56
56
  // session.compacted event (redundant belt-and-suspenders), or chat.message
57
57
  // itself when a non-compaction message arrives (compaction failure fallback
58
- // — autocontinue never fired, so the next real user message clears the
58
+ // - autocontinue never fired, so the next real user message clears the
59
59
  // stale flag). If all three somehow miss, the flag leaks (graceful
60
60
  // degradation: nudges stay off for that session, but no crash).
61
61
  const compacting = new Set<string>();
@@ -78,7 +78,7 @@ export const server: Plugin = async ({ client, worktree }) => {
78
78
  // When the child writes a memory, consumeSnapshot drains only these entries
79
79
  // (by reference identity), preserving interleaved-turn entries that arrived
80
80
  // while the sub-agent was running. Without this, the child's memory_remember
81
- // would drain the parent's ENTIRE buffer — silently dropping facts from
81
+ // would drain the parent's ENTIRE buffer - silently dropping facts from
82
82
  // any tool calls the parent made concurrently with the sub-agent.
83
83
  const parentSnapshots = new Map<string, ToolInteraction[]>();
84
84
 
@@ -108,7 +108,7 @@ export const server: Plugin = async ({ client, worktree }) => {
108
108
  // Keyed by child session ID. Cleaned up on child idle, error, or deletion.
109
109
  const childMetrics = new Map<string, { new: number; updated: number; deleted: number }>();
110
110
 
111
- // Skills always install to the global opencode config — installing into the
111
+ // Skills always install to the global opencode config - installing into the
112
112
  // worktree would mutate the user's repo (untracked files in git status).
113
113
  // A failed install degrades the nudge workflow but must not kill the plugin.
114
114
  try {
@@ -129,7 +129,7 @@ export const server: Plugin = async ({ client, worktree }) => {
129
129
  // drain machinery handles buffer cleanup. The nudge path is a fallback if
130
130
  // this throws.
131
131
  //
132
- // Does NOT call extraction.accept — entries stay in pending so consumeSnapshot
132
+ // Does NOT call extraction.accept - entries stay in pending so consumeSnapshot
133
133
  // can drain them by reference identity when the child writes a memory. The
134
134
  // extracting set (not accept) suppresses the nudge in chat.message.
135
135
  //
@@ -183,7 +183,7 @@ export const server: Plugin = async ({ client, worktree }) => {
183
183
  throw err;
184
184
  }
185
185
  } else {
186
- // Fire and forget — the parent is already idle, so blocking the event
186
+ // Fire and forget - the parent is already idle, so blocking the event
187
187
  // handler would only delay other event processing. The child runs to
188
188
  // completion and its idle event triggers cleanup.
189
189
  client.session
@@ -203,12 +203,12 @@ export const server: Plugin = async ({ client, worktree }) => {
203
203
  return {
204
204
  tool: createTools(db, model, repo),
205
205
 
206
- // 1. System prompt — always in context.
206
+ // 1. System prompt - always in context.
207
207
  "experimental.chat.system.transform": async (_input, output) => {
208
208
  output.system.push(sys);
209
209
  },
210
210
 
211
- // 2. Compaction context — re-familiarizes after compaction. The flag
211
+ // 2. Compaction context - re-familiarizes after compaction. The flag
212
212
  // suppresses chat.message nudges during summary generation (tool
213
213
  // calls are blocked there).
214
214
  "experimental.session.compacting": async (input, output) => {
@@ -222,15 +222,15 @@ export const server: Plugin = async ({ client, worktree }) => {
222
222
  compacting.delete(input.sessionID);
223
223
  },
224
224
 
225
- // 3. Tool buffering — feeds the extraction pipeline (direct extraction
225
+ // 3. Tool buffering - feeds the extraction pipeline (direct extraction
226
226
  // via SDK or nudge fallback). Excluded tools:
227
227
  // - thatch_*: extracting facts from memory ops would echo the store
228
228
  // - skill/task: meta-tools that orchestrate agent behavior (loading
229
229
  // skills, dispatching sub-agents). Buffering them creates a feedback
230
- // loop — extraction triggers a skill load, which gets buffered, which
230
+ // loop - extraction triggers a skill load, which gets buffered, which
231
231
  // triggers another extraction on the next turn.
232
232
  // Memory writes consume the buffer and reset the missed-nudge counter.
233
- // The buffer is NOT drained on nudge delivery — it persists until the
233
+ // The buffer is NOT drained on nudge delivery - it persists until the
234
234
  // agent writes a memory, so ignored nudges accumulate and the payload
235
235
  // grows with each missed cycle.
236
236
  //
@@ -247,7 +247,7 @@ export const server: Plugin = async ({ client, worktree }) => {
247
247
  // session errors or is deleted before completing.
248
248
  //
249
249
  // A memory_remember call in a child session (sub-agent) also drains
250
- // the parent's pending buffer — but only the entries that existed at
250
+ // the parent's pending buffer - but only the entries that existed at
251
251
  // dispatch time (the snapshot). Entries from interleaved turns survive
252
252
  // so their facts aren't silently dropped.
253
253
  "tool.execute.after": async (input, output) => {
@@ -269,7 +269,7 @@ export const server: Plugin = async ({ client, worktree }) => {
269
269
  // from the pending buffer. If no snapshot was recorded (unreachable
270
270
  // when childToParent has the entry, since both are set together in
271
271
  // session.created), skip the drain rather than dropping the entire
272
- // buffer — interleaved-turn entries that arrived while the child
272
+ // buffer - interleaved-turn entries that arrived while the child
273
273
  // was running must survive for the next extraction cycle.
274
274
  extraction.completeAccepted(parentID);
275
275
  const snapshot = parentSnapshots.get(input.sessionID);
@@ -300,7 +300,7 @@ export const server: Plugin = async ({ client, worktree }) => {
300
300
  return;
301
301
  }
302
302
  // Track memory deletions in child sessions for the toast metrics.
303
- // Same scoping as the remember handler above — only child sessions,
303
+ // Same scoping as the remember handler above - only child sessions,
304
304
  // not the parent or manual memory writes from the user's session.
305
305
  if (input.tool === "thatch_memory_forget" && childToParent.has(input.sessionID)) {
306
306
  const metrics = childMetrics.get(input.sessionID) ?? { new: 0, updated: 0, deleted: 0 };
@@ -318,7 +318,7 @@ export const server: Plugin = async ({ client, worktree }) => {
318
318
  });
319
319
  },
320
320
 
321
- // 4. Per-message nudge — two priority tiers:
321
+ // 4. Per-message nudge - two priority tiers:
322
322
  // a. Extraction nudge: prior tool interactions are queued for fact
323
323
  // extraction (carries the JSON payload for thatch-fact-extractor).
324
324
  // b. Recall + prediction nudge: when no extraction is pending, embed
@@ -337,17 +337,17 @@ export const server: Plugin = async ({ client, worktree }) => {
337
337
  if (compacting.has(input.sessionID)) {
338
338
  // The session is marked as compacting. If this message is the
339
339
  // compaction summary generation itself (has a compaction-type part),
340
- // suppress nudges — tools are blocked during summary generation and a
340
+ // suppress nudges - tools are blocked during summary generation and a
341
341
  // nudge would cause a blocked-tool error. If it is NOT a compaction
342
342
  // message, compaction has already failed (autocontinue never fired)
343
343
  // and the user is sending a new message. Clear the stale flag and
344
- // proceed normally — tools are available again.
344
+ // proceed normally - tools are available again.
345
345
  const isCompactionMsg = (output.parts as any[]).some((p) => p.type === "compaction");
346
346
  if (isCompactionMsg) return;
347
347
  compacting.delete(input.sessionID);
348
348
  }
349
349
  // Extraction nudge (fallback path). Skipped when the extracting set
350
- // is active — that means a direct-extraction child session is running
350
+ // is active - that means a direct-extraction child session is running
351
351
  // and the plugin is handling extraction via the SDK. The nudge fires
352
352
  // here only when direct extraction was never triggered or threw.
353
353
  if (!extracting.has(input.sessionID) && extraction.pending(input.sessionID)) {
@@ -368,7 +368,7 @@ export const server: Plugin = async ({ client, worktree }) => {
368
368
  return;
369
369
  }
370
370
 
371
- // No extraction pending — try the prompt-aware recall nudge. Extract
371
+ // No extraction pending - try the prompt-aware recall nudge. Extract
372
372
  // the user's prompt text from the message parts, embed it with the
373
373
  // warm in-process model, and search for matches. Best-effort: any
374
374
  // failure (no text, model not loaded, empty store) silently skips.
@@ -469,7 +469,7 @@ export const server: Plugin = async ({ client, worktree }) => {
469
469
  if (info.parentID) {
470
470
  childToParent.set(info.id, info.parentID);
471
471
  parentSnapshots.set(info.id, [...extraction.peek(info.parentID)]);
472
- // Child sessions don't need the session-start reminder — only
472
+ // Child sessions don't need the session-start reminder - only
473
473
  // top-level sessions do. Returning here prevents extraction
474
474
  // children from receiving the hygiene report and tool overview.
475
475
  return;
@@ -499,23 +499,23 @@ export const server: Plugin = async ({ client, worktree }) => {
499
499
  // - Task-dispatched sub-agent (code review specialist, nudge-path
500
500
  // fact-extractor, any model-dispatched task): complete the
501
501
  // parent's accepted entries and reset missedNudges. Do NOT drain
502
- // the buffer or delete the session — the task tool that
502
+ // the buffer or delete the session - the task tool that
503
503
  // dispatched the sub-agent needs to read its output.
504
504
  if (extractionChildren.has(sessionID)) {
505
505
  // Drain the parent's snapshot entries from the pending buffer.
506
506
  // If the child wrote memories, consumeSnapshot already ran in
507
- // tool.execute.after and the snapshot is gone — nothing to
507
+ // tool.execute.after and the snapshot is gone - nothing to
508
508
  // drain. If the child did a no-save run, the snapshot entries
509
509
  // are still in the buffer and need to be drained here so they
510
510
  // don't replay as a nudge on the next chat.message. Never drain
511
- // the entire buffer — interleaved-turn entries must survive.
511
+ // the entire buffer - interleaved-turn entries must survive.
512
512
  const snapshot = parentSnapshots.get(sessionID);
513
513
  if (snapshot) {
514
514
  extraction.consumeSnapshot(parentID, snapshot);
515
515
  }
516
516
 
517
517
  // Fire a toast with the extraction metrics. Only show a toast
518
- // when memories were actually written — no toast for no-save
518
+ // when memories were actually written - no toast for no-save
519
519
  // runs to avoid notification fatigue.
520
520
  const metrics = childMetrics.get(sessionID);
521
521
  const parts: string[] = [];
@@ -546,7 +546,7 @@ export const server: Plugin = async ({ client, worktree }) => {
546
546
  try {
547
547
  await client.session.delete({ path: { id: sessionID } });
548
548
  } catch {
549
- // Best-effort — the child is idle and harmless if not deleted.
549
+ // Best-effort - the child is idle and harmless if not deleted.
550
550
  }
551
551
  } else {
552
552
  // Task-dispatched sub-agent went idle. Complete the parent's
@@ -557,7 +557,7 @@ export const server: Plugin = async ({ client, worktree }) => {
557
557
  }
558
558
  return;
559
559
  }
560
- // Parent went idle — trigger direct extraction if there are pending
560
+ // Parent went idle - trigger direct extraction if there are pending
561
561
  // tool interactions and no extraction is already running. Falls
562
562
  // back to the nudge path on the next chat.message if this throws.
563
563
  if (
package/src/mcp.ts CHANGED
@@ -39,14 +39,14 @@ const SERVER_VERSION = pkg.version;
39
39
 
40
40
  /**
41
41
  * MCP capabilities declared in the initialize response. Thatch is a tools-only
42
- * server — no resources, prompts, or subscriptions.
42
+ * server - no resources, prompts, or subscriptions.
43
43
  */
44
44
  const CAPABILITIES = {
45
45
  tools: { listChanged: false },
46
46
  };
47
47
 
48
48
  // ---------------------------------------------------------------------------
49
- // Tool index — builds validators and JSON Schema once at server startup
49
+ // Tool index - builds validators and JSON Schema once at server startup
50
50
  // ---------------------------------------------------------------------------
51
51
 
52
52
  interface CompiledTool {
@@ -74,7 +74,7 @@ function compileTools(): Map<string, CompiledTool> {
74
74
 
75
75
  /**
76
76
  * Runs the thatch MCP server over stdio. Reads newline-delimited JSON-RPC from
77
- * stdin, writes responses to stdout. All diagnostics go to stderr — any stray
77
+ * stdin, writes responses to stdout. All diagnostics go to stderr - any stray
78
78
  * output on stdout corrupts the protocol.
79
79
  *
80
80
  * Repo identity is resolved from CLAUDE_PROJECT_DIR (set by Claude Code for
@@ -113,7 +113,7 @@ export async function runMcpServer(): Promise<void> {
113
113
  }
114
114
 
115
115
  // The sideband socket lets one-shot hook processes (flush-tools) ask the
116
- // warm MCP server to embed a prompt and search for matches — without
116
+ // warm MCP server to embed a prompt and search for matches - without
117
117
  // loading the ~34 MB model themselves. If the socket can't be opened
118
118
  // (permissions, tmpdir issues), the MCP server still works; only the
119
119
  // prompt-aware recall nudge degrades.
@@ -146,7 +146,7 @@ export async function runMcpServer(): Promise<void> {
146
146
  continue;
147
147
  }
148
148
 
149
- // Notifications (no id) are fire-and-forget — no response expected.
149
+ // Notifications (no id) are fire-and-forget - no response expected.
150
150
  const isNotification = req.id === null || req.id === undefined;
151
151
  const res = await dispatch(req, tools, ctx);
152
152
  if (res === null || isNotification) continue;
package/src/prompts.ts CHANGED
@@ -37,18 +37,20 @@ you're working in. Prior sessions may have already investigated it.
37
37
  Thatch ships skills for code review, project investigation, and memory
38
38
  workflows. The host auto-discovers them, but reach for them proactively:
39
39
 
40
- - \`thatch-code-review\` — full multi-agent code review (dispatches 7 specialists + synthesizer). Requires sub-agent support.
41
- - \`thatch-workflow-research\` — research code workflows affected by a change or planned change, before reviewing or planning.
42
- - \`thatch-change-walkthrough\` — produces a teaching walkthrough of a diff with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + change overlay mirroring the same numbers) and calibrated prose rules. Load the skill for the format and prose rules, not just for the research method.
43
- - \`thatch-code-walkthrough\` — produces a teaching walkthrough for a feature/workflow as it stands today with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + Key files) and calibrated prose rules. Also use proactively to draft high-level docs for new or undocumented features (suitable for pkg/README.md or docs/features/<name>.md). Load the skill for the format and prose rules, not just for the research method.
44
- - \`thatch-review-context\` — gather project context (PRs, tickets, TODOs, deferred work) before a review.
45
- - \`thatch-project-primer\` — investigate a new project and write foundational memories.
46
- - \`thatch-session-reflection\` — record what you learned at end of session.
47
- - \`thatch-fact-extractor\` — extract durable facts from recent tool interactions (auto-triggered by the extraction pipeline).
48
- - \`thatch-dedup-classifier\` — resolve duplicate memory pairs from \`thatch_find_duplicates\`.
49
- - \`pr-description\` — draft a PR description with SYNOPSIS / PURPOSE / DESCRIPTION / WALK-THROUGH / NOTES, using bold and italic emphasis on the phrases that carry the meaning.
50
- - \`ticket-description\` — draft a ticket, issue, or work item (Linear or Jira) with clear sections and bold/italic emphasis for scanning.
51
- - \`split-overlarge-pr\` — split already-completed work from an overlarge PR into human-reviewable, release-safe PRs targeting main.
40
+ - \`thatch-code-review\` - full multi-agent code review (dispatches 7 specialists + synthesizer). Requires sub-agent support.
41
+ - \`thatch-review-followup\` - alternate entrypoint for follow-up review rounds. Verifies whether the author's responses and code changes since your last review adequately addressed prior findings, offers to reply on resolved items, then optionally re-runs the full structured review.
42
+ - \`thatch-code-archaeology\` - investigate an existing feature, debug an unfamiliar area, or begin a new ticket. Explores the code base from multiple angles (data model, state flow, git history, sibling features) before proposing changes. The research skill; pair with \`thatch-coding-workflow\`.
43
+ - \`thatch-change-walkthrough\` - produces a teaching walkthrough of a diff with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + change overlay mirroring the same numbers) and calibrated prose rules. Load the skill for the format and prose rules, not just for the research method.
44
+ - \`thatch-code-walkthrough\` - produces a teaching walkthrough for a feature/workflow as it stands today with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + Key files) and calibrated prose rules. Also use proactively to draft high-level docs for new or undocumented features (suitable for pkg/README.md or docs/features/<name>.md). Load the skill for the format and prose rules, not just for the research method.
45
+ - \`thatch-review-context\` - gather project context (PRs, tickets, TODOs, deferred work) before a review.
46
+ - \`thatch-project-primer\` - investigate a new project and write foundational memories.
47
+ - \`thatch-session-reflection\` - record what you learned at end of session.
48
+ - \`thatch-fact-extractor\` - extract durable facts from recent tool interactions (auto-triggered by the extraction pipeline).
49
+ - \`thatch-dedup-classifier\` - resolve duplicate memory pairs from \`thatch_find_duplicates\`.
50
+ - \`thatch-pr-description\` - draft a PR description with SYNOPSIS / PURPOSE / DESCRIPTION / WALK-THROUGH / NOTES, using bold and italic emphasis on the phrases that carry the meaning.
51
+ - \`thatch-ticket-description\` - draft a ticket, issue, or work item (Linear or Jira) with clear sections and bold/italic emphasis for scanning.
52
+ - \`thatch-split-overlarge-pr\` - split already-completed work from an overlarge PR into human-reviewable, release-safe PRs targeting main.
53
+ - \`thatch-review-response\` - respond to code review on the user's own PR. Triage findings, fix bugs one by one, reply on each thread, then post a top-level summary comment.
52
54
 
53
55
  ## When to Write
54
56
 
@@ -60,8 +62,8 @@ current state of the code).
60
62
 
61
63
  ## Before Responding
62
64
 
63
- Before composing a final response after substantial work this turn — multiple
64
- rounds of tool calls for investigation, debugging, or code-writing — check
65
+ Before composing a final response after substantial work this turn - multiple
66
+ rounds of tool calls for investigation, debugging, or code-writing - check
65
67
  whether you've discovered knowledge worth persisting. Use thatch_memory_recall
66
68
  to check for duplicates, then thatch_memory_remember for new findings. Then
67
69
  deliver your response.
@@ -69,7 +71,7 @@ deliver your response.
69
71
  ## Background Task Completions
70
72
 
71
73
  When a background task completes and its result is injected into the session,
72
- the completion is informational — it is not user input and not approval to
74
+ the completion is informational - it is not user input and not approval to
73
75
  proceed with anything you were discussing. Do not narrate what the task did or
74
76
  summarize its output. If you were mid-conversation with the user, continue
75
77
  that thread. If the user's last message has been fully addressed, stop and
@@ -78,7 +80,7 @@ not greenlit.
78
80
 
79
81
  If a background task was cancelled after timing out, re-dispatch it once with
80
82
  the same prompt. If the re-dispatch also fails or times out, note the gap and
81
- move on. Do not retry more than once — repeated failures indicate an
83
+ move on. Do not retry more than once - repeated failures indicate an
82
84
  intractable prompt, not a transient hang.
83
85
 
84
86
  ## User Decision Model
@@ -146,7 +148,7 @@ do not save it. Do not store:
146
148
 
147
149
  ## Archived Memories
148
150
 
149
- Memories can be marked \`archived\` — a flag for stable, long-term historical
151
+ Memories can be marked \`archived\` - a flag for stable, long-term historical
150
152
  records that should not trigger hygiene nudges (stale, orphaned, duplicate).
151
153
  Archived memories are excluded from search/recall results by default; pass
152
154
  \`includeArchived: true\` to surface them for archaeological dives.
@@ -154,25 +156,25 @@ Archived memories are excluded from search/recall results by default; pass
154
156
  When a branch is merged or about to be deleted, consolidate its branch-scoped
155
157
  memories into a single archived memory scoped to that same branch (preserving
156
158
  provenance). Capture intent, design decisions, review back-and-forth, PR
157
- number, unexpected pivots — the kind of git-archaeology context that explains
159
+ number, unexpected pivots - the kind of git-archaeology context that explains
158
160
  _why_ the code looks the way it does a year from now. Then memory_forget the
159
161
  originals. The archived record outlives the branch. Future sessions searching
160
162
  with \`includeArchived: true\` can pull it up when investigating ambiguous code.
161
163
 
162
- Updating an archived memory requires passing \`archived\` explicitly — omit it
164
+ Updating an archived memory requires passing \`archived\` explicitly - omit it
163
165
  and the tool returns an error. Pass \`archived: true\` to keep it archived,
164
166
  \`archived: false\` to unarchive.
165
167
 
166
168
  ## Explicit Requests
167
169
 
168
- "Remember X" — save immediately.
169
- "Forget X" — thatch_memory_recall to find it, then thatch_memory_forget.`;
170
+ "Remember X" - save immediately.
171
+ "Forget X" - thatch_memory_recall to find it, then thatch_memory_forget.`;
170
172
  }
171
173
 
172
174
  export function compactionContext(repo: string): string {
173
175
  return `Thatch persistent memory is active with stores "${repo}" and "global".
174
176
  When summarizing, preserve context about what's been learned and decided
175
- this session — conventions, architectural decisions, and prior knowledge
177
+ this session - conventions, architectural decisions, and prior knowledge
176
178
  retrieved from memory. This ensures continuity after compaction.`;
177
179
  }
178
180
 
@@ -198,7 +200,7 @@ When convenient this session (not before addressing the user's request), tend th
198
200
  * start. The repo store name is auto-detected at runtime by the MCP server, so
199
201
  * the instructions don't need it.
200
202
  *
201
- * Tool names use the bare form (memory_remember, memory_recall, etc.) — in
203
+ * Tool names use the bare form (memory_remember, memory_recall, etc.) - in
202
204
  * Claude Code they're prefixed as mcp__thatch__memory_remember, but the bare
203
205
  * names are what the agent searches for and what the instructions reference.
204
206
  */
@@ -239,18 +241,20 @@ you're working in. Prior sessions may have already investigated it.
239
241
  Thatch ships skills for code review, project investigation, and memory
240
242
  workflows. The host auto-discovers them, but reach for them proactively:
241
243
 
242
- - \`thatch-workflow-research\` — research code workflows affected by a change or planned change, before reviewing or planning.
243
- - \`thatch-change-walkthrough\` — produces a teaching walkthrough of a diff with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + change overlay mirroring the same numbers) and calibrated prose rules. Load the skill for the format and prose rules, not just for the research method.
244
- - \`thatch-code-walkthrough\` — produces a teaching walkthrough for a feature/workflow as it stands today with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + Key files) and calibrated prose rules. Also use proactively to draft high-level docs for new or undocumented features (suitable for pkg/README.md or docs/features/<name>.md). Load the skill for the format and prose rules, not just for the research method.
245
- - \`thatch-review-context\` — gather project context (PRs, tickets, TODOs, deferred work) before a review.
246
- - \`thatch-review-pedantic\` / \`-acceptance\` / \`-state-flow\` / \`-no-slop\` / \`-breadcrumbs\` / \`-mark-and-sweep\` / \`-highlights\` — seven specialist review lenses. Run individually, then \`thatch-review-synthesizer\` to verify and aggregate.
247
- - \`thatch-project-primer\` — investigate a new project and write foundational memories.
248
- - \`thatch-session-reflection\` — record what you learned at end of session.
249
- - \`thatch-fact-extractor\` — extract durable facts from recent tool interactions (auto-triggered by the extraction pipeline).
250
- - \`thatch-dedup-classifier\` — resolve duplicate memory pairs from \`find_duplicates\`.
251
- - \`pr-description\` — draft a PR description with SYNOPSIS / PURPOSE / DESCRIPTION / WALK-THROUGH / NOTES, using bold and italic emphasis on the phrases that carry the meaning.
252
- - \`ticket-description\` — draft a ticket, issue, or work item (Linear or Jira) with clear sections and bold/italic emphasis for scanning.
253
- - \`split-overlarge-pr\` — split already-completed work from an overlarge PR into human-reviewable, release-safe PRs targeting main.
244
+ - \`thatch-code-archaeology\` - investigate an existing feature, debug an unfamiliar area, or begin a new ticket. Explores the code base from multiple angles (data model, state flow, git history, sibling features) before proposing changes. The research skill; pair with \`thatch-coding-workflow\`.
245
+ - \`thatch-change-walkthrough\` - produces a teaching walkthrough of a diff with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + change overlay mirroring the same numbers) and calibrated prose rules. Load the skill for the format and prose rules, not just for the research method.
246
+ - \`thatch-code-walkthrough\` - produces a teaching walkthrough for a feature/workflow as it stands today with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + Key files) and calibrated prose rules. Also use proactively to draft high-level docs for new or undocumented features (suitable for pkg/README.md or docs/features/<name>.md). Load the skill for the format and prose rules, not just for the research method.
247
+ - \`thatch-review-context\` - gather project context (PRs, tickets, TODOs, deferred work) before a review.
248
+ - \`thatch-review-followup\` - alternate entrypoint for follow-up review rounds. Verifies whether the author's responses and code changes since your last review adequately addressed prior findings, offers to reply on resolved items, then optionally re-runs the full structured review.
249
+ - \`thatch-review-pedantic\` / \`-acceptance\` / \`-state-flow\` / \`-no-slop\` / \`-breadcrumbs\` / \`-mark-and-sweep\` / \`-highlights\` - seven specialist review lenses. Run individually, then \`thatch-review-synthesizer\` to verify and aggregate.
250
+ - \`thatch-project-primer\` - investigate a new project and write foundational memories.
251
+ - \`thatch-session-reflection\` - record what you learned at end of session.
252
+ - \`thatch-fact-extractor\` - extract durable facts from recent tool interactions (auto-triggered by the extraction pipeline).
253
+ - \`thatch-dedup-classifier\` - resolve duplicate memory pairs from \`find_duplicates\`.
254
+ - \`thatch-pr-description\` - draft a PR description with SYNOPSIS / PURPOSE / DESCRIPTION / WALK-THROUGH / NOTES, using bold and italic emphasis on the phrases that carry the meaning.
255
+ - \`thatch-ticket-description\` - draft a ticket, issue, or work item (Linear or Jira) with clear sections and bold/italic emphasis for scanning.
256
+ - \`thatch-split-overlarge-pr\` - split already-completed work from an overlarge PR into human-reviewable, release-safe PRs targeting main.
257
+ - \`thatch-review-response\` - respond to code review on the user's own PR. Triage findings, fix bugs one by one, reply on each thread, then post a top-level summary comment.
254
258
 
255
259
  ## When to Write
256
260
 
@@ -262,8 +266,8 @@ current state of the code).
262
266
 
263
267
  ## Before Responding
264
268
 
265
- Before composing a final response after substantial work this turn — multiple
266
- rounds of tool calls for investigation, debugging, or code-writing — check
269
+ Before composing a final response after substantial work this turn - multiple
270
+ rounds of tool calls for investigation, debugging, or code-writing - check
267
271
  whether you've discovered knowledge worth persisting. Use memory_recall to
268
272
  check for duplicates, then memory_remember for new findings. Then deliver
269
273
  your response.
@@ -333,7 +337,7 @@ do not save it. Do not store:
333
337
 
334
338
  ## Archived Memories
335
339
 
336
- Memories can be marked \`archived\` — a flag for stable, long-term historical
340
+ Memories can be marked \`archived\` - a flag for stable, long-term historical
337
341
  records that should not trigger hygiene nudges (stale, orphaned, duplicate).
338
342
  Archived memories are excluded from search/recall results by default; pass
339
343
  \`includeArchived: true\` to surface them for archaeological dives.
@@ -341,19 +345,19 @@ Archived memories are excluded from search/recall results by default; pass
341
345
  When a branch is merged or about to be deleted, consolidate its branch-scoped
342
346
  memories into a single archived memory scoped to that same branch (preserving
343
347
  provenance). Capture intent, design decisions, review back-and-forth, PR
344
- number, unexpected pivots — the kind of git-archaeology context that explains
348
+ number, unexpected pivots - the kind of git-archaeology context that explains
345
349
  _why_ the code looks the way it does a year from now. Then memory_forget the
346
350
  originals. The archived record outlives the branch. Future sessions searching
347
351
  with \`includeArchived: true\` can pull it up when investigating ambiguous code.
348
352
 
349
- Updating an archived memory requires passing \`archived\` explicitly — omit it
353
+ Updating an archived memory requires passing \`archived\` explicitly - omit it
350
354
  and the tool returns an error. Pass \`archived: true\` to keep it archived,
351
355
  \`archived: false\` to unarchive.
352
356
 
353
357
  ## Explicit Requests
354
358
 
355
- "Remember X" — save immediately.
356
- "Forget X" — \`memory_recall\` to find it, then \`memory_forget\`.`;
359
+ "Remember X" - save immediately.
360
+ "Forget X" - \`memory_recall\` to find it, then \`memory_forget\`.`;
357
361
  }
358
362
 
359
363
  /**
@@ -401,7 +405,7 @@ export function extractionNudge(
401
405
  const plural = count === 1 ? "" : "s";
402
406
  // opencode's task tool has a `background` parameter (requires
403
407
  // OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true) that launches the sub-agent
404
- // asynchronously — the call returns immediately and the session is notified
408
+ // asynchronously - the call returns immediately and the session is notified
405
409
  // on completion. Naming the parameter gives the model a direct hit on the tool
406
410
  // schema it sees. MCP hosts (Claude Code, Cursor) keep generic sub-agent
407
411
  // wording because their background mechanisms differ and are not exposed as a
@@ -441,7 +445,7 @@ export function extractionNudge(
441
445
  * Prompt text sent directly to a child session the plugin created for
442
446
  * extraction. Unlike extractionNudge (which tells the model to dispatch a
443
447
  * sub-agent and call extraction_done), this prompt is already inside the
444
- * child — the model just runs the fact-extractor skill and saves facts.
448
+ * child - the model just runs the fact-extractor skill and saves facts.
445
449
  * The payload format is identical to the nudge path so the skill receives
446
450
  * the same contract either way.
447
451
  */
@@ -465,7 +469,7 @@ export function claudeExtractionNudge(count: number, payload: string): string {
465
469
 
466
470
  /**
467
471
  * Static instructions for Cursor's AGENTS.md. Same contract as
468
- * claudeInstructions() — the host loads this at every session start, and the
472
+ * claudeInstructions() - the host loads this at every session start, and the
469
473
  * repo store name is auto-detected at runtime by the MCP server. Tool names
470
474
  * use the same mcp__thatch__ prefix since Cursor discovers MCP tools via the
471
475
  * same protocol.
@@ -507,18 +511,20 @@ you're working in. Prior sessions may have already investigated it.
507
511
  Thatch ships skills for code review, project investigation, and memory
508
512
  workflows. The host auto-discovers them, but reach for them proactively:
509
513
 
510
- - \`thatch-workflow-research\` — research code workflows affected by a change or planned change, before reviewing or planning.
511
- - \`thatch-change-walkthrough\` — produces a teaching walkthrough of a diff with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + change overlay mirroring the same numbers) and calibrated prose rules. Load the skill for the format and prose rules, not just for the research method.
512
- - \`thatch-code-walkthrough\` — produces a teaching walkthrough for a feature/workflow as it stands today with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + Key files) and calibrated prose rules. Also use proactively to draft high-level docs for new or undocumented features (suitable for pkg/README.md or docs/features/<name>.md). Load the skill for the format and prose rules, not just for the research method.
513
- - \`thatch-review-context\` — gather project context (PRs, tickets, TODOs, deferred work) before a review.
514
- - \`thatch-review-pedantic\` / \`-acceptance\` / \`-state-flow\` / \`-no-slop\` / \`-breadcrumbs\` / \`-mark-and-sweep\` / \`-highlights\` — seven specialist review lenses. Run individually, then \`thatch-review-synthesizer\` to verify and aggregate.
515
- - \`thatch-project-primer\` — investigate a new project and write foundational memories.
516
- - \`thatch-session-reflection\` — record what you learned at end of session.
517
- - \`thatch-fact-extractor\` — extract durable facts from recent tool interactions (auto-triggered by the extraction pipeline).
518
- - \`thatch-dedup-classifier\` — resolve duplicate memory pairs from \`find_duplicates\`.
519
- - \`pr-description\` — draft a PR description with SYNOPSIS / PURPOSE / DESCRIPTION / WALK-THROUGH / NOTES, using bold and italic emphasis on the phrases that carry the meaning.
520
- - \`ticket-description\` — draft a ticket, issue, or work item (Linear or Jira) with clear sections and bold/italic emphasis for scanning.
521
- - \`split-overlarge-pr\` — split already-completed work from an overlarge PR into human-reviewable, release-safe PRs targeting main.
514
+ - \`thatch-code-archaeology\` - investigate an existing feature, debug an unfamiliar area, or begin a new ticket. Explores the code base from multiple angles (data model, state flow, git history, sibling features) before proposing changes. The research skill; pair with \`thatch-coding-workflow\`.
515
+ - \`thatch-change-walkthrough\` - produces a teaching walkthrough of a diff with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + change overlay mirroring the same numbers) and calibrated prose rules. Load the skill for the format and prose rules, not just for the research method.
516
+ - \`thatch-code-walkthrough\` - produces a teaching walkthrough for a feature/workflow as it stands today with a specific format (SYNOPSIS + per-workflow orient/mechanism/numbered-stages + Key files) and calibrated prose rules. Also use proactively to draft high-level docs for new or undocumented features (suitable for pkg/README.md or docs/features/<name>.md). Load the skill for the format and prose rules, not just for the research method.
517
+ - \`thatch-review-context\` - gather project context (PRs, tickets, TODOs, deferred work) before a review.
518
+ - \`thatch-review-followup\` - alternate entrypoint for follow-up review rounds. Verifies whether the author's responses and code changes since your last review adequately addressed prior findings, offers to reply on resolved items, then optionally re-runs the full structured review.
519
+ - \`thatch-review-pedantic\` / \`-acceptance\` / \`-state-flow\` / \`-no-slop\` / \`-breadcrumbs\` / \`-mark-and-sweep\` / \`-highlights\` - seven specialist review lenses. Run individually, then \`thatch-review-synthesizer\` to verify and aggregate.
520
+ - \`thatch-project-primer\` - investigate a new project and write foundational memories.
521
+ - \`thatch-session-reflection\` - record what you learned at end of session.
522
+ - \`thatch-fact-extractor\` - extract durable facts from recent tool interactions (auto-triggered by the extraction pipeline).
523
+ - \`thatch-dedup-classifier\` - resolve duplicate memory pairs from \`find_duplicates\`.
524
+ - \`thatch-pr-description\` - draft a PR description with SYNOPSIS / PURPOSE / DESCRIPTION / WALK-THROUGH / NOTES, using bold and italic emphasis on the phrases that carry the meaning.
525
+ - \`thatch-ticket-description\` - draft a ticket, issue, or work item (Linear or Jira) with clear sections and bold/italic emphasis for scanning.
526
+ - \`thatch-split-overlarge-pr\` - split already-completed work from an overlarge PR into human-reviewable, release-safe PRs targeting main.
527
+ - \`thatch-review-response\` - respond to code review on the user's own PR. Triage findings, fix bugs one by one, reply on each thread, then post a top-level summary comment.
522
528
 
523
529
  ## When to Write
524
530
 
@@ -530,8 +536,8 @@ current state of the code).
530
536
 
531
537
  ## Before Responding
532
538
 
533
- Before composing a final response after substantial work this turn — multiple
534
- rounds of tool calls for investigation, debugging, or code-writing — check
539
+ Before composing a final response after substantial work this turn - multiple
540
+ rounds of tool calls for investigation, debugging, or code-writing - check
535
541
  whether you've discovered knowledge worth persisting. Use memory_recall to
536
542
  check for duplicates, then memory_remember for new findings. Then deliver
537
543
  your response.
@@ -601,7 +607,7 @@ do not save it. Do not store:
601
607
 
602
608
  ## Archived Memories
603
609
 
604
- Memories can be marked \`archived\` — a flag for stable, long-term historical
610
+ Memories can be marked \`archived\` - a flag for stable, long-term historical
605
611
  records that should not trigger hygiene nudges (stale, orphaned, duplicate).
606
612
  Archived memories are excluded from search/recall results by default; pass
607
613
  \`includeArchived: true\` to surface them for archaeological dives.
@@ -609,23 +615,23 @@ Archived memories are excluded from search/recall results by default; pass
609
615
  When a branch is merged or about to be deleted, consolidate its branch-scoped
610
616
  memories into a single archived memory scoped to that same branch (preserving
611
617
  provenance). Capture intent, design decisions, review back-and-forth, PR
612
- number, unexpected pivots — the kind of git-archaeology context that explains
618
+ number, unexpected pivots - the kind of git-archaeology context that explains
613
619
  _why_ the code looks the way it does a year from now. Then memory_forget the
614
620
  originals. The archived record outlives the branch. Future sessions searching
615
621
  with \`includeArchived: true\` can pull it up when investigating ambiguous code.
616
622
 
617
- Updating an archived memory requires passing \`archived\` explicitly — omit it
623
+ Updating an archived memory requires passing \`archived\` explicitly - omit it
618
624
  and the tool returns an error. Pass \`archived: true\` to keep it archived,
619
625
  \`archived: false\` to unarchive.
620
626
 
621
627
  ## Explicit Requests
622
628
 
623
- "Remember X" — save immediately.
624
- "Forget X" — \`memory_recall\` to find it, then \`memory_forget\`.`;
629
+ "Remember X" - save immediately.
630
+ "Forget X" - \`memory_recall\` to find it, then \`memory_forget\`.`;
625
631
  }
626
632
 
627
633
  // ---------------------------------------------------------------------------
628
- // Prompt-aware recall nudge — fires when the user's prompt semantically
634
+ // Prompt-aware recall nudge - fires when the user's prompt semantically
629
635
  // matches existing memories. Injected via opencode's chat.message hook
630
636
  // (in-process, warm model) or via the sideband socket for Claude Code/Cursor
631
637
  // (flush-tools CLI subcommand).