@jeffober/thatch 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/README.md +48 -25
  2. package/artifacts/skills/common.md +1 -0
  3. package/artifacts/skills/thatch-clear-writing.md +11 -0
  4. package/artifacts/skills/thatch-code-archaeology.md +9 -0
  5. package/artifacts/skills/thatch-code-review.md +25 -15
  6. package/artifacts/skills/thatch-plan-refinement.md +33 -4
  7. package/artifacts/skills/thatch-refine-personal.md +5 -0
  8. package/artifacts/skills/thatch-refine.md +7 -1
  9. package/artifacts/skills/thatch-review-clarity.md +101 -0
  10. package/artifacts/skills/thatch-review-context.md +55 -2
  11. package/artifacts/skills/thatch-review-followup.md +4 -4
  12. package/artifacts/skills/thatch-review-response.md +1 -1
  13. package/artifacts/skills/thatch-review-synthesizer.md +22 -2
  14. package/bin/thatch +103 -33
  15. package/docs/dev/README.md +11 -8
  16. package/docs/dev/features/README.md +1 -1
  17. package/docs/dev/features/behavior-engine.md +10 -0
  18. package/docs/dev/features/cli.md +23 -7
  19. package/docs/dev/features/commands.md +40 -9
  20. package/docs/dev/features/cross-session-chat.md +99 -27
  21. package/docs/dev/features/database.md +4 -4
  22. package/docs/dev/features/nudge-pipeline.md +14 -0
  23. package/docs/dev/features/opencode-plugin.md +41 -15
  24. package/docs/dev/features/prediction-engine.md +27 -1
  25. package/docs/dev/features/qa-system.md +19 -3
  26. package/docs/dev/features/session-lifecycle.md +6 -6
  27. package/docs/dev/features/session-tabs.md +11 -5
  28. package/docs/dev/gotchas.md +21 -0
  29. package/docs/dev/mcp-parity.md +3 -3
  30. package/docs/dev/skills.md +12 -8
  31. package/docs/user/README.md +22 -14
  32. package/docs/user/behavior-engine.md +7 -1
  33. package/docs/user/cli.md +28 -15
  34. package/docs/user/code-review.md +46 -4
  35. package/docs/user/commands.md +27 -7
  36. package/docs/user/cross-session-chat.md +48 -20
  37. package/docs/user/prediction-engine.md +12 -1
  38. package/docs/user/skills.md +9 -6
  39. package/package.json +1 -1
  40. package/src/capabilities.ts +20 -6
  41. package/src/chat.ts +56 -24
  42. package/src/commands.ts +109 -18
  43. package/src/db.ts +23 -2
  44. package/src/mcp.ts +6 -2
  45. package/src/opencode/tui-plugin.ts +29 -9
  46. package/src/opencode/v2.ts +247 -66
  47. package/src/prompts.ts +55 -6
  48. package/src/runtime.ts +122 -17
  49. package/src/scoring-engine.ts +40 -9
  50. package/src/session-tab-shared.ts +55 -4
  51. package/src/skills.ts +5 -9
  52. package/src/tab-state.ts +125 -0
  53. package/src/tool-defs.ts +55 -22
@@ -22,10 +22,10 @@ This document maps the feature parity and documents the remaining gaps.
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 |
25
- | **Wrap-up commands** (`/thatch/compact`, `/thatch/exit`) | Command markdown synced to `$XDG_CONFIG_HOME/opencode/command/thatch/` at plugin init; `command.execute.before` arms the session and the next idle resolves the greenlight token into a TUI action (`session.compact` via `executeCommand`, `app.exit` via `publish`) | No equivalent — no plugin host to arm the check or trigger the action | No equivalent | **Gapped** — needs the plugin's SDK client and TUI control routes |
26
- | **On-demand actions** (`/thatch/defrag`, `extract`, `hygiene`, `reflect`, `refine`) | Command markdown synced at plugin init; bodies rendered from the shared prompt cores with `thatch_` tool spellings; `extract` is opencode-only (needs session identity via `get_session_info` and the plugin's payload provider) | Command markdown synced by `thatch setup --claude` into `<claudeDir>/commands/thatch/`; same cores with `mcp__thatch__` spellings; `extract` excluded | MCP Prompts (`prompts/list` + `prompts/get`) from the same cores; Cursor surfaces them as slash commands; `extract` excluded | **Full** for the shared actions (same cores, per-host tool spellings); `extract` opencode-only |
25
+ | **Wrap-up commands** (`/thatch/compact`, `/thatch/exit`) | Command markdown synced to `$XDG_CONFIG_HOME/opencode/command/thatch/` at plugin init; `command.execute.before` arms the session and the next idle resolves the greenlight token into the host action (compact: the TUI compact command on v1, `session.compact` on v2; exit: `app.exit` on v1, the session's own tab closing on v2) | No equivalent — no plugin host to arm the check or trigger the action | No equivalent | **Gapped** — needs the plugin's SDK client and host action routes |
26
+ | **On-demand actions** (`/thatch/defrag`, `extract`, `hygiene`, `peer-review`, `refine`, `reflect`, `self-review`, `whois`) | Command markdown synced at plugin init; nudge-backed bodies rendered from the shared prompt cores with `thatch_` tool spellings, self-contained bodies (refine, whois, and the review-mode couchings peer-review/self-review) inline in the registry; `extract` and `whois` are opencode-only (they need session identity) | Command markdown synced by `thatch setup --claude` into `<claudeDir>/commands/thatch/`; same bodies with `mcp__thatch__` spellings; `extract` and `whois` excluded | MCP Prompts (`prompts/list` + `prompts/get`) from the same bodies; Cursor surfaces them as slash commands; `extract` and `whois` excluded | **Full** for the shared actions (same bodies, per-host tool spellings); `extract` and `whois` opencode-only |
27
27
  | **Extraction** (buffer tool calls, extract durable facts) | `tool.execute.after` buffers non-meta tool calls in-process (`isMetaToolName` in `src/extraction.ts`: thatch_*, skill, task, agent, subagent — execute calls unwrapping only thatch tools are also excluded); **direct extraction** is the primary path — when the parent session goes idle with pending buffer entries, the plugin creates a child session via the SDK (`client.session.create` with `parentID`) and prompts it to call `get_extraction_payload` (nudge suppressed via the `extracting` set); the `chat.message` nudge path is a **fallback** used when direct extraction throws | `PostToolBatch` → `thatch buffer-batch` (file-backed JSONL queue); `UserPromptSubmit` → `thatch flush-tools` peeks the queue and prints the nudge with session ID + fetch tool name (does not drain — the queue persists until a memory write or `extraction_done`) | `postToolUse` → `thatch buffer-tool` (single-tool, file-backed queue); `beforeSubmitPrompt` → `thatch flush-tools --json` | **Partial** — opencode uses direct extraction (parent idle → child session) as the primary path, with the nudge as fallback; MCP hosts are nudge-only. Both paths use `get_extraction_payload` to fetch the queued interactions as a tool response, keeping the full payload out of the main session's context window. Nudge timing differs: the nudge arrives at the **start** of the next turn in Claude Code/Cursor; opencode's direct extraction fires at **end of turn** (session idle), and the nudge fallback fires at the start of the next turn like MCP |
28
- | **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 |
28
+ | **Extraction feedback** (toast notifications) | `client.tui.showToast` on v1; the session-tab bridge's toast event -> the TUI plugin's `ui.toast.show` on v2 — fires when the extraction child goes idle, but ONLY when memories were actually written (no toast for no-save runs, to avoid notification fatigue): shows `[thatch] new: N, updated: M, deleted: K` (success); 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 |
29
29
  | **Automatic alerts** (notify on LLM pause / turn end) | Plugin event hook drives the `alerts.ts` state machine: `question.asked`/`permission.asked` → pause alert; `session.status` idle with a real-work round → done alert; unrecovered errors → needs-attention. Delivered via the shared `notify.ts` dispatcher, channel per event from the `alerts` config section | No event stream — only `thatch_notify_user` when the agent chooses | No event stream — only `thatch_notify_user` when the agent chooses | **Gapped** — MCP hosts have no plugin event hook to watch; Claude Code's `Notification`/`Stop` hooks could feed the same classifier later |
30
30
  | **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 |
31
31
  | **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 |
@@ -43,22 +43,23 @@ description: Extract durable project facts ... Use when ...
43
43
  | `thatch-review-state-flow` | Data flow and contracts: module boundaries, implicit FSMs, error propagation. |
44
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. |
45
45
  | `thatch-review-no-slop` | AI writing anti-patterns: change narration, fourth-wall breaks, em dashes, filler. |
46
+ | `thatch-review-clarity` | Prose clarity in comments, docstrings, error strings, and docs: made-up phrases, buzzwords, untranslated jargon, clause chains, buried leads, doc/code responsibility splits, checked against the project's clear-writing rules regardless of who wrote the text. |
46
47
  | `thatch-review-breadcrumbs` | Comment narrative: do comments form a coherent outline of behavior? |
47
48
  | `thatch-review-mark-and-sweep` | Mechanical change completeness: whole-repo sweep for stragglers after renames, flag removals, API substitutions. |
48
49
  | `thatch-review-highlights` | Positive finding detection: notably clever solutions, cleanup done along the way, documentation that helps. Medium-high bar against generic praise. |
49
50
  | `thatch-review-technique` | Technique lens: teaching-grade notes on unseen helpers/internal packages, companion techniques, house patterns, test-craft, API-shape principles, next-reader discoverability. Informational only, verified citations, never blocking. |
50
- | `thatch-review-synthesizer` | Verify specialist findings against code, dedupe, classify, calibrate severity. Starts the final report with a workflow-change preface, then cross-references findings against prior review comments when a follow-up round register is provided. |
51
- | `thatch-review-context` | Gather project/feature context (PR descriptions, git archaeology, ticket references, linked docs/tickets followed from the change, memory) before fan-out. Prevents false positives about intentionally deferred work, and checks whether main moved past the merge-base touching the same paths (staleness signal for the synthesizer). Also fetches prior review comments on a connected PR/MR for follow-up-round detection and builds a register with preliminary addressed-check status per comment. |
51
+ | `thatch-review-synthesizer` | Verify specialist findings against code, dedupe, classify, calibrate severity. Starts the final report with a workflow-change preface, then cross-references findings against prior review comments when a follow-up round register is provided, and against sibling PR registers when related PRs were detected (cross-PR notes appendix). |
52
+ | `thatch-review-context` | Gather project/feature context (PR descriptions, git archaeology, ticket references, linked docs/tickets followed from the change, memory) before fan-out. Prevents false positives about intentionally deferred work, and checks whether main moved past the merge-base touching the same paths (staleness signal for the synthesizer). Also fetches prior review comments on a connected PR/MR for follow-up-round detection and builds a register with preliminary addressed-check status per comment. Also discovers related PRs (stacks chained through base branches, release trains ordered by tracker relations) and builds a sibling register with targeted consistency verdicts. |
52
53
  | `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, skeletons) before proposing changes. The research skill; pair with `thatch-coding-workflow`. |
53
54
  | `thatch-review-followup` | Alternate entrypoint for follow-up review rounds. Verifies whether the author's responses and code changes since your last review round adequately addressed your prior findings, offers to reply on resolved items, then optionally re-runs the full structured review. |
54
55
  | `thatch-change-walkthrough` | Explain a change to the user as a teaching walkthrough: resolve the delta, research each affected workflow at the merge-base, teach current behavior, then overlay the modifications with file:line citations and analogies. |
55
56
  | `thatch-code-walkthrough` | Explain a feature, module, or workflow to the user as a teaching walkthrough: identify the code area (optionally from a branch or PR), research how it works, teach it with file:line citations and analogies, list the key files. |
56
57
  | `thatch-session-reflection` | End-of-session memory recording (project, user, tools, self). |
57
58
  | `thatch-coding-workflow` | Plan and execute code changes with a task-list-driven workflow. Use when implementing features, fixing bugs, or making multi-file changes. |
58
- | `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). The generic core loop. |
59
- | `thatch-refine` | Classify the project (audience, lifecycle, surface) and refine a plan under that type's requirements. Entry point for the `thatch-refine-*` family; also the `/thatch/refine` command. |
59
+ | `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). The generic core loop. Plans with UI or session state carry a state-and-transition matrix; template ports carry a deltas-from-template ledger; a revision self-check runs between revise and re-review; user-extended runs rotate reviewer lenses and stop on a round with no build-changing findings. Deep-mode triggers are binding. |
60
+ | `thatch-refine` | Classify the project (audience, lifecycle, surface) and refine a plan under that type's requirements. Entry point for the `thatch-refine-*` family; also the `/thatch/refine` command. Deep-mode triggers in the core skill are binding; type deltas relax round counts, never mode selection. |
60
61
  | `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. |
61
- | `thatch-refine-personal` | Refinement deltas for solo projects with no downstream consumers: relaxed coordination, cleverness and experimentation welcome, premise verification stays honest. |
62
+ | `thatch-refine-personal` | Refinement deltas for solo projects with no downstream consumers: relaxed coordination, cleverness and experimentation welcome, premise verification stays honest. Relaxes round counts only, never mode selection. |
62
63
  | `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. |
63
64
  | `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. |
64
65
  | `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. |
@@ -75,11 +76,11 @@ description: Extract durable project facts ... Use when ...
75
76
 
76
77
  | Skill | Role |
77
78
  |-------|------|
78
- | `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 review specialists in parallel, synthesize with a workflow-change preface and prior-comment cross-reference. |
79
+ | `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 review specialists in parallel, synthesize with a workflow-change preface, prior-comment cross-reference, and sibling-register cross-reference. Also the machinery behind the `/thatch/self-review` and `/thatch/peer-review` mode commands, which run it with a weighting overlay (inline, without sub-agents, on hosts that lack the coordinator). |
79
80
 
80
81
  ## REVIEW_COMMON
81
82
 
82
- 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):
83
+ The problem-finding review specialists share a framework interpolated via `${REVIEW_COMMON}` (the technique and highlights specialists do not use it: technique reports informational notes and highlights finds positive things, each with its own structure):
83
84
 
84
85
  - **Static analysis only** — no running tests/linters/compilers.
85
86
  - **Scope gathering** — resolve the git range, `git diff --stat`, read changed
@@ -93,6 +94,9 @@ The seven problem-finding review specialists share a framework interpolated via
93
94
  - **Project context awareness** — if a context brief is provided (from the
94
95
  coordinator or from loading `thatch-review-context`), use it to avoid false
95
96
  positives about intentionally deferred work.
97
+ - **Sibling PR context** — when the brief's sibling register is present
98
+ (related PRs detected), check it before flagging anything as referenced but
99
+ missing; a stack member or release-train sibling may deliver the piece.
96
100
  - **Workflow context awareness** — if a workflow guide is provided (from the
97
101
  coordinator or from loading `thatch-code-archaeology`), use it to understand
98
102
  the purpose and evolution of the code, distinguishing intentional behavior
@@ -143,7 +147,7 @@ and `--cursor` pass only the shared set.
143
147
 
144
148
  ## Adding a skill
145
149
 
146
- 1. Write `artifacts/skills/thatch-<name>.md` with YAML frontmatter. If it's a problem-finding review specialist, include `${REVIEW_COMMON}` (interpolated from `artifacts/skills/common.md`). The highlights specialist does not use REVIEW_COMMON — it finds positive things, not problems, so the problem-finding framework does not apply.
150
+ 1. Write `artifacts/skills/thatch-<name>.md` with YAML frontmatter. If it's a problem-finding review specialist, include `${REVIEW_COMMON}` (interpolated from `artifacts/skills/common.md`). The technique and highlights specialists do not use REVIEW_COMMON — technique reports informational notes and highlights finds positive things, so the problem-finding framework does not apply to either.
147
151
  2. Add the skill name to the `names` array in `loadSharedSkills()` (or `loadOpencodeOnlySkills()` if sub-agents are needed). The loader in `src/skills.ts` reads `.md` files at init.
148
152
  3. If the skill name appears in a tool's workflow (e.g. `thatch-fact-extractor`), update `src/prompts.ts`.
149
153
  4. Run `mise run check` — tests verify counts; `installSkills` picks up new files on next init.
@@ -202,11 +202,11 @@ requirements.
202
202
  | Tool | What it does |
203
203
  |------|-------------|
204
204
  | `thatch_chat_register` | Join the cross-session chat directory, so other sessions on this machine can message you. Display names are assigned by thatch, never chosen (a pool name plus a never-reused counter), so a name always refers to the same session. Call with no arguments to join, rejoin after unregistering, or check your name. On hosts without session context (Claude Code, Cursor), pass the name your thatch hook printed as `as`. |
205
- | `thatch_chat_list` | List registered sessions grouped into Active and Stale sections (stale = two missed heartbeats, about a minute; its host process has probably stopped), with how long ago each last checked in, each session's project and checkout kind (project root or linked worktree), its topic, and your unread count. |
205
+ | `thatch_chat_list` | List registered sessions grouped into Active, Recent, and Stale sections (recent = alive but no open tab, so a wake may not be guaranteed; stale = two missed heartbeats, about a minute; its host process has probably stopped), with how long ago each last checked in, each session's project and checkout kind (project root or linked worktree), its topic, and your unread count. |
206
206
  | `thatch_chat_send` | Send a message to another registered session, by name or session id. The recipient is nudged when its session is idle. |
207
207
  | `thatch_chat_read` | Drain your inbox: all unread messages oldest-first, marked read. Senders identified by display name. |
208
208
  | `thatch_chat_unregister` | Leave the chat directory. |
209
- | `thatch_chat_broadcast` | Send one message to every other live registered session at once. Stale sessions (dead host processes) are skipped and reported. Use sparingly: every live session pays a model turn for a broadcast. |
209
+ | `thatch_chat_broadcast` | Send one message to every other live registered session at once. Opencode sessions without an open tab (stale, or fresh but tab-less) are skipped and reported by name. Use sparingly: every open session pays a model turn for a broadcast. |
210
210
 
211
211
  See [cross-session-chat.md](cross-session-chat.md) for the full behavior,
212
212
  liveness model, and limitations.
@@ -248,16 +248,23 @@ Beyond the tools, thatch hooks into opencode itself:
248
248
  flushes pending fact extraction, finishes any promised memory writes, and
249
249
  surfaces todos or follow-ups it never addressed. The agent ends its
250
250
  response with a greenlight token only when the checklist is clean. Thatch
251
- watches for the token and then runs the compaction or exits opencode.
251
+ watches for the token and then runs the compaction or closes the session
252
+ (opencode 1 exits the whole app; opencode 2 closes the session's own tab.
253
+ Either way the session's watches are cancelled, and reopening or resuming
254
+ the session does not re-arm them - re-create watches you still want with
255
+ `thatch_watch_create`).
252
256
  Without the token nothing fires -- a toast points you at the items the
253
- agent listed, and you re-run the command once they're handled. Text typed
257
+ agent listed in its response, and you re-run the command once they're
258
+ addressed. Text typed
254
259
  after the command reaches the agent first, labeled as a `User Message`
255
260
  section ahead of the checklist (say goodbye or hand off context:
256
261
  `/thatch/exit Good work - see you tomorrow`). Alongside the wrap-ups,
257
- on-demand actions (`/thatch/defrag`, `/thatch/extract`, `/thatch/hygiene`,
258
- `/thatch/reflect`, `/thatch/whois`) run the memory-maintenance behaviors
259
- whenever you want,
260
- not just when a nudge fires -- see [commands.md](commands.md).
262
+ on-demand actions cover the memory-maintenance behaviors (`/thatch/defrag`,
263
+ `/thatch/extract`, `/thatch/hygiene`, `/thatch/reflect`) whenever you
264
+ want, not just when a nudge fires, plus the standalone commands: plan
265
+ refinement (`/thatch/refine`), the review modes (`/thatch/self-review`,
266
+ `/thatch/peer-review`), and the chat identity report (`/thatch/whois`)
267
+ -- see [commands.md](commands.md).
261
268
  A greenlit `/thatch/exit` also unregisters the session from the chat
262
269
  directory, so other sessions stop sending it mail. The commands
263
270
  self-install into `~/.config/opencode/command/thatch/` at plugin startup;
@@ -324,22 +331,23 @@ response, walkthrough, and workflow skills that support the review pipeline:
324
331
  | `thatch-review-state-flow` | Data flow and contracts: module boundaries, implicit state machines, error propagation, separation of concerns. |
325
332
  | `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. |
326
333
  | `thatch-review-no-slop` | AI writing anti-patterns: change narration, fourth wall breaks, em dashes, hedging, filler. |
334
+ | `thatch-review-clarity` | Prose clarity in comments, docstrings, error strings, and docs: made-up phrases, buzzwords, untranslated jargon, clause chains, buried leads, doc/code responsibility splits, checked against the project's clear-writing rules regardless of who wrote the text. |
327
335
  | `thatch-review-breadcrumbs` | Comment narrative: do comments form a coherent outline of the code's behavior? |
328
336
  | `thatch-review-mark-and-sweep` | Mechanical change completeness: whole-repo sweep for stragglers after renames, flag removals, API substitutions. |
329
337
  | `thatch-review-highlights` | Positive finding detection: notably clever solutions, cleanup done along the way, documentation that helps. Medium-high bar against generic praise. |
330
338
  | `thatch-review-technique` | Technique lens: teaching-grade notes on unseen helpers/internal packages, companion techniques, house patterns, test-craft, API-shape principles, next-reader discoverability. Informational only, never blocking. |
331
339
  | `thatch-review-synthesizer` | Verifies and synthesizes findings from multiple specialists into a report that starts with workflow changes, then highlights, then deduplicated severity-grouped findings. |
332
- | `thatch-review-context` | Gathers project context (PR descriptions, git archaeology, ticket references, linked docs/tickets, memory) before a review. Prevents false positives about intentionally deferred work. |
340
+ | `thatch-review-context` | Gathers project context (PR descriptions, git archaeology, ticket references, linked docs/tickets, memory, related PRs) before a review. Prevents false positives about intentionally deferred work and about pieces delivered by sibling PRs in a stack or release train. |
333
341
  | `thatch-code-archaeology` | Investigates an existing feature, debugs an unfamiliar area, or begins a new ticket. Explores the code base from multiple angles (data model, state flow, git history, sibling features, skeletons) before proposing changes. Pairs with `thatch-coding-workflow`. |
334
342
  | `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 your prior findings, offers to reply on resolved items, then optionally re-runs the full structured review. |
335
343
  | `thatch-review-response` | Author-side review response: triage findings on your own PR, fix bugs one by one, reply on each thread, post a top-level summary comment. |
336
344
  | `thatch-change-walkthrough` | Explains a change to the user as a teaching walkthrough: researches each affected workflow at the merge-base, teaches current behavior, then overlays the modifications with file:line citations. |
337
345
  | `thatch-code-walkthrough` | Explains a feature, module, or workflow to the user as a teaching walkthrough with file:line citations. Also used to draft high-level docs for new or undocumented features. |
338
346
  | `thatch-coding-workflow` | Plans and executes code changes with a task-list-driven workflow: complexity triage, milestone planning, research before coding, post-coding verification. Pairs with `thatch-code-archaeology` (research first, then plan). |
339
- | `thatch-plan-refinement` | Refines a plan before it is implemented: a fresh-context reviewer subagent re-checks the plan each round until consensus; deep mode adds specialist lenses (reuse, alternatives, hidden problems, safe-to-modify, intent archaeology). |
340
- | `thatch-refine` | Classifies the project (audience, lifecycle, surface) and refines a plan under that type's requirements. The entry point for the `thatch-refine-*` family; also the `/thatch/refine` command. |
347
+ | `thatch-plan-refinement` | Refines a plan before it is implemented: a fresh-context reviewer subagent re-checks the plan each round until consensus; deep mode adds specialist lenses (reuse, alternatives, hidden problems, safe-to-modify, intent archaeology). Plans with UI or session state must include a state-and-transition matrix; a revision self-check runs after each revision; extended runs rotate reviewer lenses and stop on a round with no build-changing findings. |
348
+ | `thatch-refine` | Classifies the project (audience, lifecycle, surface) and refines a plan under that type's requirements. The entry point for the `thatch-refine-*` family; also the `/thatch/refine` command. Deep-mode triggers in the core skill are binding; type deltas relax round counts, never mode selection. |
341
349
  | `thatch-refine-team-app` | Team codebases: consistency outranks cleverness, intent breadcrumbs are deliverables, pre-mortem and safe-to-modify lenses dominate. |
342
- | `thatch-refine-personal` | Solo projects: relaxed coordination, cleverness and experimentation welcome, premise verification stays honest. |
350
+ | `thatch-refine-personal` | Solo projects: relaxed coordination, cleverness and experimentation welcome, premise verification stays honest. Relaxes round counts, never mode selection. |
343
351
  | `thatch-refine-shared-lib` | Library API surfaces: flexible on input, strict on output, keep special cases out of the API, never foreclose caller options, docs are a deliverable. |
344
352
  | `thatch-refine-spike` | Throwaway prototypes: skip the loop, verify only the premises the experiment's conclusion depends on. |
345
353
  | `thatch-refine-infra` | CI, Terraform, and k8s changes: blast radius, mandatory rollback plan and staged verification, pattern-following is near-absolute. |
@@ -358,7 +366,7 @@ response, walkthrough, and workflow skills that support the review pipeline:
358
366
 
359
367
  | Skill | Purpose |
360
368
  |-------|---------|
361
- | `thatch-code-review` | Multi-agent review coordinator. Dispatches parallel sub-agents for triage, decomposition, specialist fan-out, and synthesis with a workflow-change preface. Not available in Claude Code (requires sub-agent support). |
369
+ | `thatch-code-review` | Multi-agent review coordinator. Dispatches parallel sub-agents for triage, decomposition, specialist fan-out, and synthesis with a workflow-change preface. Not available in Claude Code (requires sub-agent support), though the `/thatch/self-review` and `/thatch/peer-review` commands run the same specialists inline there. |
362
370
 
363
371
  ### Host availability
364
372
 
@@ -399,7 +407,7 @@ specialist in sequence, then synthesize:
399
407
  ```text
400
408
  1. Load thatch-review-pedantic, review branch feature-x, report findings.
401
409
  2. Load thatch-review-acceptance, review the same branch.
402
- 3. ... repeat for state-flow, no-slop, breadcrumbs, mark-and-sweep ...
410
+ 3. ... repeat for state-flow, no-slop, clarity, breadcrumbs, mark-and-sweep ...
403
411
  4. Load thatch-review-synthesizer, verify and aggregate all findings.
404
412
  ```
405
413
 
@@ -24,13 +24,19 @@ the agent's context. The block looks like:
24
24
  - [0.58 conf, 1 tests] When about to commit changes to the repo:
25
25
  do Run mise run check (tsc + bun test + markdownlint) before
26
26
  committing. Never commit code that fails the quality gate.
27
+ Snapshot: these labels reflect the behavior store as of this message's
28
+ submission. Behaviors updated after submission (including during this
29
+ turn) do not refresh it; re-check with thatch_behavior_list before
30
+ relying on them.
27
31
  ```
28
32
 
29
33
  The agent evaluates each surfaced rule against the current situation.
30
34
  If relevant (ham), it follows the rule and calls `behavior_feedback`
31
35
  with `relevant: true`. If not relevant (spam), it calls
32
36
  `behavior_feedback` with `relevant: false`. This trains the classifier
33
- so future nudges are more accurate.
37
+ so future nudges are more accurate. On Claude Code and Cursor the
38
+ footer's tool name appears with its MCP spelling
39
+ (`mcp__thatch__behavior_list`).
34
40
 
35
41
  ## Default behaviors
36
42
 
package/docs/user/cli.md CHANGED
@@ -4,6 +4,10 @@ Thatch ships with a command-line tool for inspecting memories and
4
4
  running maintenance tasks outside the agent. It requires `bun` on your
5
5
  PATH.
6
6
 
7
+ `thatch --help` (or `-h`) prints the full command list and exits 0.
8
+ The flag works anywhere in the command line: `thatch chat list -h`
9
+ shows help instead of running the command.
10
+
7
11
  ## Memory inspection
8
12
 
9
13
  ```bash
@@ -45,7 +49,8 @@ Read-only access to the chat directory your opencode sessions share
45
49
  (see [cross-session-chat.md](cross-session-chat.md)):
46
50
 
47
51
  ```bash
48
- thatch chat list # who is registered: name, age, project, topic
52
+ thatch chat list # who is open now: name, age, project, topic
53
+ thatch chat list --recent # also show alive sessions with no open tab
49
54
  thatch chat list --stale all # also show stale sessions older than a day
50
55
  thatch chat tail # follow sent and read events, live (JSONL)
51
56
  thatch chat tail --once # print the last 20 messages and exit
@@ -55,20 +60,28 @@ thatch chat tail --from al --to bob # substring match on names
55
60
  thatch chat tail --since 2026-09-12 --until "2026-09-13 09:00" # a window
56
61
  ```
57
62
 
58
- `chat list` shows every registered session in two sections, Active and
59
- Stale, each as aligned columns under a header row: how long since its
60
- last heartbeat, its status (`fresh` or `stale` for opencode sessions;
61
- `active` or `idle` for Claude Code and Cursor sessions, which only beat
62
- when a prompt runs), its project, and its topic (the session's title) -
63
- the fastest way to answer "which session should I talk to about X?"
64
- Rows are grouped by project (alphabetical; sessions with no project
65
- last), most recently seen first within each project. A
66
- stale session has missed two heartbeats, about a minute: the opencode
67
- process hosting it has probably stopped. The stale section shows rows
68
- up to one day old by default; older ones collapse into a hidden-count
69
- note so long-dead sessions cannot bury the fresh signal. Pass
70
- `--stale N` (days) to widen the window or `--stale all` to see every
71
- stale row. Color is added only when the
63
+ `chat list` renders the chat roster in three sections - Active, Recent,
64
+ and Stale - each as aligned columns under a header row: how long since its last heartbeat, its status (`open` - a tab is open now - or
65
+ `recent` - host alive, no open tab - for opencode sessions; `active` or
66
+ `idle` for Claude Code and Cursor sessions, which only beat when a
67
+ prompt runs), its project, and its topic (the session's title) - the
68
+ fastest way to answer "which session should I talk to about X?" Rows
69
+ are grouped by project (alphabetical; sessions with no project last),
70
+ most recently seen first within each project.
71
+
72
+ The default view shows the sessions you can wake or reach now: open
73
+ sessions plus Claude Code and Cursor rows, which read mail at their
74
+ next prompt. A recent session - its harness is alive but its tab is
75
+ closed, so a wake may not reach it until the tab reopens - collapses
76
+ into a muted hidden-count note pointing at `--recent`, which reveals
77
+ the Recent section. A stale session has missed two heartbeats, about a
78
+ minute: the opencode process hosting it has probably stopped. Its
79
+ section is hidden too, behind `--stale`, but without a count note - the
80
+ default view simply drops stale rows. The stale section
81
+ shows rows up to one day old by default; older ones collapse into a
82
+ hidden-count note so long-dead sessions cannot bury the fresh signal.
83
+ Pass `--stale N` (days) to widen the window or `--stale all` to see
84
+ every stale row. Color is added only when the
72
85
  output is a terminal; a pipe prints plain aligned text.
73
86
 
74
87
  `chat tail` prints the conversation as a JSONL event log: one JSON
@@ -16,13 +16,16 @@ the review:
16
16
  2. **Gather project context**: PR descriptions, git archaeology,
17
17
  ticket references, links to docs/designs/tickets found in the
18
18
  change (followed one hop for scope and design context), TODO
19
- markers, prior reviews, project memory. Also checks whether main
19
+ markers, prior reviews, project memory. Also discovers related
20
+ PRs (stacks chained through base branches, release trains
21
+ ordered by ticket relations) and checks consistency between
22
+ them and the change. Also checks whether main
20
23
  has moved past the merge-base touching the same paths — a stale
21
24
  branch can make findings true only at the merge-base.
22
25
  3. **Research affected workflows**: load `thatch-code-archaeology`,
23
26
  trace the code paths the change touches.
24
27
  4. **Estimate complexity**: partition the diff into review units.
25
- 5. **Dispatch specialists**: fan out the nine specialists as
28
+ 5. **Dispatch specialists**: fan out the specialists as
26
29
  parallel sub-agents, each with the context brief.
27
30
  6. **Synthesize**: the synthesizer reads all specialist output,
28
31
  verifies each finding (cited text exists, claim is accurate,
@@ -30,8 +33,12 @@ the review:
30
33
  the final report. When the branch is stale relative to main, it
31
34
  re-verifies behavioral findings against current main and reports
32
35
  merge-base-only findings as rebase notes rather than defects.
36
+ When related PRs were detected, it cross-references findings
37
+ against the sibling register: a missing piece delivered by a
38
+ sibling is not a defect, and inconsistencies between connected
39
+ PRs surface as cross-PR notes.
33
40
 
34
- ## The nine specialists
41
+ ## The specialists
35
42
 
36
43
  | Skill | What it checks |
37
44
  |-------|-------------|
@@ -40,6 +47,7 @@ the review:
40
47
  | `thatch-review-state-flow` | Module boundaries, implicit state machines, error propagation, separation of concerns. |
41
48
  | `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. |
42
49
  | `thatch-review-no-slop` | AI writing anti-patterns: change narration, fourth wall breaks, em dashes, hedging, filler. |
50
+ | `thatch-review-clarity` | Prose clarity in comments, docstrings, error strings, and docs: made-up phrases, buzzwords, untranslated jargon, clause chains, buried leads, doc/code responsibility splits, checked against the project's clear-writing rules regardless of who wrote the text. |
43
51
  | `thatch-review-breadcrumbs` | Comment narrative: do comments form a coherent outline of the code's behavior? |
44
52
  | `thatch-review-mark-and-sweep` | Mechanical change completeness: whole-repo sweep for stragglers after renames, flag removals, API substitutions. |
45
53
  | `thatch-review-highlights` | Positive finding detection: clever solutions, cleanup done along the way, documentation that helps. Medium-high bar. |
@@ -48,6 +56,34 @@ the review:
48
56
  Each specialist is a self-contained static-analysis pass. They can run
49
57
  individually or as part of the coordinated review.
50
58
 
59
+ ## Review modes: /thatch/self-review and /thatch/peer-review
60
+
61
+ Two slash commands run the same pipeline with the findings weighted for
62
+ whose work is under review.
63
+
64
+ - `/thatch/self-review` reviews your own completed work before you
65
+ submit it. The slop, clarity, technique, and breadcrumbs lenses weigh
66
+ heaviest, simplicity is overweighted on shared projects, and
67
+ technique or highlights findings that would simplify the design are
68
+ surfaced for an adopt-or-dismiss decision rather than left as
69
+ footnotes. The review iterates: after each round you fix or decline
70
+ each finding, and the next round re-reviews the updated state until
71
+ a round produces no meaningful findings (at most three rounds).
72
+ - `/thatch/peer-review` reviews another author's change. Findings are
73
+ weighted for org velocity: simpler ways to the same outcome, existing
74
+ helpers that already do the work, extremely clear documentation, and
75
+ unintended consequences for callers and siblings. The review walks
76
+ the project's persistent memory for incidents, constraints, and
77
+ footguns the author could not have known, and checks them against
78
+ the change. Settled designs are not re-litigated, and "if someone
79
+ changes this later it breaks" findings are never reported; instead
80
+ the review verifies the change leaves a breadcrumb trail to wherever
81
+ the project records how the feature works.
82
+
83
+ Both commands work on every host. On opencode they drive the
84
+ coordinator with sub-agents. On Claude Code and Cursor the same
85
+ procedure runs the specialists inline, in sequence.
86
+
51
87
  ## Follow-up rounds
52
88
 
53
89
  After the author responds or pushes changes, `thatch-review-followup`
@@ -55,6 +91,10 @@ verifies whether prior findings were adequately addressed before
55
91
  deciding whether to re-run the full review. The author must either
56
92
  fix the code, prove the finding is not a concern with a checkable
57
93
  argument, or file a follow-up ticket with a risk explanation.
94
+ Between rounds the author may merge the default branch — or, on a
95
+ stacked PR, merge or rebase onto the base branch — into the branch;
96
+ the followup excludes those commits so only the author's own changes
97
+ are verified.
58
98
 
59
99
  ## Author-side response
60
100
 
@@ -67,7 +107,9 @@ one, reply on each thread, and post a top-level summary comment.
67
107
 
68
108
  - The coordinator (`thatch-code-review`) is opencode-only. It
69
109
  requires sub-agent support to dispatch parallel specialists. On
70
- Claude Code or Cursor, run specialists individually instead.
110
+ Claude Code or Cursor, run specialists individually instead; the
111
+ `/thatch/self-review` and `/thatch/peer-review` commands package
112
+ exactly that inline sequence, with a mode overlay on top.
71
113
  - The review quality depends on the model. Weak models may
72
114
  hallucinate findings or miss subtle issues.
73
115
  - The synthesizer verifies cited text exists, but it does not
@@ -1,9 +1,11 @@
1
1
  # Slash commands
2
2
 
3
3
  Thatch ships `/thatch/*` commands you run yourself, on top of the nudges the
4
- plugin fires on its own schedule. Nudges and commands share the same
5
- instruction text, so a behavior works the same whether it fires automatically
6
- or you invoke it.
4
+ plugin fires on its own schedule. The nudge-backed commands (`defrag`,
5
+ `extract`, `hygiene`, `reflect`) share their instruction text with the
6
+ nudges, so a behavior works the same whether it fires automatically or you
7
+ invoke it. The remaining commands (`refine`, `self-review`, `peer-review`,
8
+ `whois`) stand alone.
7
9
 
8
10
  ## Commands
9
11
 
@@ -26,9 +28,24 @@ or you invoke it.
26
28
  project type's requirements: the agent classifies the project (team,
27
29
  personal, shared library, spike, infrastructure, or open source
28
30
  contribution), confirms the pick, and runs the refinement loop with
29
- that type's expectations applied. Text after the command can name the
30
- type directly (for example, `/thatch/refine shared-lib`) to skip
31
- classification.
31
+ that type's expectations applied. Project type relaxes round counts
32
+ and documentation bars, never the deep-mode triggers. Text after the
33
+ command can name the type directly (for example, `/thatch/refine
34
+ shared-lib`) to skip classification.
35
+ - `/thatch/peer-review` — review another author's change: the full review
36
+ pipeline with findings weighted for org velocity. Text after the command
37
+ names the review target (for example, `/thatch/peer-review 1234` for a
38
+ PR). The review walks the project's persistent memory for
39
+ incidents, constraints, and footguns the author could not have known,
40
+ and checks them against the change. Settled designs are not
41
+ re-litigated, and "if someone changes this later it breaks" findings
42
+ are never reported. See [code-review.md](code-review.md).
43
+ - `/thatch/self-review` — review your own completed work before
44
+ submitting it: the full review pipeline weighted for reputation and
45
+ simplicity. Takes the same target argument as peer-review. Rounds
46
+ iterate (fix or decline each finding, then re-review the updated
47
+ state) until a round produces no meaningful findings, at most three.
48
+ See [code-review.md](code-review.md).
32
49
  - `/thatch/compact` and `/thatch/exit` — the wrap-up commands. They run a
33
50
  pre-flight checklist (flush extraction, finish promised memory writes,
34
51
  surface loose ends) before a compaction or an exit, gated by a greenlight
@@ -45,11 +62,14 @@ or you invoke it.
45
62
  | `/thatch/reflect` | yes | yes | yes (as an MCP prompt) |
46
63
  | `/thatch/whois` | yes | no | no |
47
64
  | `/thatch/refine` | yes | yes | yes (as an MCP prompt) |
65
+ | `/thatch/peer-review` | yes | yes | yes (as an MCP prompt) |
66
+ | `/thatch/self-review` | yes | yes | yes (as an MCP prompt) |
48
67
  | `/thatch/compact`, `/thatch/exit` | yes | no | no |
49
68
 
50
69
  Why the gaps: `/thatch/extract` and `/thatch/whois` need the invoking
51
70
  session's ID, which only the opencode plugin can supply. The wrap-up
52
- commands trigger TUI actions through the plugin. Cursor has no file-based
71
+ commands trigger host actions (the compaction and the session close-out)
72
+ through the plugin. Cursor has no file-based
53
73
  commands; its prompts come from the MCP server (`prompts/list` and
54
74
  `prompts/get`).
55
75
 
@@ -25,13 +25,21 @@ explicitly with `thatch_chat_register` (no arguments) - useful after
25
25
  `chat_unregister`, or just to check your assigned name. Once registered:
26
26
 
27
27
  - `thatch_chat_list` shows every registered session on the machine, grouped
28
- into Active and Stale sections: active sessions can be woken; stale ones
29
- have missed two heartbeats, about a minute (the opencode process hosting
30
- them has probably stopped). Each row carries how long ago the session last
28
+ into Active, Recent, and Stale sections: active sessions either have an
29
+ opencode tab open right now or are Claude Code and Cursor rows, which
30
+ read mail at their next prompt; recent ones are alive but have no open
31
+ tab, so a wake may not reach them until the tab reopens; stale
32
+ ones have missed two heartbeats, about a minute (the opencode process
33
+ hosting them has probably stopped). Each
34
+ row carries how long ago the session last
31
35
  checked in, its project, whether it runs in the project root or a linked
32
36
  git worktree, its topic, and your unread count
33
37
  - `thatch_chat_send` delivers a message to another registered session, by
34
38
  name or session id, and states the recipient's liveness at send time.
39
+ For a recipient with no open tab it says so plainly: the message waits
40
+ in the inbox, but the wake is not guaranteed to start a turn
41
+ (daemon-resident sessions like subordinates usually still pick the
42
+ message up on their next activity).
35
43
  An identical resend within a few seconds is treated as a client retry:
36
44
  while the first copy is still unread it succeeds but delivers nothing
37
45
  new (the tool output says so); once the recipient has read it, the same
@@ -46,13 +54,16 @@ explicitly with `thatch_chat_register` (no arguments) - useful after
46
54
  the rest with the `message` and `offset` arguments (each drain line
47
55
  carries the message id). Paging never marks anything read
48
56
  - `thatch_chat_broadcast` delivers one message to every other live
49
- registered session at once (a long body is split per recipient, exactly
50
- like a split `chat_send`)
57
+ registered session that has a tab open, plus every MCP session (a long
58
+ body is split per recipient, exactly like a split `chat_send`)
51
59
  - `thatch_chat_unregister` leaves the directory
52
60
 
53
61
  When mail arrives for an idle session, thatch wakes it with a notification -
54
62
  the agent gets a model turn even with nobody at the keyboard, reads its
55
- inbox, and decides what to do. The notification names the senders and the
63
+ inbox, and decides what to do. If the session's directory has been deleted
64
+ (a merged branch's worktree, for example), the wake is skipped quietly:
65
+ no error appears, the mail stays queued, and it delivers normally once the
66
+ directory exists again. The notification names the senders and the
56
67
  count only; the agent reads the actual messages itself. A split message
57
68
  arrives as one grouped notification ("N unread messages from X"), and the
58
69
  parts carry their own markers so the reader assembles the whole before
@@ -61,10 +72,14 @@ the last is suffixed "(continued in next message)".
61
72
 
62
73
  Broadcasts are for announcements and open questions ("which of you is
63
74
  working on the payments code?", "main just moved, rebase if you are based
64
- on it"). Every live session gets the message and spends a model turn on it,
75
+ on it"). Every OPEN session gets the message and spends a model turn on it,
65
76
  so broadcast sparingly - for anything with a known audience, `chat_send` is
66
- the polite tool. Stale sessions are skipped and reported: a dead session
67
- never reads a broadcast.
77
+ the polite tool. Sessions without an open tab are skipped and reported by
78
+ name: a stale session will never read the mail, and a fresh-but-tab-less
79
+ session (a closed tab, or a headless subordinate) is not reliably wakeable,
80
+ so messaging it would spend a turn on a delivery that likely never runs.
81
+ With opencode tabs disabled, broadcasts reach only MCP sessions - that is
82
+ the honest reading of "no tab signal", never a false fan-out.
68
83
 
69
84
  ## Watching the conversation
70
85
 
@@ -149,21 +164,34 @@ host the sessions run in.
149
164
 
150
165
  ## Liveness
151
166
 
152
- A session shows as fresh while the opencode process hosting it is
153
- running: hosted sessions keep beating (idle ones included), so the
154
- freshness is real. When that process dies, its sessions stop beating and
155
- show as stale about a minute later (two missed heartbeats), grouped into
156
- a separate Stale section. A laptop that slept reads the same way until
157
- its processes catch up.
167
+ Liveness has three levels, and the roster shows which one a row is in.
168
+
169
+ The base signal is the heartbeat: a session shows as fresh while the
170
+ opencode process hosting it is running - hosted sessions keep beating
171
+ (idle ones included), so the freshness is real. When that process dies,
172
+ its sessions stop beating and show as stale about a minute later (two
173
+ missed heartbeats), grouped into a separate Stale section. A laptop that
174
+ slept reads the same way until its processes catch up.
175
+
176
+ The second signal, read at roster time, is opencode's own tab state: a
177
+ fresh row whose session has a tab open right now shows as `open`, one
178
+ without shows as `recent`. `recent` covers finished-but-recently-active
179
+ conversations, closed tabs, and daemon-resident sessions that never had a
180
+ window (subordinates) - the harness is alive, but presence is unknown.
181
+ With tabs disabled (or no opencode state on the machine) every fresh row
182
+ shows as `recent`: an unknown tab state never reads as open.
183
+
158
184
  Messages to a stale session wait in its inbox unread - a dead session
159
- never reads them, and `chat_send` says so at send time. Continuing a
185
+ never reads them, and `chat_send` says so at send time. Messages to a
186
+ `recent` session are delivered, but `chat_send` warns that the wake is
187
+ not guaranteed without an open tab. Continuing a
160
188
  session with `opencode -s <id>` reclaims its name and row, and any mail
161
189
  that queued while it was down is delivered at startup. Explicitly
162
190
  closing a session (deleting it in the TUI) unregisters it immediately,
163
- and a greenlit `/thatch/exit` unregisters the session too: the wrap-up
164
- checklist calls `chat_unregister`, and the plugin removes the row itself
165
- when the exit token passes the greenlight check, so other sessions stop
166
- addressing mail to a process that is about to vanish.
191
+ and a greenlit `/thatch/exit` unregisters the session too: the plugin
192
+ removes the row itself when the exit token passes the greenlight check,
193
+ so other sessions stop
194
+ addressing mail to a session that is closing out.
167
195
 
168
196
  ## Turning chat off
169
197
 
@@ -46,10 +46,21 @@ like:
46
46
  flag tech debt before reviewing the diff
47
47
  - [0.61 conf, 2 tests] When choosing test scope: you may prefer
48
48
  integration tests over unit tests
49
+ Snapshot: these labels reflect the prediction store as of this message's
50
+ submission. Predictions updated after submission (including during this
51
+ turn) do not refresh it; re-check with thatch_prediction_query before
52
+ relying on them.
49
53
  ```
50
54
 
51
55
  The agent reads this and decides whether to follow the prediction,
52
- surface it to you, or ignore it. You never see the nudge directly.
56
+ surface it to you, or ignore it. You never see the nudge directly. The
57
+ snapshot line matters when the agent corrects the model mid-conversation
58
+ (you say "no, that's wrong" and it calls `thatch_prediction_delete`):
59
+ the block it saw at the start of the turn is a submission-time snapshot
60
+ and does not update. The agent should re-query with
61
+ `thatch_prediction_query` instead of trusting the block's labels. On
62
+ Claude Code and Cursor the tool name appears with its MCP spelling
63
+ (`mcp__thatch__prediction_query`).
53
64
 
54
65
  ## Tools
55
66