@jeffober/thatch 0.1.28 → 0.1.29
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 +24 -10
- package/artifacts/skills/thatch-code-review.md +9 -7
- package/artifacts/skills/thatch-review-economy.md +97 -0
- package/artifacts/skills/thatch-review-followup.md +1 -1
- package/artifacts/skills/thatch-review-synthesizer.md +15 -5
- package/bin/qa-run +38 -0
- package/bin/thatch +10 -5
- package/docs/dev/README.md +71 -18
- package/docs/dev/features/README.md +33 -0
- package/docs/dev/features/behavior-engine.md +271 -0
- package/docs/dev/features/cicd.md +89 -0
- package/docs/dev/features/cli.md +81 -0
- package/docs/dev/features/compaction-recovery.md +48 -0
- package/docs/dev/features/database.md +244 -0
- package/docs/dev/features/deduplication.md +102 -0
- package/docs/dev/features/extraction.md +253 -0
- package/docs/dev/features/hygiene.md +81 -0
- package/docs/dev/features/memory-store.md +154 -0
- package/docs/dev/features/multi-host.md +228 -0
- package/docs/dev/features/nudge-pipeline.md +282 -0
- package/docs/dev/features/prediction-engine.md +253 -0
- package/docs/dev/features/qa-system.md +205 -0
- package/docs/dev/features/session-lifecycle.md +110 -0
- package/docs/dev/features/setup.md +199 -0
- package/docs/dev/features/sideband.md +104 -0
- package/docs/dev/gotchas.md +3 -3
- package/docs/dev/mcp-parity.md +6 -4
- package/docs/dev/setup-and-hooks.md +4 -4
- package/docs/dev/skills.md +10 -8
- package/docs/plans/README.md +2 -2
- package/docs/user/README.md +58 -20
- package/docs/user/behavior-engine.md +85 -0
- package/docs/user/cli.md +98 -0
- package/docs/user/code-review.md +73 -0
- package/docs/user/deduplication.md +70 -0
- package/docs/user/default-behaviors.md +75 -0
- package/docs/user/extraction.md +74 -0
- package/docs/user/hygiene.md +76 -0
- package/docs/user/memory.md +81 -0
- package/docs/user/prediction-engine.md +87 -0
- package/docs/user/setup.md +110 -0
- package/docs/user/skills.md +97 -0
- package/package.json +2 -2
- package/src/behavior.ts +120 -0
- package/src/db.ts +160 -417
- package/src/embeddings.ts +0 -41
- package/src/extraction.ts +2 -2
- package/src/git.ts +3 -1
- package/src/index.ts +55 -9
- package/src/mcp.ts +30 -1
- package/src/prediction.ts +127 -0
- package/src/prompts.ts +135 -188
- package/src/scoring-engine.ts +374 -0
- package/src/seed-behaviors.ts +339 -0
- package/src/setup.ts +2 -6
- package/src/sideband.ts +36 -8
- package/src/skills.ts +1 -0
- package/src/tool-defs.ts +172 -25
- package/src/vector-math.ts +30 -0
- package/docs/qa/README.md +0 -175
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Setup System
|
|
2
|
+
|
|
3
|
+
Installs thatch into Claude Code and Cursor. opencode does not need setup --- it
|
|
4
|
+
auto-installs skills and injects the system prompt at plugin init. All setup
|
|
5
|
+
operations are idempotent: re-running updates drifted content without clobbering
|
|
6
|
+
unrelated config.
|
|
7
|
+
|
|
8
|
+
For the concrete artifact paths and hook event tables each host writes, see
|
|
9
|
+
[../setup-and-hooks.md](../setup-and-hooks.md). This doc covers the architecture:
|
|
10
|
+
how setup commands, the marker system, detection, auto-refresh, and binary
|
|
11
|
+
resolution fit together.
|
|
12
|
+
|
|
13
|
+
## What it does
|
|
14
|
+
|
|
15
|
+
- `thatch setup --claude` --- installs MCP config, CLAUDE.md instructions,
|
|
16
|
+
hooks, and skills for Claude Code
|
|
17
|
+
- `thatch setup --cursor` --- installs MCP config, AGENTS.md instructions,
|
|
18
|
+
hooks, and skills for Cursor
|
|
19
|
+
- `--global` flag --- installs to user-scoped config dirs instead of
|
|
20
|
+
project-local
|
|
21
|
+
- **Marker system** --- idempotent replacement of the thatch instruction block
|
|
22
|
+
in `CLAUDE.md` or `AGENTS.md` via start/end markers
|
|
23
|
+
- **`checkSetup`** --- detects installed, not-installed, or markers-broken at
|
|
24
|
+
MCP server startup
|
|
25
|
+
- **Auto-refresh** --- MCP server re-runs setup on startup if installed,
|
|
26
|
+
updating drifted content
|
|
27
|
+
- **Setup warning surfacing** --- first `tools/call` response prepends a
|
|
28
|
+
warning if setup was not run
|
|
29
|
+
- **Binary resolution** --- uses bare `thatch` if on PATH (survives updates),
|
|
30
|
+
else the absolute path to the running script
|
|
31
|
+
|
|
32
|
+
## How it works
|
|
33
|
+
|
|
34
|
+
### Setup commands
|
|
35
|
+
|
|
36
|
+
At least one of `--claude` or `--cursor` is required. Both can be passed
|
|
37
|
+
together. `--global` applies to whichever host or hosts are selected.
|
|
38
|
+
|
|
39
|
+
### Claude Code setup (`setupClaudeCode` in `src/setup.ts`)
|
|
40
|
+
|
|
41
|
+
Four artifacts, all idempotent:
|
|
42
|
+
|
|
43
|
+
1. **MCP config** --- project-local writes `.mcp.json` with a stdio thatch
|
|
44
|
+
MCP server entry. Global prints a `claude mcp add --scope user thatch --
|
|
45
|
+
<bin> mcp` command for the user to run (does not write a file, because
|
|
46
|
+
`~/.claude.json` is too complex to write directly).
|
|
47
|
+
2. **Instructions** --- appends `claudeInstructions()` to `CLAUDE.md` between
|
|
48
|
+
start and end markers (`THATCH_MARKER` / `THATCH_END_MARKER`). Project-local:
|
|
49
|
+
`<projectDir>/CLAUDE.md`. Global: `$CLAUDE_CONFIG_DIR/CLAUDE.md`.
|
|
50
|
+
3. **Hooks** --- writes to `.claude/settings.json` (project) or
|
|
51
|
+
`$CLAUDE_CONFIG_DIR/settings.json` (global). Three hooks: `SessionStart`
|
|
52
|
+
→ `thatch reminder`, `PostToolBatch` → `thatch buffer-batch`,
|
|
53
|
+
`UserPromptSubmit` → `thatch flush-tools`. Nested format:
|
|
54
|
+
`{hooks:{Event:{hooks:[{type,command}]}}}`.
|
|
55
|
+
4. **Skills** --- installs to `$CLAUDE_CONFIG_DIR/skills/` (always
|
|
56
|
+
user-scoped, even for project-local setup). `SHARED_SKILLS` only --- the
|
|
57
|
+
code-review coordinator requires sub-agent dispatch, which Claude Code
|
|
58
|
+
does not support.
|
|
59
|
+
|
|
60
|
+
### Cursor setup (`setupCursor` in `src/setup.ts`)
|
|
61
|
+
|
|
62
|
+
Four artifacts, same idempotent pattern:
|
|
63
|
+
|
|
64
|
+
1. **MCP config** --- writes `.cursor/mcp.json` (project) or
|
|
65
|
+
`$CURSOR_CONFIG_DIR/mcp.json` (global). Same JSON shape as Claude Code.
|
|
66
|
+
No `claude mcp add` equivalent needed --- Cursor reads the config file
|
|
67
|
+
directly.
|
|
68
|
+
2. **Instructions** --- appends `cursorInstructions()` to `AGENTS.md` between
|
|
69
|
+
markers (`CURSOR_MARKER` / `CURSOR_END_MARKER`). Project-local:
|
|
70
|
+
`<projectDir>/AGENTS.md`. Global: `$CURSOR_CONFIG_DIR/AGENTS.md`.
|
|
71
|
+
3. **Hooks** --- writes to `.cursor/hooks.json` (project) or
|
|
72
|
+
`$CURSOR_CONFIG_DIR/hooks.json` (global). Flat format:
|
|
73
|
+
`{version:1, hooks:{event:[{command}]}}`. Three hooks: `sessionStart`
|
|
74
|
+
→ `thatch reminder --json`, `postToolUse` → `thatch buffer-tool`,
|
|
75
|
+
`beforeSubmitPrompt` → `thatch flush-tools --json`.
|
|
76
|
+
4. **Skills** --- installs to `$CURSOR_CONFIG_DIR/skills/` (shared only).
|
|
77
|
+
|
|
78
|
+
### Marker system (`appendBlock`)
|
|
79
|
+
|
|
80
|
+
`appendBlock(path, instructions, startMarker, endMarker)` handles three cases:
|
|
81
|
+
|
|
82
|
+
1. **Both markers found** --- replace content between them. Preserve text
|
|
83
|
+
before the start marker and after the end marker. This is the normal
|
|
84
|
+
update path: re-running setup replaces the thatch block without touching
|
|
85
|
+
user-written content elsewhere in the file.
|
|
86
|
+
2. **Start marker found but end missing** --- leave the file alone. This is a
|
|
87
|
+
corrupted state --- someone edited the file and accidentally removed the
|
|
88
|
+
end marker. Writing would risk clobbering content that follows the start
|
|
89
|
+
marker. `checkSetup` reports this as `markers-broken`.
|
|
90
|
+
3. **No markers** --- append instructions to the end of the file (with a
|
|
91
|
+
separator). Create the file if it does not exist.
|
|
92
|
+
|
|
93
|
+
Start markers differ by host (the text says "Claude Code" or "Cursor"). The end
|
|
94
|
+
marker is shared.
|
|
95
|
+
|
|
96
|
+
### `checkSetup` (`src/setup.ts`)
|
|
97
|
+
|
|
98
|
+
Detects the host from environment variables set by the host process:
|
|
99
|
+
|
|
100
|
+
- `CURSOR_PROJECT_DIR` set → Cursor
|
|
101
|
+
- `CLAUDE_PROJECT_DIR` set (and Cursor not) → Claude Code
|
|
102
|
+
- Neither set → returns `null` (manual `thatch mcp` invocation, no check)
|
|
103
|
+
|
|
104
|
+
Cursor takes priority because Cursor also sets `CLAUDE_PROJECT_DIR` as an
|
|
105
|
+
alias. Without the priority check, Cursor sessions would be misidentified as
|
|
106
|
+
Claude Code.
|
|
107
|
+
|
|
108
|
+
`checkSetup` looks for start and end markers in the host's instructions file
|
|
109
|
+
--- `CLAUDE.md` for Claude Code, `AGENTS.md` for Cursor. It checks local first,
|
|
110
|
+
then global. Local takes priority.
|
|
111
|
+
|
|
112
|
+
| Outcome | Condition | Action |
|
|
113
|
+
|---------|-----------|--------|
|
|
114
|
+
| **installed** | Both markers found (local or global) | No warning |
|
|
115
|
+
| **not-installed** | No instructions file with markers | Warning surfaced on first `tools/call` |
|
|
116
|
+
| **markers-broken** | Start marker found, end marker missing | Warning with file path and fix instructions |
|
|
117
|
+
|
|
118
|
+
### Auto-refresh at MCP startup
|
|
119
|
+
|
|
120
|
+
If `checkSetup` returns `installed`, the MCP server re-runs `setupClaudeCode`
|
|
121
|
+
or `setupCursor` with the same scope. This updates skills, instructions, and
|
|
122
|
+
hooks that drifted since the last `thatch setup`. All operations are
|
|
123
|
+
idempotent --- they only write when content differs. Failure is best-effort
|
|
124
|
+
and logged to stderr.
|
|
125
|
+
|
|
126
|
+
This is how installations stay current without the user manually re-running
|
|
127
|
+
setup after upgrading thatch. The next MCP session picks up new skill content,
|
|
128
|
+
updated instructions, and any hook changes automatically.
|
|
129
|
+
|
|
130
|
+
### Setup warning surfacing
|
|
131
|
+
|
|
132
|
+
On the first `tools/call` response, if a setup warning exists, the server
|
|
133
|
+
prepends `[thatch] {warning}` to the tool's text output. The agent sees it
|
|
134
|
+
and can tell the user to run `thatch setup`. The warning is cleared after one
|
|
135
|
+
surfacing so it does not repeat on every tool call.
|
|
136
|
+
|
|
137
|
+
### Binary resolution
|
|
138
|
+
|
|
139
|
+
Setup resolves the thatch binary via `Bun.which("thatch")`. If `thatch` is on
|
|
140
|
+
`PATH` (npm global install, opencode plugin install), it uses the bare name.
|
|
141
|
+
This survives updates --- the resolved path points to whatever `thatch` is
|
|
142
|
+
current at hook execution time, not a stale absolute path.
|
|
143
|
+
|
|
144
|
+
If `thatch` is not on `PATH`, setup falls back to the absolute path of the
|
|
145
|
+
running script. This handles one-off invocations (e.g., `bun run bin/thatch
|
|
146
|
+
setup --claude`).
|
|
147
|
+
|
|
148
|
+
The resolved binary is baked into every installed hook command. Hooks are
|
|
149
|
+
short-lived processes spawned by the host after the setup session ends, so
|
|
150
|
+
they cannot rely on the original process's environment. The baked-in path
|
|
151
|
+
ensures hooks keep working across sessions.
|
|
152
|
+
|
|
153
|
+
### Hook replacement
|
|
154
|
+
|
|
155
|
+
`replaceThatchHooks` / `replaceCursorThatchHooks` filter out any existing hook
|
|
156
|
+
group whose `command` contains the string `thatch`, then add the current
|
|
157
|
+
ones. Non-thatch hooks are preserved. This handles legacy hooks --- for
|
|
158
|
+
example, an older `thatch echo` hook is replaced with the current
|
|
159
|
+
`flush-tools` hook without touching hooks from other tools.
|
|
160
|
+
|
|
161
|
+
## Interactions with other features
|
|
162
|
+
|
|
163
|
+
- [Multi-host](multi-host.md) --- setup is the installation mechanism for
|
|
164
|
+
Claude Code and Cursor. opencode auto-installs at plugin init.
|
|
165
|
+
- [Skills](../skills.md) --- setup installs skills as part of the install.
|
|
166
|
+
Skill content is plugin-owned and overwritten on drift.
|
|
167
|
+
- [Nudge pipeline](nudge-pipeline.md) --- setup installs the hooks that drive
|
|
168
|
+
the nudge pipeline for MCP hosts.
|
|
169
|
+
- [Extraction](extraction.md) --- setup installs the `buffer-batch` /
|
|
170
|
+
`buffer-tool` hooks that feed the file-backed extraction queue.
|
|
171
|
+
- [Sideband](sideband.md) --- setup installs `flush-tools`, which connects to
|
|
172
|
+
the sideband socket for warm-model access during nudge evaluation.
|
|
173
|
+
|
|
174
|
+
## Source files
|
|
175
|
+
|
|
176
|
+
| File | Role |
|
|
177
|
+
|------|------|
|
|
178
|
+
| `src/setup.ts` | `setupClaudeCode`, `setupCursor`, `checkSetup`, `appendBlock`, marker definitions, hook replacement |
|
|
179
|
+
| `bin/thatch` | `setup` subcommand --- parses flags, dispatches to `setupClaudeCode` / `setupCursor` |
|
|
180
|
+
| `src/prompts.ts` | `claudeInstructions`, `cursorInstructions` --- the instruction text appended to `CLAUDE.md` / `AGENTS.md` |
|
|
181
|
+
|
|
182
|
+
## Key invariants
|
|
183
|
+
|
|
184
|
+
1. **All operations are idempotent.** Re-running setup updates drifted content
|
|
185
|
+
without clobbering. Instructions use markers, hooks filter by `thatch`
|
|
186
|
+
string, MCP config preserves existing servers, skills diff before writing.
|
|
187
|
+
2. **Skills are always user-scoped**, even in project-local setup. Claude Code
|
|
188
|
+
and Cursor load skills from the user config dir, not the project.
|
|
189
|
+
3. **`appendBlock` leaves content alone if markers do not parse.** A start
|
|
190
|
+
marker without an end marker means the file was edited externally. Writing
|
|
191
|
+
would risk clobbering content after the start marker.
|
|
192
|
+
4. **Binary path is baked into hook commands.** Hooks are short-lived
|
|
193
|
+
processes that outlive the setup session. The resolved path ensures they
|
|
194
|
+
keep working.
|
|
195
|
+
5. **Non-thatch hooks are preserved during hook replacement.** Only hooks
|
|
196
|
+
whose `command` contains `thatch` are filtered out.
|
|
197
|
+
6. **Auto-refresh keeps installations current.** The MCP server re-runs
|
|
198
|
+
setup on startup if markers are present, picking up new skills and
|
|
199
|
+
updated instructions without manual intervention.
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Sideband IPC (MCP Hosts)
|
|
2
|
+
|
|
3
|
+
A Unix domain socket server that lets one-shot hook processes borrow the MCP server's warm embedding model. Without this, each hook invocation would load the ~34 MB model from scratch, adding 300-700 ms to every prompt.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
- Unix domain socket at a deterministic path derived from the DB path
|
|
8
|
+
- Three request methods: match (recall), predictions, behaviors
|
|
9
|
+
- One embedding round-trip per request (all three methods share the model)
|
|
10
|
+
- 2-second timeout, null on failure (callers skip the nudge gracefully)
|
|
11
|
+
- Stale socket cleanup on connection error
|
|
12
|
+
|
|
13
|
+
## How it works
|
|
14
|
+
|
|
15
|
+
### The problem it solves
|
|
16
|
+
|
|
17
|
+
Claude Code and Cursor spawn a fresh process for each hook invocation (`thatch flush-tools`, `thatch reminder`). These processes need the embedding model to embed the user's prompt for the recall/prediction/behavior nudges. Loading the ~34 MB model on every prompt would add unacceptable latency.
|
|
18
|
+
|
|
19
|
+
The MCP server is long-lived (kept alive by the host's stdio connection) and has the model warm in memory. The sideband socket lets hook processes ask the warm server to do the embedding work.
|
|
20
|
+
|
|
21
|
+
### Socket path
|
|
22
|
+
|
|
23
|
+
The path is derived from a SHA-256 hash of the DB path (first 16 hex chars), under os.tmpdir():
|
|
24
|
+
|
|
25
|
+
```text
|
|
26
|
+
$TMPDIR/thatch-<sha256(dbPath)[0:16]>.sock
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Both the MCP server and hook processes compute the same path independently (from `THATCH_DB_PATH` or the default under `XDG_CONFIG_HOME`). No out-of-band coordination needed.
|
|
30
|
+
|
|
31
|
+
Changing `THATCH_DB_PATH` moves the socket. A stale socket from a crash is cleaned up on ECONNREFUSED/ENOENT.
|
|
32
|
+
|
|
33
|
+
### Protocol
|
|
34
|
+
|
|
35
|
+
Newline-delimited JSON. One request per connection, one response.
|
|
36
|
+
|
|
37
|
+
Request:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{"method":"match|predictions|behaviors","text":"...","stores":[...],"threshold":N,"limit":N}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Response (success):
|
|
44
|
+
|
|
45
|
+
```json
|
|
46
|
+
{"ok":true,"matches":[...]}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{"ok":true,"predictions":[...]}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{"ok":true,"behaviors":[...]}
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Response (failure):
|
|
58
|
+
|
|
59
|
+
```json
|
|
60
|
+
{"ok":false,"error":"..."}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Three methods
|
|
64
|
+
|
|
65
|
+
1. **match** -- embeds text, runs `db.search` across stores, returns matches with score >= threshold as `{label, score, store}`
|
|
66
|
+
2. **predictions** -- embeds text, calls `db.scorePredictionNudge`, returns scored prediction nudge items
|
|
67
|
+
3. **behaviors** -- embeds text, calls `db.scoreBehaviorNudge`, returns scored behavior nudge items
|
|
68
|
+
|
|
69
|
+
### Client helpers
|
|
70
|
+
|
|
71
|
+
- `sidebandMatch(text, stores, threshold, limit)` -- returns matches or null on failure
|
|
72
|
+
- `sidebandPredictions(text, stores, threshold, limit)` -- returns predictions or null
|
|
73
|
+
- `sidebandBehaviors(text, stores, threshold, limit)` -- returns behaviors or null
|
|
74
|
+
|
|
75
|
+
All three return null on any failure (server not running, stale socket, timeout, parse error). Callers must treat null as "skip the nudge, fall back gracefully."
|
|
76
|
+
|
|
77
|
+
### Graceful degradation
|
|
78
|
+
|
|
79
|
+
If the socket isn't available (MCP server not running, old version, stale socket, >2s timeout), `sidebandMatch` returns null and `flush-tools` falls back to the static write nudge. The recall/prediction/behavior nudge is best-effort -- its absence never blocks the agent's workflow.
|
|
80
|
+
|
|
81
|
+
### Server lifecycle
|
|
82
|
+
|
|
83
|
+
- Opened at MCP server startup (`src/mcp.ts`). Failure is non-fatal (only the prompt-aware recall/prediction/behavior nudge degrades).
|
|
84
|
+
- Closed + socket file removed on shutdown (stdin close).
|
|
85
|
+
|
|
86
|
+
## Interactions with other features
|
|
87
|
+
|
|
88
|
+
- Nudge pipeline ([nudge-pipeline.md](nudge-pipeline.md)): MCP hosts use the sideband socket for all three nudge tiers (recall, prediction, behavior)
|
|
89
|
+
- Multi-host ([multi-host.md](multi-host.md)): only MCP hosts (Claude Code, Cursor) use the sideband; opencode has the model in-process
|
|
90
|
+
- Prediction engine ([prediction-engine.md](prediction-engine.md)): predictions method
|
|
91
|
+
- Behavior engine ([behavior-engine.md](behavior-engine.md)): behaviors method
|
|
92
|
+
- Memory store ([memory-store.md](memory-store.md)): match method uses `db.search`
|
|
93
|
+
|
|
94
|
+
## Source files
|
|
95
|
+
|
|
96
|
+
- `src/sideband.ts` -- SidebandServer (server side) + sidebandMatch/sidebandPredictions/sidebandBehaviors (client helpers)
|
|
97
|
+
|
|
98
|
+
## Key invariants
|
|
99
|
+
|
|
100
|
+
- Socket path = SHA-256 of DB path. Both sides compute it independently.
|
|
101
|
+
- Sideband failure never blocks. All client helpers return null on failure.
|
|
102
|
+
- One embedding per request (all three methods share the model).
|
|
103
|
+
- 2-second timeout default.
|
|
104
|
+
- Stale socket cleanup on ECONNREFUSED/ENOENT.
|
package/docs/dev/gotchas.md
CHANGED
|
@@ -41,7 +41,7 @@ here first. These are the things that have already cost time.
|
|
|
41
41
|
a memory, write it with `archived: true`; to unarchive, `archived: false`.
|
|
42
42
|
- **Updating an archived memory requires explicit `archived` param.** If the
|
|
43
43
|
entry is already archived and a `remember` call omits the `archived` param,
|
|
44
|
-
the tool returns an error (`db.ts:
|
|
44
|
+
the tool returns an error (`db.ts:395`). Pass `archived: true` to keep it
|
|
45
45
|
archived or `archived: false` to unarchive. This guard prevents accidental
|
|
46
46
|
unarchival via an unrelated content update.
|
|
47
47
|
|
|
@@ -61,7 +61,7 @@ here first. These are the things that have already cost time.
|
|
|
61
61
|
- **`chat.message` has two priority tiers**: extraction nudge first (returns
|
|
62
62
|
early), then the prompt-aware recall nudge. Don't run both in one turn.
|
|
63
63
|
- **The extraction nudge peeks, never flushes.** The buffer is NOT drained
|
|
64
|
-
on nudge delivery (`index.ts:
|
|
64
|
+
on nudge delivery (`index.ts:366` — `peek()` call). It persists until the
|
|
65
65
|
agent writes a memory or calls `thatch_extraction_done`. Ignored nudges
|
|
66
66
|
accumulate; the `missedNudges` counter escalates the tone (polite at 0-1
|
|
67
67
|
misses, insistent at 2, ALL-CAPS at 3+). The counter resets when the
|
|
@@ -71,7 +71,7 @@ here first. These are the things that have already cost time.
|
|
|
71
71
|
is active. The peek-not-drain semantics still hold for the fallback nudge
|
|
72
72
|
path (MCP hosts and any `triggerExtraction` failure).
|
|
73
73
|
- **A child sub-agent's `thatch_memory_remember` drains the parent's buffer**
|
|
74
|
-
via the `childToParent` Map (`index.ts:
|
|
74
|
+
via the `childToParent` Map (`index.ts:79` declaration, `index.ts:272`
|
|
75
75
|
lookup). Two paths reach this machinery: (a) the **plugin-initiated child
|
|
76
76
|
session** — `triggerExtraction` calls `client.session.create` with a
|
|
77
77
|
`parentID`, the primary opencode path; (b) the **agent-initiated background
|
package/docs/dev/mcp-parity.md
CHANGED
|
@@ -18,7 +18,7 @@ This document maps the feature parity and documents the remaining gaps.
|
|
|
18
18
|
|
|
19
19
|
| Feature | OpenCode plugin | Claude Code MCP + hooks | Cursor MCP + hooks | Parity |
|
|
20
20
|
|---------|----------------|------------------------|---------------------|--------|
|
|
21
|
-
| **Tools** (
|
|
21
|
+
| **Tools** (18, single source of truth) | Plugin tool registration, `thatch_` prefix | MCP `tools/list` + `tools/call`, `mcp__thatch__` prefix | MCP `tools/list` + `tools/call`, `mcp__thatch__` prefix | **Full** |
|
|
22
22
|
| **System prompt** (store names, usage rules) | `experimental.chat.system.transform` — dynamic, repo baked in at runtime | CLAUDE.md static text appended by `thatch setup`; repo auto-detected by the MCP server at startup | AGENTS.md static text appended by `thatch setup`; repo auto-detected at startup | **Approximate** — static text persists through compaction, so the agent retains the usage instructions, but the dynamic per-turn refresh is lost |
|
|
23
23
|
| **Session-start reminder** (recall nudge + hygiene heartbeat) | `session.created` event → `client.session.prompt` injects a synthetic message | `SessionStart` hook → `thatch reminder`; stdout becomes context | `sessionStart` hook → `thatch reminder --json`; output is `additional_context` JSON | **Full** |
|
|
24
24
|
| **Compaction context** (re-familiarize after compaction) | `experimental.session.compacting` hook appends context to the compaction output | `PostCompact` hook — side-effects only, **cannot inject context** | No equivalent hook | **Gapped** — see below |
|
|
@@ -26,6 +26,7 @@ This document maps the feature parity and documents the remaining gaps.
|
|
|
26
26
|
| **Extraction feedback** (toast notifications) | `client.tui.showToast` fires when the extraction child goes idle — shows `[thatch] new: N, updated: M, deleted: K` (success) or `extraction complete — nothing to save` (info); best-effort, silently ignored in headless mode | No TUI connection — MCP hosts have no equivalent | No TUI connection | **Gapped** — MCP hosts cannot show toast notifications |
|
|
27
27
|
| **Prompt-aware recall nudge** | `chat.message` hook embeds the prompt with the in-process warm model, searches `db.search()`, pushes a nudge part if matches ≥ threshold | `UserPromptSubmit` hook → `thatch flush-tools` connects to the MCP server's sideband socket; the warm server embeds + searches; hook prints the nudge or falls back to the write nudge | `beforeSubmitPrompt` hook → `thatch flush-tools --json` (same sideband path) | **Full** — sideband socket gives cold hook processes access to the warm MCP server's model |
|
|
28
28
|
| **Prediction auto-fire** (user decision model) | `chat.message` hook scores the prompt embedding against prediction matchers; injects a `[thatch] User decision model` nudge alongside the recall nudge (separate synthetic part, same embedding call) | `UserPromptSubmit` hook → `thatch flush-tools` fires prediction query via the sideband socket's `predictions` method in parallel with the recall nudge | `beforeSubmitPrompt` hook → `thatch flush-tools --json` (same sideband path) | **Full** — same `scorePredictionNudge` entry point in both paths |
|
|
29
|
+
| **Behavior auto-fire** (self-discipline rules) | `chat.message` hook scores the prompt embedding against behavior matchers; injects a `[thatch] Situational behaviors` nudge (separate synthetic part, same embedding call) | `UserPromptSubmit` hook → `thatch flush-tools` fires behavior query via the sideband socket's `behaviors` method in parallel with recall and predictions | `beforeSubmitPrompt` hook → `thatch flush-tools --json` (same sideband path) | **Full** — same `scoreBehaviorNudge` entry point in both paths |
|
|
29
30
|
| **Skills** | Installed to `$XDG_CONFIG_HOME/opencode/skills` at plugin init (shared **+** opencode-only) | Installed to `$CLAUDE_CONFIG_DIR/skills/` by `thatch setup` (shared only) | Installed to `~/.cursor/skills/` by `thatch setup` (shared only) | **Full** — same SKILL.md format; the code-review coordinator is opencode-only (needs sub-agents) |
|
|
30
31
|
| **Store detection** (repo identity from git remote) | `worktree` parameter from the opencode plugin | `CLAUDE_PROJECT_DIR` env (set by Claude Code for stdio MCP servers) | `CURSOR_PROJECT_DIR` then `CLAUDE_PROJECT_DIR` then cwd | **Full** |
|
|
31
32
|
| **Setup detection at startup** | n/a — plugin auto-installs at init | `checkSetup` in MCP server: detects missing or broken instructions in CLAUDE.md | Same as Claude Code (checks AGENTS.md) | **Full** — warns the agent to tell the user to run `thatch setup` |
|
|
@@ -151,9 +152,10 @@ same socket path without out-of-band coordination. The path lives under
|
|
|
151
152
|
`os.tmpdir()`.
|
|
152
153
|
|
|
153
154
|
The protocol is newline-delimited JSON: one request per connection, one
|
|
154
|
-
response. Requests are `{"method":"match",
|
|
155
|
-
"threshold":N,"limit":N}`. Responses are
|
|
156
|
-
`{"ok":
|
|
155
|
+
response. Requests are `{"method":"match|predictions|behaviors",
|
|
156
|
+
"text":"...","stores":[...],"threshold":N,"limit":N}`. Responses are
|
|
157
|
+
`{"ok":true,"matches":[...]}` / `{"ok":true,"predictions":[...]}` /
|
|
158
|
+
`{"ok":true,"behaviors":[...]}` or `{"ok":false,"error":"..."}`.
|
|
157
159
|
|
|
158
160
|
Graceful degradation: if the socket isn't available (MCP server not running,
|
|
159
161
|
old version, stale socket from a crash, or a >2 s timeout), `sidebandMatch`
|
|
@@ -35,8 +35,8 @@ threw an error (the `extracting` set is cleared on failure).
|
|
|
35
35
|
|
|
36
36
|
`client.tui.showToast` is called from the `event` hook (on child idle, with
|
|
37
37
|
extraction metrics: new/updated/deleted counts) and from `chat.message` (on
|
|
38
|
-
recall and
|
|
39
|
-
not connected (headless mode).
|
|
38
|
+
recall, prediction, and behavior matches). Best-effort — silently ignored if
|
|
39
|
+
the TUI is not connected (headless mode).
|
|
40
40
|
|
|
41
41
|
## Claude Code (MCP server + hooks)
|
|
42
42
|
|
|
@@ -71,7 +71,7 @@ in the repo; only skills are user-scoped.
|
|
|
71
71
|
|-------|---------|--------|------|
|
|
72
72
|
| `SessionStart` | `thatch reminder` | plain text to stdout (becomes context) | Recall instructions + hygiene heartbeat |
|
|
73
73
|
| `PostToolBatch` | `thatch buffer-batch` | **silent** (no stdout) | Appends a batch of tool calls to the file-backed JSONL queue |
|
|
74
|
-
| `UserPromptSubmit` | `thatch flush-tools` | nudge text to stdout | Peeks queue (extraction nudge), else recall
|
|
74
|
+
| `UserPromptSubmit` | `thatch flush-tools` | nudge text to stdout | Peeks queue (extraction nudge), else fires recall, prediction, and behavior nudges via sideband in parallel, else write nudge |
|
|
75
75
|
|
|
76
76
|
`PostToolBatch` is silent so the agent loop is not delayed; the buffered
|
|
77
77
|
content is invisible until `UserPromptSubmit` peeks it.
|
|
@@ -111,7 +111,7 @@ is honored for symmetry and forward-compatibility. Cursor has no equivalent of
|
|
|
111
111
|
|-------|---------|--------|------|
|
|
112
112
|
| `sessionStart` | `thatch reminder --json` | `{ additional_context: "..." }` | Recall + heartbeat, JSON-wrapped for Cursor |
|
|
113
113
|
| `postToolUse` | `thatch buffer-tool` | **silent** | Appends a **single** tool call to the file-backed queue |
|
|
114
|
-
| `beforeSubmitPrompt` | `thatch flush-tools --json` | JSON `additional_context` | Peeks queue, else recall via sideband, else write nudge |
|
|
114
|
+
| `beforeSubmitPrompt` | `thatch flush-tools --json` | JSON `additional_context` | Peeks queue, else recall, prediction, and behavior via sideband, else write nudge |
|
|
115
115
|
|
|
116
116
|
Differences from Claude Code:
|
|
117
117
|
|
package/docs/dev/skills.md
CHANGED
|
@@ -25,12 +25,13 @@ description: Extract durable project facts ... Use when ...
|
|
|
25
25
|
```
|
|
26
26
|
|
|
27
27
|
- `name` must match the directory name (`<skillsDir>/<name>/SKILL.md`).
|
|
28
|
-
- `description` drives when the agent loads the skill (
|
|
29
|
-
Cursor auto-discover skills and use the description for
|
|
28
|
+
- `description` drives when the agent loads the skill (opencode, Claude
|
|
29
|
+
Code, and Cursor all auto-discover skills and use the description for
|
|
30
|
+
relevance).
|
|
30
31
|
|
|
31
|
-
## The
|
|
32
|
+
## The 24 skills
|
|
32
33
|
|
|
33
|
-
**Shared (
|
|
34
|
+
**Shared (23)** — installed everywhere; no sub-agents required:
|
|
34
35
|
|
|
35
36
|
| Skill | Role |
|
|
36
37
|
|-------|------|
|
|
@@ -40,6 +41,7 @@ description: Extract durable project facts ... Use when ...
|
|
|
40
41
|
| `thatch-review-pedantic` | Mechanical correctness: spelling, naming, doc accuracy, specs, stale artifacts. |
|
|
41
42
|
| `thatch-review-acceptance` | Behavioral/product review: UX, behavioral delta, integration effects. |
|
|
42
43
|
| `thatch-review-state-flow` | Data flow and contracts: module boundaries, implicit FSMs, error propagation. |
|
|
44
|
+
| `thatch-review-economy` | Design simplicity and maintainability: is the complexity earned? Evaluates both the overall change design (forest) and individual touch points (trees) for unnecessary complexity, redundancy, and simpler available alternatives. |
|
|
43
45
|
| `thatch-review-no-slop` | AI writing anti-patterns: change narration, fourth-wall breaks, em dashes, filler. |
|
|
44
46
|
| `thatch-review-breadcrumbs` | Comment narrative: do comments form a coherent outline of behavior? |
|
|
45
47
|
| `thatch-review-mark-and-sweep` | Mechanical change completeness: whole-repo sweep for stragglers after renames, flag removals, API substitutions. |
|
|
@@ -61,11 +63,11 @@ description: Extract durable project facts ... Use when ...
|
|
|
61
63
|
|
|
62
64
|
| Skill | Role |
|
|
63
65
|
|-------|------|
|
|
64
|
-
| `thatch-code-review` | Resolve review target (incl. VCS detection and connected PR/MR lookup for follow-up round detection), gather project context, research affected workflows, estimate complexity, partition, dispatch the
|
|
66
|
+
| `thatch-code-review` | Resolve review target (incl. VCS detection and connected PR/MR lookup for follow-up round detection), gather project context, research affected workflows, estimate complexity, partition, dispatch the 8 specialists in parallel, synthesize with a workflow-change preface and prior-comment cross-reference. |
|
|
65
67
|
|
|
66
68
|
## REVIEW_COMMON
|
|
67
69
|
|
|
68
|
-
The
|
|
70
|
+
The seven problem-finding review specialists share a framework interpolated via `${REVIEW_COMMON}` (the eighth specialist, highlights, finds positive things and uses its own structure):
|
|
69
71
|
|
|
70
72
|
- **Static analysis only** — no running tests/linters/compilers.
|
|
71
73
|
- **Scope gathering** — resolve the git range, `git diff --stat`, read changed
|
|
@@ -95,7 +97,7 @@ The synthesizer reuses the same verification rigor but has its own structure
|
|
|
95
97
|
## The two arrays
|
|
96
98
|
|
|
97
99
|
```ts
|
|
98
|
-
const SHARED_SKILLS: SkillDef[] = [ /*
|
|
100
|
+
const SHARED_SKILLS: SkillDef[] = [ /* 23 skills above */ ];
|
|
99
101
|
const OPENCODE_ONLY_SKILLS: SkillDef[] = [ /* code-review coordinator */ ];
|
|
100
102
|
```
|
|
101
103
|
|
|
@@ -132,7 +134,7 @@ and `--cursor` pass only the shared set.
|
|
|
132
134
|
## Memory review skills in practice
|
|
133
135
|
|
|
134
136
|
- **Quick single lens**: load any specialist directly and point it at a branch.
|
|
135
|
-
- **Full review on opencode**: load `thatch-code-review` — it gathers project context, researches affected workflows, dispatches all
|
|
137
|
+
- **Full review on opencode**: load `thatch-code-review` — it gathers project context, researches affected workflows, dispatches all 8 specialists in parallel (with both the context brief and workflow guide injected into each briefing), then synthesizes a report that starts with the workflow changes before findings.
|
|
136
138
|
- **Full review on Claude Code/Cursor**: run each specialist in sequence, then
|
|
137
139
|
run `thatch-review-synthesizer` to verify and aggregate.
|
|
138
140
|
- **Follow-up round (re-review)**: load `thatch-review-followup` when the author
|
package/docs/plans/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Plans
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Plan documents capture design decisions that span multiple sessions.
|
|
4
4
|
Each plan is a snapshot of the reasoning at the time — subsequent plans may
|
|
5
5
|
supersede earlier ones as the project evolves.
|
|
6
6
|
|
|
@@ -9,7 +9,7 @@ Plans are temporary. When a plan is fully implemented, it **graduates**:
|
|
|
9
9
|
1. The plan file is removed from this folder.
|
|
10
10
|
2. The final architecture is documented in `docs/dev/` — either updated into
|
|
11
11
|
existing dev docs or captured in a new one.
|
|
12
|
-
3. End-to-end use-case scenarios are added to `
|
|
12
|
+
3. End-to-end use-case scenarios are added to `tests/qa/`.
|
|
13
13
|
|
|
14
14
|
Once graduated, the dev docs and use-case docs are the permanent record. The
|
|
15
15
|
plan file is no longer needed — git history preserves it if someone needs the
|