@cleocode/cleo 2026.4.15 → 2026.4.17
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/dist/cli/index.js
CHANGED
|
@@ -9205,6 +9205,9 @@ var init_brain_schema = __esm({
|
|
|
9205
9205
|
sourceSessionId: text("source_session_id"),
|
|
9206
9206
|
// soft FK to sessions
|
|
9207
9207
|
sourceType: text("source_type", { enum: BRAIN_OBSERVATION_SOURCE_TYPES }).notNull().default("agent"),
|
|
9208
|
+
/** T383/T417: agent provenance — identifies the spawned agent that produced this observation. Null for legacy entries. */
|
|
9209
|
+
agent: text("agent"),
|
|
9210
|
+
// nullable — null for legacy observations
|
|
9208
9211
|
contentHash: text("content_hash"),
|
|
9209
9212
|
// SHA-256 prefix for dedup
|
|
9210
9213
|
discoveryTokens: integer("discovery_tokens"),
|
|
@@ -9221,7 +9224,9 @@ var init_brain_schema = __esm({
|
|
|
9221
9224
|
// T033: composite replaces single-col content_hash; see brain migration
|
|
9222
9225
|
index("idx_brain_observations_content_hash_created_at").on(table.contentHash, table.createdAt),
|
|
9223
9226
|
// T033: type + project compound filter optimization
|
|
9224
|
-
index("idx_brain_observations_type_project").on(table.type, table.project)
|
|
9227
|
+
index("idx_brain_observations_type_project").on(table.type, table.project),
|
|
9228
|
+
// T417: agent provenance index for memory.find --agent filter
|
|
9229
|
+
index("idx_brain_observations_agent").on(table.agent)
|
|
9225
9230
|
]
|
|
9226
9231
|
);
|
|
9227
9232
|
brainStickyNotes = sqliteTable(
|
|
@@ -10795,6 +10800,7 @@ var init_platform_paths = __esm({
|
|
|
10795
10800
|
});
|
|
10796
10801
|
|
|
10797
10802
|
// packages/core/src/paths.ts
|
|
10803
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
10798
10804
|
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "node:fs";
|
|
10799
10805
|
import { homedir } from "node:os";
|
|
10800
10806
|
import { dirname as dirname2, join as join4, resolve as resolve2 } from "node:path";
|
|
@@ -10826,6 +10832,10 @@ function getCleoDirAbsolute(cwd) {
|
|
|
10826
10832
|
return resolve2(cwd ?? process.cwd(), cleoDir);
|
|
10827
10833
|
}
|
|
10828
10834
|
function getProjectRoot(cwd) {
|
|
10835
|
+
const scope = worktreeScope.getStore();
|
|
10836
|
+
if (scope !== void 0) {
|
|
10837
|
+
return scope.worktreeRoot;
|
|
10838
|
+
}
|
|
10829
10839
|
if (process.env["CLEO_ROOT"]) {
|
|
10830
10840
|
return process.env["CLEO_ROOT"];
|
|
10831
10841
|
}
|
|
@@ -10988,13 +10998,14 @@ function getClaudeAgentsDir() {
|
|
|
10988
10998
|
function getClaudeMemDbPath() {
|
|
10989
10999
|
return process.env["CLAUDE_MEM_DB"] ?? join4(homedir(), ".claude-mem", "claude-mem.db");
|
|
10990
11000
|
}
|
|
10991
|
-
var DEFAULT_AGENT_OUTPUTS_DIR;
|
|
11001
|
+
var worktreeScope, DEFAULT_AGENT_OUTPUTS_DIR;
|
|
10992
11002
|
var init_paths = __esm({
|
|
10993
11003
|
"packages/core/src/paths.ts"() {
|
|
10994
11004
|
"use strict";
|
|
10995
11005
|
init_src();
|
|
10996
11006
|
init_errors3();
|
|
10997
11007
|
init_platform_paths();
|
|
11008
|
+
worktreeScope = new AsyncLocalStorage();
|
|
10998
11009
|
DEFAULT_AGENT_OUTPUTS_DIR = ".cleo/agent-outputs";
|
|
10999
11010
|
}
|
|
11000
11011
|
});
|
|
@@ -17548,6 +17559,9 @@ var init_brain_accessor = __esm({
|
|
|
17548
17559
|
if (params.sourceSessionId) {
|
|
17549
17560
|
conditions.push(eq7(brainObservations.sourceSessionId, params.sourceSessionId));
|
|
17550
17561
|
}
|
|
17562
|
+
if (params.agent) {
|
|
17563
|
+
conditions.push(eq7(brainObservations.agent, params.agent));
|
|
17564
|
+
}
|
|
17551
17565
|
let query = this.db.select().from(brainObservations).orderBy(desc2(brainObservations.createdAt));
|
|
17552
17566
|
if (conditions.length > 0) {
|
|
17553
17567
|
query = query.where(and5(...conditions));
|
|
@@ -25412,44 +25426,51 @@ __export(brain_retrieval_exports, {
|
|
|
25412
25426
|
});
|
|
25413
25427
|
import { createHash as createHash3 } from "node:crypto";
|
|
25414
25428
|
async function searchBrainCompact(projectRoot, params) {
|
|
25415
|
-
const { query, limit, tables, dateStart, dateEnd } = params;
|
|
25429
|
+
const { query, limit, tables, dateStart, dateEnd, agent } = params;
|
|
25416
25430
|
if (!query || !query.trim()) {
|
|
25417
25431
|
return { results: [], total: 0, tokensEstimated: 0 };
|
|
25418
25432
|
}
|
|
25433
|
+
const effectiveTables = agent !== void 0 && agent !== null ? ["observations"] : tables;
|
|
25419
25434
|
const searchResult = await searchBrain(projectRoot, query, {
|
|
25420
25435
|
limit: limit ?? 10,
|
|
25421
|
-
tables
|
|
25436
|
+
tables: effectiveTables
|
|
25422
25437
|
});
|
|
25423
25438
|
let results = [];
|
|
25424
|
-
|
|
25425
|
-
const
|
|
25426
|
-
|
|
25427
|
-
|
|
25428
|
-
|
|
25429
|
-
|
|
25430
|
-
|
|
25431
|
-
|
|
25432
|
-
|
|
25433
|
-
|
|
25434
|
-
const
|
|
25435
|
-
|
|
25436
|
-
|
|
25437
|
-
|
|
25438
|
-
|
|
25439
|
-
|
|
25440
|
-
|
|
25441
|
-
|
|
25442
|
-
|
|
25443
|
-
const
|
|
25444
|
-
|
|
25445
|
-
|
|
25446
|
-
|
|
25447
|
-
|
|
25448
|
-
|
|
25449
|
-
|
|
25439
|
+
if (!agent) {
|
|
25440
|
+
for (const d of searchResult.decisions) {
|
|
25441
|
+
const raw = d;
|
|
25442
|
+
results.push({
|
|
25443
|
+
id: d.id,
|
|
25444
|
+
type: "decision",
|
|
25445
|
+
title: d.decision.slice(0, 80),
|
|
25446
|
+
date: (d.createdAt ?? raw["created_at"]) || ""
|
|
25447
|
+
});
|
|
25448
|
+
}
|
|
25449
|
+
for (const p2 of searchResult.patterns) {
|
|
25450
|
+
const raw = p2;
|
|
25451
|
+
results.push({
|
|
25452
|
+
id: p2.id,
|
|
25453
|
+
type: "pattern",
|
|
25454
|
+
title: p2.pattern.slice(0, 80),
|
|
25455
|
+
date: (p2.extractedAt ?? raw["extracted_at"]) || ""
|
|
25456
|
+
});
|
|
25457
|
+
}
|
|
25458
|
+
for (const l of searchResult.learnings) {
|
|
25459
|
+
const raw = l;
|
|
25460
|
+
results.push({
|
|
25461
|
+
id: l.id,
|
|
25462
|
+
type: "learning",
|
|
25463
|
+
title: l.insight.slice(0, 80),
|
|
25464
|
+
date: (l.createdAt ?? raw["created_at"]) || ""
|
|
25465
|
+
});
|
|
25466
|
+
}
|
|
25450
25467
|
}
|
|
25451
25468
|
for (const o of searchResult.observations) {
|
|
25452
25469
|
const raw = o;
|
|
25470
|
+
if (agent) {
|
|
25471
|
+
const rowAgent = o.agent ?? raw["agent"] ?? null;
|
|
25472
|
+
if (rowAgent !== agent) continue;
|
|
25473
|
+
}
|
|
25453
25474
|
results.push({
|
|
25454
25475
|
id: o.id,
|
|
25455
25476
|
type: "observation",
|
|
@@ -25663,7 +25684,15 @@ function classifyObservationType(text3) {
|
|
|
25663
25684
|
return "discovery";
|
|
25664
25685
|
}
|
|
25665
25686
|
async function observeBrain(projectRoot, params) {
|
|
25666
|
-
const {
|
|
25687
|
+
const {
|
|
25688
|
+
text: text3,
|
|
25689
|
+
title: titleParam,
|
|
25690
|
+
type: typeParam,
|
|
25691
|
+
project,
|
|
25692
|
+
sourceSessionId,
|
|
25693
|
+
sourceType,
|
|
25694
|
+
agent
|
|
25695
|
+
} = params;
|
|
25667
25696
|
if (!text3 || !text3.trim()) {
|
|
25668
25697
|
throw new Error("Observation text is required");
|
|
25669
25698
|
}
|
|
@@ -25712,6 +25741,7 @@ async function observeBrain(projectRoot, params) {
|
|
|
25712
25741
|
project: project ?? null,
|
|
25713
25742
|
sourceSessionId: validSessionId,
|
|
25714
25743
|
sourceType: sourceType ?? "agent",
|
|
25744
|
+
agent: agent ?? null,
|
|
25715
25745
|
createdAt: now2
|
|
25716
25746
|
});
|
|
25717
25747
|
if (isEmbeddingAvailable()) {
|
|
@@ -78101,6 +78131,116 @@ var init_claude_mem_migration = __esm({
|
|
|
78101
78131
|
}
|
|
78102
78132
|
});
|
|
78103
78133
|
|
|
78134
|
+
// packages/core/src/memory/mental-model-queue.ts
|
|
78135
|
+
async function drainQueue() {
|
|
78136
|
+
if (_queue.length === 0) return 0;
|
|
78137
|
+
const batch = _queue.splice(0, _queue.length);
|
|
78138
|
+
let count4 = 0;
|
|
78139
|
+
const { observeBrain: observeBrain2 } = await Promise.resolve().then(() => (init_brain_retrieval(), brain_retrieval_exports));
|
|
78140
|
+
for (const entry of batch) {
|
|
78141
|
+
try {
|
|
78142
|
+
const result = await observeBrain2(entry.projectRoot, entry.params);
|
|
78143
|
+
entry.resolve(result);
|
|
78144
|
+
count4++;
|
|
78145
|
+
} catch (err) {
|
|
78146
|
+
const error48 = err instanceof Error ? err : new Error(String(err));
|
|
78147
|
+
entry.reject(error48);
|
|
78148
|
+
}
|
|
78149
|
+
}
|
|
78150
|
+
return count4;
|
|
78151
|
+
}
|
|
78152
|
+
function exitFlush() {
|
|
78153
|
+
if (_queue.length === 0) return;
|
|
78154
|
+
drainQueue().catch(() => {
|
|
78155
|
+
});
|
|
78156
|
+
}
|
|
78157
|
+
function registerExitHooks() {
|
|
78158
|
+
if (_hooksRegistered) return;
|
|
78159
|
+
_hooksRegistered = true;
|
|
78160
|
+
process.on("exit", exitFlush);
|
|
78161
|
+
process.once("SIGINT", () => {
|
|
78162
|
+
drainQueue().catch(() => {
|
|
78163
|
+
}).finally(() => {
|
|
78164
|
+
process.exit(130);
|
|
78165
|
+
});
|
|
78166
|
+
});
|
|
78167
|
+
process.once("SIGTERM", () => {
|
|
78168
|
+
drainQueue().catch(() => {
|
|
78169
|
+
}).finally(() => {
|
|
78170
|
+
process.exit(143);
|
|
78171
|
+
});
|
|
78172
|
+
});
|
|
78173
|
+
}
|
|
78174
|
+
function ensureTimer() {
|
|
78175
|
+
if (_timer !== void 0) return;
|
|
78176
|
+
_timer = setInterval(() => {
|
|
78177
|
+
if (_queue.length === 0) return;
|
|
78178
|
+
if (_flushing) return;
|
|
78179
|
+
_flushing = true;
|
|
78180
|
+
drainQueue().catch(() => {
|
|
78181
|
+
}).finally(() => {
|
|
78182
|
+
_flushing = false;
|
|
78183
|
+
});
|
|
78184
|
+
}, FLUSH_INTERVAL_MS);
|
|
78185
|
+
if (typeof _timer.unref === "function") {
|
|
78186
|
+
_timer.unref();
|
|
78187
|
+
}
|
|
78188
|
+
}
|
|
78189
|
+
function isMentalModelObservation(params) {
|
|
78190
|
+
if (!params.agent) return false;
|
|
78191
|
+
const type = params.type ?? "discovery";
|
|
78192
|
+
return MENTAL_MODEL_TYPES.has(type);
|
|
78193
|
+
}
|
|
78194
|
+
var FLUSH_INTERVAL_MS, FLUSH_WATERMARK, MENTAL_MODEL_TYPES, _queue, _flushing, _hooksRegistered, _timer, mentalModelQueue;
|
|
78195
|
+
var init_mental_model_queue = __esm({
|
|
78196
|
+
"packages/core/src/memory/mental-model-queue.ts"() {
|
|
78197
|
+
"use strict";
|
|
78198
|
+
FLUSH_INTERVAL_MS = 5e3;
|
|
78199
|
+
FLUSH_WATERMARK = 50;
|
|
78200
|
+
MENTAL_MODEL_TYPES = /* @__PURE__ */ new Set([
|
|
78201
|
+
"discovery",
|
|
78202
|
+
"change",
|
|
78203
|
+
"feature",
|
|
78204
|
+
"decision",
|
|
78205
|
+
"bugfix",
|
|
78206
|
+
"refactor"
|
|
78207
|
+
]);
|
|
78208
|
+
_queue = [];
|
|
78209
|
+
_flushing = false;
|
|
78210
|
+
_hooksRegistered = false;
|
|
78211
|
+
mentalModelQueue = {
|
|
78212
|
+
enqueue(projectRoot, params) {
|
|
78213
|
+
registerExitHooks();
|
|
78214
|
+
ensureTimer();
|
|
78215
|
+
return new Promise((resolve16, reject) => {
|
|
78216
|
+
_queue.push({ projectRoot, params, resolve: resolve16, reject });
|
|
78217
|
+
if (_queue.length >= FLUSH_WATERMARK && !_flushing) {
|
|
78218
|
+
_flushing = true;
|
|
78219
|
+
drainQueue().catch(() => {
|
|
78220
|
+
}).finally(() => {
|
|
78221
|
+
_flushing = false;
|
|
78222
|
+
});
|
|
78223
|
+
}
|
|
78224
|
+
});
|
|
78225
|
+
},
|
|
78226
|
+
async flush() {
|
|
78227
|
+
if (_flushing) {
|
|
78228
|
+
await new Promise((r) => setTimeout(r, 50));
|
|
78229
|
+
}
|
|
78230
|
+
_flushing = true;
|
|
78231
|
+
try {
|
|
78232
|
+
return await drainQueue();
|
|
78233
|
+
} finally {
|
|
78234
|
+
_flushing = false;
|
|
78235
|
+
}
|
|
78236
|
+
},
|
|
78237
|
+
size() {
|
|
78238
|
+
return _queue.length;
|
|
78239
|
+
}
|
|
78240
|
+
};
|
|
78241
|
+
}
|
|
78242
|
+
});
|
|
78243
|
+
|
|
78104
78244
|
// packages/core/src/memory/brain-reasoning.ts
|
|
78105
78245
|
var brain_reasoning_exports = {};
|
|
78106
78246
|
__export(brain_reasoning_exports, {
|
|
@@ -78476,7 +78616,8 @@ async function memoryFind(params, projectRoot) {
|
|
|
78476
78616
|
limit: params.limit,
|
|
78477
78617
|
tables: params.tables,
|
|
78478
78618
|
dateStart: params.dateStart,
|
|
78479
|
-
dateEnd: params.dateEnd
|
|
78619
|
+
dateEnd: params.dateEnd,
|
|
78620
|
+
agent: params.agent
|
|
78480
78621
|
});
|
|
78481
78622
|
return { success: true, data: result };
|
|
78482
78623
|
} catch (error48) {
|
|
@@ -78526,14 +78667,24 @@ async function memoryFetch(params, projectRoot) {
|
|
|
78526
78667
|
async function memoryObserve(params, projectRoot) {
|
|
78527
78668
|
try {
|
|
78528
78669
|
const root = resolveRoot(projectRoot);
|
|
78529
|
-
const
|
|
78670
|
+
const observeParams = {
|
|
78530
78671
|
text: params.text,
|
|
78531
78672
|
title: params.title,
|
|
78532
78673
|
type: params.type,
|
|
78533
78674
|
project: params.project,
|
|
78534
78675
|
sourceSessionId: params.sourceSessionId,
|
|
78535
|
-
sourceType: params.sourceType
|
|
78536
|
-
|
|
78676
|
+
sourceType: params.sourceType,
|
|
78677
|
+
agent: params.agent
|
|
78678
|
+
};
|
|
78679
|
+
let result;
|
|
78680
|
+
if (isMentalModelObservation(observeParams) && observeParams.agent) {
|
|
78681
|
+
result = await mentalModelQueue.enqueue(root, {
|
|
78682
|
+
...observeParams,
|
|
78683
|
+
agent: observeParams.agent
|
|
78684
|
+
});
|
|
78685
|
+
} else {
|
|
78686
|
+
result = await observeBrain(root, observeParams);
|
|
78687
|
+
}
|
|
78537
78688
|
return { success: true, data: result };
|
|
78538
78689
|
} catch (error48) {
|
|
78539
78690
|
return {
|
|
@@ -79133,6 +79284,7 @@ var init_engine_compat = __esm({
|
|
|
79133
79284
|
init_brain_links();
|
|
79134
79285
|
init_brain_retrieval();
|
|
79135
79286
|
init_learnings();
|
|
79287
|
+
init_mental_model_queue();
|
|
79136
79288
|
init_patterns();
|
|
79137
79289
|
}
|
|
79138
79290
|
});
|
|
@@ -101465,11 +101617,31 @@ var init_registry5 = __esm({
|
|
|
101465
101617
|
gateway: "query",
|
|
101466
101618
|
domain: "orchestrate",
|
|
101467
101619
|
operation: "analyze",
|
|
101468
|
-
description:
|
|
101620
|
+
description: 'orchestrate.analyze (query) \u2014 absorbs critical.path via mode param; Wave 7a adds mode="parallel-safety"',
|
|
101469
101621
|
tier: 1,
|
|
101470
101622
|
idempotent: true,
|
|
101471
101623
|
sessionRequired: false,
|
|
101472
|
-
requiredParams: []
|
|
101624
|
+
requiredParams: [],
|
|
101625
|
+
params: [
|
|
101626
|
+
{
|
|
101627
|
+
name: "epicId",
|
|
101628
|
+
type: "string",
|
|
101629
|
+
required: false,
|
|
101630
|
+
description: "Epic ID for standard analysis (required unless mode=critical-path or parallel-safety)"
|
|
101631
|
+
},
|
|
101632
|
+
{
|
|
101633
|
+
name: "mode",
|
|
101634
|
+
type: "string",
|
|
101635
|
+
required: false,
|
|
101636
|
+
description: 'Analysis mode: omit for standard analysis, "critical-path" for CPM, "parallel-safety" for dep-graph grouping'
|
|
101637
|
+
},
|
|
101638
|
+
{
|
|
101639
|
+
name: "taskIds",
|
|
101640
|
+
type: "array",
|
|
101641
|
+
required: false,
|
|
101642
|
+
description: 'Task ID list for mode="parallel-safety" \u2014 returns {parallelSafe, groups} dep-graph analysis'
|
|
101643
|
+
}
|
|
101644
|
+
]
|
|
101473
101645
|
},
|
|
101474
101646
|
{
|
|
101475
101647
|
gateway: "query",
|
|
@@ -101524,7 +101696,16 @@ var init_registry5 = __esm({
|
|
|
101524
101696
|
tier: 0,
|
|
101525
101697
|
idempotent: true,
|
|
101526
101698
|
sessionRequired: false,
|
|
101527
|
-
requiredParams: ["query"]
|
|
101699
|
+
requiredParams: ["query"],
|
|
101700
|
+
params: [
|
|
101701
|
+
{
|
|
101702
|
+
name: "agent",
|
|
101703
|
+
type: "string",
|
|
101704
|
+
required: false,
|
|
101705
|
+
description: "Filter results to observations produced by the named agent (T418 mental models)",
|
|
101706
|
+
cli: { flag: "--agent <name>" }
|
|
101707
|
+
}
|
|
101708
|
+
]
|
|
101528
101709
|
},
|
|
101529
101710
|
{
|
|
101530
101711
|
gateway: "query",
|
|
@@ -104053,6 +104234,70 @@ var init_registry5 = __esm({
|
|
|
104053
104234
|
sessionRequired: false,
|
|
104054
104235
|
requiredParams: ["templateId", "epicId"]
|
|
104055
104236
|
},
|
|
104237
|
+
// orchestrate — Wave 7a dispatch ops (T408, T409, T410, T415)
|
|
104238
|
+
{
|
|
104239
|
+
gateway: "query",
|
|
104240
|
+
domain: "orchestrate",
|
|
104241
|
+
operation: "classify",
|
|
104242
|
+
description: "orchestrate.classify (query) \u2014 classify a request against CANT team registry to route to correct team/lead/protocol",
|
|
104243
|
+
tier: 2,
|
|
104244
|
+
idempotent: true,
|
|
104245
|
+
sessionRequired: false,
|
|
104246
|
+
requiredParams: ["request"],
|
|
104247
|
+
params: [
|
|
104248
|
+
{
|
|
104249
|
+
name: "request",
|
|
104250
|
+
type: "string",
|
|
104251
|
+
required: true,
|
|
104252
|
+
description: "The request or task description to classify against team consult-when hints"
|
|
104253
|
+
},
|
|
104254
|
+
{
|
|
104255
|
+
name: "context",
|
|
104256
|
+
type: "string",
|
|
104257
|
+
required: false,
|
|
104258
|
+
description: "Optional additional context to improve classification accuracy"
|
|
104259
|
+
}
|
|
104260
|
+
]
|
|
104261
|
+
},
|
|
104262
|
+
{
|
|
104263
|
+
gateway: "query",
|
|
104264
|
+
domain: "orchestrate",
|
|
104265
|
+
operation: "fanout.status",
|
|
104266
|
+
description: "orchestrate.fanout.status (query) \u2014 get status of a running fanout by its manifest entry ID",
|
|
104267
|
+
tier: 2,
|
|
104268
|
+
idempotent: true,
|
|
104269
|
+
sessionRequired: false,
|
|
104270
|
+
requiredParams: ["manifestEntryId"],
|
|
104271
|
+
params: [
|
|
104272
|
+
{
|
|
104273
|
+
name: "manifestEntryId",
|
|
104274
|
+
type: "string",
|
|
104275
|
+
required: true,
|
|
104276
|
+
description: "Manifest entry ID returned by orchestrate.fanout"
|
|
104277
|
+
}
|
|
104278
|
+
]
|
|
104279
|
+
},
|
|
104280
|
+
{
|
|
104281
|
+
gateway: "mutate",
|
|
104282
|
+
domain: "orchestrate",
|
|
104283
|
+
operation: "fanout",
|
|
104284
|
+
description: "orchestrate.fanout (mutate) \u2014 fan out N spawn requests in parallel via Promise.allSettled",
|
|
104285
|
+
tier: 2,
|
|
104286
|
+
idempotent: false,
|
|
104287
|
+
sessionRequired: false,
|
|
104288
|
+
requiredParams: ["items"],
|
|
104289
|
+
params: [
|
|
104290
|
+
{
|
|
104291
|
+
name: "items",
|
|
104292
|
+
type: "array",
|
|
104293
|
+
required: true,
|
|
104294
|
+
description: "Array of {team, taskId, skill?} objects to fan out"
|
|
104295
|
+
}
|
|
104296
|
+
]
|
|
104297
|
+
},
|
|
104298
|
+
// orchestrate — Wave 7a: analyze parallel-safety mode (T410)
|
|
104299
|
+
// Note: orchestrate.analyze already registered above; this documents the new
|
|
104300
|
+
// mode="parallel-safety" variant via the existing analyze operation's params.
|
|
104056
104301
|
// conduit — agent messaging operations (replaces standalone clawmsgr scripts)
|
|
104057
104302
|
{
|
|
104058
104303
|
gateway: "query",
|
|
@@ -105631,13 +105876,27 @@ async function orchestrateSpawnExecute(taskId, adapterId, protocolType, projectR
|
|
|
105631
105876
|
}
|
|
105632
105877
|
};
|
|
105633
105878
|
}
|
|
105879
|
+
let composedPrompt = spawnContext.prompt;
|
|
105880
|
+
try {
|
|
105881
|
+
const { composeSpawnPayload } = await import("@cleocode/cant");
|
|
105882
|
+
const { brainContextProvider } = await import("@cleocode/cant");
|
|
105883
|
+
const { createHash: createHash14 } = await import("node:crypto");
|
|
105884
|
+
const projectHash = createHash14("sha256").update(cwd).digest("hex").slice(0, 12);
|
|
105885
|
+
const agentDef = spawnContext.agentDef;
|
|
105886
|
+
if (agentDef) {
|
|
105887
|
+
const provider2 = brainContextProvider(cwd);
|
|
105888
|
+
const payload = await composeSpawnPayload(agentDef, provider2, projectHash);
|
|
105889
|
+
composedPrompt = payload.systemPrompt;
|
|
105890
|
+
}
|
|
105891
|
+
} catch {
|
|
105892
|
+
}
|
|
105634
105893
|
const cleoSpawnContext = {
|
|
105635
105894
|
taskId: spawnContext.taskId,
|
|
105636
105895
|
protocol: protocolType || spawnContext.protocol,
|
|
105637
|
-
prompt:
|
|
105896
|
+
prompt: composedPrompt,
|
|
105638
105897
|
provider: provider.id,
|
|
105639
105898
|
options: {
|
|
105640
|
-
prompt:
|
|
105899
|
+
prompt: composedPrompt
|
|
105641
105900
|
},
|
|
105642
105901
|
workingDirectory: cwd,
|
|
105643
105902
|
tokenResolution: {
|
|
@@ -110231,7 +110490,9 @@ var init_memory2 = __esm({
|
|
|
110231
110490
|
limit: params?.limit,
|
|
110232
110491
|
tables: params?.tables,
|
|
110233
110492
|
dateStart: params?.dateStart,
|
|
110234
|
-
dateEnd: params?.dateEnd
|
|
110493
|
+
dateEnd: params?.dateEnd,
|
|
110494
|
+
// T418: optional agent filter for per-agent mental model retrieval
|
|
110495
|
+
agent: params?.agent
|
|
110235
110496
|
},
|
|
110236
110497
|
projectRoot
|
|
110237
110498
|
);
|
|
@@ -110440,7 +110701,9 @@ var init_memory2 = __esm({
|
|
|
110440
110701
|
type: params?.type,
|
|
110441
110702
|
project: params?.project,
|
|
110442
110703
|
sourceSessionId: params?.sourceSessionId,
|
|
110443
|
-
sourceType: params?.sourceType
|
|
110704
|
+
sourceType: params?.sourceType,
|
|
110705
|
+
// T417: optional agent provenance for mental model observations
|
|
110706
|
+
agent: params?.agent
|
|
110444
110707
|
},
|
|
110445
110708
|
projectRoot
|
|
110446
110709
|
);
|
|
@@ -111241,7 +111504,241 @@ var init_nexus2 = __esm({
|
|
|
111241
111504
|
});
|
|
111242
111505
|
|
|
111243
111506
|
// packages/cleo/src/dispatch/domains/orchestrate.ts
|
|
111244
|
-
|
|
111507
|
+
async function orchestrateClassify(request, context, projectRoot) {
|
|
111508
|
+
try {
|
|
111509
|
+
const { getCleoCantWorkflowsDir: getCleoCantWorkflowsDir2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
111510
|
+
const { readFileSync: readFileSync101, readdirSync: readdirSync42, existsSync: existsSync131 } = await import("node:fs");
|
|
111511
|
+
const { join: join131 } = await import("node:path");
|
|
111512
|
+
const workflowsDir = getCleoCantWorkflowsDir2();
|
|
111513
|
+
const combined = `${request} ${context ?? ""}`.toLowerCase();
|
|
111514
|
+
const matches = [];
|
|
111515
|
+
if (existsSync131(workflowsDir)) {
|
|
111516
|
+
const files = readdirSync42(workflowsDir).filter((f2) => f2.endsWith(".cant"));
|
|
111517
|
+
for (const file2 of files) {
|
|
111518
|
+
try {
|
|
111519
|
+
const src = readFileSync101(join131(workflowsDir, file2), "utf-8");
|
|
111520
|
+
const teamMatch = /^team\s+(\S+):/m.exec(src);
|
|
111521
|
+
if (!teamMatch) continue;
|
|
111522
|
+
const teamName = teamMatch[1];
|
|
111523
|
+
const cwMatch = /consult-when:\s*["']?(.+?)["']?\s*$/m.exec(src);
|
|
111524
|
+
const consultWhen = cwMatch ? cwMatch[1].trim() : "";
|
|
111525
|
+
const stagesMatch = /stages:\s*\[([^\]]+)\]/.exec(src);
|
|
111526
|
+
const stages = stagesMatch ? stagesMatch[1].split(",").map((s3) => s3.trim()) : [];
|
|
111527
|
+
const hintWords = consultWhen.toLowerCase().split(/\s+/);
|
|
111528
|
+
const score = hintWords.filter((w2) => combined.includes(w2)).length;
|
|
111529
|
+
matches.push({ team: teamName, score, consultWhen, stages });
|
|
111530
|
+
} catch {
|
|
111531
|
+
}
|
|
111532
|
+
}
|
|
111533
|
+
}
|
|
111534
|
+
const localCantDir = join131(projectRoot, ".cleo", "workflows");
|
|
111535
|
+
if (existsSync131(localCantDir)) {
|
|
111536
|
+
const files = readdirSync42(localCantDir).filter((f2) => f2.endsWith(".cant"));
|
|
111537
|
+
for (const file2 of files) {
|
|
111538
|
+
try {
|
|
111539
|
+
const src = readFileSync101(join131(localCantDir, file2), "utf-8");
|
|
111540
|
+
const teamMatch = /^team\s+(\S+):/m.exec(src);
|
|
111541
|
+
if (!teamMatch) continue;
|
|
111542
|
+
const teamName = teamMatch[1];
|
|
111543
|
+
const cwMatch = /consult-when:\s*["']?(.+?)["']?\s*$/m.exec(src);
|
|
111544
|
+
const consultWhen = cwMatch ? cwMatch[1].trim() : "";
|
|
111545
|
+
const stagesMatch = /stages:\s*\[([^\]]+)\]/.exec(src);
|
|
111546
|
+
const stages = stagesMatch ? stagesMatch[1].split(",").map((s3) => s3.trim()) : [];
|
|
111547
|
+
const hintWords = consultWhen.toLowerCase().split(/\s+/);
|
|
111548
|
+
const score = hintWords.filter((w2) => combined.includes(w2)).length;
|
|
111549
|
+
matches.push({ team: teamName, score, consultWhen, stages });
|
|
111550
|
+
} catch {
|
|
111551
|
+
}
|
|
111552
|
+
}
|
|
111553
|
+
}
|
|
111554
|
+
if (matches.length === 0) {
|
|
111555
|
+
return {
|
|
111556
|
+
success: true,
|
|
111557
|
+
data: {
|
|
111558
|
+
team: null,
|
|
111559
|
+
lead: null,
|
|
111560
|
+
protocol: null,
|
|
111561
|
+
stage: null,
|
|
111562
|
+
confidence: 0,
|
|
111563
|
+
reasoning: "No CANT team definitions found. Seed teams.cant in the global workflows dir (W7b runtime enforcement) to enable team routing."
|
|
111564
|
+
}
|
|
111565
|
+
};
|
|
111566
|
+
}
|
|
111567
|
+
matches.sort((a, b2) => b2.score - a.score);
|
|
111568
|
+
const best = matches[0];
|
|
111569
|
+
return {
|
|
111570
|
+
success: true,
|
|
111571
|
+
data: {
|
|
111572
|
+
team: best.team,
|
|
111573
|
+
lead: null,
|
|
111574
|
+
// lead resolution requires W7b runtime bridge
|
|
111575
|
+
protocol: "base-subagent",
|
|
111576
|
+
// default protocol stub
|
|
111577
|
+
stage: best.stages[0] ?? null,
|
|
111578
|
+
confidence: best.score > 0 ? 0.5 : 0.1,
|
|
111579
|
+
reasoning: best.score > 0 ? `Matched team '${best.team}' via consult-when hint: "${best.consultWhen}"` : `No strong match found; defaulting to first registered team '${best.team}'`
|
|
111580
|
+
}
|
|
111581
|
+
};
|
|
111582
|
+
} catch (error48) {
|
|
111583
|
+
getLogger("domain:orchestrate").error(
|
|
111584
|
+
{ operation: "classify", err: error48 },
|
|
111585
|
+
error48 instanceof Error ? error48.message : String(error48)
|
|
111586
|
+
);
|
|
111587
|
+
return {
|
|
111588
|
+
success: false,
|
|
111589
|
+
error: {
|
|
111590
|
+
code: "E_CLASSIFY_FAILED",
|
|
111591
|
+
message: error48 instanceof Error ? error48.message : String(error48)
|
|
111592
|
+
}
|
|
111593
|
+
};
|
|
111594
|
+
}
|
|
111595
|
+
}
|
|
111596
|
+
async function orchestrateFanout(items, projectRoot) {
|
|
111597
|
+
const manifestEntryId = `fanout-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
111598
|
+
try {
|
|
111599
|
+
const settled = await Promise.allSettled(
|
|
111600
|
+
items.map(async (item) => {
|
|
111601
|
+
const spawnResult = await orchestrateSpawnExecute(
|
|
111602
|
+
item.taskId,
|
|
111603
|
+
/* adapterId */
|
|
111604
|
+
void 0,
|
|
111605
|
+
/* protocolType */
|
|
111606
|
+
void 0,
|
|
111607
|
+
projectRoot,
|
|
111608
|
+
/* tier */
|
|
111609
|
+
void 0
|
|
111610
|
+
);
|
|
111611
|
+
if (!spawnResult.success) {
|
|
111612
|
+
return {
|
|
111613
|
+
taskId: item.taskId,
|
|
111614
|
+
status: "failed",
|
|
111615
|
+
error: spawnResult.error?.message ?? `Spawn failed for task ${item.taskId}`
|
|
111616
|
+
};
|
|
111617
|
+
}
|
|
111618
|
+
const data = spawnResult.data;
|
|
111619
|
+
return {
|
|
111620
|
+
taskId: item.taskId,
|
|
111621
|
+
status: "spawned",
|
|
111622
|
+
instanceId: typeof data?.instanceId === "string" ? data.instanceId : void 0
|
|
111623
|
+
};
|
|
111624
|
+
})
|
|
111625
|
+
);
|
|
111626
|
+
const results = settled.map((outcome, i) => {
|
|
111627
|
+
if (outcome.status === "fulfilled") {
|
|
111628
|
+
return outcome.value;
|
|
111629
|
+
}
|
|
111630
|
+
return {
|
|
111631
|
+
taskId: items[i].taskId,
|
|
111632
|
+
status: "failed",
|
|
111633
|
+
error: outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason)
|
|
111634
|
+
};
|
|
111635
|
+
});
|
|
111636
|
+
fanoutManifestStore.set(manifestEntryId, {
|
|
111637
|
+
results,
|
|
111638
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
111639
|
+
});
|
|
111640
|
+
return {
|
|
111641
|
+
success: true,
|
|
111642
|
+
data: {
|
|
111643
|
+
manifestEntryId,
|
|
111644
|
+
results,
|
|
111645
|
+
total: items.length,
|
|
111646
|
+
spawned: results.filter((r) => r.status === "spawned").length,
|
|
111647
|
+
failed: results.filter((r) => r.status === "failed").length
|
|
111648
|
+
}
|
|
111649
|
+
};
|
|
111650
|
+
} catch (error48) {
|
|
111651
|
+
getLogger("domain:orchestrate").error(
|
|
111652
|
+
{ operation: "fanout", err: error48 },
|
|
111653
|
+
error48 instanceof Error ? error48.message : String(error48)
|
|
111654
|
+
);
|
|
111655
|
+
return {
|
|
111656
|
+
success: false,
|
|
111657
|
+
error: {
|
|
111658
|
+
code: "E_FANOUT_FAILED",
|
|
111659
|
+
message: error48 instanceof Error ? error48.message : String(error48)
|
|
111660
|
+
}
|
|
111661
|
+
};
|
|
111662
|
+
}
|
|
111663
|
+
}
|
|
111664
|
+
async function orchestrateAnalyzeParallelSafety(taskIds, projectRoot) {
|
|
111665
|
+
if (taskIds.length === 0) {
|
|
111666
|
+
return {
|
|
111667
|
+
success: true,
|
|
111668
|
+
data: {
|
|
111669
|
+
parallelSafe: true,
|
|
111670
|
+
groups: [],
|
|
111671
|
+
note: "No tasks provided \u2014 trivially parallel-safe"
|
|
111672
|
+
}
|
|
111673
|
+
};
|
|
111674
|
+
}
|
|
111675
|
+
try {
|
|
111676
|
+
let transitiveClose2 = function(id, visited = /* @__PURE__ */ new Set()) {
|
|
111677
|
+
if (visited.has(id)) return visited;
|
|
111678
|
+
visited.add(id);
|
|
111679
|
+
const deps = depMap.get(id) ?? [];
|
|
111680
|
+
for (const dep of deps) {
|
|
111681
|
+
transitiveClose2(dep, visited);
|
|
111682
|
+
}
|
|
111683
|
+
return visited;
|
|
111684
|
+
}, parallelSafe2 = function(a, b2) {
|
|
111685
|
+
const closureA = closures.get(a) ?? /* @__PURE__ */ new Set();
|
|
111686
|
+
const closureB = closures.get(b2) ?? /* @__PURE__ */ new Set();
|
|
111687
|
+
return !closureA.has(b2) && !closureB.has(a);
|
|
111688
|
+
};
|
|
111689
|
+
var transitiveClose = transitiveClose2, parallelSafe = parallelSafe2;
|
|
111690
|
+
const { getAccessor: getAccessor2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
111691
|
+
const accessor = await getAccessor2(projectRoot);
|
|
111692
|
+
const result = await accessor.queryTasks({});
|
|
111693
|
+
const allTasks = result?.tasks ?? [];
|
|
111694
|
+
const depMap = /* @__PURE__ */ new Map();
|
|
111695
|
+
for (const t of allTasks) {
|
|
111696
|
+
const deps = t.blockers ?? [];
|
|
111697
|
+
depMap.set(t.id, deps);
|
|
111698
|
+
}
|
|
111699
|
+
const closures = /* @__PURE__ */ new Map();
|
|
111700
|
+
for (const id of taskIds) {
|
|
111701
|
+
closures.set(id, transitiveClose2(id));
|
|
111702
|
+
}
|
|
111703
|
+
const groups = [];
|
|
111704
|
+
for (const id of taskIds) {
|
|
111705
|
+
let placed = false;
|
|
111706
|
+
for (const group of groups) {
|
|
111707
|
+
if (group.every((member) => parallelSafe2(id, member))) {
|
|
111708
|
+
group.push(id);
|
|
111709
|
+
placed = true;
|
|
111710
|
+
break;
|
|
111711
|
+
}
|
|
111712
|
+
}
|
|
111713
|
+
if (!placed) {
|
|
111714
|
+
groups.push([id]);
|
|
111715
|
+
}
|
|
111716
|
+
}
|
|
111717
|
+
const isFullyParallelSafe = groups.length <= 1;
|
|
111718
|
+
return {
|
|
111719
|
+
success: true,
|
|
111720
|
+
data: {
|
|
111721
|
+
parallelSafe: isFullyParallelSafe,
|
|
111722
|
+
groups,
|
|
111723
|
+
taskCount: taskIds.length,
|
|
111724
|
+
groupCount: groups.length
|
|
111725
|
+
}
|
|
111726
|
+
};
|
|
111727
|
+
} catch (error48) {
|
|
111728
|
+
getLogger("domain:orchestrate").error(
|
|
111729
|
+
{ operation: "analyze/parallel-safety", err: error48 },
|
|
111730
|
+
error48 instanceof Error ? error48.message : String(error48)
|
|
111731
|
+
);
|
|
111732
|
+
return {
|
|
111733
|
+
success: false,
|
|
111734
|
+
error: {
|
|
111735
|
+
code: "E_ANALYZE_FAILED",
|
|
111736
|
+
message: error48 instanceof Error ? error48.message : String(error48)
|
|
111737
|
+
}
|
|
111738
|
+
};
|
|
111739
|
+
}
|
|
111740
|
+
}
|
|
111741
|
+
var OrchestrateHandler, fanoutManifestStore;
|
|
111245
111742
|
var init_orchestrate2 = __esm({
|
|
111246
111743
|
"packages/cleo/src/dispatch/domains/orchestrate.ts"() {
|
|
111247
111744
|
"use strict";
|
|
@@ -111297,9 +111794,73 @@ var init_orchestrate2 = __esm({
|
|
|
111297
111794
|
case "analyze": {
|
|
111298
111795
|
const epicId = params?.epicId;
|
|
111299
111796
|
const mode = params?.mode;
|
|
111797
|
+
if (mode === "parallel-safety") {
|
|
111798
|
+
const taskIds = params?.taskIds;
|
|
111799
|
+
const result2 = await orchestrateAnalyzeParallelSafety(taskIds ?? [], projectRoot);
|
|
111800
|
+
return wrapResult(result2, "query", "orchestrate", "analyze", startTime);
|
|
111801
|
+
}
|
|
111300
111802
|
const result = await orchestrateAnalyze(epicId, projectRoot, mode);
|
|
111301
111803
|
return wrapResult(result, "query", "orchestrate", "analyze", startTime);
|
|
111302
111804
|
}
|
|
111805
|
+
case "classify": {
|
|
111806
|
+
const request = params?.request;
|
|
111807
|
+
if (!request) {
|
|
111808
|
+
return errorResult(
|
|
111809
|
+
"query",
|
|
111810
|
+
"orchestrate",
|
|
111811
|
+
operation,
|
|
111812
|
+
"E_INVALID_INPUT",
|
|
111813
|
+
"request is required",
|
|
111814
|
+
startTime
|
|
111815
|
+
);
|
|
111816
|
+
}
|
|
111817
|
+
const context = params?.context;
|
|
111818
|
+
const result = await orchestrateClassify(request, context, projectRoot);
|
|
111819
|
+
return wrapResult(result, "query", "orchestrate", operation, startTime);
|
|
111820
|
+
}
|
|
111821
|
+
case "fanout.status": {
|
|
111822
|
+
const manifestEntryId = params?.manifestEntryId;
|
|
111823
|
+
if (!manifestEntryId) {
|
|
111824
|
+
return errorResult(
|
|
111825
|
+
"query",
|
|
111826
|
+
"orchestrate",
|
|
111827
|
+
operation,
|
|
111828
|
+
"E_INVALID_INPUT",
|
|
111829
|
+
"manifestEntryId is required",
|
|
111830
|
+
startTime
|
|
111831
|
+
);
|
|
111832
|
+
}
|
|
111833
|
+
const entry = fanoutManifestStore.get(manifestEntryId);
|
|
111834
|
+
if (!entry) {
|
|
111835
|
+
return {
|
|
111836
|
+
meta: dispatchMeta("query", "orchestrate", operation, startTime),
|
|
111837
|
+
success: true,
|
|
111838
|
+
data: {
|
|
111839
|
+
manifestEntryId,
|
|
111840
|
+
pending: [],
|
|
111841
|
+
running: [],
|
|
111842
|
+
complete: [],
|
|
111843
|
+
failed: [],
|
|
111844
|
+
found: false
|
|
111845
|
+
}
|
|
111846
|
+
};
|
|
111847
|
+
}
|
|
111848
|
+
const spawned = entry.results.filter((r) => r.status === "spawned").map((r) => r.taskId);
|
|
111849
|
+
const failed = entry.results.filter((r) => r.status === "failed").map((r) => r.taskId);
|
|
111850
|
+
return {
|
|
111851
|
+
meta: dispatchMeta("query", "orchestrate", operation, startTime),
|
|
111852
|
+
success: true,
|
|
111853
|
+
data: {
|
|
111854
|
+
manifestEntryId,
|
|
111855
|
+
pending: [],
|
|
111856
|
+
running: spawned,
|
|
111857
|
+
complete: [],
|
|
111858
|
+
failed,
|
|
111859
|
+
found: true,
|
|
111860
|
+
completedAt: entry.completedAt
|
|
111861
|
+
}
|
|
111862
|
+
};
|
|
111863
|
+
}
|
|
111303
111864
|
case "context": {
|
|
111304
111865
|
const epicId = params?.epicId;
|
|
111305
111866
|
const result = await orchestrateContext(epicId, projectRoot);
|
|
@@ -111552,6 +112113,21 @@ var init_orchestrate2 = __esm({
|
|
|
111552
112113
|
}
|
|
111553
112114
|
});
|
|
111554
112115
|
}
|
|
112116
|
+
case "fanout": {
|
|
112117
|
+
const items = params?.items;
|
|
112118
|
+
if (!items || !Array.isArray(items) || items.length === 0) {
|
|
112119
|
+
return errorResult(
|
|
112120
|
+
"mutate",
|
|
112121
|
+
"orchestrate",
|
|
112122
|
+
operation,
|
|
112123
|
+
"E_INVALID_INPUT",
|
|
112124
|
+
"items array is required and must be non-empty",
|
|
112125
|
+
startTime
|
|
112126
|
+
);
|
|
112127
|
+
}
|
|
112128
|
+
const result = await orchestrateFanout(items, projectRoot);
|
|
112129
|
+
return wrapResult(result, "mutate", "orchestrate", operation, startTime);
|
|
112130
|
+
}
|
|
111555
112131
|
case "tessera.instantiate": {
|
|
111556
112132
|
const templateId = params?.templateId;
|
|
111557
112133
|
const epicId = params?.epicId;
|
|
@@ -111627,7 +112203,10 @@ var init_orchestrate2 = __esm({
|
|
|
111627
112203
|
"waves",
|
|
111628
112204
|
"bootstrap",
|
|
111629
112205
|
"unblock.opportunities",
|
|
111630
|
-
"tessera.list"
|
|
112206
|
+
"tessera.list",
|
|
112207
|
+
// Wave 7a (T379)
|
|
112208
|
+
"classify",
|
|
112209
|
+
"fanout.status"
|
|
111631
112210
|
],
|
|
111632
112211
|
mutate: [
|
|
111633
112212
|
"start",
|
|
@@ -111636,11 +112215,14 @@ var init_orchestrate2 = __esm({
|
|
|
111636
112215
|
"spawn.execute",
|
|
111637
112216
|
"validate",
|
|
111638
112217
|
"parallel",
|
|
111639
|
-
"tessera.instantiate"
|
|
112218
|
+
"tessera.instantiate",
|
|
112219
|
+
// Wave 7a (T379)
|
|
112220
|
+
"fanout"
|
|
111640
112221
|
]
|
|
111641
112222
|
};
|
|
111642
112223
|
}
|
|
111643
112224
|
};
|
|
112225
|
+
fanoutManifestStore = /* @__PURE__ */ new Map();
|
|
111644
112226
|
}
|
|
111645
112227
|
});
|
|
111646
112228
|
|
|
@@ -121160,7 +121742,7 @@ function registerMemoryBrainCommand(program) {
|
|
|
121160
121742
|
memory.command("find <query>").description("Search BRAIN memory (all tables, or filter by --type pattern|learning)").option("--type <type>", "Filter by memory type: pattern or learning (default: all)").option(
|
|
121161
121743
|
"--pattern-type <type>",
|
|
121162
121744
|
"Filter patterns by type: workflow, blocker, success, failure, optimization"
|
|
121163
|
-
).option("--min-confidence <n>", "Minimum confidence for learnings", parseFloat).option("--actionable", "Only show actionable learnings").option("--limit <n>", "Maximum results", parseInt).option("--json", "Output as JSON").action(async (query, opts) => {
|
|
121745
|
+
).option("--min-confidence <n>", "Minimum confidence for learnings", parseFloat).option("--actionable", "Only show actionable learnings").option("--limit <n>", "Maximum results", parseInt).option("--agent <name>", "Filter observations by agent provenance name (Wave 8 mental models)").option("--json", "Output as JSON").action(async (query, opts) => {
|
|
121164
121746
|
const memType = opts["type"];
|
|
121165
121747
|
if (memType === "pattern") {
|
|
121166
121748
|
await dispatchFromCli(
|
|
@@ -121194,7 +121776,9 @@ function registerMemoryBrainCommand(program) {
|
|
|
121194
121776
|
"find",
|
|
121195
121777
|
{
|
|
121196
121778
|
query,
|
|
121197
|
-
limit: opts["limit"]
|
|
121779
|
+
limit: opts["limit"],
|
|
121780
|
+
// T418: forward agent filter when provided
|
|
121781
|
+
...opts["agent"] !== void 0 && { agent: opts["agent"] }
|
|
121198
121782
|
},
|
|
121199
121783
|
{ command: "memory", operation: "memory.find" }
|
|
121200
121784
|
);
|
|
@@ -121218,14 +121802,18 @@ function registerMemoryBrainCommand(program) {
|
|
|
121218
121802
|
}
|
|
121219
121803
|
cliOutput(result, { command: "memory", operation: "memory.stats" });
|
|
121220
121804
|
});
|
|
121221
|
-
memory.command("observe <text>").description("Save an observation to brain.db").option("--title <title>", "Short title for the observation").
|
|
121805
|
+
memory.command("observe <text>").description("Save an observation to brain.db").option("--title <title>", "Short title for the observation").option(
|
|
121806
|
+
"--agent <name>",
|
|
121807
|
+
"Tag this observation with the producing agent name (Wave 8 mental models)"
|
|
121808
|
+
).action(async (text3, opts) => {
|
|
121222
121809
|
await dispatchFromCli(
|
|
121223
121810
|
"mutate",
|
|
121224
121811
|
"memory",
|
|
121225
121812
|
"observe",
|
|
121226
121813
|
{
|
|
121227
121814
|
text: text3,
|
|
121228
|
-
title: opts["title"]
|
|
121815
|
+
title: opts["title"],
|
|
121816
|
+
...opts["agent"] !== void 0 && { agent: opts["agent"] }
|
|
121229
121817
|
},
|
|
121230
121818
|
{ command: "memory", operation: "memory.observe" }
|
|
121231
121819
|
);
|