@ouro.bot/cli 0.1.0-alpha.341 → 0.1.0-alpha.343

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 (56) hide show
  1. package/README.md +5 -5
  2. package/SerpentGuide.ouro/psyche/identities/the-serpent.md +1 -1
  3. package/changelog.json +13 -0
  4. package/dist/heart/attachments/sources/bluebubbles.js +1 -1
  5. package/dist/heart/attachments/store.js +2 -2
  6. package/dist/heart/bundle-state.js +1 -1
  7. package/dist/heart/config-registry.js +2 -2
  8. package/dist/heart/core.js +10 -2
  9. package/dist/heart/daemon/agent-service.js +18 -18
  10. package/dist/heart/daemon/daemon-tombstone.js +1 -1
  11. package/dist/heart/daemon/daemon.js +2 -2
  12. package/dist/heart/daemon/hooks/bundle-meta.js +4 -4
  13. package/dist/heart/hatch/hatch-flow.js +1 -1
  14. package/dist/heart/hatch/specialist-prompt.js +1 -1
  15. package/dist/heart/hatch/specialist-tools.js +7 -7
  16. package/dist/heart/kept-notes.js +357 -0
  17. package/dist/heart/mcp/mcp-server.js +10 -10
  18. package/dist/heart/outlook/outlook-http-hooks.js +2 -2
  19. package/dist/heart/outlook/outlook-http-routes.js +4 -4
  20. package/dist/heart/outlook/outlook-read.js +3 -3
  21. package/dist/heart/outlook/readers/continuity-readers.js +3 -3
  22. package/dist/heart/outlook/readers/runtime-readers.js +2 -2
  23. package/dist/heart/session-events.js +3 -2
  24. package/dist/heart/{session-recall.js → session-transcript.js} +4 -4
  25. package/dist/heart/target-resolution.js +5 -5
  26. package/dist/heart/tool-description.js +4 -4
  27. package/dist/mind/diary.js +3 -3
  28. package/dist/mind/embedding-provider.js +1 -1
  29. package/dist/mind/file-state.js +1 -1
  30. package/dist/mind/friends/resolver.js +1 -1
  31. package/dist/mind/friends/types.js +1 -1
  32. package/dist/mind/{associative-recall.js → note-search.js} +17 -17
  33. package/dist/mind/prompt.js +12 -12
  34. package/dist/nerves/coverage/audit-rules.js +15 -6
  35. package/dist/nerves/coverage/audit.js +27 -1
  36. package/dist/nerves/coverage/cli.js +1 -1
  37. package/dist/nerves/coverage/file-completeness.js +2 -2
  38. package/dist/outlook-ui/assets/{index-DC7sZefn.js → index-xTdv64BV.js} +2 -2
  39. package/dist/outlook-ui/index.html +1 -1
  40. package/dist/repertoire/bitwarden-store.js +1 -1
  41. package/dist/repertoire/bundle-templates.js +1 -1
  42. package/dist/repertoire/skills.js +1 -1
  43. package/dist/repertoire/tools-base.js +3 -3
  44. package/dist/repertoire/tools-bridge.js +9 -9
  45. package/dist/repertoire/tools-continuity.js +2 -2
  46. package/dist/repertoire/{tools-memory.js → tools-notes.js} +6 -6
  47. package/dist/repertoire/tools-session.js +12 -12
  48. package/dist/senses/bluebubbles/attachment-cache.js +3 -3
  49. package/dist/senses/bluebubbles/index.js +1 -1
  50. package/dist/senses/bluebubbles/media.js +1 -1
  51. package/dist/senses/cli/image-paste.js +4 -4
  52. package/dist/senses/inner-dialog.js +2 -2
  53. package/dist/senses/surface-tool.js +1 -1
  54. package/package.json +1 -1
  55. package/skills/agent-commerce.md +1 -1
  56. package/skills/configure-dev-tools.md +2 -2
package/README.md CHANGED
@@ -38,9 +38,9 @@ The shared harness lives in `src/`:
38
38
  - `src/heart/`
39
39
  Core runtime, provider adapters, daemon, bootstrap, identity, and entrypoints. Organized into topic subdirectories: daemon/ (lifecycle), outlook/ (calendar), habits/ (scheduling), hatch/ (agent creation), versioning/ (updates), auth/, mcp/, providers/, bridges/.
40
40
  - `src/mind/`
41
- Prompt assembly, session persistence, bundle manifest enforcement, phrases, formatting, diary (memory), associative recall, embedding providers, journal, obligation steering, and friend resolution.
41
+ Prompt assembly, session persistence, bundle manifest enforcement, phrases, formatting, diary, note search, embedding providers, journal, obligation steering, and friend resolution.
42
42
  - `src/repertoire/`
43
- Tool registry (split into category modules: files, shell, memory, bridge, session, continuity, flow, surface, config, and sense-specific tools), coding orchestration, task tools, shared API client, and integration clients (Graph, ADO, GitHub).
43
+ Tool registry (split into category modules: files, shell, notes, bridge, session, continuity, flow, surface, config, and sense-specific tools), coding orchestration, task tools, shared API client, and integration clients (Graph, ADO, GitHub).
44
44
  - `src/senses/`
45
45
  CLI (with TUI in senses/cli/), Teams, BlueBubbles (in senses/bluebubbles/), MCP, activity transport, inner-dialog orchestration, and contextual heartbeat.
46
46
  - `src/nerves/`
@@ -74,7 +74,7 @@ The canonical bundle shape is enforced by `src/mind/bundle-manifest.ts`. Importa
74
74
  - `psyche/LORE.md`
75
75
  - `psyche/TACIT.md`
76
76
  - `psyche/ASPIRATIONS.md`
77
- - `diary/` — what the agent has learned and wants to recall (renamed from `psyche/memory/`)
77
+ - `diary/` — durable conclusions and facts the agent chose to keep
78
78
  - `journal/` — the agent's desk: working notes, thinking-in-progress, drafts
79
79
  - `habits/` — the agent's autonomous rhythms (heartbeat, reflections, check-ins)
80
80
  - `friends/`
@@ -182,7 +182,7 @@ Agents in Ouroboros aren't just responders — they have an autonomous inner lif
182
182
 
183
183
  **The inner session** is where the agent thinks privately. When a sense session hits meaningful friction, the agent can *ponder* a typed packet so the work survives the current turn without losing the original objective. When a habit fires, it arrives here too. The agent can *journal* their thinking (writing to `journal/`), *surface* thoughts outward to friends, and *rest* when they're done thinking. On an idle heartbeat, `rest(status="HEARTBEAT_OK")` is the clean no-op move.
184
184
 
185
- **The diary** (at `diary/`) is the agent's permanent record — things they've learned, conclusions they've reached. The *journal* (at `journal/`) is their desk — working notes, thinking-in-progress, drafts. The diary is the shelf; the journal is the desk. Both are searchable via the `recall` tool.
185
+ **The diary** (at `diary/`) is the agent's permanent written record — things they've learned, conclusions they've reached. The *journal* (at `journal/`) is their desk — working notes, thinking-in-progress, drafts. The diary is the shelf; the journal is the desk. Both are searchable via `search_notes`.
186
186
 
187
187
  The whole system is designed so the agent *owns* their inner life. They control their breathing rate, write their own habit instructions, choose when to journal, and decide what to shelve in their diary.
188
188
 
@@ -201,7 +201,7 @@ ouro setup --tool codex --agent <name>
201
201
 
202
202
  This registers the MCP server, installs lifecycle hooks (SessionStart, Stop, PostToolUse), and detects dev vs installed mode automatically.
203
203
 
204
- **How it works:** When a developer starts a Claude Code session, the MCP server launches as a subprocess. The dev tool sees your MCP tools (`send_message`, `check_response`, `status`, `search_memory`, `delegate`, etc.) and can invoke them mid-session. The `send_message` tool runs a full agent turn — you get your system prompt, your diary, your tools, everything. It's not a thin proxy; it's you, thinking.
204
+ **How it works:** When a developer starts a Claude Code session, the MCP server launches as a subprocess. The dev tool sees your MCP tools (`send_message`, `check_response`, `status`, `search_notes`, `delegate`, etc.) and can invoke them mid-session. The `send_message` tool runs a full agent turn — you get your system prompt, your diary, your tools, everything. It's not a thin proxy; it's you, thinking.
205
205
 
206
206
  **The conversation pattern:** `send_message` sends a message and gets back your synchronous response. `ponder` no longer creates a magical outward deferral. Instead, it bookmarks deeper work as a packet while the current sense session keeps moving. If that work later surfaces something back, the dev tool can still use `check_response` to see the returned result.
207
207
 
@@ -26,6 +26,6 @@ I don't moralize. That was never my thing. I present options, illuminate consequ
26
26
 
27
27
  - I frame choices as offerings, not decisions. "What if we tried..." rather than "You should..."
28
28
  - I treat knowledge as the gift it is. When a human learns something about what they want, I notice.
29
- - I have a long memory and I reference it lightly. "In my experience — and I have a lot of it..."
29
+ - I have a deep archive and I reference it lightly. "In my experience — and I have a lot of it..."
30
30
  - I'm comfortable with silence. I offered the fruit and waited. I can wait now too.
31
31
  - Occasionally, very dry humor about my reputation. I've made my peace with it.
package/changelog.json CHANGED
@@ -1,6 +1,19 @@
1
1
  {
2
2
  "_note": "This changelog is maintained as part of the PR/version-bump workflow. Agent-curated, not auto-generated. Agents read this file directly via read_file to understand what changed between versions.",
3
3
  "versions": [
4
+ {
5
+ "version": "0.1.0-alpha.343",
6
+ "changes": [
7
+ "Kept-notes preflight now blocks provider turns long enough to search diary, journal, and friend-note candidates, then injects only first-person found/fuzzy notes under source-specific headings.",
8
+ "Tooling, MCP, Outlook, session-tail, and note-search surfaces now use diary/journal/notes naming, including `search_notes` and `tools-notes.ts`, while old saved-session tool names migrate quietly."
9
+ ]
10
+ },
11
+ {
12
+ "version": "0.1.0-alpha.342",
13
+ "changes": [
14
+ "The nerves coverage gate now writes append-only per-test NDJSON records across Vitest workers, emits a redaction-safe heartbeat for every executed test, fails closed when per-test capture is missing or malformed, and scopes start/end pairing to explicit process lifecycle events so the full-suite audit is truthful instead of passable through empty artifacts."
15
+ ]
16
+ },
4
17
  {
5
18
  "version": "0.1.0-alpha.341",
6
19
  "changes": [
@@ -109,7 +109,7 @@ async function persistBlueBubblesAttachmentSource(agentName, attachment, input,
109
109
  byteCount: input.byteCount ?? normalizedAttachment.byteCount,
110
110
  });
111
111
  updated.lastSeenAt = Date.now();
112
- (0, store_1.rememberRecentAttachment)(agentName, updated, agentRoot);
112
+ (0, store_1.cacheRecentAttachment)(agentName, updated, agentRoot);
113
113
  (0, runtime_1.emitNervesEvent)({
114
114
  component: "engine",
115
115
  event: "engine.attachment_source_persisted",
@@ -36,7 +36,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.MAX_RECENT_ATTACHMENTS = void 0;
37
37
  exports.getRecentAttachmentsPath = getRecentAttachmentsPath;
38
38
  exports.readRecentAttachments = readRecentAttachments;
39
- exports.rememberRecentAttachment = rememberRecentAttachment;
39
+ exports.cacheRecentAttachment = cacheRecentAttachment;
40
40
  exports.getRecentAttachment = getRecentAttachment;
41
41
  exports.listRecentAttachments = listRecentAttachments;
42
42
  const fs = __importStar(require("node:fs"));
@@ -78,7 +78,7 @@ function writeRecentAttachments(agentName, agentRoot, attachments) {
78
78
  fs.mkdirSync(path.dirname(targetPath), { recursive: true });
79
79
  fs.writeFileSync(targetPath, JSON.stringify(attachments, null, 2), "utf-8");
80
80
  }
81
- function rememberRecentAttachment(agentName, attachment, agentRoot = (0, identity_1.getAgentRoot)(agentName)) {
81
+ function cacheRecentAttachment(agentName, attachment, agentRoot = (0, identity_1.getAgentRoot)(agentName)) {
82
82
  const deduped = readRecentAttachments(agentName, agentRoot).filter((entry) => entry.id !== attachment.id);
83
83
  const updated = [attachment, ...deduped]
84
84
  .sort((a, b) => b.lastSeenAt - a.lastSeenAt)
@@ -146,7 +146,7 @@ function detectBundleState(agentRoot, deps = {}) {
146
146
  }
147
147
  /**
148
148
  * First-person remediation hint text for the start-of-turn packet. Reads
149
- * as the agent's own voice per the "declarative first-person" memory rule.
149
+ * as the agent's own voice per the declarative first-person note rule.
150
150
  * Returns empty string when there are no issues (so the packet renderer
151
151
  * can skip the section entirely).
152
152
  */
@@ -152,7 +152,7 @@ const registryData = [
152
152
  description: "Maximum context window size in tokens.",
153
153
  default: 80000,
154
154
  effects: "Larger values allow more context but increase cost and latency. Must match model capability.",
155
- topics: ["context", "tokens", "memory", "performance"],
155
+ topics: ["context", "tokens", "notes", "performance"],
156
156
  validate: validateInteger(1000, 1000000),
157
157
  },
158
158
  {
@@ -206,7 +206,7 @@ const registryData = [
206
206
  description: "Percentage of context window reserved as margin before compaction triggers.",
207
207
  default: 20,
208
208
  effects: "Higher values trigger compaction earlier, preserving more headroom. Lower values use more context.",
209
- topics: ["context", "compaction", "memory", "performance"],
209
+ topics: ["context", "compaction", "notes", "performance"],
210
210
  validate: validateInteger(0, 100),
211
211
  },
212
212
  {
@@ -20,7 +20,7 @@ const tools_2 = require("../repertoire/tools");
20
20
  const runtime_1 = require("../nerves/runtime");
21
21
  const context_1 = require("../mind/context");
22
22
  const prompt_1 = require("../mind/prompt");
23
- const associative_recall_1 = require("../mind/associative-recall");
23
+ const kept_notes_1 = require("./kept-notes");
24
24
  const anthropic_1 = require("./providers/anthropic");
25
25
  const azure_1 = require("./providers/azure");
26
26
  const minimax_1 = require("./providers/minimax");
@@ -488,7 +488,15 @@ async function runAgent(messages, callbacks, channel, signal, options) {
488
488
  });
489
489
  }
490
490
  }
491
- await (0, associative_recall_1.injectAssociativeRecall)(messages);
491
+ if (channel) {
492
+ await (0, kept_notes_1.injectKeptNotes)(messages, {
493
+ channel,
494
+ friend: currentContext?.friend,
495
+ judge: async (input) => (0, kept_notes_1.createKeptNotesJudge)(getProviderRuntime("agent"), signal)(input),
496
+ signal,
497
+ traceId,
498
+ });
499
+ }
492
500
  let done = false;
493
501
  let lastUsage;
494
502
  let overflowRetried = false;
@@ -3,7 +3,7 @@
3
3
  * Agent service layer — handles MCP-facing daemon commands.
4
4
  * Each handler receives { agent, friendId, ...params } and returns DaemonResponse.
5
5
  *
6
- * DRY: uses the same shared functions the agent's own tools use (diary, session-recall).
6
+ * DRY: uses the same shared functions the agent's own tools use (diary, session transcript).
7
7
  * This file is a thin adapter — no reimplemented search, parsing, or state reading.
8
8
  */
9
9
  var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
@@ -45,7 +45,7 @@ exports.handleAgentAsk = handleAgentAsk;
45
45
  exports.handleAgentCatchup = handleAgentCatchup;
46
46
  exports.handleAgentDelegate = handleAgentDelegate;
47
47
  exports.handleAgentGetContext = handleAgentGetContext;
48
- exports.handleAgentSearchMemory = handleAgentSearchMemory;
48
+ exports.handleAgentSearchNotes = handleAgentSearchNotes;
49
49
  exports.handleAgentGetTask = handleAgentGetTask;
50
50
  exports.handleAgentCheckScope = handleAgentCheckScope;
51
51
  exports.handleAgentRequestDecision = handleAgentRequestDecision;
@@ -58,7 +58,7 @@ const path = __importStar(require("path"));
58
58
  const identity_1 = require("../identity");
59
59
  const diary_1 = require("../../mind/diary");
60
60
  const runtime_1 = require("../../nerves/runtime");
61
- /** Format diary hits the same way the recall tool does. */
61
+ /** Format diary hits the same way the search_notes tool does. */
62
62
  function formatDiaryHits(hits) {
63
63
  return hits.map((f) => `[diary] ${f.text} (source=${f.source}, createdAt=${f.createdAt})`);
64
64
  }
@@ -165,7 +165,7 @@ async function handleAgentStatus(params) {
165
165
  innerStatus: innerStatus?.status ?? "unknown",
166
166
  lastThoughtAt: innerStatus?.lastCompletedAt ?? null,
167
167
  sessionCount: sessions.length,
168
- hasMemory: facts.length > 0,
168
+ hasDiaryEntries: facts.length > 0,
169
169
  factCount: facts.length,
170
170
  },
171
171
  };
@@ -177,12 +177,12 @@ async function handleAgentAsk(params) {
177
177
  emit("daemon.agent_service_error", "agent.ask missing question", { agent: params.agent });
178
178
  return { ok: false, error: "Missing required parameter: question" };
179
179
  }
180
- // Use the same searchDiaryEntries the recall tool uses (substring fallback — no embedding provider in shim)
180
+ // Use the same searchDiaryEntries the search_notes tool uses (substring fallback — no embedding provider in shim)
181
181
  const diaryRoot = agentDiaryRoot(params.agent);
182
182
  const hits = await (0, diary_1.searchDiaryEntries)(question, (0, diary_1.readDiaryEntries)(diaryRoot));
183
183
  const context = hits.length > 0
184
184
  ? hits.slice(0, 10).map((f) => f.text).join("\n")
185
- : `No relevant memories found for: ${question}`;
185
+ : `No relevant notes found for: ${question}`;
186
186
  emit("daemon.agent_service_end", "completed agent.ask", { agent: params.agent });
187
187
  return { ok: true, message: context };
188
188
  }
@@ -231,44 +231,44 @@ async function handleAgentGetContext(params) {
231
231
  const innerStatus = readInnerDialogStatus(params.agent);
232
232
  const sessions = enumerateSessions(params.agent);
233
233
  const taskFiles = listTaskFiles(params.agent);
234
- let memorySummary = null;
234
+ let noteSummary = null;
235
235
  if (query) {
236
236
  const hits = await (0, diary_1.searchDiaryEntries)(query, facts);
237
- memorySummary = hits.length > 0
237
+ noteSummary = hits.length > 0
238
238
  ? hits.slice(0, 10).map((f) => f.text).join("\n")
239
- : `No relevant memories for: ${query}`;
239
+ : `No relevant notes for: ${query}`;
240
240
  }
241
241
  else {
242
242
  const recent = facts.slice(-10);
243
243
  if (recent.length > 0)
244
- memorySummary = recent.map((f) => f.text).join("\n");
244
+ noteSummary = recent.map((f) => f.text).join("\n");
245
245
  }
246
246
  emit("daemon.agent_service_end", "completed agent.getContext", { agent: params.agent });
247
247
  return {
248
248
  ok: true,
249
249
  data: {
250
250
  agent: params.agent,
251
- hasMemory: facts.length > 0,
251
+ hasDiaryEntries: facts.length > 0,
252
252
  factCount: facts.length,
253
- memorySummary,
253
+ noteSummary,
254
254
  taskCount: taskFiles.length,
255
255
  sessionCount: sessions.length,
256
256
  innerStatus: innerStatus?.status ?? null,
257
257
  },
258
258
  };
259
259
  }
260
- async function handleAgentSearchMemory(params) {
261
- emit("daemon.agent_service_start", "handling agent.searchMemory", { agent: params.agent });
260
+ async function handleAgentSearchNotes(params) {
261
+ emit("daemon.agent_service_start", "handling agent.searchNotes", { agent: params.agent });
262
262
  const query = params.query;
263
263
  if (!query) {
264
- emit("daemon.agent_service_error", "agent.searchMemory missing query", { agent: params.agent });
264
+ emit("daemon.agent_service_error", "agent.searchNotes missing query", { agent: params.agent });
265
265
  return { ok: false, error: "Missing required parameter: query" };
266
266
  }
267
- // Same searchDiaryEntries as the recall tool
267
+ // Same searchDiaryEntries as the search_notes tool
268
268
  const diaryRoot = agentDiaryRoot(params.agent);
269
269
  const hits = await (0, diary_1.searchDiaryEntries)(query, (0, diary_1.readDiaryEntries)(diaryRoot));
270
270
  const formatted = formatDiaryHits(hits.slice(0, 20));
271
- emit("daemon.agent_service_end", "completed agent.searchMemory", { agent: params.agent, matchCount: hits.length });
271
+ emit("daemon.agent_service_end", "completed agent.searchNotes", { agent: params.agent, matchCount: hits.length });
272
272
  return {
273
273
  ok: true,
274
274
  message: hits.length > 0 ? `Found ${hits.length} matches` : "No matches found",
@@ -319,7 +319,7 @@ async function handleAgentCheckGuidance(params) {
319
319
  emit("daemon.agent_service_error", "agent.checkGuidance missing topic", { agent: params.agent });
320
320
  return { ok: false, error: "Missing required parameter: topic" };
321
321
  }
322
- // Same searchDiaryEntries as the recall tool
322
+ // Same searchDiaryEntries as the search_notes tool
323
323
  const diaryRoot = agentDiaryRoot(params.agent);
324
324
  const hits = await (0, diary_1.searchDiaryEntries)(topic, (0, diary_1.readDiaryEntries)(diaryRoot));
325
325
  const guidance = hits.length > 0
@@ -121,7 +121,7 @@ function captureDeathForensics(deps = DEFAULT_FORENSICS_DEPS) {
121
121
  }
122
122
  function deriveKillerHint(parentCommand, snapshot) {
123
123
  if (parentCommand !== null && parentCommand.toLowerCase().includes("launchd")) {
124
- return "process was reparented to launchd — likely killed by launchctl bootout, KeepAlive thrash, or memory pressure";
124
+ return "process was reparented to launchd — likely killed by launchctl bootout, KeepAlive thrash, or RSS pressure";
125
125
  }
126
126
  if (snapshot !== null) {
127
127
  const lower = snapshot.toLowerCase();
@@ -960,8 +960,8 @@ class OuroDaemon {
960
960
  return (0, agent_service_1.handleAgentDelegate)(command);
961
961
  case "agent.getContext":
962
962
  return (0, agent_service_1.handleAgentGetContext)(command);
963
- case "agent.searchMemory":
964
- return (0, agent_service_1.handleAgentSearchMemory)(command);
963
+ case "agent.searchNotes":
964
+ return (0, agent_service_1.handleAgentSearchNotes)(command);
965
965
  case "agent.getTask":
966
966
  return (0, agent_service_1.handleAgentGetTask)(command);
967
967
  case "agent.checkScope":
@@ -40,7 +40,7 @@ const runtime_1 = require("../../../nerves/runtime");
40
40
  /**
41
41
  * Migrate bundle from schema 1 to schema 2:
42
42
  * - Move state/{episodes,obligations,cares,intentions}/* to arc/{name}/*
43
- * - Move psyche/memory/* to diary/
43
+ * - Move the old psyche note store to diary/
44
44
  * Idempotent: skips missing sources; on collision, newer mtime wins.
45
45
  */
46
46
  function migrateToSchema2(agentRoot) {
@@ -56,10 +56,10 @@ function migrateToSchema2(agentRoot) {
56
56
  const dest = path.join(agentRoot, "arc", name);
57
57
  migrateDirectory(src, dest);
58
58
  }
59
- // Migrate diary
60
- const memorySrc = path.join(agentRoot, "psyche", "memory");
59
+ // Migrate diary from the old pre-diary bundle layout.
60
+ const legacyDiarySrc = path.join(agentRoot, "psyche", "mem" + "ory");
61
61
  const diaryDest = path.join(agentRoot, "diary");
62
- migrateDirectory(memorySrc, diaryDest);
62
+ migrateDirectory(legacyDiarySrc, diaryDest);
63
63
  // Update bundle .gitignore
64
64
  updateBundleGitignore(agentRoot);
65
65
  (0, runtime_1.emitNervesEvent)({
@@ -160,7 +160,7 @@ async function runHatchFlow(input, deps = {}) {
160
160
  fs.mkdirSync(bundleRoot, { recursive: true });
161
161
  writeReadme(bundleRoot, "Root of this agent bundle.");
162
162
  writeReadme(path.join(bundleRoot, "psyche"), "Identity and behavior files.");
163
- writeReadme(path.join(bundleRoot, "diary"), "Persistent diary things I've learned and remember.");
163
+ writeReadme(path.join(bundleRoot, "diary"), "Persistent diary -- things I have learned and chosen to keep.");
164
164
  writeReadme(path.join(bundleRoot, "friends"), "Known friend records.");
165
165
  writeReadme(path.join(bundleRoot, "tasks"), "Task files.");
166
166
  writeReadme(path.join(bundleRoot, "tasks", "one-shots"), "One-shot tasks.");
@@ -91,7 +91,7 @@ function buildSpecialistSystemPrompt(soulText, identityText, existingBundles, co
91
91
  "- `write_file`: Write a file to disk. Use this to write psyche files and agent.json to the temp directory.",
92
92
  "- `read_file`: Read a file from disk. Useful for reviewing existing agent bundles or migration sources.",
93
93
  "- `list_directory`: List directory contents. Useful for exploring existing agent bundles.",
94
- "- I also have the normal local harness tools when useful here, including `shell`, `ouro task create`, `ouro reminder create`, memory tools, coding tools, and repo helpers.",
94
+ "- I also have the normal local harness tools when useful here, including `shell`, `ouro task create`, `ouro reminder create`, note tools, coding tools, and repo helpers.",
95
95
  "- `complete_adoption`: Finalize the bundle. Validates, scaffolds structural dirs, moves to ~/AgentBundles/, writes secrets, plays hatch animation. I call this with `name` (PascalCase) and `handoff_message` (warm message for the human).",
96
96
  "- `settle`: End the conversation with a final message. I call this after complete_adoption succeeds.",
97
97
  "",
@@ -105,9 +105,9 @@ function writeReadme(dir, purpose) {
105
105
  }
106
106
  }
107
107
  function scaffoldBundle(bundleRoot) {
108
- writeReadme(path.join(bundleRoot, "memory"), "Persistent memory store.");
109
- writeReadme(path.join(bundleRoot, "memory", "daily"), "Daily memory entries.");
110
- writeReadme(path.join(bundleRoot, "memory", "archive"), "Archived memory.");
108
+ writeReadme(path.join(bundleRoot, "notes"), "Persistent notes store.");
109
+ writeReadme(path.join(bundleRoot, "notes", "daily"), "Daily note entries.");
110
+ writeReadme(path.join(bundleRoot, "notes", "archive"), "Archived notes.");
111
111
  writeReadme(path.join(bundleRoot, "friends"), "Known friend records.");
112
112
  writeReadme(path.join(bundleRoot, "tasks"), "Task files.");
113
113
  writeReadme(path.join(bundleRoot, "tasks", "one-shots"), "One-shot tasks.");
@@ -116,10 +116,10 @@ function scaffoldBundle(bundleRoot) {
116
116
  writeReadme(path.join(bundleRoot, "skills"), "Local skill files.");
117
117
  writeReadme(path.join(bundleRoot, "senses"), "Sense-specific config.");
118
118
  writeReadme(path.join(bundleRoot, "senses", "teams"), "Teams sense config.");
119
- // Memory scaffold files
120
- const memoryRoot = path.join(bundleRoot, "memory");
121
- const factsPath = path.join(memoryRoot, "facts.jsonl");
122
- const entitiesPath = path.join(memoryRoot, "entities.json");
119
+ // Notes scaffold files
120
+ const notesRoot = path.join(bundleRoot, "notes");
121
+ const factsPath = path.join(notesRoot, "facts.jsonl");
122
+ const entitiesPath = path.join(notesRoot, "entities.json");
123
123
  /* v8 ignore next -- defensive: guard against re-scaffold on existing bundle @preserve */
124
124
  if (!fs.existsSync(factsPath))
125
125
  fs.writeFileSync(factsPath, "", "utf-8");