@jeffober/thatch 0.2.0 → 0.2.2
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.
- package/README.md +4 -2
- package/artifacts/skills/thatch-fact-extractor.md +1 -1
- package/artifacts/skills/thatch-memory-verify.md +2 -2
- package/artifacts/skills/thatch-plan-refinement.md +3 -2
- package/artifacts/skills/thatch-refine-infra.md +66 -0
- package/artifacts/skills/thatch-refine-oss-contribution.md +68 -0
- package/artifacts/skills/thatch-refine-personal.md +61 -0
- package/artifacts/skills/thatch-refine-shared-lib.md +69 -0
- package/artifacts/skills/thatch-refine-spike.md +53 -0
- package/artifacts/skills/thatch-refine-team-app.md +69 -0
- package/artifacts/skills/thatch-refine.md +84 -0
- package/docs/dev/README.md +11 -7
- package/docs/dev/features/cross-session-chat.md +8 -1
- package/docs/dev/features/memory-store.md +1 -1
- package/docs/dev/features/nudge-pipeline.md +12 -0
- package/docs/dev/features/opencode-plugin.md +1 -1
- package/docs/dev/features/session-lifecycle.md +1 -1
- package/docs/dev/gotchas.md +71 -1
- package/docs/dev/mcp-parity.md +1 -1
- package/docs/dev/setup-and-hooks.md +1 -1
- package/docs/dev/skills.md +8 -1
- package/docs/user/README.md +8 -1
- package/docs/user/commands.md +8 -0
- package/docs/user/memory.md +1 -1
- package/docs/user/skills.md +12 -0
- package/package.json +1 -1
- package/src/chat.ts +17 -0
- package/src/commands.ts +23 -3
- package/src/db.ts +77 -12
- package/src/extraction.ts +89 -3
- package/src/index.ts +45 -0
- package/src/opencode/v2.ts +48 -4
- package/src/prompts.ts +118 -30
- package/src/runtime.ts +271 -72
- package/src/skills.ts +7 -0
- package/src/tool-defs.ts +156 -28
- package/src/watchers.ts +14 -0
package/src/opencode/v2.ts
CHANGED
|
@@ -72,6 +72,10 @@ export async function setup(context: V2Context): Promise<V2Cleanup | void> {
|
|
|
72
72
|
// here, and the pump lets their events through.
|
|
73
73
|
const childSessions = new Set<string>();
|
|
74
74
|
|
|
75
|
+
// Tool executions currently running against this instance's runtime (see
|
|
76
|
+
// the counter in the tool execute wrapper below).
|
|
77
|
+
let inflightTools = 0;
|
|
78
|
+
|
|
75
79
|
const capabilities = buildCapabilities(context, worktree, childSessions);
|
|
76
80
|
const runtime = await createRuntime({ capabilities, directory, worktree });
|
|
77
81
|
// Seed the forwarding set from rehydrated child bookkeeping: after a
|
|
@@ -97,9 +101,33 @@ export async function setup(context: V2Context): Promise<V2Cleanup | void> {
|
|
|
97
101
|
description: def.description,
|
|
98
102
|
input: z.toJSONSchema(z.object(def.args)),
|
|
99
103
|
execute: async (input: unknown, toolContext: V2ToolContext) => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
104
|
+
// In-flight counter (read by the cleanup below): v2 tears the old
|
|
105
|
+
// activation down while a call it registered may still be running,
|
|
106
|
+
// so cleanup waits briefly for stragglers before disposing the
|
|
107
|
+
// runtime whose db they use.
|
|
108
|
+
inflightTools++;
|
|
109
|
+
try {
|
|
110
|
+
const host: HostToolContext | undefined = trimHostContext(toolContext);
|
|
111
|
+
const result: string = await def.execute(input as Record<string, unknown>, runtime.coreContext, host);
|
|
112
|
+
return { content: result } as Tool.Result;
|
|
113
|
+
} catch (err) {
|
|
114
|
+
// A db closed mid-call by a concurrent reload's dispose surfaces
|
|
115
|
+
// here even after the wait (the call may have started racing the
|
|
116
|
+
// cleanup itself). Fail the call with an explicit retry hint -
|
|
117
|
+
// the reloaded instance is live by then, so a retry succeeds.
|
|
118
|
+
// (Hard failures are never retried by models - every prior
|
|
119
|
+
// session that hit one just abandoned the call.)
|
|
120
|
+
if (err instanceof Error && /closed database|connection closed/i.test(err.message)) {
|
|
121
|
+
return {
|
|
122
|
+
content:
|
|
123
|
+
"thatch: the plugin was reloaded mid-call and this instance's database handle " +
|
|
124
|
+
"was closed underneath it. The reloaded instance is live - retry the same call.",
|
|
125
|
+
} as Tool.Result;
|
|
126
|
+
}
|
|
127
|
+
throw err;
|
|
128
|
+
} finally {
|
|
129
|
+
inflightTools--;
|
|
130
|
+
}
|
|
103
131
|
},
|
|
104
132
|
});
|
|
105
133
|
}
|
|
@@ -296,11 +324,21 @@ export async function setup(context: V2Context): Promise<V2Cleanup | void> {
|
|
|
296
324
|
// second setup after a skipped or partial cleanup would double every
|
|
297
325
|
// poller, pump, and nudge. The pump await is safe: its body is fully
|
|
298
326
|
// try/caught and abort ends the loop, so it settles promptly.
|
|
327
|
+
//
|
|
328
|
+
// Before disposing the runtime, briefly drain in-flight tool executions:
|
|
329
|
+
// v2 tears this activation down mid-turn, and an execute whose db access
|
|
330
|
+
// would race the close either completes here or (past the bound) hits the
|
|
331
|
+
// lazy reopen + retry hint in the wrapper. The bound keeps a hung tool
|
|
332
|
+
// from holding the reload hostage.
|
|
299
333
|
let disposed = false;
|
|
300
334
|
return async () => {
|
|
301
335
|
if (disposed) return;
|
|
302
336
|
disposed = true;
|
|
303
337
|
controller.abort();
|
|
338
|
+
const drainDeadline = Date.now() + 5_000;
|
|
339
|
+
while (inflightTools > 0 && Date.now() < drainDeadline) {
|
|
340
|
+
await new Promise((resolve) => setTimeout(resolve, 25));
|
|
341
|
+
}
|
|
304
342
|
await pump;
|
|
305
343
|
registerTools.dispose();
|
|
306
344
|
registerToolHook.dispose();
|
|
@@ -394,7 +432,13 @@ export function translateEvent(located: { type: string; data?: any }): { type: s
|
|
|
394
432
|
const data = located.data ?? {};
|
|
395
433
|
switch (located.type) {
|
|
396
434
|
case "session.created":
|
|
397
|
-
|
|
435
|
+
// v2 publishes the v1-compat payload { sessionID, info: SessionInfo };
|
|
436
|
+
// the parent link lives at info.parentID (the task tool dispatches
|
|
437
|
+
// sub-agents with parentID), not at the payload top level. Without
|
|
438
|
+
// this, childToParent never populates on v2 and every child-session
|
|
439
|
+
// behavior (buffer drain, nudge suppression, child cleanup) silently
|
|
440
|
+
// only works on v1.
|
|
441
|
+
return [{ type: "session.created", properties: { info: { id: data.sessionID, parentID: data.info?.parentID ?? data.parentID } } }];
|
|
398
442
|
case "session.deleted":
|
|
399
443
|
return [{ type: "session.deleted", properties: { info: { id: data.sessionID } } }];
|
|
400
444
|
case "session.execution.started":
|
package/src/prompts.ts
CHANGED
|
@@ -10,6 +10,29 @@ export function predictionVerb(evidenceCount: number): string {
|
|
|
10
10
|
return evidenceCount === 0 ? "you may prefer" : "you tend to";
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Shared nudge-line formatter for the prediction and behavior surfaces.
|
|
15
|
+
* The model supplies the matcher and statement text, and both frequently
|
|
16
|
+
* arrive already carrying the render prefixes: matchers phrased as
|
|
17
|
+
* "When ..." (a natural situation phrasing, or copied from an earlier
|
|
18
|
+
* nudge) and statements copied with the evidence verb ("you tend to ...").
|
|
19
|
+
* The unconditional prefixes doubled that text in every rendered nudge,
|
|
20
|
+
* so each prefix is skipped when the supplied text already carries it.
|
|
21
|
+
*/
|
|
22
|
+
export function formatWhenLine(
|
|
23
|
+
confidence: number,
|
|
24
|
+
evidenceCount: number,
|
|
25
|
+
matcher: string,
|
|
26
|
+
statement: string,
|
|
27
|
+
verb: string,
|
|
28
|
+
): string {
|
|
29
|
+
const matcherText = /^when\b/i.test(matcher) ? matcher : `When ${matcher}`;
|
|
30
|
+
const statementText = new RegExp(`^${verb}\b`, "i").test(statement) || /^you (?:tend to|may prefer)\b/i.test(statement)
|
|
31
|
+
? statement
|
|
32
|
+
: `${verb} ${statement}`;
|
|
33
|
+
return `[${confidence.toFixed(2)} conf, ${evidenceCount} tests] ${matcherText}: ${statementText}`;
|
|
34
|
+
}
|
|
35
|
+
|
|
13
36
|
/**
|
|
14
37
|
* Cross-session chat section of the opencode system prompt. Omitted when the
|
|
15
38
|
* user disabled chat via config (chat.enabled: false), so a disabled feature
|
|
@@ -73,6 +96,49 @@ ought to trigger it and widen the wording to the broadest surface of the
|
|
|
73
96
|
class - a matcher that only names this incident never fires for the next
|
|
74
97
|
one.`;
|
|
75
98
|
|
|
99
|
+
/**
|
|
100
|
+
* The artifact-pointer bullet of the "How to Write" section. Names no
|
|
101
|
+
* tools, so it is shared verbatim by both prompt variants (the
|
|
102
|
+
* class-lesson convention above).
|
|
103
|
+
*/
|
|
104
|
+
const artifactPointerBullet = `- Artifact memories should carry their pointers: file paths, ticket IDs,
|
|
105
|
+
package names. Verification is cheap later only if the memory says where
|
|
106
|
+
to check. A pointer is provenance for durable knowledge, not knowledge
|
|
107
|
+
itself - a bare "where X lives" is exactly what the durability test
|
|
108
|
+
excludes.`;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* "Memories are pointers, not truth" instruction body, shared by all three
|
|
112
|
+
* prompt variants. Takes a ToolNamer because the section names memory tools
|
|
113
|
+
* (thatch_memory_remember on opencode, bare on MCP hosts, whose
|
|
114
|
+
* instructions establish the bare-name convention). Staleness is a
|
|
115
|
+
* property of the claim's relationship to a mutable world, not of the
|
|
116
|
+
* memory's age.
|
|
117
|
+
*/
|
|
118
|
+
export function memoryPointersSection(tool: ToolNamer): string {
|
|
119
|
+
return `## Memories Are Pointers, Not Truth
|
|
120
|
+
|
|
121
|
+
${tool("memory_recall")} surfaces a point-in-time record: a semantic guide
|
|
122
|
+
associating "what I'm looking for" with "where I should look", written when
|
|
123
|
+
the knowledge was current. Memories speed up research - they do not replace
|
|
124
|
+
it, and they are not a source of truth.
|
|
125
|
+
|
|
126
|
+
- **Policy memories** ("the user always wants X", "check CI after merging")
|
|
127
|
+
are self-executing: they are the ground truth for behavior.
|
|
128
|
+
- **Artifact memories** ("feature X lives in <file> and uses <technique>")
|
|
129
|
+
are pointers to checkable claims about code, docs, tickets, or git.
|
|
130
|
+
Follow the pointer and assert from the source, not from the memory.
|
|
131
|
+
|
|
132
|
+
Before asserting an artifact claim from memory, re-derive it from the
|
|
133
|
+
current source. Confirming the reference still exists verifies little: the
|
|
134
|
+
file can survive while the behavior changed (scope drift, priority shifts,
|
|
135
|
+
implementation details that proved too complex in practice).
|
|
136
|
+
The source wins. When reality has moved on, correct the record with
|
|
137
|
+
${tool("memory_remember")} (overwrite: true) or ${tool("memory_forget")} -
|
|
138
|
+
silently; memory maintenance is not user-facing. For a deep staleness check
|
|
139
|
+
of a specific memory, load the thatch-memory-verify skill.`;
|
|
140
|
+
}
|
|
141
|
+
|
|
76
142
|
export function systemPrompt(repo: string, chatEnabled = true): string {
|
|
77
143
|
return `# Persistence
|
|
78
144
|
|
|
@@ -106,13 +172,16 @@ WIP, PR status). Unscoped memories are project-wide and always included in searc
|
|
|
106
172
|
|
|
107
173
|
## Session Startup
|
|
108
174
|
|
|
109
|
-
1. thatch_memory_recall "user preferences and personality"
|
|
110
|
-
2. thatch_memory_recall "project architecture and conventions"
|
|
111
|
-
3. If on a non-main branch, thatch_memory_recall with the branch name
|
|
175
|
+
1. thatch_memory_recall({ query: "user preferences and personality" })
|
|
176
|
+
2. thatch_memory_recall({ query: "project architecture and conventions" })
|
|
177
|
+
3. If on a non-main branch, thatch_memory_recall with the branch name as the query
|
|
112
178
|
4. thatch_memory_list and thatch_store_list to see what's available
|
|
113
179
|
|
|
114
180
|
Before diving into code, thatch_memory_recall with a query relevant to the area
|
|
115
|
-
you're working in. Prior sessions may have already investigated it.
|
|
181
|
+
you're working in. Prior sessions may have already investigated it. All thatch
|
|
182
|
+
tools take a single object argument: never a bare positional string. Call them
|
|
183
|
+
directly, or through the Code Mode execute runtime when the harness only
|
|
184
|
+
exposes tools through code.
|
|
116
185
|
|
|
117
186
|
## Skills
|
|
118
187
|
|
|
@@ -123,6 +192,13 @@ workflows. The host auto-discovers them, but reach for them proactively:
|
|
|
123
192
|
- \`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.
|
|
124
193
|
- \`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\`.
|
|
125
194
|
- \`thatch-plan-refinement\` - refine a plan before implementing it: fresh-context reviewer rounds until consensus, with an optional deep-mode lens fan-out (reuse, alternatives, hidden problems, safe-to-modify, archaeology). Use when a plan for a code change is about to be built or the user asks to stress-test a plan.
|
|
195
|
+
- \`thatch-refine\` - classify the project (audience, lifecycle, surface) and refine a plan under that type's requirements: team codebases owe coordination and intent breadcrumbs, personal projects allow cleverness, shared libraries owe API hygiene. Entry point for the thatch-refine-* family; also the /thatch/refine command.
|
|
196
|
+
- \`thatch-refine-team-app\` - refinement deltas for multi-developer team codebases: consistency outranks cleverness, intent breadcrumbs are deliverables, pre-mortem and safe-to-modify lenses dominate.
|
|
197
|
+
- \`thatch-refine-personal\` - refinement deltas for solo projects with no downstream consumers: relaxed coordination, cleverness and experimentation welcome, premise verification stays honest.
|
|
198
|
+
- \`thatch-refine-shared-lib\` - refinement deltas for changes touching a library's API surface: flexible on input, strict on output, keep special cases out of the API, never foreclose caller options, docs are a deliverable.
|
|
199
|
+
- \`thatch-refine-spike\` - refinement deltas for throwaway prototypes: skip the loop, verify only the premises the experiment's conclusion depends on, state the question and the time box.
|
|
200
|
+
- \`thatch-refine-infra\` - refinement deltas for CI, Terraform, and k8s changes: blast radius across pipelines and environments, rollback plan and staged verification are mandatory, pattern-following is near-absolute.
|
|
201
|
+
- \`thatch-refine-oss-contribution\` - refinement deltas for PRs to repos you do not maintain: the maintainer's design authority governs, minimal diff, upstream discussion gates significant design work.
|
|
126
202
|
- \`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.
|
|
127
203
|
- \`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.
|
|
128
204
|
- \`thatch-review-context\` - gather project context (PRs, tickets, TODOs, deferred work) before a review.
|
|
@@ -134,7 +210,7 @@ workflows. The host auto-discovers them, but reach for them proactively:
|
|
|
134
210
|
- \`thatch-ticket-description\` - draft a ticket, issue, or work item (Linear or Jira) with clear sections and bold/italic emphasis for scanning.
|
|
135
211
|
- \`thatch-split-overlarge-pr\` - split already-completed work from an overlarge PR into human-reviewable, release-safe PRs targeting main.
|
|
136
212
|
- \`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.
|
|
137
|
-
- \`thatch-memory-verify\` - fact-check a single memory against the current codebase and correct stale claims. Use when a memory
|
|
213
|
+
- \`thatch-memory-verify\` - fact-check a single memory against the current codebase and correct stale claims. Use when a memory looks stale or when preparing a knowledge export.
|
|
138
214
|
- \`thatch-knowledge-export\` - compile everything thatch knows about a topic into a curated markdown file for knowledge transfer. Searches across stores, curates out personal noise, fact-checks code-related memories, and generates a clean export.
|
|
139
215
|
- \`thatch-clear-writing\` - prose rules for any human-facing text not covered by a dedicated writing skill: PR and ticket comments, documentation, plans, reports, and chat replies. Load before drafting any of those.
|
|
140
216
|
|
|
@@ -162,15 +238,7 @@ whether you've discovered knowledge worth persisting. Use thatch_memory_recall
|
|
|
162
238
|
to check for duplicates, then thatch_memory_remember for new findings. Then
|
|
163
239
|
deliver your response.
|
|
164
240
|
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
When thatch_memory_show or thatch_memory_recall returns a memory with an old
|
|
168
|
-
updated_at date (more than a few weeks), consider loading the
|
|
169
|
-
thatch-memory-verify skill to fact-check its code-related claims against the
|
|
170
|
-
current codebase before relying on them. This is not mandatory for every old
|
|
171
|
-
memory. Use judgment: a memory about a stable architectural decision may be
|
|
172
|
-
fine for months, while a memory about file locations or function names is
|
|
173
|
-
more likely to drift.
|
|
241
|
+
${memoryPointersSection(opencodeToolName)}
|
|
174
242
|
|
|
175
243
|
## Background Task Completions
|
|
176
244
|
|
|
@@ -187,6 +255,12 @@ the same prompt. If the re-dispatch also fails or times out, note the gap and
|
|
|
187
255
|
move on. Do not retry more than once - repeated failures indicate an
|
|
188
256
|
intractable prompt, not a transient hang.
|
|
189
257
|
|
|
258
|
+
When the fact-extractor sub-agent completes, its "Extraction complete."
|
|
259
|
+
report is a background-task completion, not an extraction nudge: the buffer
|
|
260
|
+
is drained and nothing follows from it. Never re-dispatch an extractor
|
|
261
|
+
because a completion arrived - a new extraction nudge is the only dispatch
|
|
262
|
+
signal.
|
|
263
|
+
|
|
190
264
|
## Watchers
|
|
191
265
|
|
|
192
266
|
Use thatch_watch_create to watch a GitHub PR for events (comments, review
|
|
@@ -304,6 +378,7 @@ config in memory.
|
|
|
304
378
|
- One topic per memory. Write for a future instance with zero current context.
|
|
305
379
|
- Confidence 1-2: single signal. 5-6: moderate. 9: explicitly stated.
|
|
306
380
|
10: hard constraint.
|
|
381
|
+
${artifactPointerBullet}
|
|
307
382
|
|
|
308
383
|
## What NOT to Store
|
|
309
384
|
|
|
@@ -422,13 +497,14 @@ WIP, PR status). Unscoped memories are project-wide and always included in searc
|
|
|
422
497
|
|
|
423
498
|
## Session Startup
|
|
424
499
|
|
|
425
|
-
1. \`memory_recall\` "user preferences and personality" (global store)
|
|
426
|
-
2. \`memory_recall\` "project architecture and conventions" (project store)
|
|
427
|
-
3. If on a non-main branch, \`memory_recall\` with the branch name
|
|
500
|
+
1. \`memory_recall\` with \`{"query": "user preferences and personality"}\` (global store)
|
|
501
|
+
2. \`memory_recall\` with \`{"query": "project architecture and conventions"}\` (project store)
|
|
502
|
+
3. If on a non-main branch, \`memory_recall\` with the branch name as the query
|
|
428
503
|
4. \`memory_list\` and \`store_list\` to see what's available
|
|
429
504
|
|
|
430
505
|
Before diving into code, \`memory_recall\` with a query relevant to the area
|
|
431
|
-
you're working in. Prior sessions may have already investigated it.
|
|
506
|
+
you're working in. Prior sessions may have already investigated it. All thatch
|
|
507
|
+
tools take a single JSON object argument: never a bare positional string.
|
|
432
508
|
|
|
433
509
|
## Skills
|
|
434
510
|
|
|
@@ -437,6 +513,13 @@ workflows. The host auto-discovers them, but reach for them proactively:
|
|
|
437
513
|
|
|
438
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\`.
|
|
439
515
|
- \`thatch-plan-refinement\` - refine a plan before implementing it: fresh-context reviewer rounds until consensus, with an optional deep-mode lens fan-out (reuse, alternatives, hidden problems, safe-to-modify, archaeology). Use when a plan for a code change is about to be built or the user asks to stress-test a plan.
|
|
516
|
+
- \`thatch-refine\` - classify the project (audience, lifecycle, surface) and refine a plan under that type's requirements: team codebases owe coordination and intent breadcrumbs, personal projects allow cleverness, shared libraries owe API hygiene. Entry point for the thatch-refine-* family; also the /thatch/refine command.
|
|
517
|
+
- \`thatch-refine-team-app\` - refinement deltas for multi-developer team codebases: consistency outranks cleverness, intent breadcrumbs are deliverables, pre-mortem and safe-to-modify lenses dominate.
|
|
518
|
+
- \`thatch-refine-personal\` - refinement deltas for solo projects with no downstream consumers: relaxed coordination, cleverness and experimentation welcome, premise verification stays honest.
|
|
519
|
+
- \`thatch-refine-shared-lib\` - refinement deltas for changes touching a library's API surface: flexible on input, strict on output, keep special cases out of the API, never foreclose caller options, docs are a deliverable.
|
|
520
|
+
- \`thatch-refine-spike\` - refinement deltas for throwaway prototypes: skip the loop, verify only the premises the experiment's conclusion depends on, state the question and the time box.
|
|
521
|
+
- \`thatch-refine-infra\` - refinement deltas for CI, Terraform, and k8s changes: blast radius across pipelines and environments, rollback plan and staged verification are mandatory, pattern-following is near-absolute.
|
|
522
|
+
- \`thatch-refine-oss-contribution\` - refinement deltas for PRs to repos you do not maintain: the maintainer's design authority governs, minimal diff, upstream discussion gates significant design work.
|
|
440
523
|
- \`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.
|
|
441
524
|
- \`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.
|
|
442
525
|
- \`thatch-review-context\` - gather project context (PRs, tickets, TODOs, deferred work) before a review.
|
|
@@ -450,7 +533,7 @@ workflows. The host auto-discovers them, but reach for them proactively:
|
|
|
450
533
|
- \`thatch-ticket-description\` - draft a ticket, issue, or work item (Linear or Jira) with clear sections and bold/italic emphasis for scanning.
|
|
451
534
|
- \`thatch-split-overlarge-pr\` - split already-completed work from an overlarge PR into human-reviewable, release-safe PRs targeting main.
|
|
452
535
|
- \`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.
|
|
453
|
-
- \`thatch-memory-verify\` - fact-check a single memory against the current codebase and correct stale claims. Use when a memory
|
|
536
|
+
- \`thatch-memory-verify\` - fact-check a single memory against the current codebase and correct stale claims. Use when a memory looks stale or when preparing a knowledge export.
|
|
454
537
|
- \`thatch-knowledge-export\` - compile everything thatch knows about a topic into a curated markdown file for knowledge transfer. Searches across stores, curates out personal noise, fact-checks code-related memories, and generates a clean export.
|
|
455
538
|
- \`thatch-clear-writing\` - prose rules for any human-facing text not covered by a dedicated writing skill: PR and ticket comments, documentation, plans, reports, and chat replies. Load before drafting any of those.
|
|
456
539
|
|
|
@@ -478,14 +561,7 @@ whether you've discovered knowledge worth persisting. Use memory_recall to
|
|
|
478
561
|
check for duplicates, then memory_remember for new findings. Then deliver
|
|
479
562
|
your response.
|
|
480
563
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
When memory_show or memory_recall returns a memory with an old updated_at
|
|
484
|
-
date (more than a few weeks), consider loading the thatch-memory-verify skill
|
|
485
|
-
to fact-check its code-related claims against the current codebase before
|
|
486
|
-
relying on them. This is not mandatory for every old memory. Use judgment: a
|
|
487
|
-
memory about a stable architectural decision may be fine for months, while a
|
|
488
|
-
memory about file locations or function names is more likely to drift.
|
|
564
|
+
${memoryPointersSection(bareToolName)}
|
|
489
565
|
|
|
490
566
|
## User Decision Model
|
|
491
567
|
|
|
@@ -571,6 +647,7 @@ hand-editable; do not store thatch config in memory.
|
|
|
571
647
|
- One topic per memory. Write for a future instance with zero current context.
|
|
572
648
|
- Confidence 1-2: single signal. 5-6: moderate. 9: explicitly stated.
|
|
573
649
|
10: hard constraint.
|
|
650
|
+
${artifactPointerBullet}
|
|
574
651
|
|
|
575
652
|
## What NOT to Store
|
|
576
653
|
|
|
@@ -683,6 +760,13 @@ export type ToolNamer = (name: string) => string;
|
|
|
683
760
|
export const opencodeToolName: ToolNamer = (name) => `thatch_${name}`;
|
|
684
761
|
export const mcpToolName: ToolNamer = (name) => `mcp__thatch__${name}`;
|
|
685
762
|
|
|
763
|
+
/**
|
|
764
|
+
* The bare name itself. Used by prompt sections embedded in instructions
|
|
765
|
+
* that establish the bare-name convention (mcpInstructions and twins): the
|
|
766
|
+
* model maps bare names to the host spelling at call time.
|
|
767
|
+
*/
|
|
768
|
+
export const bareToolName: ToolNamer = (name) => name;
|
|
769
|
+
|
|
686
770
|
/**
|
|
687
771
|
* The extraction instruction body. sessionIdArg is either ` with session_id
|
|
688
772
|
* "X"` (the nudge path: the sub-agent's session differs from the parent's)
|
|
@@ -866,7 +950,11 @@ function formatRecallNudge(matches: NudgeMatch[], toolName: string): string {
|
|
|
866
950
|
const verb = n === 1 ? "relates" : "relate";
|
|
867
951
|
const labels = matches.slice(0, 2).map((m) => `"${m.label}"`).join(", ");
|
|
868
952
|
const etc = n > 2 ? ", etc." : "";
|
|
869
|
-
return
|
|
953
|
+
return (
|
|
954
|
+
`[thatch] ${n} ${word} ${verb} to this prompt (${labels}${etc}). ` +
|
|
955
|
+
`Use ${toolName}({ query: "..." }) before responding - the argument is ` +
|
|
956
|
+
`a single object with a "query" key, never a bare positional string.`
|
|
957
|
+
);
|
|
870
958
|
}
|
|
871
959
|
|
|
872
960
|
// ---------------------------------------------------------------------------
|
|
@@ -879,7 +967,7 @@ function formatRecallNudge(matches: NudgeMatch[], toolName: string): string {
|
|
|
879
967
|
export function predictionNudge(items: PredictionNudgeItem[]): string {
|
|
880
968
|
const lines = items.map((p) => {
|
|
881
969
|
const verb = predictionVerb(p.evidence_count);
|
|
882
|
-
return `-
|
|
970
|
+
return `- ${formatWhenLine(p.confidence, p.evidence_count, p.matcher_description, p.statement, verb)}`;
|
|
883
971
|
});
|
|
884
972
|
return `[thatch] User decision model\n${lines.join("\n")}`;
|
|
885
973
|
}
|
|
@@ -893,7 +981,7 @@ export function predictionNudge(items: PredictionNudgeItem[]): string {
|
|
|
893
981
|
export function behaviorNudge(items: BehaviorNudgeItem[]): string {
|
|
894
982
|
const lines = items.map((b) => {
|
|
895
983
|
const verb = b.evidence_count === 0 ? "consider" : "do";
|
|
896
|
-
return `-
|
|
984
|
+
return `- ${formatWhenLine(b.confidence, b.evidence_count, b.matcher_description, b.statement, verb)}`;
|
|
897
985
|
});
|
|
898
986
|
return `[thatch] Situational behaviors\n${lines.join("\n")}`;
|
|
899
987
|
}
|