thoth-agents 0.1.18 → 0.2.0

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 (37) hide show
  1. package/README.md +55 -12
  2. package/dist/agents/prompt-dialects.d.ts +9 -0
  3. package/dist/{chunk-6K3ZXIMC.js → chunk-3NOVCFN7.js} +88 -29
  4. package/dist/chunk-4WYCZ5Z7.js +698 -0
  5. package/dist/{chunk-SOT5ZY53.js → chunk-WH3F3GWE.js} +1498 -350
  6. package/dist/cli/claude-code-install.d.ts +53 -0
  7. package/dist/cli/claude-code-paths.d.ts +31 -0
  8. package/dist/cli/codex-install.d.ts +1 -5
  9. package/dist/cli/commands.d.ts +1 -1
  10. package/dist/cli/index.js +85 -27
  11. package/dist/cli/managed-state-io.d.ts +16 -0
  12. package/dist/cli/operations/claude-code.d.ts +21 -0
  13. package/dist/cli/tui/index.js +87 -9
  14. package/dist/cli/tui/operations.d.ts +2 -0
  15. package/dist/cli/types.d.ts +3 -3
  16. package/dist/config/index.d.ts +1 -1
  17. package/dist/config/schema.d.ts +11 -0
  18. package/dist/config/utils.d.ts +5 -0
  19. package/dist/harness/adapters/claude-code.d.ts +24 -0
  20. package/dist/harness/core/memory-governance.d.ts +39 -4
  21. package/dist/harness/core/package-version.d.ts +7 -0
  22. package/dist/harness/types.d.ts +1 -1
  23. package/dist/harness/writers/claude-code-plugin-package.d.ts +32 -0
  24. package/dist/harness/writers/claude-code-skill-layout.d.ts +16 -0
  25. package/dist/harness/writers/claude-code-subagent.d.ts +26 -0
  26. package/dist/harness/writers/fs-skill-collect.d.ts +7 -0
  27. package/dist/hooks/phase-reminder/index.d.ts +2 -0
  28. package/dist/hooks/thoth-mem/protocol.d.ts +2 -2
  29. package/dist/index.js +54 -512
  30. package/package.json +1 -1
  31. package/src/skills/_shared/persistence-contract.md +18 -14
  32. package/src/skills/_shared/thoth-mem-convention.md +18 -18
  33. package/src/skills/executing-plans/SKILL.md +6 -4
  34. package/src/skills/plan-reviewer/SKILL.md +4 -2
  35. package/src/skills/thoth-mem-agents/SKILL.md +3 -0
  36. package/thoth-agents.schema.json +16 -0
  37. package/dist/chunk-DYGVRAMS.js +0 -182
@@ -83,26 +83,29 @@ Subagents must not create fallback sessions.
83
83
 
84
84
  ## Retrieval Protocol
85
85
 
86
- ### 3-Layer Recall for thoth-mem and hybrid modes
86
+ ### Recall funnel for thoth-mem and hybrid modes
87
87
 
88
- Always complete the full three layers before using memory content as source
88
+ Always complete the recall funnel before using memory content as source
89
89
  material:
90
90
 
91
- 1. **Layer 1 (Compact):** `mem_recall(mode="compact")` to scan IDs/titles with
92
- exact topic-key or focused query terms.
93
- 2. **Layer 2 (Context):** `mem_recall(mode="context")` to expand the strongest
94
- hits into retrieved text.
95
- 3. **Layer 3 (Full):** `mem_get(id=...)` to fetch full content. Use
96
- `include_timeline=true` when chronology matters.
91
+ 1. `mem_recall(mode="compact")` scan candidate IDs/titles with exact topic-key
92
+ or focused query terms.
93
+ 2. `mem_recall(mode="context")` expand the strongest hits into retrieved text.
94
+ 3. `mem_get(id=...)` fetch full content; use
95
+ `mem_get(include_timeline=true)` when chronology matters.
97
96
 
98
- Optional fused context: `mem_context(..., recall_query="...")` when one recent
99
- context view is useful; it does not replace the three-layer recall.
97
+ Use HyDE/fused hybrid recall (sentence + chunk vectors, FTS, KG enrichment) for
98
+ semantic or ambiguous searches; narrow with `topic_key`, `type`, `time_from`,
99
+ `time_to`, `scope`, `project`, and `session_id` filters; use
100
+ `mem_context(recall_query=...)` or bounded
101
+ `mem_project(action="graph"|"topics"|"topic")` for supplemental project
102
+ context. Supplemental context does not replace the recall funnel.
100
103
 
101
104
  ### Mode-specific retrieval
102
105
 
103
- 1. If mode is `thoth-mem`, use three-layer recall with exact SDD topic key.
106
+ 1. If mode is `thoth-mem`, use the recall funnel with exact SDD topic key.
104
107
  2. If mode is `openspec`, read canonical OpenSpec files only.
105
- 3. If mode is `hybrid`, use three-layer recall first.
108
+ 3. If mode is `hybrid`, use the recall funnel first.
106
109
  4. In `hybrid`, if nothing is found in thoth-mem, read canonical OpenSpec
107
110
  files as fallback.
108
111
  5. In `hybrid`, if filesystem fallback succeeds, re-save the artifact to
@@ -148,8 +151,9 @@ original intent, accepted scope, deferred areas, and justified exclusions.
148
151
  ## Recovery Notes
149
152
 
150
153
  - Prefer exact topic-key queries over broad natural-language recall.
151
- - Always apply the three-layer recall (`mem_recall compact` ->
152
- `mem_recall context` -> `mem_get`) before treating memory as source material.
154
+ - Always apply the recall funnel (`mem_recall(mode="compact")` ->
155
+ `mem_recall(mode="context")` -> `mem_get(...)`) before treating memory as
156
+ source material.
153
157
  - In `openspec`, repair missing/stale artifacts by rewriting canonical OpenSpec
154
158
  files.
155
159
  - In `thoth-mem`, repair missing/stale artifacts by re-saving full artifacts via
@@ -81,30 +81,30 @@ Persist with `mem_save` using canonical SDD topic keys and required metadata:
81
81
  Recovery path for state artifacts:
82
82
  `mem_recall(mode="compact", query="topic_key:sdd/{change-name}/state")` ->
83
83
  `mem_recall(mode="context", query="topic_key:sdd/{change-name}/state")` when needed ->
84
- `mem_get(id=...)` (or `include_timeline=true` when chronology matters) ->
84
+ `mem_get(id=...)` (or `mem_get(include_timeline=true)` when chronology matters) ->
85
85
  parse YAML -> restore phase state.
86
86
 
87
- ## Three-Layer Recall Protocol
87
+ ## Recall Funnel Protocol
88
88
 
89
89
  For delegated handoffs, subagents may use recall only when dispatch includes
90
90
  both parent `session_id` and `project`.
91
91
 
92
- 1. **Compact scan**
93
-
94
- `mem_recall(mode="compact")` with exact topic-key query for token-efficient IDs
95
- and ranking.
96
-
97
- 2. **Context expansion**
98
-
99
- `mem_recall(mode="context")` to expand strongest hits into retrieved text.
100
-
101
- 3. **Full body fetch**
102
-
103
- `mem_get(id=...)` to retrieve full artifact content. Use
104
- `include_timeline=true` when chronology matters.
105
-
106
- Optional: `mem_context(..., recall_query="...")` can provide fused recent
107
- context, but it does not replace the three-layer recall.
92
+ 1. `mem_recall(mode="compact")` with exact topic-key query for token-efficient
93
+ IDs and ranking.
94
+ 2. `mem_recall(mode="context")` to expand strongest hits into retrieved text.
95
+ 3. `mem_get(id=...)` to retrieve full artifact content; use
96
+ `mem_get(include_timeline=true)` when chronology matters.
97
+
98
+ Use HyDE/fused hybrid recall (sentence + chunk vectors, FTS, KG enrichment) for
99
+ semantic or ambiguous searches; set `mem_recall` `limit` from 1 to 20; narrow
100
+ with `topic_key`, `type`, `time_from`, `time_to`, `scope`, `project`, and
101
+ `session_id` filters. Use `mem_get` with `kind="observation"|"prompt"`,
102
+ `include_timeline=true` plus `before`/`after`, and `offset`/`max_length` for
103
+ large content. Use `mem_context(recall_query=...)` or bounded
104
+ `mem_project(action="graph"|"topics"|"topic")` for supplemental project
105
+ context; `mem_project(action="graph")` relations are `HAS_TYPE`, `IN_PROJECT`,
106
+ `HAS_TOPIC_KEY`, `HAS_WHAT`, `HAS_WHY`, `HAS_WHERE`, and `HAS_LEARNED`.
107
+ Supplemental context does not replace the recall funnel.
108
108
 
109
109
  ## Save Contract
110
110
 
@@ -71,9 +71,10 @@ The orchestrator owns task progress tracking.
71
71
  2. Load task artifacts using mode-aware retrieval:
72
72
  - `openspec`/`hybrid`: scan `openspec/changes/` for active changes and read
73
73
  `tasks.md`.
74
- - `thoth-mem`: recover tasks via 3-layer recall
74
+ - `thoth-mem`: recover tasks via the recall funnel
75
75
  (`mem_recall(mode="compact")` -> `mem_recall(mode="context")` ->
76
- `mem_get(id=...)`) using topic key `sdd/{change-name}/tasks`.
76
+ `mem_get(...)`) using topic key `sdd/{change-name}/tasks`; use
77
+ `mem_get(include_timeline=true)` when task chronology matters.
77
78
  3. Find the first unchecked task in state `- [ ]` or `- [~]`.
78
79
  4. Build a mental model of the plan: total tasks, remaining work,
79
80
  parallelizable work, and dependency order.
@@ -233,9 +234,10 @@ To resume safely:
233
234
  2. Recover task state using mode-aware retrieval:
234
235
  - `openspec`: read `openspec/changes/{change-name}/tasks.md`.
235
236
  - `thoth-mem`: recover `sdd/{change-name}/tasks` and
236
- `sdd/{change-name}/apply-progress` via 3-layer recall
237
+ `sdd/{change-name}/apply-progress` via the recall funnel
237
238
  (`mem_recall(mode="compact")` -> `mem_recall(mode="context")` ->
238
- `mem_get(id=...)`).
239
+ `mem_get(...)`); use `mem_get(include_timeline=true)` when task chronology
240
+ matters.
239
241
  - `hybrid`: do both recovery paths and prefer thoth-mem as the source of
240
242
  truth if state diverges.
241
243
  3. Resume from the first task marked `- [ ]` or `- [~]`.
@@ -21,8 +21,10 @@ to hand to implementation.
21
21
 
22
22
  Review the tasks artifact for true execution blockers. Retrieve it according to
23
23
  the persistence mode: read `openspec/changes/{change-name}/tasks.md` for
24
- openspec/hybrid modes, use thoth-mem 3-layer recall for thoth-mem/hybrid modes,
25
- or read from inline context for none mode.
24
+ openspec/hybrid modes, use the thoth-mem recall funnel
25
+ (`mem_recall(mode="compact")` -> `mem_recall(mode="context")` ->
26
+ `mem_get(...)`) for thoth-mem/hybrid modes, or read from inline context for none
27
+ mode.
26
28
 
27
29
  The artifact governance validator is not part of this review. Plan-reviewer is
28
30
  only the pre-execution approval gate for the task plan; it does not run the
@@ -88,6 +88,7 @@ Learned: caveats or edge cases
88
88
  3. `mem_get(id=...)`
89
89
 
90
90
  Use `mem_get(id=..., include_timeline=true)` when chronology matters.
91
+ Set `mem_recall` `limit` from 1 to 20. Use `mem_get` with `kind="observation"|"prompt"`, `include_timeline=true` plus `before`/`after`, and `offset`/`max_length` for large content.
91
92
  Use `mem_context(..., recall_query="...")` only as optional fused context, not
92
93
  as a replacement for the recall funnel.
93
94
 
@@ -101,6 +102,8 @@ Use `mem_project` for project-level navigation:
101
102
  - `action="topics"`
102
103
  - `action="topic"`
103
104
 
105
+ `mem_project(action="graph")` relations are `HAS_TYPE`, `IN_PROJECT`, `HAS_TOPIC_KEY`, `HAS_WHAT`, `HAS_WHY`, `HAS_WHERE`, and `HAS_LEARNED`.
106
+
104
107
  ### Session close and compaction
105
108
 
106
109
  Before ending meaningful work, root records continuity with either:
@@ -466,6 +466,22 @@
466
466
  "type": "boolean"
467
467
  }
468
468
  }
469
+ },
470
+ "claudeCode": {
471
+ "type": "object",
472
+ "properties": {
473
+ "enabled": {
474
+ "default": false,
475
+ "type": "boolean"
476
+ },
477
+ "outputRoot": {
478
+ "type": "string"
479
+ },
480
+ "dryRun": {
481
+ "default": true,
482
+ "type": "boolean"
483
+ }
484
+ }
469
485
  }
470
486
  },
471
487
  "title": "thoth-agents",
@@ -1,182 +0,0 @@
1
- // src/utils/subprocess.ts
2
- import {
3
- spawn as nodeSpawn,
4
- spawnSync as nodeSpawnSync
5
- } from "child_process";
6
- import { Readable } from "stream";
7
- function emptyReadableStream() {
8
- return new ReadableStream({
9
- start(controller) {
10
- controller.close();
11
- }
12
- });
13
- }
14
- function toWebReadable(stream) {
15
- if (!stream) {
16
- return emptyReadableStream();
17
- }
18
- return Readable.toWeb(
19
- stream
20
- );
21
- }
22
- function fallbackStdin() {
23
- return {
24
- write: () => void 0,
25
- end: () => void 0
26
- };
27
- }
28
- function spawn(command, options = {}) {
29
- const child = nodeSpawn(command[0], command.slice(1), {
30
- cwd: options.cwd,
31
- env: options.env,
32
- stdio: [
33
- options.stdin ?? "pipe",
34
- options.stdout ?? "pipe",
35
- options.stderr ?? "pipe"
36
- ]
37
- });
38
- const managed = {
39
- stdin: child.stdin ?? fallbackStdin(),
40
- stdout: toWebReadable(child.stdout),
41
- stderr: toWebReadable(child.stderr),
42
- exited: new Promise((resolve) => {
43
- child.on("exit", (code) => {
44
- managed.exitCode = code;
45
- resolve(code ?? 1);
46
- });
47
- child.on("error", () => {
48
- managed.exitCode = 1;
49
- resolve(1);
50
- });
51
- }),
52
- exitCode: child.exitCode,
53
- kill: () => {
54
- child.kill();
55
- }
56
- };
57
- return managed;
58
- }
59
- function spawnSync(command, options = {}) {
60
- const result = nodeSpawnSync(command[0], command.slice(1), {
61
- cwd: options.cwd,
62
- env: options.env,
63
- stdio: [
64
- options.stdin ?? "ignore",
65
- options.stdout ?? "pipe",
66
- options.stderr ?? "pipe"
67
- ]
68
- });
69
- return { exitCode: result.status };
70
- }
71
-
72
- // src/cli/system.ts
73
- import { statSync } from "fs";
74
- var cachedOpenCodePath = null;
75
- function getOpenCodePaths() {
76
- const home = process.env.HOME || process.env.USERPROFILE || "";
77
- return [
78
- // PATH (try this first)
79
- "opencode",
80
- // User local installations (Linux & macOS)
81
- `${home}/.local/bin/opencode`,
82
- `${home}/.opencode/bin/opencode`,
83
- `${home}/bin/opencode`,
84
- // System-wide installations
85
- "/usr/local/bin/opencode",
86
- "/opt/opencode/bin/opencode",
87
- "/usr/bin/opencode",
88
- "/bin/opencode",
89
- // macOS specific
90
- "/Applications/OpenCode.app/Contents/MacOS/opencode",
91
- `${home}/Applications/OpenCode.app/Contents/MacOS/opencode`,
92
- // Homebrew (macOS & Linux)
93
- "/opt/homebrew/bin/opencode",
94
- "/home/linuxbrew/.linuxbrew/bin/opencode",
95
- `${home}/homebrew/bin/opencode`,
96
- // macOS user Library
97
- `${home}/Library/Application Support/opencode/bin/opencode`,
98
- // Snap (Linux)
99
- "/snap/bin/opencode",
100
- "/var/snap/opencode/current/bin/opencode",
101
- // Flatpak (Linux)
102
- "/var/lib/flatpak/exports/bin/ai.opencode.OpenCode",
103
- `${home}/.local/share/flatpak/exports/bin/ai.opencode.OpenCode`,
104
- // Nix (Linux/macOS)
105
- "/nix/store/opencode/bin/opencode",
106
- `${home}/.nix-profile/bin/opencode`,
107
- "/run/current-system/sw/bin/opencode",
108
- // Cargo (Rust toolchain)
109
- `${home}/.cargo/bin/opencode`,
110
- // npm/npx global
111
- `${home}/.npm-global/bin/opencode`,
112
- "/usr/local/lib/node_modules/opencode/bin/opencode",
113
- // Yarn global
114
- `${home}/.yarn/bin/opencode`,
115
- // PNPM
116
- `${home}/.pnpm-global/bin/opencode`
117
- ];
118
- }
119
- function resolveOpenCodePath() {
120
- if (cachedOpenCodePath) {
121
- return cachedOpenCodePath;
122
- }
123
- const paths = getOpenCodePaths();
124
- for (const opencodePath of paths) {
125
- if (opencodePath === "opencode") continue;
126
- try {
127
- const stat = statSync(opencodePath);
128
- if (stat.isFile()) {
129
- cachedOpenCodePath = opencodePath;
130
- return opencodePath;
131
- }
132
- } catch {
133
- }
134
- }
135
- return "opencode";
136
- }
137
- async function isOpenCodeInstalled() {
138
- const paths = getOpenCodePaths();
139
- for (const opencodePath of paths) {
140
- try {
141
- const proc = spawn([opencodePath, "--version"], {
142
- stdout: "pipe",
143
- stderr: "pipe"
144
- });
145
- await proc.exited;
146
- if (proc.exitCode === 0) {
147
- cachedOpenCodePath = opencodePath;
148
- return true;
149
- }
150
- } catch {
151
- }
152
- }
153
- return false;
154
- }
155
- async function getOpenCodeVersion() {
156
- const opencodePath = resolveOpenCodePath();
157
- try {
158
- const proc = spawn([opencodePath, "--version"], {
159
- stdout: "pipe",
160
- stderr: "pipe"
161
- });
162
- const output = await new Response(proc.stdout).text();
163
- await proc.exited;
164
- if (proc.exitCode === 0) {
165
- return output.trim();
166
- }
167
- } catch {
168
- }
169
- return null;
170
- }
171
- function getOpenCodePath() {
172
- const path = resolveOpenCodePath();
173
- return path === "opencode" ? null : path;
174
- }
175
-
176
- export {
177
- spawn,
178
- spawnSync,
179
- isOpenCodeInstalled,
180
- getOpenCodeVersion,
181
- getOpenCodePath
182
- };