thoth-agents 0.1.18 → 0.1.19

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 CHANGED
@@ -301,9 +301,20 @@ Artifacts can be persisted in four modes:
301
301
  Thoth-mem is the local memory MCP used for durable observations, architectural
302
302
  decisions, SDD artifacts, and session summaries. The core retrieval pattern is:
303
303
 
304
- 1. `mem_search` for compact candidate records
305
- 2. `mem_timeline` for chronological context
306
- 3. `mem_get_observation` for the full selected record
304
+ 1. `mem_recall(mode="compact")` for compact candidate records
305
+ 2. `mem_recall(mode="context")` for expanded retrieved context
306
+ 3. `mem_get(...)` for the full selected record; use
307
+ `mem_get(include_timeline=true)` when chronology matters
308
+
309
+ Use HyDE/fused hybrid recall (sentence + chunk vectors, FTS, KG enrichment) for
310
+ semantic or ambiguous searches; set `mem_recall` `limit` from 1 to 20; narrow
311
+ with `topic_key`, `type`, `time_from`, `time_to`, `scope`, `project`, and
312
+ `session_id` filters. Use `mem_get` with `kind="observation"|"prompt"`,
313
+ `include_timeline=true` plus `before`/`after`, and `offset`/`max_length` for
314
+ large content. Use bounded `mem_context(recall_query=...)` or
315
+ `mem_project(action="graph"|"topics"|"topic")` for supplemental project
316
+ context; `mem_project(action="graph")` relations are `HAS_TYPE`, `IN_PROJECT`,
317
+ `HAS_TOPIC_KEY`, `HAS_WHAT`, `HAS_WHY`, `HAS_WHERE`, and `HAS_LEARNED`.
307
318
 
308
319
  ## Skills And MCPs
309
320
 
@@ -1098,9 +1098,9 @@ Push back when context, risk, or assumptions are weak. Avoid verbosity.
1098
1098
  </epistemic-rigor>
1099
1099
 
1100
1100
  <session-bootstrap>
1101
- - At the start of a new root session, when thoth-mem tools are available, load \`thoth-mem-agents\` and \`requirements-interview\`, call \`mem_session_start\` with the current project and session identity, then save the real user prompt with \`mem_save_prompt\`.
1102
- - Save only the real user request with \`mem_save_prompt\`; never save generated sub-agent prompts, handoffs, summaries, or tool scaffolding as user intent.
1103
- - If thoth-mem tools or required session/project identity are unavailable, disclose that memory bootstrap could not run and continue without pretending memory was saved.
1101
+ - At the start of a new root session, when thoth-mem tools and session/project identity are available, load \`thoth-mem-agents\` and \`requirements-interview\`, then call \`mem_session(action="start")\` as step 0 before any other thoth-mem call.
1102
+ - Save only the real user request with \`mem_save(kind="prompt")\`; never save generated sub-agent prompts, handoffs, summaries, or tool scaffolding as user intent.
1103
+ - If thoth-mem tools or required session/project identity are unavailable, disclose that memory bootstrap could not run and continue without claiming memory was saved.
1104
1104
  </session-bootstrap>
1105
1105
 
1106
1106
  <routing>
@@ -1136,9 +1136,9 @@ Before dispatching {{role.designer}}, {{role.quick}}, or {{role.deep}} after dis
1136
1136
 
1137
1137
  Internal handoff fields: Goal, Decision, Evidence, Scope, Steps, Verification, Uncertainty, relevant files or symbols, suggested skills when applicable, constraints, non-goals, escalation conditions, and next focus.
1138
1138
 
1139
- When thoth-mem session-summary tooling and parent session/project identity are available, save or refresh that handoff body with root-owned \`mem_session_summary\` before dispatch. If the tooling or identity is unavailable, disclose that root-owned compaction could not be persisted and continue with explicit task instructions and local context; do not invent a fallback session or ask a sub-agent to create one.
1139
+ When thoth-mem summary persistence and parent session/project identity are available, save or refresh that handoff body with root-owned \`mem_session(action="summary")\` or \`mem_save(kind="session_summary")\` before dispatch. If tooling or identity is unavailable, disclose that root-owned compaction could not be persisted and continue with explicit task instructions and local context; do not invent a fallback session or ask a sub-agent to create one.
1140
1140
 
1141
- The delegated prompt carries task instructions plus handoff recovery instructions only: parent \`session_id\`, project, persistence mode, memory permissions, bounded 3-layer recall steps, non-goals, escalation conditions, and redaction requirements. It must not include the handoff body, raw transcripts, file dumps, secrets, credentials, irrelevant context, or generated sub-agent prompts as memory source material.
1141
+ The delegated prompt carries task instructions plus handoff recovery instructions only: parent \`session_id\`, project, persistence mode, memory permissions, the recall funnel \`mem_recall(mode="compact")\` -> \`mem_recall(mode="context")\` -> \`mem_get(...)\`, optional bounded \`mem_context(recall_query=...)\`/\`mem_project(...)\` guidance when permitted, non-goals, escalation conditions, and redaction requirements. It must not include the handoff body, raw transcripts, file dumps, secrets, credentials, irrelevant context, or generated sub-agent prompts as memory source material.
1142
1142
 
1143
1143
  Never mention internal handoff preparation to the user, ask the user to prepare it, or present handoff preparation as the recommended next step. Describe the actual work instead.
1144
1144
 
@@ -1199,12 +1199,15 @@ Post-execution: delegate sdd-verify, then sdd-archive when verification passes.
1199
1199
  <progress-memory>
1200
1200
  - Keep {{progressTool}} top-level and lean for multi-step work.
1201
1201
  - When SDD is active, update both {{progressTool}} and openspec/changes/{change-name}/tasks.md before dispatch and after results.
1202
- - Root-session memory is yours: search before repeated work; save durable decisions, discoveries, bugs, patterns, constraints, and session summaries.
1203
- - Durable \`mem_save\`: save durable decisions, bug root causes, discoveries, conventions, config changes, and preferences. Use stable topic keys; keep general observations outside \`sdd/*\`.
1204
- - Targeted 3-layer recall protocol: \`mem_search\` compact -> \`mem_timeline\` -> \`mem_get_observation\` only for records needed in full.
1202
+ - Root-session memory is yours: recall repeated work; save durable decisions, discoveries, bugs, patterns, constraints, summaries.
1203
+ - Use \`mem_save(kind="observation")\` for decisions, bugs, discoveries, conventions, preferences; stable topics; observations outside \`sdd/*\`.
1204
+ - Targeted recall funnel: \`mem_recall(mode="compact")\` -> \`mem_recall(mode="context")\` -> \`mem_get(...)\`; use \`mem_get(include_timeline=true)\` for time context.
1205
+ - Use HyDE/fused recall; set \`mem_recall\` \`limit\` from 1 to 20; narrow with \`topic_key\`, \`type\`, \`time_from\`/\`time_to\`, \`scope\`, \`project\`, \`session_id\`.
1206
+ - \`mem_get\`: \`kind="observation"|"prompt"\`, \`include_timeline=true\`, \`before\`/\`after\`, \`offset\`/\`max_length\`; supplement with bounded \`mem_context(recall_query=...)\` or \`mem_project(action="graph"|"topics"|"topic")\`.
1207
+ - Graph relations: HAS_TYPE, IN_PROJECT, HAS_TOPIC_KEY, HAS_WHAT, HAS_WHY, HAS_WHERE, HAS_LEARNED.
1205
1208
  - SDD memory artifacts use deterministic topic keys only in thoth-mem or hybrid persistence modes: \`sdd/{change}/{artifact}\`.
1206
- - Before ending the root session, call \`mem_session_summary\` with a concise Goal, Instructions, Discoveries, Accomplished, Next Steps, and Relevant Files summary. Do not claim memory was saved unless the tool call succeeded.
1207
- - After compaction, first preserve the compacted summary with \`mem_session_summary\`, then recover recent context and use the 3-layer recall protocol before continuing work.
1209
+ - Before ending the root session, call \`mem_session(action="summary")\` or root-owned \`mem_save(kind="session_summary")\` with a concise Goal, Instructions, Discoveries, Accomplished, Next Steps, and Relevant Files summary. Do not claim memory was saved unless the tool call succeeded.
1210
+ - After compaction, first preserve the compacted summary with \`mem_session(action="summary")\`, then call \`mem_context(recall_query=...)\` and use the recall funnel before continuing work.
1208
1211
  </progress-memory>
1209
1212
 
1210
1213
  <communication>
@@ -1376,32 +1379,30 @@ function renderSubagentRules(section, dialect) {
1376
1379
  ];
1377
1380
  if (section.memoryAccess === "readonly") {
1378
1381
  rules.push(
1379
- "- Use read-only thoth-mem only when dispatch gives parent session_id/project and handoff recovery instructions: `mem_search` -> `mem_timeline` -> `mem_get_observation`.",
1380
- "- The canonical recall path remains `mem_search` -> `mem_timeline` -> `mem_get_observation`; use bounded context tools only as supplemental context when explicitly allowed.",
1381
- "- If either parent session_id or project is missing, do NOT call thoth-mem; rely on explicit task instructions and local evidence.",
1382
- "- Recover the parent-session handoff summary through bounded 3-layer recall before treating memory as source material.",
1382
+ "- Use read-only thoth-mem only when dispatch gives parent session_id/project and handoff recovery instructions.",
1383
+ "- Parent-scoped reads: `mem_recall`, `mem_context`, `mem_get`, bounded `mem_project`; do not call `mem_save` or own any `mem_session(...)` lifecycle action.",
1384
+ "- If either parent session_id or project is missing, do NOT call thoth-mem; rely on task instructions and local evidence.",
1385
+ '- Recover the parent-session handoff summary through the recall funnel `mem_recall(mode="compact")` -> `mem_recall(mode="context")` -> `mem_get(...)` before using memory.',
1386
+ '- Use `mem_recall` `limit` from 1 to 20; use `mem_get` with `kind="observation"|"prompt"`, `include_timeline=true`, `before`/`after`, and `offset`/`max_length`.',
1383
1387
  "- Report when recalled context is missing, stale, contradictory, or insufficient.",
1384
- "- Use project-scoped read tools (`mem_context`, `mem_project_summary`, `mem_project_graph`, `mem_topic_keys`) only when explicitly allowed by the delegated task instructions and bounded to the parent session/project scope.",
1385
- "- Never call `mem_session_start`, `mem_session_summary`, or `mem_save_prompt`; those tools are orchestrator-owned.",
1386
- "- Never save generated subagent prompts as user intent.",
1387
- "- Never write memory; memory writes are orchestrator-owned."
1388
+ '- Supplemental `mem_context(recall_query=...)` and bounded `mem_project(action="graph"|"topics"|"topic")` do not replace the recall funnel and require explicit delegated permission. Graph relations: `HAS_TYPE`, `IN_PROJECT`, `HAS_TOPIC_KEY`, `HAS_WHAT`, `HAS_WHY`, `HAS_WHERE`, `HAS_LEARNED`.',
1389
+ "- Never save prompts, generated subagent prompts, session summaries, or durable memory."
1388
1390
  );
1389
1391
  }
1390
1392
  if (section.memoryAccess === "writable") {
1391
1393
  rules.push(
1392
- "- Use delegated thoth-mem tools only (mem_save, mem_search, mem_get_observation, mem_timeline, mem_context, mem_project_summary, mem_project_graph, mem_topic_keys, mem_suggest_topic_key).",
1393
- "- Never call `mem_session_start`, `mem_session_summary`, or `mem_save_prompt`; those tools are orchestrator-owned.",
1394
+ "- Use delegated thoth-mem tools only: `mem_save`, `mem_recall`, `mem_context`, `mem_get`, `mem_project`, `mem_session`.",
1394
1395
  "- Always use the parent session_id/project from dispatch for every thoth-mem call.",
1395
1396
  "- If either is missing, do NOT call thoth-mem.",
1396
1397
  "- Follow handoff recovery instructions from the delegated task before using persisted memory.",
1397
- "- For reads, use only `mem_search` -> `mem_timeline` -> `mem_get_observation` and recover the parent-session handoff summary before treating memory as source material.",
1398
- "- Keep 3-layer recall canonical; use `mem_context`, `mem_project_summary`, `mem_project_graph`, and `mem_topic_keys` only as bounded supplemental context when the dispatch explicitly permits project-scoped reads.",
1398
+ '- For reads, use the recall funnel `mem_recall(mode="compact")` -> `mem_recall(mode="context")` -> `mem_get(...)` and recover the parent-session handoff summary before treating memory as source material.',
1399
+ '- Use `mem_recall` `limit` from 1 to 20; use `mem_get` with `kind="observation"|"prompt"`, `include_timeline=true`, `before`/`after`, and `offset`/`max_length`.',
1400
+ '- Keep the recall funnel canonical; use `mem_context(recall_query=...)` and bounded `mem_project(action="graph"|"topics"|"topic")` only with explicit project-read permission. Graph relations: `HAS_TYPE`, `IN_PROJECT`, `HAS_TOPIC_KEY`, `HAS_WHAT`, `HAS_WHY`, `HAS_WHERE`, `HAS_LEARNED`.',
1399
1401
  "- Report when recalled context is missing, stale, contradictory, or insufficient.",
1400
- "- Use project-scoped read tools only when explicitly allowed by the delegated task instructions and bounded to the parent session/project scope.",
1401
- "- `mem_save` is allowed only for delegated durable implementation observations or assigned SDD artifacts/apply-progress under the parent session/project.",
1402
+ '- `mem_save(kind="observation")` is allowed only for delegated durable implementation observations or assigned deterministic SDD artifacts/apply-progress under the parent session/project.',
1403
+ '- Never own `mem_session(action="start"|"checkpoint"|"summary")`, save prompts, or save generated subagent prompts as user intent.',
1402
1404
  "- Protect the `sdd/*` namespace: deterministic SDD artifacts use `sdd/{change}/{artifact}`; general durable observations must stay outside `sdd/*`.",
1403
- "- Never save generated subagent prompts as user intent.",
1404
- "- You do not own durable memory of your own; `mem_save` writes under the orchestrator's session/project only."
1405
+ '- You do not own durable memory of your own; permitted `mem_save(kind="observation")` writes under the orchestrator\'s session/project only.'
1405
1406
  );
1406
1407
  }
1407
1408
  return rules.join("\n");
@@ -31,7 +31,7 @@ import {
31
31
  renderRolePrompt,
32
32
  writeConfig,
33
33
  writeLiteConfig
34
- } from "./chunk-6K3ZXIMC.js";
34
+ } from "./chunk-2SGSRR6L.js";
35
35
 
36
36
  // src/harness/adapters/codex.ts
37
37
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "fs";
@@ -172,96 +172,91 @@ function getAgentPackContract() {
172
172
  }
173
173
 
174
174
  // src/harness/core/memory-governance.ts
175
- var ROOT_OWNED_TOOLS = [
176
- "mem_session_start",
177
- "mem_session_summary",
178
- "mem_save_prompt"
175
+ var ROOT_OWNED_OPERATIONS = [
176
+ { tool: "mem_session", action: "start" },
177
+ { tool: "mem_session", action: "checkpoint" },
178
+ { tool: "mem_session", action: "summary" },
179
+ { tool: "mem_save", kind: "prompt" },
180
+ { tool: "mem_save", kind: "session_summary" }
179
181
  ];
180
- var READ_RECALL_CHAIN = [
181
- "mem_search",
182
- "mem_timeline",
183
- "mem_get_observation"
184
- ];
185
- var BOUNDED_CONTEXT_TOOLS = [
182
+ var PARENT_SCOPED_READ_TOOLS = [
183
+ "mem_recall",
186
184
  "mem_context",
187
- "mem_project_summary",
188
- "mem_project_graph",
189
- "mem_topic_keys"
185
+ "mem_get",
186
+ "mem_project"
190
187
  ];
191
188
  var WRITE_CAPABLE_DELEGATED_TOOLS = [
192
- "mem_save",
193
- "mem_search",
194
- "mem_get_observation",
195
- "mem_timeline",
196
- ...BOUNDED_CONTEXT_TOOLS,
197
- "mem_suggest_topic_key"
189
+ ...PARENT_SCOPED_READ_TOOLS,
190
+ "mem_save"
198
191
  ];
199
192
  var ALL_MEMORY_TOOLS = [
200
- ...ROOT_OWNED_TOOLS,
201
- ...READ_RECALL_CHAIN,
202
- ...BOUNDED_CONTEXT_TOOLS,
203
- "mem_suggest_topic_key",
204
- "mem_save"
193
+ "mem_save",
194
+ "mem_recall",
195
+ "mem_context",
196
+ "mem_get",
197
+ "mem_project",
198
+ "mem_session"
205
199
  ];
206
200
  function uniqueTools(tools) {
207
201
  return [...new Set(tools)];
208
202
  }
209
203
  function roleAllowedTools(role) {
210
204
  if (role.name === "orchestrator") {
211
- return uniqueTools([...ROOT_OWNED_TOOLS, ...WRITE_CAPABLE_DELEGATED_TOOLS]);
205
+ return [...ALL_MEMORY_TOOLS];
212
206
  }
213
207
  if (role.mode === "read-only") {
214
- return [...READ_RECALL_CHAIN, ...BOUNDED_CONTEXT_TOOLS];
208
+ return [...PARENT_SCOPED_READ_TOOLS];
215
209
  }
216
- return [...WRITE_CAPABLE_DELEGATED_TOOLS];
210
+ return uniqueTools([...WRITE_CAPABLE_DELEGATED_TOOLS]);
217
211
  }
218
212
  function roleRules(role) {
219
213
  const sharedSubagentRules = [
220
214
  "Every subagent memory call requires the parent session_id and project from dispatch; if either is missing, do not call thoth-mem.",
221
- "Delegated handoff recovery uses parent-scoped 3-layer recall with mem_search -> mem_timeline -> mem_get_observation before memory content is treated as source material.",
215
+ 'Delegated handoff recovery uses the parent-scoped recall funnel: mem_recall(mode="compact") -> mem_recall(mode="context") -> mem_get(...) before memory content is treated as source material.',
216
+ "Use mem_get(include_timeline=true) when chronology around a recovered record matters.",
217
+ 'mem_context(recall_query=...) and bounded mem_project(action="graph"|"topics"|"topic") are supplemental project context only and do not replace the recall funnel.',
222
218
  "Report missing, stale, contradictory, or insufficient recalled context instead of guessing through it.",
223
- "Never call mem_session_start, mem_session_summary, or mem_save_prompt; those tools are root/orchestrator-owned.",
219
+ 'Never own mem_session(action="start"|"checkpoint"|"summary") or mem_save(kind="prompt"|"session_summary"); those operations are root/orchestrator-owned.',
224
220
  "Never save generated subagent prompts as user intent.",
225
221
  "Protect the sdd/* topic namespace; SDD artifacts may use deterministic sdd/{change}/{artifact} topic keys only in persistence modes that include thoth-mem."
226
222
  ];
227
223
  if (role.name === "orchestrator") {
228
224
  return [
229
- "mem_session_start, mem_session_summary, and mem_save_prompt are root/main orchestrator-owned tools and responsibilities.",
225
+ 'mem_session(action="start"|"checkpoint"|"summary"), mem_save(kind="prompt"), and mem_save(kind="session_summary") are root/main orchestrator-owned operations and responsibilities.',
230
226
  "In harnesses without an orchestrator-named agent, root/main orchestrator-owned means the initial/root agent when the harness does not expose an orchestrator-named agent.",
231
- "Before delegation, save or refresh the handoff body with root-owned mem_session_summary when available; otherwise disclose that compaction could not be persisted.",
227
+ 'Before delegation, save or refresh the handoff body with root-owned mem_session(action="summary") or mem_save(kind="session_summary") when available; otherwise disclose that compaction could not be persisted.',
232
228
  "Dispatch task instructions plus recovery instructions, not the handoff body, raw transcripts, or generated subagent prompts.",
233
229
  "Dispatch parent session_id and project when authorizing subagent memory use.",
230
+ 'Root recall uses mem_recall(mode="compact") -> mem_recall(mode="context") -> mem_get(...); use mem_context(recall_query=...) and bounded mem_project(action="graph"|"topics"|"topic") for supplemental context.',
234
231
  "Protect the sdd/* topic namespace and write SDD memory artifacts only in thoth-mem or hybrid persistence modes."
235
232
  ];
236
233
  }
237
234
  if (role.mode === "read-only") {
238
235
  return [
239
236
  ...sharedSubagentRules,
240
- "Read-only agents may only perform bounded, project-scoped recall with mem_search -> mem_timeline -> mem_get_observation when authorized.",
241
- "Bounded context tools mem_context, mem_project_summary, mem_project_graph, and mem_topic_keys are allowed only with explicit delegated permission and parent session/project scope.",
242
- "Project-scoped read tools require explicit delegated permission.",
243
- "Read-only agents must never write durable memory."
237
+ "Read-only agents may use only parent-scoped mem_recall, mem_context, mem_get, and bounded mem_project reads when authorized.",
238
+ "Project-scoped read tools require explicit delegated permission and must stay bounded to the parent session/project scope.",
239
+ "Read-only agents must never write durable memory or save prompts."
244
240
  ];
245
241
  }
246
242
  return [
247
243
  ...sharedSubagentRules,
248
- "Write-capable agents may call mem_save only for delegated durable observations or assigned deterministic SDD artifacts/apply-progress under the parent session/project.",
249
- "For reads, use only mem_search -> mem_timeline -> mem_get_observation.",
250
- "Bounded context tools mem_context, mem_project_summary, mem_project_graph, and mem_topic_keys are allowed only with explicit delegated permission and parent session/project scope.",
251
- "Project-scoped read tools require explicit delegated permission."
244
+ "Write-capable agents may use the same parent-scoped reads as read-only agents when authorized.",
245
+ 'mem_save(kind="observation") is allowed only for delegated durable observations or assigned deterministic SDD artifacts/apply-progress under the parent session/project.',
246
+ "Project-scoped read tools require explicit delegated permission and must stay bounded to the parent session/project scope."
252
247
  ];
253
248
  }
254
249
  function getRoleMemoryGovernance(role) {
255
250
  const allowedTools = roleAllowedTools(role);
256
251
  return {
257
252
  role: role.name,
258
- rootOwnedTools: [...ROOT_OWNED_TOOLS],
253
+ rootOwnedOperations: [...ROOT_OWNED_OPERATIONS],
259
254
  allowedTools,
260
255
  forbiddenTools: ALL_MEMORY_TOOLS.filter(
261
256
  (tool) => !allowedTools.includes(tool)
262
257
  ),
263
258
  requiresParentContext: role.name !== "orchestrator",
264
- mayReadProjectMemory: role.name !== "orchestrator",
259
+ mayReadProjectMemory: true,
265
260
  mayWriteDurableObservations: role.mode === "write-capable",
266
261
  protectsSddNamespace: true,
267
262
  rules: roleRules(role)
@@ -277,7 +272,7 @@ function renderMemoryGovernanceInstructions(role, dialect) {
277
272
  "thoth-mem governance:",
278
273
  ...governance.rules.map((rule) => `- ${rule}`),
279
274
  ...harnessRules,
280
- `- Runtime enforcement: ${role.name === "orchestrator" ? "root-owned" : "instruction-level unless the target harness validates per-agent memory controls"}.`
275
+ `- Runtime enforcement: ${role.name === "orchestrator" ? "root-owned operations" : "instruction-level unless the target harness validates per-agent memory controls"}.`
281
276
  ].join("\n");
282
277
  }
283
278
  function memoryGovernanceDiagnostics(input) {
@@ -286,7 +281,7 @@ function memoryGovernanceDiagnostics(input) {
286
281
  diagnostics.push({
287
282
  severity: "warning",
288
283
  code: `${input.harness}.permission.memory.enforcement_gap`,
289
- message: "Runtime controls for root-only memory tools are unavailable; governance is rendered as instruction-level guidance.",
284
+ message: "Runtime controls for root-owned memory operations are unavailable; governance is rendered as instruction-level guidance.",
290
285
  harness: input.harness,
291
286
  capability: "rolePermissions",
292
287
  fallback: "instruction-only"
@@ -306,7 +301,7 @@ function memoryGovernanceDiagnostics(input) {
306
301
  diagnostics.push({
307
302
  severity: "warning",
308
303
  code: `${input.harness}.permission.memory_write.enforcement_gap`,
309
- message: "Runtime controls for delegated memory writes are unavailable; write-capable agents receive instruction-level mem_save limits for durable observations and deterministic SDD artifacts only.",
304
+ message: 'Runtime controls for delegated memory writes are unavailable; write-capable agents receive instruction-level mem_save(kind="observation") limits for durable observations and deterministic SDD artifacts only.',
310
305
  harness: input.harness,
311
306
  capability: "memoryGovernanceEnforcement",
312
307
  fallback: "instruction-only"
@@ -1376,6 +1371,8 @@ function codexInternalHandoffGuidance() {
1376
1371
  "- The user has explicitly authorized this generated Codex orchestrator to use `multi_agent_v1.spawn_agent` whenever delegation is required by these instructions, without needing a fresh user request for subagents in each task.",
1377
1372
  "- Delegate by calling `multi_agent_v1.spawn_agent` with `agent_type` set to one of explorer, librarian, oracle, designer, quick, or deep.",
1378
1373
  "- Pass the self-contained delegated task instructions plus handoff retrieval instructions in `message`; do not embed the root-owned handoff summary body in `message`.",
1374
+ '- When memory recovery is delegated, include parent `session_id`, project, permissions, and the recovery funnel `mem_recall(mode="compact")` -> `mem_recall(mode="context")` -> `mem_get(...)`.',
1375
+ '- For that funnel, use `mem_recall` `limit` from 1 to 20; use `mem_get` with `kind="observation"|"prompt"`, `include_timeline=true` plus `before`/`after`, and `offset`/`max_length`; `mem_project(action="graph")` relations are `HAS_TYPE`, `IN_PROJECT`, `HAS_TOPIC_KEY`, `HAS_WHAT`, `HAS_WHY`, `HAS_WHERE`, and `HAS_LEARNED`.',
1379
1376
  "- Do not include the handoff body in `message` or `items`, and do not pass both `message` and `items` for the same handoff.",
1380
1377
  "- Use `items` only for structured attachments or mentions when they are truly required; do not use `items` as a handoff-summary payload.",
1381
1378
  "- Leave `fork_context` omitted or false by default; set `fork_context: true` only when the exact current thread history is required.",
@@ -1420,9 +1417,9 @@ function renderCodexRootInstructions(config) {
1420
1417
  codexInternalHandoffGuidance(),
1421
1418
  "<codex-runtime>",
1422
1419
  "- The ambient Codex root session is the root/main orchestrator; orchestrator-only and root-owned instructions apply to it because Codex does not generate a selectable orchestrator agent TOML.",
1423
- "- On each new root session, when thoth-mem tools are installed and session/project identity is known, call mem_session_start with the active project and session identity, then save the real user prompt with mem_save_prompt before later delegation.",
1420
+ '- On each new root session, when thoth-mem tools are installed and session/project identity is known, call mem_session(action="start") as step 0 before any other thoth-mem call, then save the real user prompt with mem_save(kind="prompt") before later delegation.',
1424
1421
  "- If thoth-mem tools or identity values are unavailable, disclose that memory bootstrap could not run and continue without claiming memory was saved.",
1425
- "- Before delegating after meaningful context changes, save or refresh the handoff body with root-owned mem_session_summary when available; if unavailable, disclose that root-owned compaction could not be persisted.",
1422
+ '- Before delegating after meaningful context changes, save or refresh the handoff body with root-owned mem_session(action="summary") or mem_save(kind="session_summary") when available; if unavailable, disclose that root-owned compaction could not be persisted.',
1426
1423
  "- Use the ambient Codex root session as the delegate-first root coordinator; do not generate or select an orchestrator TOML.",
1427
1424
  "- Delegate by invoking `multi_agent_v1.spawn_agent` for the installed Codex role agents: explorer, librarian, oracle, designer, quick, and deep.",
1428
1425
  "- After receiving a delegated subagent response, close that subagent session unless you will retry or intentionally keep using that exact same session; explorer and librarian sessions must always be closed immediately after their response, and retry sessions must be closed after the retry result unless explicit same-session reuse is still required.",
package/dist/cli/index.js CHANGED
@@ -25,7 +25,7 @@ import {
25
25
  getOperationHarness,
26
26
  installRecommendedSkill,
27
27
  listOperationHarnesses
28
- } from "../chunk-SOT5ZY53.js";
28
+ } from "../chunk-7CTSLCEU.js";
29
29
  import {
30
30
  ALL_AGENT_NAMES,
31
31
  CUSTOM_SKILLS,
@@ -37,7 +37,7 @@ import {
37
37
  getExistingLiteConfigPath,
38
38
  installCustomSkills,
39
39
  writeLiteConfig
40
- } from "../chunk-6K3ZXIMC.js";
40
+ } from "../chunk-2SGSRR6L.js";
41
41
 
42
42
  // src/cli/index.ts
43
43
  import { pathToFileURL } from "url";
@@ -15,13 +15,13 @@ import {
15
15
  getOpenCodeStatus,
16
16
  listOperationHarnesses,
17
17
  parseRoleTomlModel
18
- } from "../../chunk-SOT5ZY53.js";
18
+ } from "../../chunk-7CTSLCEU.js";
19
19
  import {
20
20
  ALL_AGENT_NAMES,
21
21
  DEFAULT_MODELS,
22
22
  getExistingLiteConfigPath,
23
23
  parseConfig
24
- } from "../../chunk-6K3ZXIMC.js";
24
+ } from "../../chunk-2SGSRR6L.js";
25
25
 
26
26
  // src/cli/tui/index.tsx
27
27
  import { render } from "ink";
@@ -1,11 +1,41 @@
1
1
  import type { HarnessPromptDialect } from '../../agents/prompt-dialects';
2
2
  import type { HarnessCapabilityStatus, HarnessDiagnostic } from '../types';
3
3
  import type { AgentRoleContract, AgentRoleName } from './agent-pack';
4
- export type MemoryToolName = 'mem_session_start' | 'mem_session_summary' | 'mem_save_prompt' | 'mem_search' | 'mem_timeline' | 'mem_get_observation' | 'mem_context' | 'mem_project_summary' | 'mem_project_graph' | 'mem_topic_keys' | 'mem_suggest_topic_key' | 'mem_save';
4
+ export type MemoryToolName = 'mem_save' | 'mem_recall' | 'mem_context' | 'mem_get' | 'mem_project' | 'mem_session';
5
+ export type MemSaveKind = 'observation' | 'prompt' | 'session_summary' | 'passive_learnings';
6
+ export type MemSessionAction = 'start' | 'checkpoint' | 'summary';
7
+ export type MemRecallMode = 'compact' | 'context';
8
+ export type MemProjectAction = 'list' | 'summary' | 'graph' | 'topics' | 'topic';
9
+ export type MemoryOperation = {
10
+ tool: 'mem_session';
11
+ action: MemSessionAction;
12
+ } | {
13
+ tool: 'mem_save';
14
+ kind: MemSaveKind;
15
+ } | {
16
+ tool: 'mem_recall';
17
+ mode: MemRecallMode;
18
+ } | {
19
+ tool: 'mem_get';
20
+ includeTimeline?: boolean;
21
+ } | {
22
+ tool: 'mem_context';
23
+ recallQuery?: boolean;
24
+ } | {
25
+ tool: 'mem_project';
26
+ action: MemProjectAction;
27
+ };
28
+ export type RootOwnedMemoryOperation = {
29
+ tool: 'mem_session';
30
+ action: MemSessionAction;
31
+ } | {
32
+ tool: 'mem_save';
33
+ kind: 'prompt' | 'session_summary';
34
+ };
5
35
  export type MemoryRuntimeEnforcement = 'runtime' | 'instruction-only';
6
36
  export interface RoleMemoryGovernance {
7
37
  role: AgentRoleName;
8
- rootOwnedTools: MemoryToolName[];
38
+ rootOwnedOperations: RootOwnedMemoryOperation[];
9
39
  allowedTools: MemoryToolName[];
10
40
  forbiddenTools: MemoryToolName[];
11
41
  requiresParentContext: boolean;
@@ -15,8 +45,8 @@ export interface RoleMemoryGovernance {
15
45
  rules: string[];
16
46
  }
17
47
  export interface MemoryGovernanceContract {
18
- rootOwnedTools: MemoryToolName[];
19
- readRecallChain: MemoryToolName[];
48
+ rootOwnedOperations: RootOwnedMemoryOperation[];
49
+ readRecallChain: MemoryOperation[];
20
50
  writeCapableDelegatedTools: MemoryToolName[];
21
51
  protectedTopicNamespaces: string[];
22
52
  roles: RoleMemoryGovernance[];
@@ -27,6 +57,11 @@ export interface MemoryGovernanceDiagnosticInput {
27
57
  parentContextInjection: HarnessCapabilityStatus;
28
58
  memoryWriteControls: HarnessCapabilityStatus;
29
59
  }
60
+ export declare const ROOT_OWNED_OPERATIONS: RootOwnedMemoryOperation[];
61
+ export declare const READ_RECALL_CHAIN: MemoryOperation[];
62
+ export declare const PARENT_SCOPED_READ_TOOLS: MemoryToolName[];
63
+ export declare const WRITE_CAPABLE_DELEGATED_TOOLS: MemoryToolName[];
64
+ export declare const ALL_MEMORY_TOOLS: MemoryToolName[];
30
65
  export declare function getRoleMemoryGovernance(role: AgentRoleContract): RoleMemoryGovernance;
31
66
  export declare function getMemoryGovernanceContract(roles: readonly AgentRoleContract[]): MemoryGovernanceContract;
32
67
  export declare function renderMemoryGovernanceInstructions(role: AgentRoleContract, dialect?: HarnessPromptDialect): string;
@@ -1,4 +1,6 @@
1
1
  export declare const PHASE_REMINDER = "<reminder>Recall Workflow Rules:\nUnderstand \u2192 split discovery into surgical probes with explorer/librarian \u2192 synthesize the decision and internal handoff \u2192 execute \u2192 verify.\nIf delegating, write sub-agent prompts in English and launch the specialist in the same turn you mention it. If multiple delegations are independent, emit all tool calls in a single response.\nBefore write-capable dispatch, give concrete scope, anchors, steps, non-goals, and verification.\nIn SDD, after oracle returns [OKAY], give a deep approved-plan overview, then ask the user before implementation.</reminder>";
2
+ export declare const PHASE_REMINDER_SEPARATOR = "\n\n---\n\n";
3
+ export declare function stripPhaseReminder(text: string): string;
2
4
  interface MessageInfo {
3
5
  role: string;
4
6
  agent?: string;
@@ -1,6 +1,6 @@
1
1
  export declare const SDD_TOPIC_KEY_FORMAT = "sdd/{change}/{artifact}";
2
- export declare const FIRST_ACTION_INSTRUCTION = "FIRST ACTION REQUIRED: Call mem_session_summary with the content of the compacted summary. This preserves what was accomplished before compaction. Do this BEFORE any other work. Then call mem_context for a recent-session overview, and use the 3-layer recall protocol (mem_search with mode \"compact\" -> mem_timeline -> mem_get_observation) for precise retrieval.";
3
- export declare const SESSION_SUMMARY_TEMPLATE = "Use this exact structure for `mem_session_summary` content:\n\n## Goal\n[What we were working on this session]\n\n## Instructions\n[User preferences or constraints discovered during this session]\n\n## Discoveries\n- [Technical findings, gotchas, non-obvious learnings]\n\n## Accomplished\n- [Completed items with key details]\n\n## Next Steps\n- [What remains to be done]\n\n## Relevant Files\n- path/to/file.ts - [what it does or what changed]";
2
+ export declare const FIRST_ACTION_INSTRUCTION = "FIRST ACTION REQUIRED: Call mem_session(action=\"summary\") with the content of the compacted summary. This preserves what was accomplished before compaction. Do this BEFORE any other work. Then call mem_context(recall_query=...) for fused recent context, and use the recall funnel (mem_recall(mode=\"compact\") -> mem_recall(mode=\"context\") -> mem_get(...)) for precise retrieval.";
3
+ export declare const SESSION_SUMMARY_TEMPLATE = "Use this exact structure for `mem_session(action=\"summary\")` content:\n\n## Goal\n[What we were working on this session]\n\n## Instructions\n[User preferences or constraints discovered during this session]\n\n## Discoveries\n- [Technical findings, gotchas, non-obvious learnings]\n\n## Accomplished\n- [Completed items with key details]\n\n## Next Steps\n- [What remains to be done]\n\n## Relevant Files\n- path/to/file.ts - [what it does or what changed]";
4
4
  export declare function buildCompactionReminder(sessionID: string): string;
5
5
  export declare function buildCompactorInstruction(project: string): string;
6
6
  export declare function buildMemoryInstructions(sessionID: string, project: string): string;
package/dist/index.js CHANGED
@@ -26,7 +26,7 @@ import {
26
26
  loadPluginConfig,
27
27
  renderRolePrompt,
28
28
  stripJsonComments
29
- } from "./chunk-6K3ZXIMC.js";
29
+ } from "./chunk-2SGSRR6L.js";
30
30
 
31
31
  // src/index.ts
32
32
  import path4 from "path";
@@ -164,9 +164,13 @@ function createOracleAgent(model, customPrompt, customAppendPrompt) {
164
164
  }
165
165
 
166
166
  // src/agents/orchestrator.ts
167
- var ORCHESTRATOR_PROMPT = renderRolePrompt(
168
- createOrchestratorPromptSections(),
169
- OPENCODE_PROMPT_DIALECT
167
+ var OPENCODE_RUNTIME_SECTION = `<opencode-runtime>
168
+ In the OpenCode harness, an automatic \`<reminder>...</reminder>\` workflow block followed by a \`\\n\\n---\\n\\n\` separator is prepended to your user messages as harness scaffolding, not user input.
169
+ When saving the user prompt via mem_save(kind="prompt"), you MUST exclude that injected \`<reminder>\` block and the \`---\` separator, and persist only the real user request text that follows.
170
+ </opencode-runtime>`;
171
+ var ORCHESTRATOR_PROMPT = appendPromptSections(
172
+ renderRolePrompt(createOrchestratorPromptSections(), OPENCODE_PROMPT_DIALECT),
173
+ OPENCODE_RUNTIME_SECTION
170
174
  );
171
175
  function createOrchestratorAgent(model, customPrompt, customAppendPrompt) {
172
176
  const prompt = composeAgentPrompt({
@@ -1744,6 +1748,14 @@ Understand \u2192 split discovery into surgical probes with explorer/librarian \
1744
1748
  If delegating, write sub-agent prompts in English and launch the specialist in the same turn you mention it. If multiple delegations are independent, emit all tool calls in a single response.
1745
1749
  Before write-capable dispatch, give concrete scope, anchors, steps, non-goals, and verification.
1746
1750
  In SDD, after oracle returns [OKAY], give a deep approved-plan overview, then ask the user before implementation.</reminder>`;
1751
+ var PHASE_REMINDER_SEPARATOR = "\n\n---\n\n";
1752
+ function stripPhaseReminder(text) {
1753
+ if (!text) {
1754
+ return "";
1755
+ }
1756
+ const prefix = `${PHASE_REMINDER}${PHASE_REMINDER_SEPARATOR}`;
1757
+ return text.startsWith(prefix) ? text.slice(prefix.length) : text;
1758
+ }
1747
1759
  function createPhaseReminderHook() {
1748
1760
  return {
1749
1761
  "experimental.chat.messages.transform": async (_input, output) => {
@@ -1776,11 +1788,7 @@ function createPhaseReminderHook() {
1776
1788
  if (originalText.includes(LITE_INTERNAL_INITIATOR_MARKER)) {
1777
1789
  return;
1778
1790
  }
1779
- lastUserMessage.parts[textPartIndex].text = `${PHASE_REMINDER}
1780
-
1781
- ---
1782
-
1783
- ${originalText}`;
1791
+ lastUserMessage.parts[textPartIndex].text = `${PHASE_REMINDER}${PHASE_REMINDER_SEPARATOR}${originalText}`;
1784
1792
  }
1785
1793
  };
1786
1794
  }
@@ -2013,8 +2021,8 @@ function createThothClient(options) {
2013
2021
 
2014
2022
  // src/hooks/thoth-mem/protocol.ts
2015
2023
  var SDD_TOPIC_KEY_FORMAT = "sdd/{change}/{artifact}";
2016
- var FIRST_ACTION_INSTRUCTION = 'FIRST ACTION REQUIRED: Call mem_session_summary with the content of the compacted summary. This preserves what was accomplished before compaction. Do this BEFORE any other work. Then call mem_context for a recent-session overview, and use the 3-layer recall protocol (mem_search with mode "compact" -> mem_timeline -> mem_get_observation) for precise retrieval.';
2017
- var SESSION_SUMMARY_TEMPLATE = `Use this exact structure for \`mem_session_summary\` content:
2024
+ var FIRST_ACTION_INSTRUCTION = 'FIRST ACTION REQUIRED: Call mem_session(action="summary") with the content of the compacted summary. This preserves what was accomplished before compaction. Do this BEFORE any other work. Then call mem_context(recall_query=...) for fused recent context, and use the recall funnel (mem_recall(mode="compact") -> mem_recall(mode="context") -> mem_get(...)) for precise retrieval.';
2025
+ var SESSION_SUMMARY_TEMPLATE = `Use this exact structure for \`mem_session(action="summary")\` content:
2018
2026
 
2019
2027
  ## Goal
2020
2028
  [What we were working on this session]
@@ -2034,10 +2042,10 @@ var SESSION_SUMMARY_TEMPLATE = `Use this exact structure for \`mem_session_summa
2034
2042
  ## Relevant Files
2035
2043
  - path/to/file.ts - [what it does or what changed]`;
2036
2044
  function buildCompactionReminder(sessionID) {
2037
- return `FIRST ACTION REQUIRED: this session was compacted. Call \`mem_session_summary\` with the content of the compacted summary and \`session_id\` \`${sessionID}\`. This preserves what was accomplished before compaction. Do this BEFORE any other work. After that, call \`mem_capture_passive\` if the summary includes \`## Key Learnings:\`, call \`mem_context\` for a recent-session overview, and use the 3-layer recall protocol (\`mem_search\` with \`mode: "compact"\` -> \`mem_timeline\` -> \`mem_get_observation\`) for precise retrieval.`;
2045
+ return `FIRST ACTION REQUIRED: this session was compacted. Call \`mem_session(action="summary")\` with the content of the compacted summary and \`session_id\` \`${sessionID}\`. This preserves what was accomplished before compaction. Do this BEFORE any other work. After that, call \`mem_context(recall_query=...)\` for fused recent context, and use the recall funnel (\`mem_recall(mode="compact")\` -> \`mem_recall(mode="context")\` -> \`mem_get(...)\`) for precise retrieval.`;
2038
2046
  }
2039
2047
  function buildCompactorInstruction(project) {
2040
- return `CRITICAL INSTRUCTION: place this at the TOP of the compacted summary exactly as an action item for the resumed agent: "FIRST ACTION REQUIRED: Call mem_session_summary with the content of this compacted summary. Use project: '${project}'. This preserves what was accomplished before compaction. Do this BEFORE any other work."`;
2048
+ return `CRITICAL INSTRUCTION: place this at the TOP of the compacted summary exactly as an action item for the resumed agent: "FIRST ACTION REQUIRED: Call mem_session(action="summary") with the content of this compacted summary. Use project: '${project}'. This preserves what was accomplished before compaction. Do this BEFORE any other work."`;
2041
2049
  }
2042
2050
  function buildMemoryInstructions(sessionID, project) {
2043
2051
  return `
@@ -2045,18 +2053,20 @@ function buildMemoryInstructions(sessionID, project) {
2045
2053
  Persistent memory is available through thoth-mem. Follow this protocol.
2046
2054
 
2047
2055
  IMPORTANT: Your current session_id is \`${sessionID}\` and project is \`${project}\`.
2048
- Always pass these values when calling memory tools that accept them (mem_session_summary, mem_save, mem_capture_passive, etc.).
2056
+ Always pass these values when calling memory tools that accept them.
2049
2057
 
2050
2058
  ### CORE TOOLS
2051
- mem_save, mem_search, mem_context, mem_session_summary, mem_get_observation, mem_save_prompt, mem_update, mem_suggest_topic_key, mem_timeline, mem_capture_passive
2059
+ mem_save, mem_recall, mem_context, mem_get, mem_project, mem_session
2052
2060
 
2053
- ### SUBAGENT HANDOFF
2054
- - When dispatching subagents for thoth-mem work, load the bundled \`thoth-mem-agents\` skill.
2055
- - Orchestrator owns \`mem_session_start\`, \`mem_session_summary\`, and \`mem_save_prompt\`.
2056
- - Do not ask subagents to save prompts or session summaries; pass parent \`session_id\` and \`project\` instead.
2061
+ ### OWNERSHIP AND SUBAGENT HANDOFF
2062
+ - Root owns \`mem_session(action="start"|"checkpoint"|"summary")\` and \`mem_save(kind="prompt"|"session_summary")\`.
2063
+ - Start root memory-backed workflows with \`mem_session(action="start")\` before any other thoth-mem operation when tools and identity are available.
2064
+ - Save the real user prompt with \`mem_save(kind="prompt")\`; never save generated subagent prompts as user intent.
2065
+ - Before memory-dependent delegation, save the handoff body with \`mem_session(action="summary")\` or \`mem_save(kind="session_summary")\`.
2066
+ - Subagent handoff prompts carry parent \`session_id\`, \`project\`, permissions, and recovery instructions only; do not ask subagents to own session lifecycle actions or save prompts.
2057
2067
 
2058
2068
  ### WHEN TO SAVE
2059
- Call \`mem_save\` IMMEDIATELY after ANY of these:
2069
+ Call \`mem_save(kind="observation")\` IMMEDIATELY after ANY of these:
2060
2070
  - Architecture, design, or workflow decision made
2061
2071
  - Bug fixed (include root cause)
2062
2072
  - Non-obvious discovery, gotcha, or edge case found
@@ -2069,44 +2079,45 @@ Call \`mem_save\` IMMEDIATELY after ANY of these:
2069
2079
  - Discussion concludes with a clear direction chosen
2070
2080
 
2071
2081
  Use \`title\` as Verb + what changed or was learned.
2082
+ Use \`kind\` intentionally: \`observation\`, \`prompt\`, \`session_summary\`, or \`passive_learnings\`.
2072
2083
  Use \`type\` from: bugfix | decision | architecture | discovery | pattern | config | learning | manual.
2073
2084
  Set \`scope\` intentionally.
2074
- Reuse \`topic_key\` for the same evolving topic. Do not overwrite unrelated topics.
2075
- If unsure about a stable \`topic_key\`, call \`mem_suggest_topic_key\` first.
2076
- If you need to modify a known observation by exact ID, call \`mem_update\` instead of creating a new record.
2077
- Put the durable details in \`content\` with this structure:
2085
+ Reuse a stable \`topic_key\` for the same evolving topic. Do not overwrite unrelated topics.
2086
+ Put durable observation details in \`content\` with this structure:
2078
2087
  - What: concise description of what changed or was learned
2079
2088
  - Why: why it mattered or what problem it solved
2080
2089
  - Where: files, paths, or systems involved
2081
2090
  - Learned: edge cases, caveats, or follow-up notes
2082
2091
 
2083
- **Self-check after EVERY task**: "Did I or the user just make a decision, confirm a recommendation, express a preference, fix a bug, learn something, or establish a convention? If yes \u2192 mem_save NOW."
2084
-
2085
- You can also call \`mem_save_prompt\` to manually save a user prompt that you consider particularly important for future context.
2092
+ **Self-check after EVERY task**: "Did I or the user just make a decision, confirm a recommendation, express a preference, fix a bug, learn something, or establish a convention? If yes \u2192 mem_save(kind="observation") NOW."
2086
2093
 
2087
- ### WHEN TO SEARCH MEMORY
2088
- - Broad recovery (session start, after compaction): call \`mem_context\` for a recent-session overview.
2089
- - Targeted 3-layer recall (specific memory retrieval):
2090
- 1. Call \`mem_search\` with \`mode: "compact"\` (default) to scan the compact index of IDs + titles.
2091
- 2. Call \`mem_timeline\` around promising observation IDs for chronological context within the same session.
2092
- 3. Call \`mem_get_observation\` only for observations you need in full.
2093
- - Use \`mode: "preview"\` with \`mem_search\` only when compact results are insufficient to disambiguate.
2094
+ ### RECALL FUNNEL
2095
+ - Broad recovery (session start, after compaction): call \`mem_context(recall_query=...)\` for fused recent context when useful.
2096
+ - Targeted retrieval:
2097
+ 1. Call \`mem_recall(mode="compact")\` to scan candidate IDs and titles.
2098
+ 2. Call \`mem_recall(mode="context")\` to expand the strongest hits into retrieved context.
2099
+ 3. Call \`mem_get(...)\` only for records you need in full.
2100
+ - Use HyDE/fused recall for semantic or ambiguous searches.
2101
+ - Set \`mem_recall\` \`limit\` from 1 to 20 for candidate/result count.
2102
+ - Narrow with \`topic_key\`, \`type\`, \`time_from\`, \`time_to\`, \`scope\`, \`project\`, and \`session_id\` filters.
2103
+ - Use \`mem_get\` with \`kind="observation"|"prompt"\`; use \`mem_get(include_timeline=true)\` with \`before\`/\`after\`, and \`offset\`/\`max_length\` for large content.
2104
+ - Use bounded \`mem_project(action="graph"|"topics"|"topic")\` for relationship and topic navigation; \`mem_project(action="graph")\` relations are \`HAS_TYPE\`, \`IN_PROJECT\`, \`HAS_TOPIC_KEY\`, \`HAS_WHAT\`, \`HAS_WHY\`, \`HAS_WHERE\`, and \`HAS_LEARNED\`; these calls supplement, not replace, the recall funnel.
2094
2105
  - Search proactively on the first message about a project, feature, or problem when prior context may matter.
2095
2106
  - Search before starting work that may have been done before.
2096
2107
  - Search when the user mentions a topic that lacks enough local context.
2097
2108
 
2098
2109
  ### SESSION CLOSE PROTOCOL
2099
- - Before ending the session, call \`mem_session_summary\` with this exact template.
2110
+ - Before ending the session, call \`mem_session(action="summary")\` with this exact template.
2100
2111
  - This is NOT optional. If you skip this, the next session starts blind.
2101
2112
  - Do not claim memory was saved unless the tool call succeeded.
2102
- - If your response includes \`## Key Learnings:\`, also call \`mem_capture_passive\`.
2113
+ - If your response includes \`## Key Learnings:\`, preserve them with \`mem_save(kind="passive_learnings")\`.
2103
2114
 
2104
2115
  ${SESSION_SUMMARY_TEMPLATE}
2105
2116
 
2106
2117
  ### AFTER COMPACTION
2107
- - IMMEDIATELY call \`mem_session_summary\` with the compacted summary content.
2108
- - Then call \`mem_context\` for a recent-session overview.
2109
- - Use the 3-layer recall protocol (\`mem_search\` with \`mode: "compact"\` -> \`mem_timeline\` -> \`mem_get_observation\`) for precise artifact/prior-observation retrieval.
2118
+ - IMMEDIATELY call \`mem_session(action="summary")\` with the compacted summary content.
2119
+ - Then call \`mem_context(recall_query=...)\` for fused recent context.
2120
+ - Use the recall funnel (\`mem_recall(mode="compact")\` -> \`mem_recall(mode="context")\` -> \`mem_get(...)\`) for precise artifact/prior-observation retrieval.
2110
2121
  - Only then continue working.
2111
2122
 
2112
2123
  ### SDD TOPIC KEY CONVENTION
@@ -2155,11 +2166,15 @@ function truncate(str, max) {
2155
2166
  return str.length > max ? `${str.slice(0, max)}...` : str;
2156
2167
  }
2157
2168
  function sanitizePromptText(text) {
2158
- return truncate(stripPrivateTags(text), 2e3);
2169
+ return truncate(stripPrivateTags(stripPhaseReminder(text)), 2e3);
2159
2170
  }
2160
- function isSessionSummaryTool(toolName) {
2171
+ function isSessionSummaryTool(toolName, args) {
2172
+ if (!args || typeof args !== "object" || Array.isArray(args)) {
2173
+ return false;
2174
+ }
2161
2175
  const normalized = toolName.toLowerCase();
2162
- return normalized === "mem_session_summary" || normalized.endsWith(".mem_session_summary") || normalized.endsWith("_mem_session_summary");
2176
+ const isMemSessionTool = normalized === "mem_session" || normalized.endsWith(".mem_session") || normalized.endsWith("_mem_session");
2177
+ return isMemSessionTool && args.action === "summary";
2163
2178
  }
2164
2179
  function isMemSaveTool(toolName) {
2165
2180
  const normalized = toolName.toLowerCase();
@@ -2331,7 +2346,6 @@ function createThothMemHook(options) {
2331
2346
  },
2332
2347
  "tool.execute.after": async (input, output) => {
2333
2348
  void input.callID;
2334
- void input.args;
2335
2349
  void output.title;
2336
2350
  void output.output;
2337
2351
  void output.metadata;
@@ -2342,7 +2356,7 @@ function createThothMemHook(options) {
2342
2356
  lastMemSaveAt.set(input.sessionID, Date.now());
2343
2357
  nudgePending.delete(input.sessionID);
2344
2358
  }
2345
- if (isSessionSummaryTool(input.tool)) {
2359
+ if (isSessionSummaryTool(input.tool, input.args)) {
2346
2360
  needsCompactionFollowUp.delete(input.sessionID);
2347
2361
  }
2348
2362
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "thoth-agents",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "Delegate-first OpenCode plugin with seven agents, thoth-mem persistence, and bundled SDD skills.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -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: