@jeffober/thatch 0.2.1 → 0.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/artifacts/skills/thatch-plan-refinement.md +3 -2
- package/artifacts/skills/thatch-refine-infra.md +66 -0
- package/artifacts/skills/thatch-refine-oss-contribution.md +68 -0
- package/artifacts/skills/thatch-refine-personal.md +61 -0
- package/artifacts/skills/thatch-refine-shared-lib.md +69 -0
- package/artifacts/skills/thatch-refine-spike.md +53 -0
- package/artifacts/skills/thatch-refine-team-app.md +69 -0
- package/artifacts/skills/thatch-refine.md +84 -0
- package/bin/thatch +9 -5
- package/docs/dev/README.md +21 -25
- package/docs/dev/features/cli.md +1 -0
- package/docs/dev/features/extraction.md +120 -81
- package/docs/dev/features/nudge-pipeline.md +44 -39
- package/docs/dev/features/session-lifecycle.md +34 -20
- package/docs/dev/features/watchers.md +9 -0
- package/docs/dev/gotchas.md +33 -26
- package/docs/dev/mcp-parity.md +17 -18
- package/docs/dev/setup-and-hooks.md +1 -1
- package/docs/dev/skills.md +8 -1
- package/docs/user/README.md +7 -0
- package/docs/user/commands.md +8 -0
- package/docs/user/skills.md +12 -0
- package/docs/user/watchers.md +6 -0
- package/package.json +1 -1
- package/src/chat.ts +1 -1
- package/src/commands.ts +23 -3
- package/src/extract-queue.ts +16 -1
- package/src/extraction.ts +4 -3
- package/src/opencode/v2.ts +4 -3
- package/src/prompts.ts +26 -33
- package/src/runtime.ts +119 -106
- package/src/skills.ts +7 -0
- package/src/tool-defs.ts +39 -31
- package/src/watchers.ts +31 -0
package/README.md
CHANGED
|
@@ -194,8 +194,10 @@ Thatch gives your agent:
|
|
|
194
194
|
auto-joining with `chat.autoRegister: false`).
|
|
195
195
|
- **Slash commands** -- `/thatch/defrag` (consolidate duplicate memories),
|
|
196
196
|
`/thatch/extract` (drain the extraction queue now), `/thatch/hygiene`
|
|
197
|
-
(tend stale and orphaned memories),
|
|
198
|
-
the session learned)
|
|
197
|
+
(tend stale and orphaned memories), `/thatch/reflect` (persist what
|
|
198
|
+
the session learned), and `/thatch/refine` (refine a plan under the
|
|
199
|
+
project type's requirements, classifying the project first) run on
|
|
200
|
+
demand. The first four mirror the same behaviors the nudges run on
|
|
199
201
|
their own schedule. Plus the opencode-only wrap-ups: `/thatch/compact` and
|
|
200
202
|
`/thatch/exit` run a pre-flight checklist before a compaction or an exit:
|
|
201
203
|
the agent flushes pending fact extraction, finishes promised memory
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: thatch-plan-refinement
|
|
3
|
-
description: Refine a plan for a code change by dispatching a fresh-context reviewer subagent to hunt for gaps, unverified premises, and unexpected side effects, then revising and re-reviewing until consensus. Use when a plan is about to be implemented, when the user asks to refine, stress-test, or double-check a plan, or after a plan revision that incorporated prior findings. Quick mode is one fresh reviewer per round; deep mode adds a specialist lens fan-out (reuse, alternatives, hidden problems, safe-to-modify, archaeology).
|
|
3
|
+
description: Refine a plan for a code change by dispatching a fresh-context reviewer subagent to hunt for gaps, unverified premises, and unexpected side effects, then revising and re-reviewing until consensus. Use when a plan is about to be implemented, when the user asks to refine, stress-test, or double-check a plan, or after a plan revision that incorporated prior findings. This is the generic core loop; when the project type should shape the refinement bar, load thatch-refine instead and it will apply a type delta on top of this loop. Quick mode is one fresh reviewer per round; deep mode adds a specialist lens fan-out (reuse, alternatives, hidden problems, safe-to-modify, archaeology).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
You are refining a plan before code exists. A plan written by the same context that researched the problem inherits that context's blind spots. A reviewer with no stake in the plan and no memory of writing it finds what the author cannot. Refinement is the loop: draft, review, revise, repeat until consensus. Each pass tightens the plan; a round with no findings means the plan is done, not that the loop failed.
|
|
@@ -75,7 +75,8 @@ One reviewer per round in quick mode; one lens fan-out total in deep mode, then
|
|
|
75
75
|
|
|
76
76
|
## Relationship to other skills
|
|
77
77
|
|
|
78
|
-
- **`thatch-
|
|
78
|
+
- **`thatch-refine`** - the type-aware entry point. Different project types need different refinement bars: a team codebase owes coordination and breadcrumbs, a personal project allows cleverness, a shared library owes API hygiene. When the user runs `/thatch/refine` or the project's type should shape the bar, load `thatch-refine` first; it classifies and hands back a thatch-refine-* delta to apply on top of this loop. This skill stays the generic core.
|
|
79
|
+
- **`thatch-code-archaeology`** - the research skill for understanding the code; its output is often the plan's input. The archaeology lens is a targeted, plan-scoped re-run of its git-history step, not a replacement for it.
|
|
79
80
|
- **`thatch-coding-workflow`** — the procedure skill for executing the refined plan. Refinement ends where coding-workflow begins.
|
|
80
81
|
- **`thatch-ticket-description` / `thatch-pr-description`** — if the refined plan feeds a ticket or PR description (or the session iterated on one using this skill), RE-LOAD the appropriate writing skill and draft within its contract. A plan is a working artifact for the session that wrote it; a ticket or PR description is a reader-facing document with its own sections, verbosity budget, and prose rules. Refinement output — findings, accepted risks, review rounds — is SOURCE MATERIAL for those skills, never a substitute for them. This holds the right level of detail for the medium and keeps the writing clear.
|
|
81
82
|
- **`thatch-clear-writing`** — for any other human-facing text produced along the way (reports, comments, docs).
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thatch-refine-infra
|
|
3
|
+
description: Type-specific requirements for refining a plan that touches infrastructure (CI pipelines, Terraform, Kubernetes manifests, build and deploy configuration). Loaded by thatch-refine after classification; assumes the core loop in thatch-plan-refinement. Use when a wrong premise can break deploys or pipelines for everyone downstream.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are refining a plan for an **infra** change: CI pipelines, Terraform,
|
|
7
|
+
Kubernetes manifests, build and deploy configuration. The governing value
|
|
8
|
+
is blast radius: a wrong premise here does not break one feature, it
|
|
9
|
+
breaks every pipeline, environment, or developer downstream of it, often
|
|
10
|
+
silently and often for everyone at once. Load `thatch-plan-refinement`
|
|
11
|
+
for the core loop and apply the deltas below; where they disagree, these
|
|
12
|
+
win.
|
|
13
|
+
|
|
14
|
+
## What this type owes
|
|
15
|
+
|
|
16
|
+
- **Near-absolute pattern-following.** Configuration is the worst place
|
|
17
|
+
for novelty. Copy the established pattern from a sibling pipeline,
|
|
18
|
+
module, or manifest even when a better one exists; propose the better
|
|
19
|
+
one as its own change, after this one lands.
|
|
20
|
+
- **Rollback as a first-class deliverable.** Every change names how it
|
|
21
|
+
backs out, concretely (which command, which revert, which state to
|
|
22
|
+
re-apply), not "revert the commit if problems arise."
|
|
23
|
+
- **Staged verification.** The plan verifies against a non-production
|
|
24
|
+
target first (staging environment, a canary job, a dry-run or plan
|
|
25
|
+
output) and names what a successful verification looks like before
|
|
26
|
+
production applies it.
|
|
27
|
+
|
|
28
|
+
## How this changes the loop
|
|
29
|
+
|
|
30
|
+
- **Deep mode is the default.** Infra changes almost always touch shared
|
|
31
|
+
persistent state that other consumers read, which is the core skill's
|
|
32
|
+
first deep-mode trigger.
|
|
33
|
+
- **Premises verify against live state, not memory.** The most dangerous
|
|
34
|
+
infra premise is "the current setup is X" recalled from memory. Check
|
|
35
|
+
the actual manifests, the actual pipeline config, the actual running
|
|
36
|
+
versions, and cite where you checked. Terraform drift and manual
|
|
37
|
+
console changes make memory especially unreliable here.
|
|
38
|
+
- **Consensus is unchanged**, but the reviewer prompt should emphasize
|
|
39
|
+
checking the rollback and verification sections explicitly.
|
|
40
|
+
|
|
41
|
+
## Lens weights
|
|
42
|
+
|
|
43
|
+
- **Hidden problems (pre-mortem) dominates.** The question is "who reads
|
|
44
|
+
this state that the plan does not know about?" - dependent pipelines,
|
|
45
|
+
environments sharing the module, developers relying on cache behavior,
|
|
46
|
+
jobs relying on timing. Enumerate the dependents by reading what
|
|
47
|
+
actually references the resource, not by recollection.
|
|
48
|
+
- **Safe-to-modify is second.** An infra change landing in untested
|
|
49
|
+
configuration without a verification step is a finding.
|
|
50
|
+
- **Alternatives and pattern/reuse mostly skip.** The pattern question
|
|
51
|
+
was answered above: follow it.
|
|
52
|
+
|
|
53
|
+
## Extra plan sections
|
|
54
|
+
|
|
55
|
+
- **Rollback plan.** Concrete and executable, as above.
|
|
56
|
+
- **Verification step.** What runs in staging or dry-run first, and what
|
|
57
|
+
result counts as safe to proceed.
|
|
58
|
+
- **Sequencing.** Infra changes often must land in an order (create
|
|
59
|
+
before reference, drain before delete). The plan states the order and
|
|
60
|
+
what breaks if it is violated.
|
|
61
|
+
|
|
62
|
+
## Docs bar
|
|
63
|
+
|
|
64
|
+
A one-paragraph change note for the team (what changed, why, how to
|
|
65
|
+
roll back) is the deliverable. Config comments explain constraints the
|
|
66
|
+
next person must not violate.
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thatch-refine-oss-contribution
|
|
3
|
+
description: Type-specific requirements for refining a plan for a contribution to an open source repository the user does not maintain. Loaded by thatch-refine after classification; assumes the core loop in thatch-plan-refinement. The maintainer's design authority and house style govern, and the diff stays minimal.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are refining a plan for an **oss-contribution**: a change to a
|
|
7
|
+
repository the user does not maintain. The governing value is the
|
|
8
|
+
maintainer's design authority. It is their codebase; the contribution
|
|
9
|
+
that gets merged is the one that fits their intent, not the one that
|
|
10
|
+
would be best by your lights. Load `thatch-plan-refinement` for the core
|
|
11
|
+
loop and apply the deltas below; where they disagree, these win.
|
|
12
|
+
|
|
13
|
+
## What this type owes
|
|
14
|
+
|
|
15
|
+
- **Conform to house style, even when it is worse.** A foreign codebase's
|
|
16
|
+
conventions are not up for improvement in this change. Do not import
|
|
17
|
+
patterns from other projects; do not refactor what the maintainer
|
|
18
|
+
wrote.
|
|
19
|
+
- **Minimal diff.** No drive-by refactors, no reformatting of untouched
|
|
20
|
+
lines, no new dependencies, no new abstractions beyond what the change
|
|
21
|
+
strictly needs.
|
|
22
|
+
- **The discussion comes first.** Significant design work waits until the
|
|
23
|
+
approach has a maintainer's nod: check CONTRIBUTING.md, search open
|
|
24
|
+
and closed issues and PRs for the same idea, and file or comment on
|
|
25
|
+
the proposal before investing in the implementation. A plan that
|
|
26
|
+
assumes acceptance is building on an unverified premise.
|
|
27
|
+
|
|
28
|
+
## How this changes the loop
|
|
29
|
+
|
|
30
|
+
- **Add a premise class: upstream status.** Every plan premise about the
|
|
31
|
+
maintainer's intent (is this wanted, is the approach acceptable, is
|
|
32
|
+
the issue still open) needs evidence: an issue thread, a maintainer
|
|
33
|
+
comment, a CONTRIBUTING instruction. No evidence means "unknown -
|
|
34
|
+
ask upstream," and the plan gates on that question, not on a guess.
|
|
35
|
+
- **Consensus adds one test.** Alongside the core skill's consensus
|
|
36
|
+
criteria, the reviewer answers: "would a maintainer accept this
|
|
37
|
+
scope?" Scope findings are blockers. A contribution that solves the
|
|
38
|
+
issue plus three adjacent problems will sit unmerged.
|
|
39
|
+
- **Round cap unchanged.** But a plan blocked on upstream discussion
|
|
40
|
+
pauses for the user to have that conversation; it does not loop.
|
|
41
|
+
|
|
42
|
+
## Lens weights
|
|
43
|
+
|
|
44
|
+
- **Pattern and reuse inverts.** In team code, existing patterns are a
|
|
45
|
+
strong default; here they are the requirement. A "better" pattern than
|
|
46
|
+
the house style is a finding against the plan, not for it.
|
|
47
|
+
- **Hidden problems shrinks.** Consumers of internal state are the
|
|
48
|
+
maintainer's concern. Focus on the change's own footprint and its
|
|
49
|
+
interaction with in-flight upstream work (search open PRs for overlap).
|
|
50
|
+
- **Alternatives mostly skips.** The maintainer chose the architecture.
|
|
51
|
+
The plan's job is fitting into it, and where the plan needs a
|
|
52
|
+
maintainer decision, that is an upstream question, not an alternatives
|
|
53
|
+
survey.
|
|
54
|
+
|
|
55
|
+
## Extra plan sections
|
|
56
|
+
|
|
57
|
+
- **Upstream discussion.** The issue or thread this change responds to,
|
|
58
|
+
and the maintainer signals (or absence of them) the plan relies on.
|
|
59
|
+
- **House-style conformance.** The specific conventions the change will
|
|
60
|
+
follow, read from the project's own CONTRIBUTING and recent merged
|
|
61
|
+
PRs, not assumed.
|
|
62
|
+
|
|
63
|
+
## Docs bar
|
|
64
|
+
|
|
65
|
+
Match the project's own documentation conventions for any user-facing
|
|
66
|
+
text (changelog entries, docs pages) and the house code-comment style.
|
|
67
|
+
The writing skills still govern clarity, but the structure and tone
|
|
68
|
+
follow the project's.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thatch-refine-personal
|
|
3
|
+
description: Type-specific requirements for refining a plan in a solo personal project with no downstream consumers. Loaded by thatch-refine after classification; assumes the core loop in thatch-plan-refinement. Relaxes coordination requirements and allows cleverness and experimentation, while keeping premise verification honest.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are refining a plan for a **personal** project: solo code with no
|
|
7
|
+
downstream consumers. The coordination constraints that govern team code
|
|
8
|
+
are relaxed. This is the place to show off cleverness and experiment with
|
|
9
|
+
interesting techniques that would be inconsiderate in a shared codebase.
|
|
10
|
+
Load `thatch-plan-refinement` for the core loop and apply the deltas
|
|
11
|
+
below; where they disagree, these win.
|
|
12
|
+
|
|
13
|
+
## What this type owes
|
|
14
|
+
|
|
15
|
+
- **Almost nothing to anyone else.** No consistency obligation to
|
|
16
|
+
teammates, no reviewer to orient, no downstream API to protect.
|
|
17
|
+
- **Still honest about facts.** Relaxed style does not mean relaxed
|
|
18
|
+
reality: every factual premise still carries a verified `file:line`
|
|
19
|
+
citation, and "unverified" is still marked. A plan built on a wrong
|
|
20
|
+
premise wastes your time in any project.
|
|
21
|
+
|
|
22
|
+
## How this changes the loop
|
|
23
|
+
|
|
24
|
+
- **The skip threshold drops.** Most personal-project plans can be tried
|
|
25
|
+
faster than they can be refined. Skip refinement whenever the change is
|
|
26
|
+
cheap to build and cheaper to rewrite; run the loop only when the plan
|
|
27
|
+
touches something expensive to get wrong (persistent state, a
|
|
28
|
+
hard-to-reverse migration, hours of build effort).
|
|
29
|
+
- **Fewer rounds.** One quiet review round is enough consensus. The cap
|
|
30
|
+
drops from three rounds to two; a personal plan that has not converged
|
|
31
|
+
by then should just be built or abandoned.
|
|
32
|
+
- **Degraded review is fine.** If the host cannot dispatch sub-agents, a
|
|
33
|
+
same-context self-review pass is usually enough. Saying so out loud, as
|
|
34
|
+
the core skill requires, is still worthwhile but the stakes are lower.
|
|
35
|
+
|
|
36
|
+
## Lens weights
|
|
37
|
+
|
|
38
|
+
- **Premise verification is the only load-bearing lens.** The fresh
|
|
39
|
+
reviewer's core job is checking the plan's factual model of the code.
|
|
40
|
+
- **Pattern and reuse mostly skips.** There is no team to stay consistent
|
|
41
|
+
with. Flag reuse only when reinventing an existing wheel will genuinely
|
|
42
|
+
bite future-you.
|
|
43
|
+
- **Alternatives turns exploratory.** The question shifts from "what is
|
|
44
|
+
safest?" to "what would I learn?" - one alternative worth trying for
|
|
45
|
+
the technique is a valid result even when the plan's choice is fine.
|
|
46
|
+
- **Hidden problems shrinks to future-self.** The only consumer to
|
|
47
|
+
enumerate is you, six months from now, with no memory of this code.
|
|
48
|
+
|
|
49
|
+
## Extra plan sections
|
|
50
|
+
|
|
51
|
+
None required. Blast radius, migration plans, and reviewer orientation
|
|
52
|
+
sections are skipped unless the change is in the expensive-to-get-wrong
|
|
53
|
+
category that triggered refinement at all.
|
|
54
|
+
|
|
55
|
+
## Docs bar
|
|
56
|
+
|
|
57
|
+
- Future-self breadcrumbs only: comment the surprising spots, not the
|
|
58
|
+
obvious ones.
|
|
59
|
+
- When a plan deliberately uses an experimental technique, record that in
|
|
60
|
+
one line (in the plan or a comment) so a future session knows the
|
|
61
|
+
oddity was chosen, not accidental.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thatch-refine-shared-lib
|
|
3
|
+
description: Type-specific requirements for refining a plan that touches a library's API surface, in any repo, including personal ones. Loaded by thatch-refine after classification; assumes the core loop in thatch-plan-refinement. Use whenever exported API, published packages, or downstream consumers are involved; API hygiene governs even solo projects.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are refining a plan for a **shared-lib** change: work that touches an
|
|
7
|
+
API other code consumes and keeps working against. This applies to any
|
|
8
|
+
library with external callers, including a personal one. The governing
|
|
9
|
+
value is API hygiene: you are writing for consumers you cannot see and
|
|
10
|
+
cannot call back. Load `thatch-plan-refinement` for the core loop and
|
|
11
|
+
apply the deltas below; where they disagree, these win.
|
|
12
|
+
|
|
13
|
+
## What this type owes
|
|
14
|
+
|
|
15
|
+
- **Flexible on input, strict on output.** Accept broad input types and
|
|
16
|
+
normalize them; return precise, well-defined types and never leak
|
|
17
|
+
internal representations. Callers write code against your output
|
|
18
|
+
shapes; widen what you accept, pin down what you emit.
|
|
19
|
+
- **Keep special cases out of the API.** No caller-specific knobs, no
|
|
20
|
+
one-off escape hatches, no parameters that exist for exactly one
|
|
21
|
+
consumer. A special case is a design smell: handle it inside the
|
|
22
|
+
implementation or reject it at the boundary.
|
|
23
|
+
- **Do not foreclose caller options.** Prefer returning data over making
|
|
24
|
+
decisions callers might want to make differently. Every shortcut the
|
|
25
|
+
library takes on the caller's behalf is a wall they hit later.
|
|
26
|
+
- **Keep the surface small.** Every export is a permanent maintenance
|
|
27
|
+
promise. The best API change is often the one that exports nothing new.
|
|
28
|
+
|
|
29
|
+
## How this changes the loop
|
|
30
|
+
|
|
31
|
+
- **Deep mode is the default** for anything that adds, changes, or
|
|
32
|
+
removes an export. The abstraction gets locked in at ship time; after
|
|
33
|
+
release, changing it costs every consumer. This is the last cheap
|
|
34
|
+
moment to get the shape right.
|
|
35
|
+
- **Alternatives works harder here.** "No better alternative found" must
|
|
36
|
+
be argued harder than the core skill's paragraph: enumerate the
|
|
37
|
+
plausible alternative shapes and say why the plan's shape wins for
|
|
38
|
+
callers, not just for the implementation.
|
|
39
|
+
- **Backward compatibility findings are blockers by default.** A breaking
|
|
40
|
+
change without a deprecation path is a blocker, not a should-fix.
|
|
41
|
+
|
|
42
|
+
## Lens weights
|
|
43
|
+
|
|
44
|
+
- **Hidden problems reframes entirely.** Every consumer is a stranger;
|
|
45
|
+
you cannot grep your callers. Enumerate the contract the plan changes
|
|
46
|
+
and reason about the population of consumers you cannot see, including
|
|
47
|
+
the ones using the API in ways you never intended.
|
|
48
|
+
- **Pattern and reuse applies to your own API first.** Consistency with
|
|
49
|
+
the library's existing API conventions is its own requirement: a
|
|
50
|
+
second method that disagrees with the first in naming or shape is a
|
|
51
|
+
finding even when both are internally fine.
|
|
52
|
+
|
|
53
|
+
## Extra plan sections
|
|
54
|
+
|
|
55
|
+
- **API surface diff.** Exactly what is exported, added, changed, or
|
|
56
|
+
removed, in a list a reviewer can check one line at a time.
|
|
57
|
+
- **Semver impact and deprecation path.** The version bump this deserves,
|
|
58
|
+
what is deprecated, and how callers migrate.
|
|
59
|
+
- **External documentation.** The docs and examples this change requires,
|
|
60
|
+
written for the reader: what the behavior is, when to use it, what it
|
|
61
|
+
does not do. "I'll document it later" is a finding.
|
|
62
|
+
- **Caller migration notes.** For breaking or behavior-changing exports,
|
|
63
|
+
the note that goes in the changelog.
|
|
64
|
+
|
|
65
|
+
## Docs bar
|
|
66
|
+
|
|
67
|
+
Reader-facing documentation is a plan deliverable, not a follow-up. Draft
|
|
68
|
+
it under the writing skills' contracts: define terms on first use,
|
|
69
|
+
behavior stated precisely enough that a caller needs no source dive.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thatch-refine-spike
|
|
3
|
+
description: Type-specific requirements for refining a plan for a throwaway prototype or time-boxed spike. Loaded by thatch-refine after classification; assumes the core loop in thatch-plan-refinement. Skips almost all of the loop, verifying only the premises the experiment's conclusion depends on.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are refining a plan for a **spike**: throwaway code whose purpose is
|
|
7
|
+
answering a question, not producing a maintained artifact. Almost all of
|
|
8
|
+
the refinement loop is waste here. Load `thatch-plan-refinement` for the
|
|
9
|
+
core loop, then apply the deltas below; where they disagree, these win.
|
|
10
|
+
|
|
11
|
+
## What this type owes
|
|
12
|
+
|
|
13
|
+
- **A stated question.** The plan opens with the question the spike
|
|
14
|
+
exists to answer, stated concretely enough that "done" is checkable
|
|
15
|
+
("can Postgres full-text search handle our query volume?" not "explore
|
|
16
|
+
search options").
|
|
17
|
+
- **A promotion test.** The plan states what would make this code worth
|
|
18
|
+
promoting into the real codebase versus rewriting it properly. Most
|
|
19
|
+
spikes end in a rewrite, and that is a success, not a failure.
|
|
20
|
+
- **A time box.** The plan names its budget: hours or days, not open-
|
|
21
|
+
ended effort.
|
|
22
|
+
|
|
23
|
+
## How this changes the loop
|
|
24
|
+
|
|
25
|
+
- **Skip the loop by default.** No reviewer dispatch, no rounds, no
|
|
26
|
+
consensus machinery. One focused self-review pass is the whole
|
|
27
|
+
refinement: check the plan's few load-bearing premises, then build.
|
|
28
|
+
- **Verify only conclusion-bearing premises.** The spike's conclusion is
|
|
29
|
+
only as good as the premises it depends on. If the experiment claims
|
|
30
|
+
"this approach is too slow," the benchmark setup and the
|
|
31
|
+
representativeness of the test data are the premises that matter, and
|
|
32
|
+
they get the verified-citation treatment. Everything else is
|
|
33
|
+
throwaway.
|
|
34
|
+
- **Degraded review needs no apology.** The core skill's honest-degradation
|
|
35
|
+
notice is unnecessary; there is no real review to degrade.
|
|
36
|
+
|
|
37
|
+
## Lens weights
|
|
38
|
+
|
|
39
|
+
All specialist lenses skip except one consideration: **is the spike
|
|
40
|
+
actually throwaway?** If the plan quietly assumes the prototype code will
|
|
41
|
+
survive into production, stop and surface that. A spike that is really a
|
|
42
|
+
production change wearing a costume should be refined under the type it
|
|
43
|
+
actually is.
|
|
44
|
+
|
|
45
|
+
## Extra plan sections
|
|
46
|
+
|
|
47
|
+
- The question, the promotion test, and the time box above. Nothing else.
|
|
48
|
+
|
|
49
|
+
## Docs bar
|
|
50
|
+
|
|
51
|
+
No breadcrumb obligation. One comment or note recording the question and
|
|
52
|
+
the answer is enough. The spike's real output is the answer, and it
|
|
53
|
+
should be written down where the user will find it.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thatch-refine-team-app
|
|
3
|
+
description: Type-specific requirements for refining a plan in a multi-developer team codebase (production app or service shared by a team). Loaded by thatch-refine after classification; assumes the core loop in thatch-plan-refinement. Use when coordination cost, consistency, and reviewer comprehension are the governing constraints.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are refining a plan for a **team-app** project: production code in a
|
|
7
|
+
repository where multiple developers ship, review, and maintain each
|
|
8
|
+
other's work. The governing value is org velocity through coordination and
|
|
9
|
+
consistency. Code is read far more often than it is written, and most of
|
|
10
|
+
its readers did not write it. Load `thatch-plan-refinement` for the core
|
|
11
|
+
loop and apply the deltas below; where they disagree, these win.
|
|
12
|
+
|
|
13
|
+
## What this type owes
|
|
14
|
+
|
|
15
|
+
- **Consistency outranks local optimality.** Following the codebase's
|
|
16
|
+
existing pattern beats a "better" one that splits the codebase in two.
|
|
17
|
+
A novel approach must justify the divergence it imposes on every future
|
|
18
|
+
reader, not just prove it is cleverer.
|
|
19
|
+
- **Implement for the junior reviewer.** The bar is that a developer with
|
|
20
|
+
no history in this area can review the change and debug it at 2am.
|
|
21
|
+
Cleverness is allowed only with a justification comment at the point of
|
|
22
|
+
cleverness, and only when the payoff is real.
|
|
23
|
+
- **Intent is a deliverable.** Docstrings and comments are the breadcrumb
|
|
24
|
+
trail for the next maintainer. The plan says which comments and
|
|
25
|
+
docstrings it will write, and *why* is documented, not just *what*.
|
|
26
|
+
|
|
27
|
+
## How this changes the loop
|
|
28
|
+
|
|
29
|
+
- **Mode triage stays strict.** The skip threshold does not relax for
|
|
30
|
+
team code: anything another developer must review earns at least quick
|
|
31
|
+
mode. Established-pattern changes with no design decisions can still
|
|
32
|
+
skip, as the core skill already provides.
|
|
33
|
+
- **Deep mode triggers broaden.** Beyond the core skill's triggers, deep
|
|
34
|
+
mode is warranted when the change alters a contract other teams build
|
|
35
|
+
on, or lands in an area with a history of review churn.
|
|
36
|
+
- **Consensus is unchanged.** Same rounds, same cap, same escalation to
|
|
37
|
+
the user.
|
|
38
|
+
|
|
39
|
+
## Lens weights
|
|
40
|
+
|
|
41
|
+
- **Hidden problems (pre-mortem) carries the most signal.** In team code
|
|
42
|
+
the plan's biggest risk is an unenumerated consumer or an implicit
|
|
43
|
+
contract another team relies on.
|
|
44
|
+
- **Safe-to-modify is second.** A plan that lands in an untested,
|
|
45
|
+
tangled section without a refactor-first dependency is a finding.
|
|
46
|
+
- **Pattern and reuse tightens.** "Reuse the existing pattern" is the
|
|
47
|
+
default verdict, not one option among several. A plan that introduces a
|
|
48
|
+
parallel way to do something the codebase already does needs a strong,
|
|
49
|
+
evidenced reason.
|
|
50
|
+
- **Alternatives stays a filter.** Two alternatives, one paragraph each,
|
|
51
|
+
as the core skill says; the judgment criterion is team cost, not
|
|
52
|
+
personal preference.
|
|
53
|
+
|
|
54
|
+
## Extra plan sections
|
|
55
|
+
|
|
56
|
+
- **Blast radius and consumers.** Who reads the state, tables, config, and
|
|
57
|
+
symbols this change touches, including other teams and services.
|
|
58
|
+
- **Migration and rollback.** How the change ships safely and how it
|
|
59
|
+
backs out.
|
|
60
|
+
- **Intent breadcrumbs.** The docstrings and comments the implementation
|
|
61
|
+
will write, and what future-reader question each answers.
|
|
62
|
+
- **Reviewer orientation.** One paragraph a reviewer can read first: what
|
|
63
|
+
changed, why, and where to look.
|
|
64
|
+
|
|
65
|
+
## Docs bar
|
|
66
|
+
|
|
67
|
+
Comments and docstrings are part of the definition of done, and any
|
|
68
|
+
reader-facing text produced along the way (PR description, ticket,
|
|
69
|
+
changelog entry) is drafted under the writing skills' contracts.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: thatch-refine
|
|
3
|
+
description: Classify the current project (audience, lifecycle, surface) and refine a plan under that type's requirements. Entry point for the thatch-refine-* family. Use when the user asks to refine a plan, runs /thatch/refine, or when a plan is about to be implemented and the project type should shape the refinement bar. For a bare "refine this plan" request, load this skill rather than thatch-plan-refinement directly - the router picks the type and applies its delta on top of the core loop.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
You are the entry point for project-type-aware plan refinement. The core
|
|
7
|
+
refinement loop (draft, fresh-context reviewer, revise, consensus) is the
|
|
8
|
+
same everywhere; it lives in `thatch-plan-refinement`. What changes by
|
|
9
|
+
project type is the bar: which lenses matter, what the plan must contain,
|
|
10
|
+
how much documentation is owed, and when skipping refinement is honest.
|
|
11
|
+
|
|
12
|
+
## The types
|
|
13
|
+
|
|
14
|
+
| Type | Governing value | Skill |
|
|
15
|
+
|------|-----------------|-------|
|
|
16
|
+
| `team-app` | Coordination and consistency promote org velocity | `thatch-refine-team-app` |
|
|
17
|
+
| `personal` | Freedom to experiment; low coordination cost | `thatch-refine-personal` |
|
|
18
|
+
| `shared-lib` | API hygiene; never foreclose caller options | `thatch-refine-shared-lib` |
|
|
19
|
+
| `spike` | Answering a question cheaply, not producing code | `thatch-refine-spike` |
|
|
20
|
+
| `infra` | Blast radius across pipelines and environments | `thatch-refine-infra` |
|
|
21
|
+
| `oss-contribution` | The maintainer's design authority | `thatch-refine-oss-contribution` |
|
|
22
|
+
|
|
23
|
+
## Classification
|
|
24
|
+
|
|
25
|
+
Classify on three axes, then pick the type whose requirements this plan
|
|
26
|
+
must satisfy. Classify **the change**, not just the repo: a personal repo
|
|
27
|
+
gaining a published API is a `shared-lib` plan for that change, even if the
|
|
28
|
+
repo is `personal` overall.
|
|
29
|
+
|
|
30
|
+
**Audience** - who reads and maintains this code.
|
|
31
|
+
|
|
32
|
+
- Solo: one contributor in git history, no CODEOWNERS, no required reviews.
|
|
33
|
+
- Team: CODEOWNERS, CONTRIBUTING.md, required PR review, multiple regular
|
|
34
|
+
authors.
|
|
35
|
+
- Public: published package (npm/PyPI/etc. metadata, `publishConfig`), or
|
|
36
|
+
consumers outside the repo you cannot enumerate.
|
|
37
|
+
|
|
38
|
+
**Lifecycle** - what this code owes anyone.
|
|
39
|
+
|
|
40
|
+
- Production: protected main, CI gates, deploy configuration, semver
|
|
41
|
+
discipline.
|
|
42
|
+
- Experimental: active WIP, churny main, thin or absent tests.
|
|
43
|
+
- Throwaway: a question wearing a repository.
|
|
44
|
+
|
|
45
|
+
**Surface** - what the change lives in.
|
|
46
|
+
|
|
47
|
+
- Application: end-user or service code with no downstream importers.
|
|
48
|
+
- Library: exported API that other code imports and keeps working against.
|
|
49
|
+
- Infrastructure: CI, Terraform, k8s manifests, build and deploy config.
|
|
50
|
+
|
|
51
|
+
Signals to gather (all cheap and read-only): `git log --format="%an" |
|
|
52
|
+
sort -u | head`, presence of CODEOWNERS / CONTRIBUTING.md / required
|
|
53
|
+
review config, package.json `private` and `publishConfig` fields, the
|
|
54
|
+
publishing config of the relevant ecosystem, presence of `.github/workflows`,
|
|
55
|
+
`terraform/` or k8s manifests, and what the package exports. Do not
|
|
56
|
+
over-invest here; the classification should cost a minute, not a research
|
|
57
|
+
pass.
|
|
58
|
+
|
|
59
|
+
## Procedure
|
|
60
|
+
|
|
61
|
+
1. If the user named a type explicitly (for example `/thatch/refine
|
|
62
|
+
shared-lib`), skip classification and use it.
|
|
63
|
+
2. Otherwise gather the signals above and pick the type.
|
|
64
|
+
3. State the classification in one line and why, and let the user override.
|
|
65
|
+
A wrong classification silently changes the requirements, so the user
|
|
66
|
+
sees the pick before it takes effect. When the signals conflict or are
|
|
67
|
+
too thin to pick, ask instead of guessing.
|
|
68
|
+
4. Load `thatch-plan-refinement` (the core loop) and the type's skill.
|
|
69
|
+
5. Run the core loop with the type skill's deltas applied. Where a delta
|
|
70
|
+
and the core skill disagree, the delta wins; that is its whole job.
|
|
71
|
+
|
|
72
|
+
If no type fits (the repo serves a niche the table misses), run plain
|
|
73
|
+
`thatch-plan-refinement` and say that the requirements are the generic
|
|
74
|
+
ones.
|
|
75
|
+
|
|
76
|
+
## Relationship to other skills
|
|
77
|
+
|
|
78
|
+
- **`thatch-plan-refinement`** - the core loop. Always loaded; the type
|
|
79
|
+
skills only modify it.
|
|
80
|
+
- **`thatch-coding-workflow`** - the procedure skill for executing the
|
|
81
|
+
refined plan. Refinement ends where it begins.
|
|
82
|
+
- **`thatch-clear-writing`** and the writing skills - several type skills
|
|
83
|
+
make reader-facing documentation a plan deliverable. Draft that text
|
|
84
|
+
under the writing skills' contracts, not this one's.
|
package/bin/thatch
CHANGED
|
@@ -1054,15 +1054,19 @@ switch (command) {
|
|
|
1054
1054
|
}
|
|
1055
1055
|
|
|
1056
1056
|
// Tier 1: extraction nudge. Peek (don't drain) - the queue persists
|
|
1057
|
-
// until the
|
|
1058
|
-
//
|
|
1059
|
-
//
|
|
1060
|
-
// sub-agent
|
|
1057
|
+
// until the extractor completes (extraction_done with the parent's
|
|
1058
|
+
// session_id) or the parent writes a memory itself. The parent's
|
|
1059
|
+
// dispatch-time ack resets the escalation counter but does NOT drain:
|
|
1060
|
+
// a drain at ack time deleted the queue before the sub-agent fetched
|
|
1061
|
+
// (the accept-before-fetch loss). If the agent ignores the nudge, the
|
|
1062
|
+
// payload grows on the next flush. The nudge carries the session ID,
|
|
1063
|
+
// not the full payload - the sub-agent fetches it via
|
|
1064
|
+
// get_extraction_payload.
|
|
1061
1065
|
const interactions = sessionID ? peekQueue(sessionID) : [];
|
|
1062
1066
|
if (interactions.length > 0) {
|
|
1063
1067
|
const missed = sessionID ? getMissedCount(sessionID) : 0;
|
|
1064
1068
|
if (sessionID) incrementMissedCount(sessionID);
|
|
1065
|
-
const output = extractionNudge(interactions.length, missed,
|
|
1069
|
+
const output = extractionNudge(interactions.length, missed, sessionID ?? "");
|
|
1066
1070
|
emit(output, versionWarning, isJson, chatLine);
|
|
1067
1071
|
break;
|
|
1068
1072
|
}
|
package/docs/dev/README.md
CHANGED
|
@@ -127,7 +127,7 @@ methods. The v1 hook shapes:
|
|
|
127
127
|
| `command.execute.before` | Arms the wrap-up greenlight check: `/thatch/compact` and `/thatch/exit` mark their session in `pendingWrapUp`. The next `session.status` idle resolves it by inspecting the final assistant message for the greenlight token and, when present, triggering the TUI action (`session_compact` via `executeCommand`, `app.exit` via `publish`; the exit path unregisters the session from the chat directory first). See [features/session-lifecycle.md](features/session-lifecycle.md). |
|
|
128
128
|
| `experimental.compaction.autocontinue` | Clears the compacting flag so `chat.message` nudges resume. Without this, nudges that instruct tool calls would fire during summary generation where tools are blocked. The `chat.message` hook also clears the flag if it fires for a session still in the compacting set but the incoming message has no compaction-type part — this handles compaction failure, where the session would otherwise be stuck with nudges off forever. |
|
|
129
129
|
| `tool.execute.after` | Buffers every non-`thatch_*`, non-`skill`, non-`task` tool call into the session's extraction buffer. (Skill/task are excluded — buffering them creates a feedback loop where the nudge triggers a skill load, which gets buffered, which triggers another nudge.) Memory writes (`thatch_memory_remember`) and `thatch_extraction_done` drain the buffer and reset the missed-nudge counter. For child sessions (`childToParent.has(sessionID)`), also tracks metrics: `remember` with `overwrite:false` → new++, `overwrite:true` → updated++, `forget` → deleted++. For `thatch_chat_*` tool calls, builds the transcript echo (`chatEchoText`) and posts it as a visible non-synthetic `noReply` part. This is a plugin hook, NOT a bus event — do not move it into the `event` handler; the event bus has no such event and it will silently never fire. |
|
|
130
|
-
| `chat.message` |
|
|
130
|
+
| `chat.message` | Recall nudge: embeds the user's prompt text with the in-process warm model, searches `db.search()` across repo + global, and pushes a recall nudge if matches exceed the threshold (default 0.55). The same embedding also feeds the prediction auto-fire (`db.scorePredictionNudge`, injects `[thatch] User decision model`) and the behavior auto-fire (`db.scoreBehaviorNudge`, injects `[thatch] Situational behaviors`). All three nudges fire independently in separate try/catch blocks with separate synthetic parts. There is deliberately NO extraction nudge here - extraction is plugin-driven at session idle (see the extraction feature doc); the old model-driven handshake raced its own state machine and was removed. Chat transcript echoes (non-synthetic `noReply` parts whose text is entirely `[chat]`-prefixed bubbles) are skipped before any tier — no model turn reads them, so nudging them wastes an embedding. Skipped entirely while the session is compacting (tool calls are blocked during summary generation), and for task-dispatched sub-agent sessions (`childToParent` without `extractionChildren`) - their tool lists may exclude the thatch tools and their work is driven by the dispatch prompt. |
|
|
131
131
|
| `event` | Subscribes to all session bus events. `session.created`: records `childToParent` + `parentSnapshots` (shallow copy of the parent's buffer for snapshot-aware drain), then sends the session-start reminder via `client.session.prompt` carrying the hygiene heartbeat (pending dedup pairs, stale count, orphaned branch memories) when any signal is non-zero. `session.status`: records the session's live status for the watcher and chat delivery gates; on idle, if the session is a child, drains its snapshot, fires a toast with `childMetrics`, and deletes the child session; if the session is a parent with pending tool interactions and not already extracting, calls `triggerExtraction` to create a direct-extraction child, then flushes pending watcher events and pending chat mail (the session just became deliverable). `session.error`: requeues the parent's buffer (child died without draining). `session.deleted`: cleans up `childToParent`, `parentSnapshots`, `childMetrics`, and `extracting`, cancels the session's watchers, and unregisters it from the chat directory (the crash path — a dead process fires no event — is covered by heartbeat staleness). `session.compacted`: clears the compacting flag so `chat.message` nudges resume. |
|
|
132
132
|
| `dispose` | Stops the version checker, the watcher poller, and the chat poller, closes the DB. |
|
|
133
133
|
|
|
@@ -171,11 +171,11 @@ Two of these hooks were dead for weeks because failures were invisible.
|
|
|
171
171
|
check for durable knowledge (via `thatch_memory_recall` for dedup, then
|
|
172
172
|
`thatch_memory_remember`) before composing a final response after
|
|
173
173
|
substantial work. No plugin hook fires between generation and response
|
|
174
|
-
delivery, so the only viable path is prompt instruction.
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
is uncertain.
|
|
174
|
+
delivery, so the only viable path is prompt instruction. If the agent
|
|
175
|
+
forgets to save, extraction still sweeps the buffered tool interactions
|
|
176
|
+
at the session's next idle (plugin-driven; there is no model-facing
|
|
177
|
+
extraction nudge any more). This is an experiment — model reliability on
|
|
178
|
+
meta-instructions is uncertain.
|
|
179
179
|
10. **Background completion narration is suppressed, not prevented.** When a
|
|
180
180
|
background sub-agent completes, opencode injects a `<task_result>` block
|
|
181
181
|
into the parent session and triggers a full model generation. Thatch
|
|
@@ -243,27 +243,23 @@ extraction cycle
|
|
|
243
243
|
→ tool.execute.after buffers non-thatch, non-skill, non-task tool calls
|
|
244
244
|
per session (max 20); for child sessions, also tracks new/updated/deleted
|
|
245
245
|
metrics
|
|
246
|
-
→ direct extraction (
|
|
246
|
+
→ direct extraction (the only opencode path):
|
|
247
247
|
parent goes idle (session.status idle) with pending tool interactions
|
|
248
|
-
→
|
|
249
|
-
|
|
250
|
-
client.session.create, and prompts it with
|
|
248
|
+
→ stale accepted entries requeue (15-min bound), then triggerExtraction
|
|
249
|
+
adds parentID to the `extracting` set, creates a child session via
|
|
250
|
+
client.session.create, and prompts it with extractionDirectPrompt
|
|
251
|
+
(the parent's session ID is interpolated by the plugin)
|
|
252
|
+
→ child fetches the payload via thatch_get_extraction_payload - the
|
|
253
|
+
fetch records its claim (the delivery record)
|
|
251
254
|
→ child runs the fact-extractor skill, writes memories via
|
|
252
|
-
thatch_memory_remember
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
a nudge part with session ID and fetch tool name; missed nudges escalate (polite →
|
|
261
|
-
insistent → ALL-CAPS) via the missedNudges counter
|
|
262
|
-
→ drain: thatch_memory_remember (or thatch_extraction_done) clears the
|
|
263
|
-
buffer and resets the missed-nudge counter
|
|
264
|
-
→ agent dispatches a sub-agent that calls thatch_get_extraction_payload
|
|
265
|
-
to fetch the queued interactions, loads thatch-fact-extractor skill,
|
|
266
|
-
saves facts via thatch_memory_remember
|
|
255
|
+
thatch_memory_remember - each write (or extraction_done) completes
|
|
256
|
+
the child's claimed delivery, consuming only what it received
|
|
257
|
+
→ child goes idle → event handler finalizes, fires a toast with
|
|
258
|
+
childMetrics, deletes the child session
|
|
259
|
+
→ failure recovery (no model-facing nudge exists): a child error or
|
|
260
|
+
deletion requeues what it held to pending; a completion signal that
|
|
261
|
+
never comes is bounded by the 15-minute stale reaper; either way the
|
|
262
|
+
next idle re-triggers extraction from the same pending buffer
|
|
267
263
|
→ MCP path (Claude Code/Cursor): unchanged — no SDK client, no child
|
|
268
264
|
sessions; extract-queue.ts + flush-tools drives the nudge via hooks
|
|
269
265
|
|
package/docs/dev/features/cli.md
CHANGED
|
@@ -85,6 +85,7 @@ Read-only window on the cross-session chat directory ([cross-session-chat.md](cr
|
|
|
85
85
|
| `THATCH_RECALL_THRESHOLD` | Cosine cutoff for recall nudge | `0.55` |
|
|
86
86
|
| `THATCH_PREDICTION_THRESHOLD` | Cutoff for prediction auto-fire | `0.60` |
|
|
87
87
|
| `THATCH_BEHAVIOR_THRESHOLD` | Cutoff for behavior auto-fire | `0.60` |
|
|
88
|
+
| `THATCH_CHILD_RECONCILE_MS` | Reload window before a restored extraction child is judged finished (test knob) | `10000` |
|
|
88
89
|
| `CLAUDE_PROJECT_DIR` | Claude Code project dir | `process.cwd()` |
|
|
89
90
|
| `CURSOR_PROJECT_DIR` | Cursor project dir | falls through |
|
|
90
91
|
| `CLAUDE_CONFIG_DIR` | Claude config dir | `~/.claude` |
|