@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.
- package/README.md +7 -7
- package/artifacts/skills/common.md +1 -1
- package/artifacts/skills/thatch-change-walkthrough.md +2 -2
- package/artifacts/skills/thatch-code-archaeology.md +252 -0
- package/artifacts/skills/thatch-code-review.md +4 -4
- package/artifacts/skills/thatch-code-walkthrough.md +2 -2
- package/artifacts/skills/thatch-coding-workflow.md +79 -0
- package/artifacts/skills/{pr-description.md → thatch-pr-description.md} +1 -1
- package/artifacts/skills/thatch-review-context.md +9 -0
- package/artifacts/skills/thatch-review-followup.md +29 -1
- package/artifacts/skills/thatch-review-pedantic.md +16 -1
- package/artifacts/skills/thatch-review-response.md +365 -0
- package/artifacts/skills/thatch-review-synthesizer.md +92 -5
- package/artifacts/skills/{split-overlarge-pr.md → thatch-split-overlarge-pr.md} +1 -1
- package/artifacts/skills/{ticket-description.md → thatch-ticket-description.md} +3 -3
- package/bin/release +3 -3
- package/bin/thatch +8 -8
- package/docs/dev/README.md +1 -1
- package/docs/dev/skills.md +29 -9
- package/docs/plans/README.md +9 -6
- package/docs/plans/intuition-drives.md +147 -0
- package/docs/plans/nomenclater.md +89 -0
- package/docs/plans/prediction-consolidation.md +361 -0
- package/docs/qa/README.md +20 -3
- package/docs/user/README.md +19 -5
- package/package.json +1 -1
- package/src/db.ts +6 -6
- package/src/embeddings.ts +2 -2
- package/src/extract-queue.ts +4 -4
- package/src/extraction.ts +4 -4
- package/src/git.ts +1 -1
- package/src/hygiene.ts +1 -1
- package/src/index.ts +28 -28
- package/src/mcp.ts +5 -5
- package/src/prompts.ts +71 -68
- package/src/setup.ts +19 -19
- package/src/sideband.ts +3 -3
- package/src/skills.ts +104 -6
- package/src/tool-defs.ts +11 -11
- package/src/tools.ts +1 -1
- package/artifacts/skills/thatch-workflow-research.md +0 -91
- package/docs/in-progress/prediction-engine.md +0 -404
- package/docs/plans/001-memory-store.md +0 -106
- package/docs/plans/002-agent-driven-pipelines.md +0 -59
- package/docs/plans/003-memory-hygiene.md +0 -61
- package/docs/qa/use-cases/README.md +0 -51
- package/docs/qa/use-cases/UC-001-memory-roundtrip.md +0 -20
- package/docs/qa/use-cases/UC-002-dedup-cycle.md +0 -23
- package/docs/qa/use-cases/UC-003-extraction-nudge.md +0 -56
- package/docs/qa/use-cases/UC-004-cli-inspection.md +0 -22
- package/docs/qa/use-cases/UC-005-setup-install.md +0 -34
- package/docs/qa/use-cases/UC-006-cursor-hook-lifecycle.md +0 -32
- package/docs/qa/use-cases/UC-007-recall-nudge.md +0 -31
- package/docs/qa/use-cases/UC-008-hygiene-heartbeat.md +0 -26
- package/docs/qa/use-cases/UC-009-flush-tools-tiers.md +0 -33
- package/docs/qa/use-cases/UC-010-prime.md +0 -25
- package/docs/qa/use-cases/UC-011-write-time-similarity-warning.md +0 -24
- package/docs/qa/use-cases/UC-012-model-migration.md +0 -28
- package/docs/qa/use-cases/UC-013-compaction-context.md +0 -25
- package/docs/qa/use-cases/UC-014-skill-install-drift.md +0 -28
- package/docs/qa/use-cases/UC-015-env-override-matrix.md +0 -28
- package/docs/qa/use-cases/UC-016-concurrent-session-isolation.md +0 -37
- package/docs/qa/use-cases/UC-017-buffer-tool-vs-buffer-batch.md +0 -27
- package/docs/qa/use-cases/UC-018-mcp-startup-setup-detection.md +0 -38
- package/docs/qa/use-cases/UC-019-archived-memory-lifecycle.md +0 -36
- package/docs/qa/use-cases/UC-020-extraction-escalation.md +0 -52
- package/docs/qa/use-cases/UC-021-prediction-autofire.md +0 -21
- package/docs/qa/use-cases/UC-022-prediction-dedup.md +0 -19
- package/docs/qa/use-cases/UC-023-prediction-confidence-model.md +0 -23
- package/docs/qa/use-cases/UC-024-prediction-delete.md +0 -20
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
# Use Cases
|
|
2
|
-
|
|
3
|
-
Manual end-to-end QA scenarios for thatch. Each use case has preconditions,
|
|
4
|
-
steps, and expected results. These cover behavior the automated suite can't:
|
|
5
|
-
real opencode sessions, the real embedding model, and the CLI.
|
|
6
|
-
|
|
7
|
-
Newer use cases carry an _Automatable_ note flagging which are pure
|
|
8
|
-
file/IPC/CLI contracts ready to graduate into `bun:test` integration tests.
|
|
9
|
-
|
|
10
|
-
| Use case | Covers |
|
|
11
|
-
|----------|--------|
|
|
12
|
-
| [UC-001](UC-001-memory-roundtrip.md) | Remember/recall across sessions, store naming, duplicate rejection |
|
|
13
|
-
| [UC-002](UC-002-dedup-cycle.md) | Full dedup review cycle: find, classify, resolve, mark checked |
|
|
14
|
-
| [UC-003](UC-003-extraction-nudge.md) | Tool buffering → extraction nudge → agent-driven fact saving |
|
|
15
|
-
| [UC-004](UC-004-cli-inspection.md) | CLI commands, arg validation, env overrides |
|
|
16
|
-
| [UC-005](UC-005-setup-install.md) | `thatch setup --claude`/`--cursor`, project-local + `--global`, idempotent re-run, legacy hook migration |
|
|
17
|
-
| [UC-006](UC-006-cursor-hook-lifecycle.md) | Cursor hook lifecycle: `buffer-tool` (`conversation_id`), `flush-tools --json`, queue peek |
|
|
18
|
-
| [UC-007](UC-007-recall-nudge.md) | Prompt-aware recall nudge — opencode in-process + Claude/Cursor sideband paths; no telemetry |
|
|
19
|
-
| [UC-008](UC-008-hygiene-heartbeat.md) | Hygiene heartbeat: stale 90d, orphaned branches, pending dedup; advisory, agent-driven |
|
|
20
|
-
| [UC-009](UC-009-flush-tools-tiers.md) | `flush-tools` three-tier priority (extraction > recall > write) + sideband degradation |
|
|
21
|
-
| [UC-010](UC-010-prime.md) | `thatch prime` CLI dispatch chain (opencode/Cursor/claude), child exit code |
|
|
22
|
-
| [UC-011](UC-011-write-time-similarity-warning.md) | Write-time warning never blocks; merge or mark-distinct reconciliation |
|
|
23
|
-
| [UC-012](UC-012-model-migration.md) | `THATCH_MODEL` change: old memories skipped (not corrupted) until re-saved |
|
|
24
|
-
| [UC-013](UC-013-compaction-context.md) | Compaction context re-familiarization (opencode-only) |
|
|
25
|
-
| [UC-014](UC-014-skill-install-drift.md) | Skill install: 20 shared vs 21 opencode; drift overwritten on re-setup |
|
|
26
|
-
| [UC-015](UC-015-env-override-matrix.md) | `THATCH_DB_PATH`, `XDG_CONFIG_HOME`, `CLAUDE_CONFIG_DIR`, `THATCH_QUEUE_DIR`, `THATCH_RECALL_THRESHOLD`, `THATCH_MODEL` |
|
|
27
|
-
| [UC-016](UC-016-concurrent-session-isolation.md) | Per-session extraction isolation (in-memory + file queue); shared stateless sideband |
|
|
28
|
-
| [UC-017](UC-017-buffer-tool-vs-buffer-batch.md) | `buffer-batch` (Claude, `tool_calls[]`+`session_id`) vs `buffer-tool` (Cursor, single+`conversation_id`) |
|
|
29
|
-
| [UC-018](UC-018-mcp-startup-setup-detection.md) | MCP startup detects missing/broken setup instructions and warns the agent |
|
|
30
|
-
| [UC-019](UC-019-archived-memory-lifecycle.md) | Archive, search exclusion, update guard, unarchive |
|
|
31
|
-
| [UC-020](UC-020-extraction-escalation.md) | Nudge escalation (polite → insistent → ALL-CAPS), buffer persistence, `extraction_done` accept/complete |
|
|
32
|
-
| [UC-021](UC-021-prediction-autofire.md) | Prediction auto-fire: matcher scores prompt, prediction nudge injected alongside recall |
|
|
33
|
-
| [UC-022](UC-022-prediction-dedup.md) | Prediction create-on-existing: dedup finds match, links edge without disconfirming |
|
|
34
|
-
| [UC-023](UC-023-prediction-confidence-model.md) | Bayesian confidence math: create, confirm, soft (weak disconfirm), disconfirm signals |
|
|
35
|
-
| [UC-024](UC-024-prediction-delete.md) | Prediction delete with cascade, provenance inspection, not-found handling |
|
|
36
|
-
|
|
37
|
-
## Template
|
|
38
|
-
|
|
39
|
-
```markdown
|
|
40
|
-
# UC-NNN: Title
|
|
41
|
-
|
|
42
|
-
**Preconditions**
|
|
43
|
-
- State of the system before the test
|
|
44
|
-
|
|
45
|
-
**Steps**
|
|
46
|
-
1. Action
|
|
47
|
-
2. Action
|
|
48
|
-
|
|
49
|
-
**Expected**
|
|
50
|
-
- Observable outcome
|
|
51
|
-
```
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# UC-001: Remember and recall across sessions
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- thatch configured as a plugin in opencode (npm or local path)
|
|
5
|
-
- Working directory is a git repo with an `origin` remote
|
|
6
|
-
|
|
7
|
-
**Steps**
|
|
8
|
-
1. In an opencode session, ask the agent to remember a distinctive fact, e.g.
|
|
9
|
-
"remember that our staging DB lives at staging-db.internal:5432".
|
|
10
|
-
2. Confirm the agent calls `thatch_memory_remember` and reports `[saved]`.
|
|
11
|
-
3. End the session. Start a fresh session in the same repo.
|
|
12
|
-
4. Ask a related question: "where does staging data live?"
|
|
13
|
-
|
|
14
|
-
**Expected**
|
|
15
|
-
- The agent calls `thatch_memory_recall` and surfaces the saved fact with a
|
|
16
|
-
similarity score.
|
|
17
|
-
- `thatch list` (CLI) shows the memory in the repo's store (named
|
|
18
|
-
`owner/repo` from the git remote), not in `global`.
|
|
19
|
-
- Saving the same label again without `overwrite: true` is rejected with an
|
|
20
|
-
error naming the label and store.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# UC-002: Deduplication review cycle
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- A store containing at least two memories with near-identical content
|
|
5
|
-
(e.g. save "the API rate limit is 100 req/min" twice under different labels)
|
|
6
|
-
|
|
7
|
-
**Steps**
|
|
8
|
-
1. Ask the agent to check for duplicate memories.
|
|
9
|
-
2. Agent calls `thatch_find_duplicates`; the similar pair is reported with a
|
|
10
|
-
score above the 0.85 default threshold.
|
|
11
|
-
3. Agent loads the `thatch-dedup-classifier` skill and classifies the pair.
|
|
12
|
-
4. For a true duplicate: agent merges content via
|
|
13
|
-
`thatch_memory_remember(overwrite: true)` on the better label and deletes
|
|
14
|
-
the other via `thatch_memory_forget`.
|
|
15
|
-
5. For a false positive (unrelated/supplement/contradiction kept as-is):
|
|
16
|
-
agent records the verdict via `thatch_dedup_mark_checked`.
|
|
17
|
-
6. Ask the agent to check for duplicates again.
|
|
18
|
-
|
|
19
|
-
**Expected**
|
|
20
|
-
- After step 4 or 5, `thatch_find_duplicates` no longer reports the pair.
|
|
21
|
-
- Overwriting either memory of a checked pair afterwards clears the verdict:
|
|
22
|
-
the pair becomes eligible for re-reporting.
|
|
23
|
-
- Forgetting a memory clears all verdicts involving it.
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# UC-003: Fact extraction from tool activity
|
|
2
|
-
|
|
3
|
-
_Automatable: buffer/peek/escalation contract could be tested with the mock
|
|
4
|
-
client and a synthetic tool call sequence._
|
|
5
|
-
|
|
6
|
-
**Preconditions**
|
|
7
|
-
- thatch plugin active in an opencode session
|
|
8
|
-
|
|
9
|
-
**Steps**
|
|
10
|
-
1. Do some real work: have the agent read files, run commands, edit code —
|
|
11
|
-
any non-`thatch_*`, non-`skill`, non-`task` tool activity.
|
|
12
|
-
2. The agent's turn ends and the session goes idle.
|
|
13
|
-
|
|
14
|
-
**Expected (opencode — direct extraction, primary path)**
|
|
15
|
-
- The plugin's `event` hook catches `session.status` idle with pending tool
|
|
16
|
-
interactions and calls `triggerExtraction`: creates a child session via
|
|
17
|
-
`client.session.create({ parentID })` and prompts it via
|
|
18
|
-
`client.session.promptAsync` (or `client.session.prompt` fire-and-forget
|
|
19
|
-
if the env var is unset).
|
|
20
|
-
- The `extracting` set suppresses the nudge in `chat.message` while the
|
|
21
|
-
child runs — no nudge text appears in the user's conversation.
|
|
22
|
-
- The child loads `thatch-fact-extractor` and saves durable facts via
|
|
23
|
-
`thatch_memory_remember` — or saves nothing if the activity was routine.
|
|
24
|
-
- A `thatch_memory_remember` call in the child drains the parent's snapshot
|
|
25
|
-
entries from the buffer (via `consumeSnapshot` with `parentSnapshots`).
|
|
26
|
-
- When the child goes idle, the parent's snapshot entries are drained
|
|
27
|
-
(covering no-save runs where no memory was written), the child session is
|
|
28
|
-
deleted, and a toast notification fires with the extraction metrics
|
|
29
|
-
(`[thatch] new: N, updated: M, deleted: K`, or
|
|
30
|
-
`[thatch] extraction complete — nothing to save`).
|
|
31
|
-
- If `triggerExtraction` throws, the `extracting` set is cleared and the
|
|
32
|
-
nudge fires as a fallback on the next `chat.message` (see below).
|
|
33
|
-
|
|
34
|
-
**Expected (fallback nudge path — opencode when direct extraction fails,
|
|
35
|
-
and all MCP hosts)**
|
|
36
|
-
- The agent's context for the next message includes a `[thatch]` nudge
|
|
37
|
-
carrying a JSON payload summarizing the buffered tool interactions (tool
|
|
38
|
-
name, title, truncated args/output).
|
|
39
|
-
- The buffer is **not** drained on nudge delivery — it persists until the
|
|
40
|
-
agent writes a memory or accepts it by calling `thatch_extraction_done`.
|
|
41
|
-
Accepting quiets the nudge while holding the entries until the extractor
|
|
42
|
-
completes; a child extractor that errors or is deleted requeues them. If
|
|
43
|
-
the nudge is ignored, the next message carries a repeat nudge, escalating
|
|
44
|
-
in urgency:
|
|
45
|
-
- 1st-2nd miss: polite tone
|
|
46
|
-
- 3rd consecutive miss (missedCount=2): insistent (directive) tone
|
|
47
|
-
- 4th+ consecutive miss (missedCount>=3): ALL-CAPS tone
|
|
48
|
-
The counter resets when the buffer drains (memory write) or is accepted
|
|
49
|
-
(`thatch_extraction_done`).
|
|
50
|
-
- A `thatch_memory_remember` call in a child sub-agent session also drains
|
|
51
|
-
the parent's buffer (via the `childToParent` Map), so dispatching the
|
|
52
|
-
fact-extractor as a background task clears the parent's queue.
|
|
53
|
-
- Two concurrent sessions never see each other's interactions in a nudge.
|
|
54
|
-
- The agent's own `thatch_*` tool calls never appear in a payload (no
|
|
55
|
-
feedback loop). `skill` and `task` tool calls are also excluded (buffering
|
|
56
|
-
them would create a nudge → skill load → buffer → nudge loop).
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# UC-004: Inspecting stores from the shell
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- Bun on PATH; thatch installed (`npm i -g @jeffober/thatch` or a checkout)
|
|
5
|
-
- At least one memory saved via opencode
|
|
6
|
-
|
|
7
|
-
**Steps**
|
|
8
|
-
1. `thatch stores` — list all stores.
|
|
9
|
-
2. `cd` into the project's repo, then `thatch list` — labels default to the
|
|
10
|
-
repo's store.
|
|
11
|
-
3. `thatch show <label>` — full content.
|
|
12
|
-
4. `thatch search "some topic"` — semantic search (downloads/loads the real
|
|
13
|
-
embedding model on first use; prints a loading notice to stderr).
|
|
14
|
-
5. `thatch search some topic` (unquoted, multi-word).
|
|
15
|
-
6. `thatch search "query" bogus-store`.
|
|
16
|
-
|
|
17
|
-
**Expected**
|
|
18
|
-
- Steps 1–4 behave as described; search results are ranked with scores.
|
|
19
|
-
- Step 5 exits non-zero with an error telling you to quote the query —
|
|
20
|
-
it must NOT silently search a store named "topic".
|
|
21
|
-
- Step 6 exits non-zero listing the stores that do exist.
|
|
22
|
-
- All commands respect `THATCH_DB_PATH` and `$XDG_CONFIG_HOME`.
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
# UC-005: Setup install (Claude Code and Cursor)
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- Thatch installed and `bun` on PATH
|
|
5
|
-
- Target config dirs writable (`$XDG_CONFIG_HOME`, `$CLAUDE_CONFIG_DIR`, `~/.cursor`)
|
|
6
|
-
|
|
7
|
-
**Steps**
|
|
8
|
-
1. From a project root: `thatch setup --claude`
|
|
9
|
-
2. From the same project root: `thatch setup --cursor`
|
|
10
|
-
3. Repeat both commands (re-run idempotence and drift recovery)
|
|
11
|
-
4. Add a non-thatch hook to `.claude/settings.json` and `.cursor/hooks.json`,
|
|
12
|
-
then re-run setup
|
|
13
|
-
5. From elsewhere: `thatch setup --cursor --global`, then `thatch setup --claude --global`
|
|
14
|
-
|
|
15
|
-
**Expected**
|
|
16
|
-
- `--claude` project-local writes `.mcp.json` (`mcpServers.thatch`, stdio + `["mcp"]`),
|
|
17
|
-
appends a thatch block to `CLAUDE.md` bracketed by start/end markers (replaced, not
|
|
18
|
-
duplicated, on re-run), writes `.claude/settings.json` hooks (`SessionStart` -> `thatch reminder`,
|
|
19
|
-
`PostToolBatch` -> `thatch buffer-batch`, `UserPromptSubmit` -> `thatch flush-tools`), and installs
|
|
20
|
-
**20 shared skills** (no code-review coordinator) to `$CLAUDE_CONFIG_DIR/skills/` — user-scoped
|
|
21
|
-
even in project-local mode.
|
|
22
|
-
- `--cursor` project-local writes `.cursor/mcp.json`, appends to `AGENTS.md`, writes
|
|
23
|
-
`.cursor/hooks.json` in the **flat format** (`{version:1, hooks:{...}}`): `sessionStart` ->
|
|
24
|
-
`thatch reminder --json`, `postToolUse` -> `thatch buffer-tool`, `beforeSubmitPrompt` ->
|
|
25
|
-
`thatch flush-tools --json`; and installs 20 shared skills to `~/.cursor/skills/`.
|
|
26
|
-
- Re-run is idempotent: instructions are not duplicated, thatch hooks are replaced (not appended),
|
|
27
|
-
and non-thatch hooks are preserved. A legacy `thatch echo` hook is replaced with `flush-tools`.
|
|
28
|
-
- `--global` (Claude) writes `~/.claude/CLAUDE.md` + `~/.claude/settings.json` but **no project
|
|
29
|
-
`.mcp.json`** — it prints a `claude mcp add --scope user` command instead. `--global` (Cursor)
|
|
30
|
-
writes `~/.cursor/mcp.json`, `~/.cursor/AGENTS.md`, `~/.cursor/hooks.json`, `~/.cursor/skills/`.
|
|
31
|
-
|
|
32
|
-
_Automatable: yes — file presence and shape assertions on `.mcp.json`, `hooks.json`,
|
|
33
|
-
`CLAUDE.md`/`AGENTS.md` blocks, and the skills directory. `setup.test.ts` already covers the
|
|
34
|
-
unit contract; this is the end-to-end runbook version._
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
# UC-006: Cursor hook lifecycle
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- `thatch setup --cursor` has run; `.cursor/mcp.json` registers the thatch MCP server
|
|
5
|
-
- A store with at least one memory (for the recall tier)
|
|
6
|
-
|
|
7
|
-
**Steps**
|
|
8
|
-
1. Start a Cursor agent session; the MCP server boots and opens its sideband socket.
|
|
9
|
-
2. Have the agent run a non-thatch tool (e.g. read a file). The `postToolUse` hook runs
|
|
10
|
-
`thatch buffer-tool`, reading Cursor's stdin (`conversation_id`), and appends one
|
|
11
|
-
interaction to the session's queue file. Stdout is empty.
|
|
12
|
-
3. Have the agent run a thatch tool (`mcp__thatch__memory_list`). The hook fires but filters
|
|
13
|
-
it out — nothing is appended.
|
|
14
|
-
4. Submit a prompt. The `beforeSubmitPrompt` hook runs `thatch flush-tools --json`.
|
|
15
|
-
5. Submit the next prompt with no fresh tool activity since step 4.
|
|
16
|
-
|
|
17
|
-
**Expected**
|
|
18
|
-
- `buffer-tool` normalizes `conversation_id` to a safe session file name and appends exactly one
|
|
19
|
-
interaction per call; thatch's own `mcp__thatch__*` tools never enter the queue (no self-echo).
|
|
20
|
-
- `flush-tools` peeks the queue first (extraction tier): prints the JSON payload wrapped for
|
|
21
|
-
Cursor as `additional_context`. The queue is **not** deleted — it persists until the agent
|
|
22
|
-
writes a memory or calls `thatch_extraction_done`, so ignored nudges repeat and escalate
|
|
23
|
-
(polite to insistent to ALL-CAPS) on subsequent calls.
|
|
24
|
-
- With the queue empty and the sideband socket live, a semantically matching prompt yields a
|
|
25
|
-
recall nudge using the bare `memory_recall` tool name; below `THATCH_RECALL_THRESHOLD`
|
|
26
|
-
(default 0.55), no nudge.
|
|
27
|
-
- `buffer-tool` and `flush-tools --json` output is the shape Cursor's `additional_context`
|
|
28
|
-
field consumes.
|
|
29
|
-
|
|
30
|
-
_Automatable: partial — the `buffer-tool` and `flush-tools --json` CLI contracts are fully
|
|
31
|
-
automatable; the live Cursor agent loop (booting the MCP server, the agent acting on a nudge)
|
|
32
|
-
is manual._
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# UC-007: Prompt-aware recall nudge
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- A store with a memorable fact, e.g. "staging DB at staging-db.internal:5432"
|
|
5
|
-
- An opencode session AND (separately) a Claude Code / Cursor session with the MCP server
|
|
6
|
-
running and the sideband socket live
|
|
7
|
-
|
|
8
|
-
**Steps**
|
|
9
|
-
|
|
10
|
-
**opencode path**
|
|
11
|
-
1. Send a prompt matching the memory, e.g. "where does staging data live?"
|
|
12
|
-
2. Send an unrelated prompt.
|
|
13
|
-
3. Send a prompt shorter than 10 characters.
|
|
14
|
-
|
|
15
|
-
**Claude Code / Cursor path**
|
|
16
|
-
4. With the MCP server running and the sideband socket live, send a matching prompt (queue empty).
|
|
17
|
-
5. Stop the MCP server; send a matching prompt.
|
|
18
|
-
|
|
19
|
-
**Expected**
|
|
20
|
-
- opencode: the `chat.message` hook embeds the prompt text (skipped when shorter than 10 chars),
|
|
21
|
-
searches `db.search([repo, global])`; a match at or above 0.55 pushes a synthetic nudge part
|
|
22
|
-
with labels and scores (singular wording for one match; up to two labels plus "etc." for more).
|
|
23
|
-
- No match above threshold produces no nudge.
|
|
24
|
-
- The nudge uses `db.search`, not `db.recall`, so **no recall telemetry is stamped** — usage
|
|
25
|
-
tracking fires only on explicit `thatch_memory_recall` / CLI `search`, not on nudges.
|
|
26
|
-
- Claude Code / Cursor: `flush-tools` asks the warm MCP server via the sideband socket; the
|
|
27
|
-
returned labels become a nudge using the bare `memory_recall` name. With the MCP server down,
|
|
28
|
-
the recall nudge is absent (UC-009 covers the write-nudge fallback).
|
|
29
|
-
|
|
30
|
-
_Automatable: partial — the sideband embed + search round-trip and threshold logic are
|
|
31
|
-
unit-tested in `sideband.test.ts`; a live agent observing and acting on the nudge is manual._
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
# UC-008: Hygiene heartbeat
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- A store with: one memory not updated or recalled in 90+ days; one memory scoped to a git
|
|
5
|
-
branch that no longer exists; two near-duplicate memories (similarity > 0.85)
|
|
6
|
-
- A second, clean store for the negative case
|
|
7
|
-
|
|
8
|
-
**Steps**
|
|
9
|
-
1. `thatch hygiene` (from the repo)
|
|
10
|
-
2. `thatch reminder` (Claude Code hook shape) and `thatch reminder --json` (Cursor)
|
|
11
|
-
3. Start an opencode session and a Claude Code / Cursor session (the session-start path)
|
|
12
|
-
4. Run the same commands from a directory that is **not** a git repo
|
|
13
|
-
|
|
14
|
-
**Expected**
|
|
15
|
-
- The report names three signals — pending duplicate pairs, stale-memory count, orphaned-branch
|
|
16
|
-
memory count — and **only the non-zero ones**. A fully healthy store prints "Store is healthy."
|
|
17
|
-
(or `null`) and the reminder omits the hygiene block entirely.
|
|
18
|
-
- Both `reminder` shapes fold the hygiene block into the session-start text only when it is non-null.
|
|
19
|
-
- Outside a git repo, the orphaned-branch check is **skipped** — a missing branch list would
|
|
20
|
-
otherwise make everything look orphaned; stale and dup signals still report.
|
|
21
|
-
- Signals are advisory: thatch never deletes or merges memories itself. The agent acts on the
|
|
22
|
-
nudge to fix the store, by the same `memory_forget` / `dedup_mark_checked` tools as UC-002.
|
|
23
|
-
|
|
24
|
-
_Automatable: yes — `thatch hygiene` and `hygieneReport()` are pure functions over the DB and
|
|
25
|
-
git state (`hygiene.test.ts` covers the unit contract); the live session-injection path is
|
|
26
|
-
manual._
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# UC-009: flush-tools tier priority and sideband degradation
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- A Claude Code / Cursor session; `.mcp.json` and hooks installed
|
|
5
|
-
- At least one memory for the recall tier to match
|
|
6
|
-
- For the failure modes: a way to stop the MCP server and to leave a stale socket file
|
|
7
|
-
|
|
8
|
-
**Steps**
|
|
9
|
-
1. Put buffered non-thatch tool interactions in the queue (via `buffer-tool` / `buffer-batch`),
|
|
10
|
-
then run `thatch flush-tools --json`.
|
|
11
|
-
2. With the queue empty and the MCP server running, send a prompt matching a memory (recall tier),
|
|
12
|
-
then a prompt below threshold.
|
|
13
|
-
3. Stop the MCP server; run `flush-tools` with an empty queue.
|
|
14
|
-
4. Leave a stale socket file from a crashed MCP server; run `flush-tools`.
|
|
15
|
-
5. Make the sideband server hang (> 2 s); run `flush-tools`.
|
|
16
|
-
|
|
17
|
-
**Expected**
|
|
18
|
-
- Tiers fire in strict priority — **extraction > recall > write** — at most one nudge per call:
|
|
19
|
-
- extraction: queue non-empty -> JSON payload. The queue is peeked, not
|
|
20
|
-
deleted; it persists until a memory write or `extraction_done` (drains via
|
|
21
|
-
`consumeQueue` in `appendBatch`).
|
|
22
|
-
- recall: queue empty, socket live, match at or above `THATCH_RECALL_THRESHOLD` (default 0.55)
|
|
23
|
-
-> nudge with match labels; below threshold -> no nudge.
|
|
24
|
-
- write: socket unavailable, no matches, or socket error -> static
|
|
25
|
-
"did you learn anything worth persisting?" nudge.
|
|
26
|
-
- Sideband failure **never blocks** the agent: server down, a stale socket file, and a > 2 s
|
|
27
|
-
timeout all degrade to the write nudge. A stale socket file left by a crash is cleaned up on
|
|
28
|
-
connection error.
|
|
29
|
-
- `--json` wraps whichever nudge fires for Cursor's `additional_context`; plain stdout for Claude Code.
|
|
30
|
-
|
|
31
|
-
_Automatable: yes — `flush-tools` is a deterministic CLI contract and sideband failure modes
|
|
32
|
-
(server down, stale socket, timeout) plus tier ordering are filesystem/IPC only, with no LLM in
|
|
33
|
-
the loop._
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# UC-010: thatch prime
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- Thatch installed and `bun` on PATH
|
|
5
|
-
- At least one of: opencode (for `opencode run`), Cursor (`agent` CLI), or Claude Code
|
|
6
|
-
(`claude`) on PATH
|
|
7
|
-
|
|
8
|
-
**Steps**
|
|
9
|
-
1. From a project root, run `thatch prime`
|
|
10
|
-
2. Let the selected child CLI run the `thatch-project-primer` skill to completion
|
|
11
|
-
3. After it finishes, inspect the project store (`thatch list`)
|
|
12
|
-
|
|
13
|
-
**Expected**
|
|
14
|
-
- `prime` resolves the first available CLI in order — `opencode run`, then
|
|
15
|
-
`agent -p --approve-mcps` (Cursor), then `claude` — and spawns it with the project-primer
|
|
16
|
-
prompt.
|
|
17
|
-
- The primer skill recalls existing memories first, investigates the codebase from multiple
|
|
18
|
-
angles, and writes foundational memories via `thatch_memory_remember` (project vs global
|
|
19
|
-
assignment per its own rules), then runs dedup afterward.
|
|
20
|
-
- `prime` exits with the **child process's exit code** (0 on success).
|
|
21
|
-
- If no supported CLI is on PATH, `prime` fails fast with a clear error rather than spawning
|
|
22
|
-
nothing.
|
|
23
|
-
|
|
24
|
-
_Automatable: partial — the CLI dispatch selection (which child, which flags, exit-code
|
|
25
|
-
pass-through) is automatable; the LLM's real investigation and memory writing are manual._
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
# UC-011: Write-time similarity warning
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- A store with a memory, e.g. `API rate limit` -> "the API rate limit is 100 req/min"
|
|
5
|
-
- A second, similar memory not yet saved
|
|
6
|
-
|
|
7
|
-
**Steps**
|
|
8
|
-
1. Save the second memory under a different label with similar content, without
|
|
9
|
-
`overwrite: true`.
|
|
10
|
-
2. Read the tool's response.
|
|
11
|
-
|
|
12
|
-
**Expected**
|
|
13
|
-
- The save **succeeds** (`[saved] ...`) — the warning never blocks. The response
|
|
14
|
-
also carries a warning listing the existing memory with a similarity score and
|
|
15
|
-
instructions to reconcile.
|
|
16
|
-
- Two reconciliation paths both work:
|
|
17
|
-
- Merge: `memory_remember` the merged content with `overwrite: true` on the
|
|
18
|
-
better label, then `memory_forget` the other. The survivor has the combined
|
|
19
|
-
content; the deleted label is gone.
|
|
20
|
-
- Mark distinct: `dedup_mark_checked` the pair as `unrelated`. A subsequent
|
|
21
|
-
`find_duplicates` no longer reports the pair.
|
|
22
|
-
|
|
23
|
-
_Automatable: yes — the "save proceeds + warning lists similar entries" contract
|
|
24
|
-
and both reconciliation paths are pure tool/DB calls with no LLM in the loop._
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# UC-012: THATCH_MODEL migration (mixed embedding dimensions)
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- A store with memories embedded by a model of dimension A (e.g. the default
|
|
5
|
-
384-dim `bge-small-en-v1.5`)
|
|
6
|
-
- A second model available whose vectors have a **different** dimension
|
|
7
|
-
|
|
8
|
-
**Steps**
|
|
9
|
-
1. `export THATCH_MODEL=<other-model>` (different vector dimension).
|
|
10
|
-
2. Start a fresh session. `memory_list` and `memory_show` an old memory by label.
|
|
11
|
-
3. `memory_recall` for a topic that matches an old memory.
|
|
12
|
-
4. Save a new memory with the new model; `memory_recall` for it.
|
|
13
|
-
5. `memory_show` an old memory and inspect its `model` tag.
|
|
14
|
-
|
|
15
|
-
**Expected**
|
|
16
|
-
- `list` and `show` still return the old memories — the data is intact, **not
|
|
17
|
-
corrupted and not deleted**.
|
|
18
|
-
- `recall` returns **no matches** for the old memories: entries whose vector
|
|
19
|
-
dimension differs from the query are skipped, not scored. This is a silent
|
|
20
|
-
skip, not an error.
|
|
21
|
-
- The new memory embeds at the new dimension and is recallable.
|
|
22
|
-
- `show` reveals the old memories carry the old model tag while new ones carry
|
|
23
|
-
the new tag. There is **no automatic re-embedding** — old memories stay
|
|
24
|
-
invisible to search until re-saved.
|
|
25
|
-
|
|
26
|
-
_Automatable: yes — dimension-skip and data-intact assertions are pure DB calls;
|
|
27
|
-
use two `MockEmbeddingModel` instances with different dimensions (no network, no
|
|
28
|
-
real model download)._
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# UC-013: Compaction context (opencode-only)
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- An opencode session that grows long enough to trigger context compaction
|
|
5
|
-
- Several memories already stored in the repo's store
|
|
6
|
-
|
|
7
|
-
**Steps**
|
|
8
|
-
1. Work in the session until opencode compacts the context window.
|
|
9
|
-
2. Inspect the compaction output.
|
|
10
|
-
3. After compaction, ask the agent something that should use a memory tool.
|
|
11
|
-
|
|
12
|
-
**Expected**
|
|
13
|
-
- The compaction output includes the thatch re-familiarization context block
|
|
14
|
-
pushed by `experimental.session.compacting` — it reminds the agent that
|
|
15
|
-
`thatch_memory_recall` exists and that memories persist.
|
|
16
|
-
- After compaction, the agent still knows the memory tools exist and uses them
|
|
17
|
-
(it does not "forget" thatch just because the window was summarized).
|
|
18
|
-
- This behavior is **opencode-only**. Claude Code's `PostCompact` hook is
|
|
19
|
-
side-effects only and cannot inject context; Cursor has no equivalent hook.
|
|
20
|
-
See `docs/dev/mcp-parity.md` for the gap and its mitigation (CLAUDE.md /
|
|
21
|
-
AGENTS.md persists through compaction; the `SessionStart` recall reminder
|
|
22
|
-
runs again after compaction in Claude Code).
|
|
23
|
-
|
|
24
|
-
_Automatable: no — requires a live opencode compaction event. The hook's string
|
|
25
|
-
content is unit-tested, but actual compaction injection is manual._
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# UC-014: Skill install and drift recovery
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- Thatch installed; the host's skills directory empty
|
|
5
|
-
- `bun` on PATH
|
|
6
|
-
|
|
7
|
-
**Steps**
|
|
8
|
-
1. `thatch setup --claude` (and/or start an opencode session, and/or
|
|
9
|
-
`thatch setup --cursor`).
|
|
10
|
-
2. List the skills directory.
|
|
11
|
-
3. Edit one `SKILL.md` file locally to introduce drift.
|
|
12
|
-
4. Re-run `setup` (or restart opencode).
|
|
13
|
-
5. Check whether the `thatch-code-review` coordinator skill is present.
|
|
14
|
-
|
|
15
|
-
**Expected**
|
|
16
|
-
- Claude Code and Cursor install exactly **20 shared skills** to the skills
|
|
17
|
-
dir — the coordinator (`thatch-code-review`) is **absent** (it needs
|
|
18
|
-
sub-agents, which those hosts lack).
|
|
19
|
-
- opencode installs **21** — the 20 shared plus the coordinator.
|
|
20
|
-
- The locally edited `SKILL.md` is **overwritten** with the canonical content
|
|
21
|
-
on the next `setup`/init (drift detection: a file is only rewritten when its
|
|
22
|
-
content differs from the definition). Unrelated skill files are untouched.
|
|
23
|
-
- Skills never land in the worktree — always under the user-scoped config dir
|
|
24
|
-
(`~/.claude/skills`, `~/.cursor/skills`, `$XDG_CONFIG_HOME/opencode/skills`).
|
|
25
|
-
|
|
26
|
-
_Automatable: yes — file presence, count (20 vs 21), content-diff-overwrite, and
|
|
27
|
-
coordinator host-gating are all file assertions (`setup.test.ts` already covers
|
|
28
|
-
the unit contract)._
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# UC-015: Environment variable override matrix
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- Writable temp directories; `bun` on PATH
|
|
5
|
-
|
|
6
|
-
**Steps**
|
|
7
|
-
Set each variable and confirm the effect at the documented resolution point.
|
|
8
|
-
|
|
9
|
-
| Variable | Set to | Expected effect |
|
|
10
|
-
|----------|--------|------------------|
|
|
11
|
-
| `THATCH_DB_PATH` | a temp file path | the SQLite DB is created there (CLI + plugin + MCP) |
|
|
12
|
-
| `XDG_CONFIG_HOME` | a temp dir | the default DB (`$XDG_CONFIG_HOME/thatch/thatch.db`) and opencode skill dir move there; the real `~/.config` is untouched |
|
|
13
|
-
| `CLAUDE_CONFIG_DIR` | a temp dir | `thatch setup --claude --global` writes CLAUDE.md, settings.json, and skills under that dir; project-local keeps project paths but skills under the custom dir |
|
|
14
|
-
| `THATCH_QUEUE_DIR` | a temp dir | extraction-queue JSONL files land there instead of `$XDG_CACHE_HOME/thatch/queue` |
|
|
15
|
-
| `THATCH_RECALL_THRESHOLD` | a low value (e.g. `0.2`) | the prompt-aware recall nudge fires for weaker matches (a prompt that matched nothing at 0.55 now surfaces results) |
|
|
16
|
-
| `THATCH_MODEL` | a different model name | new memories carry the new model tag and vector dimension; old memories become invisible to search (see UC-012) |
|
|
17
|
-
|
|
18
|
-
**Expected**
|
|
19
|
-
- Each override takes effect at the point the docs describe (see
|
|
20
|
-
`docs/dev/setup-and-hooks.md` and the dev README config section). None require
|
|
21
|
-
a restart beyond the process that reads them.
|
|
22
|
-
- `THATCH_DB_PATH` and `XDG_CONFIG_HOME` change the **same** sideband socket
|
|
23
|
-
path (it is a hash of the resolved DB path) — so a hook process and the MCP
|
|
24
|
-
server must both resolve the same DB path or they miss each other.
|
|
25
|
-
|
|
26
|
-
_Automatable: yes — env resolution is deterministic and side-effect-free;
|
|
27
|
-
`setup.test.ts` already covers `CLAUDE_CONFIG_DIR`; the rest follow the same
|
|
28
|
-
shape._
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# UC-016: Concurrent session isolation
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- Two opencode sessions in the same repo (A and B)
|
|
5
|
-
- (Separately) two Claude Code / Cursor hook processes with different session IDs
|
|
6
|
-
|
|
7
|
-
**Steps**
|
|
8
|
-
|
|
9
|
-
**opencode (in-memory buffer)**
|
|
10
|
-
1. In session A, run a non-thatch tool (the extraction ring buffer records it).
|
|
11
|
-
2. In session B, send a message — `chat.message` runs.
|
|
12
|
-
3. In session A, send a message — `chat.message` runs.
|
|
13
|
-
|
|
14
|
-
**Claude Code / Cursor (file-backed queue)**
|
|
15
|
-
4. Hook process for session A calls `buffer-tool`/`buffer-batch`.
|
|
16
|
-
5. Hook process for session B calls `buffer-tool`/`buffer-batch`.
|
|
17
|
-
6. `flush-tools` is invoked for session A, then for session B.
|
|
18
|
-
|
|
19
|
-
**Sideband (shared warm model)**
|
|
20
|
-
7. Both sessions' `flush-tools` connect to the same sideband socket.
|
|
21
|
-
|
|
22
|
-
**Expected**
|
|
23
|
-
- **No cross-session bleed** in either path: session B's `chat.message` produces
|
|
24
|
-
no nudge from session A's buffered interaction; session B's message only sees
|
|
25
|
-
its own buffer. The in-memory `ExtractionPipeline` and the file-backed queue are
|
|
26
|
-
both keyed by session ID.
|
|
27
|
-
- `flush-tools` for session A peeks only A's queue file (does not delete it); a
|
|
28
|
-
second flush for A returns the same content with an escalated missed-nudge
|
|
29
|
-
counter (the queue persists until a memory write or `extraction_done`). Session
|
|
30
|
-
B's queue file is untouched and is peeked on its own flush.
|
|
31
|
-
- The sideband socket is **shared** (one warm MCP server) but **stateless per
|
|
32
|
-
query**: each request embeds a fresh prompt and returns its own matches. Two
|
|
33
|
-
concurrent match requests do not interfere.
|
|
34
|
-
|
|
35
|
-
_Automatable: yes — `extraction.test.ts` (in-memory per-session) and
|
|
36
|
-
`extract-queue.test.ts` (file-backed per-session) already cover isolation; the
|
|
37
|
-
sideband is a stateless request/response so concurrency is trivially safe._
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
# UC-017: buffer-tool vs buffer-batch contract
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- A Claude Code setup (`PostToolBatch` -> `buffer-batch`) and a Cursor setup
|
|
5
|
-
(`postToolUse` -> `buffer-tool`)
|
|
6
|
-
|
|
7
|
-
**Steps**
|
|
8
|
-
1. **Claude Code**: a `PostToolBatch` fires with a `tool_calls` array (several
|
|
9
|
-
tools, one a `mcp__thatch__*` call) and a `session_id`.
|
|
10
|
-
2. **Cursor**: a `postToolUse` fires for a single tool with a `conversation_id`.
|
|
11
|
-
3. Run `flush-tools` for both.
|
|
12
|
-
|
|
13
|
-
**Expected**
|
|
14
|
-
- `buffer-batch` (Claude Code) reads the `tool_calls` array and `session_id`,
|
|
15
|
-
appends all interactions to the session's JSONL queue, filters out
|
|
16
|
-
`mcp__thatch__*` calls, and caps at 20 (oldest dropped). It is **silent**.
|
|
17
|
-
- `buffer-tool` (Cursor) reads **one** tool call, normalizes `conversation_id`
|
|
18
|
-
to a safe filename (unsafe chars -> underscore), appends that single
|
|
19
|
-
interaction, filters `mcp__thatch__*`, same 20 cap. Also silent.
|
|
20
|
-
- Both write the same `ToolInteraction` shape to the same JSONL format, so
|
|
21
|
-
`flush-tools` drains them identically and `buildExtractionPayload` produces an
|
|
22
|
-
identical contract for the fact-extractor skill.
|
|
23
|
-
- Thatch's own tools never appear in either queue (no self-echo feedback loop).
|
|
24
|
-
|
|
25
|
-
_Automatable: yes — `extract-queue.test.ts` covers both shapes (batch with
|
|
26
|
-
`tool_calls` and single-tool), the `mcp__thatch__*` filter, the 20 cap, and
|
|
27
|
-
back-compat with `buildExtractionPayload`._
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
# UC-018: MCP startup setup detection
|
|
2
|
-
|
|
3
|
-
**Preconditions**
|
|
4
|
-
- Thatch installed and `bun` on PATH
|
|
5
|
-
- MCP server launched by Claude Code (`thatch mcp` with `CLAUDE_PROJECT_DIR` set)
|
|
6
|
-
or Cursor (`thatch mcp` with `CURSOR_PROJECT_DIR` set)
|
|
7
|
-
|
|
8
|
-
**Steps**
|
|
9
|
-
1. Start a Claude Code session in a project where `thatch setup --claude` was
|
|
10
|
-
never run (no `CLAUDE.md` with thatch markers, neither local nor global).
|
|
11
|
-
2. Call any thatch tool (e.g. `mcp__thatch__store_list`).
|
|
12
|
-
3. Repeat in a project where setup was run but `CLAUDE.md` was edited externally
|
|
13
|
-
and the thatch block's end marker was deleted.
|
|
14
|
-
4. Repeat in a project where setup was run correctly.
|
|
15
|
-
5. Repeat all steps for Cursor (substituting `--cursor`, `AGENTS.md`,
|
|
16
|
-
`CURSOR_PROJECT_DIR`).
|
|
17
|
-
|
|
18
|
-
**Expected**
|
|
19
|
-
- **Not-installed**: The first `tools/call` response is prepended with a
|
|
20
|
-
warning: "[thatch] Thatch is running as an MCP server but has not been set
|
|
21
|
-
up for Claude Code. ... Tell the user to run: thatch setup --claude". The
|
|
22
|
-
warning also appears on stderr. Subsequent tool responses are clean (warning
|
|
23
|
-
is one-shot).
|
|
24
|
-
- **Markers-broken**: The first `tools/call` response is prepended with a
|
|
25
|
-
warning naming the corrupted file and instructing the user to run
|
|
26
|
-
`thatch setup` (or manually remove the corrupted block and re-run).
|
|
27
|
-
- **Installed**: No warning. Tool responses are clean from the first call.
|
|
28
|
-
- **Cursor**: Same behavior, with "Cursor" substituted for "Claude Code" and
|
|
29
|
-
`thatch setup --cursor` in the message. When both `CURSOR_PROJECT_DIR` and
|
|
30
|
-
`CLAUDE_PROJECT_DIR` are set, Cursor detection takes priority.
|
|
31
|
-
- **No env var**: When neither `CURSOR_PROJECT_DIR` nor `CLAUDE_PROJECT_DIR` is
|
|
32
|
-
set (manual `thatch mcp` invocation), `checkSetup` returns `null` and no
|
|
33
|
-
warning is emitted.
|
|
34
|
-
|
|
35
|
-
_Automatable: yes — `setup.test.ts` already covers the unit contract (10 tests
|
|
36
|
-
in the `checkSetup` describe block: null, local, global, not-installed,
|
|
37
|
-
markers-broken, local priority, Cursor variants, Cursor priority). This is the
|
|
38
|
-
end-to-end runbook version._
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# UC-019: Archived memory lifecycle
|
|
2
|
-
|
|
3
|
-
_Automatable: archive guard + search/dedup/staleness exclusion are pure DB
|
|
4
|
-
contract testable with a temp DB._
|
|
5
|
-
|
|
6
|
-
**Preconditions**
|
|
7
|
-
- thatch plugin active in an opencode session (or CLI with a test store)
|
|
8
|
-
|
|
9
|
-
**Steps**
|
|
10
|
-
1. Save a memory scoped to a feature branch:
|
|
11
|
-
`thatch_memory_remember` with `branch: "feature-x"`, `label: "Feature X design decisions"`, `content: "..."`.
|
|
12
|
-
2. Merge or delete the branch. Save a consolidated archived memory:
|
|
13
|
-
`thatch_memory_remember` with `overwrite: true`, `archived: true`,
|
|
14
|
-
`branch: "feature-x"`, same label, consolidated content.
|
|
15
|
-
3. Search for content related to the archived memory:
|
|
16
|
-
`thatch_memory_recall` with a relevant query (no `includeArchived`).
|
|
17
|
-
4. Search again with `includeArchived: true`.
|
|
18
|
-
5. Attempt to update the archived memory's content without passing the
|
|
19
|
-
`archived` param.
|
|
20
|
-
6. Unarchive the memory: `thatch_memory_remember` with `overwrite: true`,
|
|
21
|
-
`archived: false`.
|
|
22
|
-
|
|
23
|
-
**Expected**
|
|
24
|
-
- Step 2: the memory is saved with `archived: true`. The `archived` column is
|
|
25
|
-
set to 1 in the database.
|
|
26
|
-
- Step 3: the archived memory does NOT appear in search results — `search`
|
|
27
|
-
filters `WHERE archived = 0`.
|
|
28
|
-
- Step 4: the archived memory DOES appear when `includeArchived: true` is
|
|
29
|
-
passed.
|
|
30
|
-
- Step 5: the tool returns an error: `"Feature X design decisions" is
|
|
31
|
-
archived. Pass archived: true to keep it archived, or archived: false to
|
|
32
|
-
unarchive it.` The content is NOT updated.
|
|
33
|
-
- Step 6: the memory is unarchived (`archived` column set to 0). It reappears
|
|
34
|
-
in normal search results.
|
|
35
|
-
- `find_duplicates` does not surface archived memories as candidates.
|
|
36
|
-
- `staleEntryCount` (hygiene) does not count archived memories as stale.
|