@ouro.bot/cli 0.1.0-alpha.290 → 0.1.0-alpha.292
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/changelog.json
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
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.292",
|
|
6
|
+
"changes": [
|
|
7
|
+
"feat(mind): add structured provenance tracking to diary entries. New DiaryEntryProvenance interface records tool, channel (cli/teams/bluebubbles/inner/mcp), friend identity (id + name), and trust level (family/friend/acquaintance/stranger) at write time. diary_write handler automatically extracts provenance from ToolContext. Associative recall and recall tool render provenance fields when present. Fully backwards compatible — existing entries without provenance parse and display normally. 19 tests across 4 test files with 100% coverage on new code."
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"version": "0.1.0-alpha.291",
|
|
12
|
+
"changes": [
|
|
13
|
+
"fix(coding): eliminate silent `~/AgentBundles/default.ouro` real-fs leak in the coding session manager. Root cause: `src/repertoire/coding/manager.ts` had a `safeAgentName()` helper that caught `getAgentName()` throws (which happens in vitest because there's no `--agent` in argv) and silently fell back to `\"default\"`. Combined with `src/repertoire/coding/index.ts:8` constructing the singleton as `new CodingSessionManager({})` (no options — real fs, no agentName), every vitest run that called `getCodingSessionManager()` followed by `resetCodingSessionManager()` triggered `shutdown()` → `persistState()` → `fs.mkdirSync('~/AgentBundles/default.ouro/state/coding', { recursive: true })` + `fs.writeFileSync('.../sessions.json', ...)`. This wrote real files under the developer's home directory on every coverage-gate run. The observable symptom was `~/AgentBundles/default.ouro/` reappearing minutes after `rm -rf` — PR B's housekeeping cleanup couldn't stick. Fix: deleted `safeAgentName()` and made the constructor's `agentName` default call `getAgentName()` directly, so construction fails loudly in vitest when identity isn't mocked. Updated `index.test.ts` to mock both `../../../heart/identity` and `fs` so the singleton can be tested without touching real disk. Updated `session-manager.test.ts`, `session-manager-branches.test.ts`, and `session-manager-persistence.test.ts` to either inline `agentName: \"test-coding-agent\"` in `noPersistence` or mock `../../../heart/identity` at file top. One persistence test assertion updated from `parentAgent === \"default\"` to `\"test-coding-agent\"`. Full coverage gate passes, 171 coding tests pass, `~/AgentBundles/default.ouro` stays deleted across 3 consecutive coverage-gate runs."
|
|
14
|
+
]
|
|
15
|
+
},
|
|
4
16
|
{
|
|
5
17
|
"version": "0.1.0-alpha.290",
|
|
6
18
|
"changes": [
|
|
@@ -197,8 +197,17 @@ async function injectAssociativeRecall(messages, options) {
|
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
199
|
for (const fact of recalled) {
|
|
200
|
+
let meta = `score=${fact.score.toFixed(3)} source=${fact.source}`;
|
|
201
|
+
if (fact.provenance) {
|
|
202
|
+
if (fact.provenance.channel)
|
|
203
|
+
meta += ` channel=${fact.provenance.channel}`;
|
|
204
|
+
if (fact.provenance.friendName)
|
|
205
|
+
meta += ` friend=${fact.provenance.friendName}`;
|
|
206
|
+
if (fact.provenance.trust)
|
|
207
|
+
meta += ` trust=${fact.provenance.trust}`;
|
|
208
|
+
}
|
|
200
209
|
resultLines.push({
|
|
201
|
-
text: `[diary] ${fact.text} [
|
|
210
|
+
text: `[diary] ${fact.text} [${meta}]`,
|
|
202
211
|
score: fact.score,
|
|
203
212
|
});
|
|
204
213
|
}
|
package/dist/mind/diary.js
CHANGED
|
@@ -235,6 +235,7 @@ async function saveDiaryEntry(options) {
|
|
|
235
235
|
about: options.about?.trim() || undefined,
|
|
236
236
|
createdAt: (options.now ?? (() => new Date()))().toISOString(),
|
|
237
237
|
embedding,
|
|
238
|
+
...(options.provenance ? { provenance: options.provenance } : {}),
|
|
238
239
|
};
|
|
239
240
|
return appendEntriesWithDedup(stores, [fact], { semanticThreshold: SEMANTIC_DEDUP_THRESHOLD });
|
|
240
241
|
}
|
|
@@ -39,14 +39,6 @@ const path = __importStar(require("path"));
|
|
|
39
39
|
const identity_1 = require("../../heart/identity");
|
|
40
40
|
const runtime_1 = require("../../nerves/runtime");
|
|
41
41
|
const spawner_1 = require("./spawner");
|
|
42
|
-
function safeAgentName() {
|
|
43
|
-
try {
|
|
44
|
-
return (0, identity_1.getAgentName)();
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
return "default";
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
42
|
function defaultStateFilePath(agentName) {
|
|
51
43
|
return path.join((0, identity_1.getAgentRoot)(agentName), "state", "coding", "sessions.json");
|
|
52
44
|
}
|
|
@@ -186,7 +178,16 @@ class CodingSessionManager {
|
|
|
186
178
|
this.writeFileSync = options.writeFileSync ?? fs.writeFileSync;
|
|
187
179
|
this.mkdirSync = options.mkdirSync ?? fs.mkdirSync;
|
|
188
180
|
this.pidAlive = options.pidAlive ?? isPidAlive;
|
|
189
|
-
|
|
181
|
+
// No silent fallback to "default" — if there's no agentName and no
|
|
182
|
+
// explicit option, getAgentName() throws. The previous `safeAgentName`
|
|
183
|
+
// helper fell back to "default" and ended up writing coding session
|
|
184
|
+
// state to `~/AgentBundles/default.ouro/state/coding/sessions.json` on
|
|
185
|
+
// every vitest run because the coding manager singleton constructs with
|
|
186
|
+
// `{}`. That leaked real-fs state into the developer's home directory
|
|
187
|
+
// on every coverage run. Production callers always pass via argv (see
|
|
188
|
+
// getAgentName); test callers must either pass `agentName` explicitly
|
|
189
|
+
// or mock `../../heart/identity`.
|
|
190
|
+
this.agentName = options.agentName ?? (0, identity_1.getAgentName)();
|
|
190
191
|
this.stateFilePath = options.stateFilePath ?? defaultStateFilePath(this.agentName);
|
|
191
192
|
this.artifactDirPath = options.artifactDirPath
|
|
192
193
|
?? (options.stateFilePath ? path.dirname(options.stateFilePath) : defaultArtifactDirPath(this.agentName));
|
|
@@ -172,7 +172,16 @@ exports.memoryToolDefinitions = [
|
|
|
172
172
|
// Search diary entries
|
|
173
173
|
const hits = await (0, diary_1.searchDiaryEntries)(query, (0, diary_1.readDiaryEntries)());
|
|
174
174
|
for (const fact of hits) {
|
|
175
|
-
|
|
175
|
+
let meta = `source=${fact.source}, createdAt=${fact.createdAt}`;
|
|
176
|
+
if (fact.provenance) {
|
|
177
|
+
if (fact.provenance.channel)
|
|
178
|
+
meta += `, channel=${fact.provenance.channel}`;
|
|
179
|
+
if (fact.provenance.friendName)
|
|
180
|
+
meta += `, friend=${fact.provenance.friendName}`;
|
|
181
|
+
if (fact.provenance.trust)
|
|
182
|
+
meta += `, trust=${fact.provenance.trust}`;
|
|
183
|
+
}
|
|
184
|
+
resultLines.push(`[diary] ${fact.text} (${meta})`);
|
|
176
185
|
}
|
|
177
186
|
// Search journal index
|
|
178
187
|
const agentRoot = (0, identity_1.getAgentRoot)();
|
|
@@ -219,14 +228,32 @@ exports.memoryToolDefinitions = [
|
|
|
219
228
|
},
|
|
220
229
|
},
|
|
221
230
|
},
|
|
222
|
-
handler: async (a) => {
|
|
231
|
+
handler: async (a, ctx) => {
|
|
223
232
|
const entry = (a.entry || "").trim();
|
|
224
233
|
if (!entry)
|
|
225
234
|
return "entry is required";
|
|
235
|
+
let provenance;
|
|
236
|
+
if (ctx?.context) {
|
|
237
|
+
const p = { tool: "diary_write" };
|
|
238
|
+
const channel = ctx.context.channel?.channel;
|
|
239
|
+
if (channel)
|
|
240
|
+
p.channel = channel;
|
|
241
|
+
const friendId = ctx.context.friend?.id;
|
|
242
|
+
if (friendId)
|
|
243
|
+
p.friendId = friendId;
|
|
244
|
+
const friendName = ctx.context.friend?.name;
|
|
245
|
+
if (friendName)
|
|
246
|
+
p.friendName = friendName;
|
|
247
|
+
const trust = ctx.context.friend?.trustLevel;
|
|
248
|
+
if (trust)
|
|
249
|
+
p.trust = trust;
|
|
250
|
+
provenance = p;
|
|
251
|
+
}
|
|
226
252
|
const result = await (0, diary_1.saveDiaryEntry)({
|
|
227
253
|
text: entry,
|
|
228
254
|
source: "tool:diary_write",
|
|
229
255
|
about: typeof a.about === "string" ? a.about : undefined,
|
|
256
|
+
provenance,
|
|
230
257
|
});
|
|
231
258
|
return `saved diary entry (added=${result.added}, skipped=${result.skipped})`;
|
|
232
259
|
},
|