@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
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,19 +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-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-workflow-research\` — research code workflows affected by a change or planned change, before reviewing or planning.
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
- - \`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
- - \`ticket-description\` — draft a ticket, issue, or work item (Linear or Jira) with clear sections and bold/italic emphasis for scanning.
52
- - \`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.
53
54
 
54
55
  ## When to Write
55
56
 
@@ -61,8 +62,8 @@ current state of the code).
61
62
 
62
63
  ## Before Responding
63
64
 
64
- Before composing a final response after substantial work this turn — multiple
65
- 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
66
67
  whether you've discovered knowledge worth persisting. Use thatch_memory_recall
67
68
  to check for duplicates, then thatch_memory_remember for new findings. Then
68
69
  deliver your response.
@@ -70,7 +71,7 @@ deliver your response.
70
71
  ## Background Task Completions
71
72
 
72
73
  When a background task completes and its result is injected into the session,
73
- 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
74
75
  proceed with anything you were discussing. Do not narrate what the task did or
75
76
  summarize its output. If you were mid-conversation with the user, continue
76
77
  that thread. If the user's last message has been fully addressed, stop and
@@ -79,7 +80,7 @@ not greenlit.
79
80
 
80
81
  If a background task was cancelled after timing out, re-dispatch it once with
81
82
  the same prompt. If the re-dispatch also fails or times out, note the gap and
82
- 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
83
84
  intractable prompt, not a transient hang.
84
85
 
85
86
  ## User Decision Model
@@ -147,7 +148,7 @@ do not save it. Do not store:
147
148
 
148
149
  ## Archived Memories
149
150
 
150
- 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
151
152
  records that should not trigger hygiene nudges (stale, orphaned, duplicate).
152
153
  Archived memories are excluded from search/recall results by default; pass
153
154
  \`includeArchived: true\` to surface them for archaeological dives.
@@ -155,25 +156,25 @@ Archived memories are excluded from search/recall results by default; pass
155
156
  When a branch is merged or about to be deleted, consolidate its branch-scoped
156
157
  memories into a single archived memory scoped to that same branch (preserving
157
158
  provenance). Capture intent, design decisions, review back-and-forth, PR
158
- number, unexpected pivots — the kind of git-archaeology context that explains
159
+ number, unexpected pivots - the kind of git-archaeology context that explains
159
160
  _why_ the code looks the way it does a year from now. Then memory_forget the
160
161
  originals. The archived record outlives the branch. Future sessions searching
161
162
  with \`includeArchived: true\` can pull it up when investigating ambiguous code.
162
163
 
163
- Updating an archived memory requires passing \`archived\` explicitly — omit it
164
+ Updating an archived memory requires passing \`archived\` explicitly - omit it
164
165
  and the tool returns an error. Pass \`archived: true\` to keep it archived,
165
166
  \`archived: false\` to unarchive.
166
167
 
167
168
  ## Explicit Requests
168
169
 
169
- "Remember X" — save immediately.
170
- "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.`;
171
172
  }
172
173
 
173
174
  export function compactionContext(repo: string): string {
174
175
  return `Thatch persistent memory is active with stores "${repo}" and "global".
175
176
  When summarizing, preserve context about what's been learned and decided
176
- this session — conventions, architectural decisions, and prior knowledge
177
+ this session - conventions, architectural decisions, and prior knowledge
177
178
  retrieved from memory. This ensures continuity after compaction.`;
178
179
  }
179
180
 
@@ -199,7 +200,7 @@ When convenient this session (not before addressing the user's request), tend th
199
200
  * start. The repo store name is auto-detected at runtime by the MCP server, so
200
201
  * the instructions don't need it.
201
202
  *
202
- * 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
203
204
  * Claude Code they're prefixed as mcp__thatch__memory_remember, but the bare
204
205
  * names are what the agent searches for and what the instructions reference.
205
206
  */
@@ -240,19 +241,20 @@ you're working in. Prior sessions may have already investigated it.
240
241
  Thatch ships skills for code review, project investigation, and memory
241
242
  workflows. The host auto-discovers them, but reach for them proactively:
242
243
 
243
- - \`thatch-workflow-research\` — research code workflows affected by a change or planned change, before reviewing or planning.
244
- - \`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.
245
- - \`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.
246
- - \`thatch-review-context\` — gather project context (PRs, tickets, TODOs, deferred work) before a review.
247
- - \`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.
248
- - \`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.
249
- - \`thatch-project-primer\` — investigate a new project and write foundational memories.
250
- - \`thatch-session-reflection\` — record what you learned at end of session.
251
- - \`thatch-fact-extractor\` — extract durable facts from recent tool interactions (auto-triggered by the extraction pipeline).
252
- - \`thatch-dedup-classifier\` — resolve duplicate memory pairs from \`find_duplicates\`.
253
- - \`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.
254
- - \`ticket-description\` — draft a ticket, issue, or work item (Linear or Jira) with clear sections and bold/italic emphasis for scanning.
255
- - \`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.
256
258
 
257
259
  ## When to Write
258
260
 
@@ -264,8 +266,8 @@ current state of the code).
264
266
 
265
267
  ## Before Responding
266
268
 
267
- Before composing a final response after substantial work this turn — multiple
268
- 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
269
271
  whether you've discovered knowledge worth persisting. Use memory_recall to
270
272
  check for duplicates, then memory_remember for new findings. Then deliver
271
273
  your response.
@@ -335,7 +337,7 @@ do not save it. Do not store:
335
337
 
336
338
  ## Archived Memories
337
339
 
338
- 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
339
341
  records that should not trigger hygiene nudges (stale, orphaned, duplicate).
340
342
  Archived memories are excluded from search/recall results by default; pass
341
343
  \`includeArchived: true\` to surface them for archaeological dives.
@@ -343,19 +345,19 @@ Archived memories are excluded from search/recall results by default; pass
343
345
  When a branch is merged or about to be deleted, consolidate its branch-scoped
344
346
  memories into a single archived memory scoped to that same branch (preserving
345
347
  provenance). Capture intent, design decisions, review back-and-forth, PR
346
- number, unexpected pivots — the kind of git-archaeology context that explains
348
+ number, unexpected pivots - the kind of git-archaeology context that explains
347
349
  _why_ the code looks the way it does a year from now. Then memory_forget the
348
350
  originals. The archived record outlives the branch. Future sessions searching
349
351
  with \`includeArchived: true\` can pull it up when investigating ambiguous code.
350
352
 
351
- Updating an archived memory requires passing \`archived\` explicitly — omit it
353
+ Updating an archived memory requires passing \`archived\` explicitly - omit it
352
354
  and the tool returns an error. Pass \`archived: true\` to keep it archived,
353
355
  \`archived: false\` to unarchive.
354
356
 
355
357
  ## Explicit Requests
356
358
 
357
- "Remember X" — save immediately.
358
- "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\`.`;
359
361
  }
360
362
 
361
363
  /**
@@ -403,7 +405,7 @@ export function extractionNudge(
403
405
  const plural = count === 1 ? "" : "s";
404
406
  // opencode's task tool has a `background` parameter (requires
405
407
  // OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true) that launches the sub-agent
406
- // asynchronously — the call returns immediately and the session is notified
408
+ // asynchronously - the call returns immediately and the session is notified
407
409
  // on completion. Naming the parameter gives the model a direct hit on the tool
408
410
  // schema it sees. MCP hosts (Claude Code, Cursor) keep generic sub-agent
409
411
  // wording because their background mechanisms differ and are not exposed as a
@@ -443,7 +445,7 @@ export function extractionNudge(
443
445
  * Prompt text sent directly to a child session the plugin created for
444
446
  * extraction. Unlike extractionNudge (which tells the model to dispatch a
445
447
  * sub-agent and call extraction_done), this prompt is already inside the
446
- * 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.
447
449
  * The payload format is identical to the nudge path so the skill receives
448
450
  * the same contract either way.
449
451
  */
@@ -467,7 +469,7 @@ export function claudeExtractionNudge(count: number, payload: string): string {
467
469
 
468
470
  /**
469
471
  * Static instructions for Cursor's AGENTS.md. Same contract as
470
- * claudeInstructions() — the host loads this at every session start, and the
472
+ * claudeInstructions() - the host loads this at every session start, and the
471
473
  * repo store name is auto-detected at runtime by the MCP server. Tool names
472
474
  * use the same mcp__thatch__ prefix since Cursor discovers MCP tools via the
473
475
  * same protocol.
@@ -509,19 +511,20 @@ you're working in. Prior sessions may have already investigated it.
509
511
  Thatch ships skills for code review, project investigation, and memory
510
512
  workflows. The host auto-discovers them, but reach for them proactively:
511
513
 
512
- - \`thatch-workflow-research\` — research code workflows affected by a change or planned change, before reviewing or planning.
513
- - \`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.
514
- - \`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.
515
- - \`thatch-review-context\` — gather project context (PRs, tickets, TODOs, deferred work) before a review.
516
- - \`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.
517
- - \`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.
518
- - \`thatch-project-primer\` — investigate a new project and write foundational memories.
519
- - \`thatch-session-reflection\` — record what you learned at end of session.
520
- - \`thatch-fact-extractor\` — extract durable facts from recent tool interactions (auto-triggered by the extraction pipeline).
521
- - \`thatch-dedup-classifier\` — resolve duplicate memory pairs from \`find_duplicates\`.
522
- - \`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.
523
- - \`ticket-description\` — draft a ticket, issue, or work item (Linear or Jira) with clear sections and bold/italic emphasis for scanning.
524
- - \`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.
525
528
 
526
529
  ## When to Write
527
530
 
@@ -533,8 +536,8 @@ current state of the code).
533
536
 
534
537
  ## Before Responding
535
538
 
536
- Before composing a final response after substantial work this turn — multiple
537
- 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
538
541
  whether you've discovered knowledge worth persisting. Use memory_recall to
539
542
  check for duplicates, then memory_remember for new findings. Then deliver
540
543
  your response.
@@ -604,7 +607,7 @@ do not save it. Do not store:
604
607
 
605
608
  ## Archived Memories
606
609
 
607
- 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
608
611
  records that should not trigger hygiene nudges (stale, orphaned, duplicate).
609
612
  Archived memories are excluded from search/recall results by default; pass
610
613
  \`includeArchived: true\` to surface them for archaeological dives.
@@ -612,23 +615,23 @@ Archived memories are excluded from search/recall results by default; pass
612
615
  When a branch is merged or about to be deleted, consolidate its branch-scoped
613
616
  memories into a single archived memory scoped to that same branch (preserving
614
617
  provenance). Capture intent, design decisions, review back-and-forth, PR
615
- number, unexpected pivots — the kind of git-archaeology context that explains
618
+ number, unexpected pivots - the kind of git-archaeology context that explains
616
619
  _why_ the code looks the way it does a year from now. Then memory_forget the
617
620
  originals. The archived record outlives the branch. Future sessions searching
618
621
  with \`includeArchived: true\` can pull it up when investigating ambiguous code.
619
622
 
620
- Updating an archived memory requires passing \`archived\` explicitly — omit it
623
+ Updating an archived memory requires passing \`archived\` explicitly - omit it
621
624
  and the tool returns an error. Pass \`archived: true\` to keep it archived,
622
625
  \`archived: false\` to unarchive.
623
626
 
624
627
  ## Explicit Requests
625
628
 
626
- "Remember X" — save immediately.
627
- "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\`.`;
628
631
  }
629
632
 
630
633
  // ---------------------------------------------------------------------------
631
- // Prompt-aware recall nudge — fires when the user's prompt semantically
634
+ // Prompt-aware recall nudge - fires when the user's prompt semantically
632
635
  // matches existing memories. Injected via opencode's chat.message hook
633
636
  // (in-process, warm model) or via the sideband socket for Claude Code/Cursor
634
637
  // (flush-tools CLI subcommand).