@cleocode/cleo 2026.4.15 → 2026.4.16
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/cleo",
|
|
3
|
-
"version": "2026.4.
|
|
3
|
+
"version": "2026.4.16",
|
|
4
4
|
"description": "CLEO CLI — the assembled product consuming @cleocode/core",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/cli/index.js",
|
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"citty": "^0.2.1",
|
|
16
|
-
"@cleocode/caamp": "2026.4.
|
|
17
|
-
"@cleocode/cant": "2026.4.
|
|
18
|
-
"@cleocode/
|
|
19
|
-
"@cleocode/
|
|
20
|
-
"@cleocode/
|
|
21
|
-
"@cleocode/runtime": "2026.4.
|
|
16
|
+
"@cleocode/caamp": "2026.4.16",
|
|
17
|
+
"@cleocode/cant": "2026.4.16",
|
|
18
|
+
"@cleocode/contracts": "2026.4.16",
|
|
19
|
+
"@cleocode/lafs": "2026.4.16",
|
|
20
|
+
"@cleocode/core": "2026.4.16",
|
|
21
|
+
"@cleocode/runtime": "2026.4.16"
|
|
22
22
|
},
|
|
23
23
|
"engines": {
|
|
24
24
|
"node": ">=24.0.0"
|
|
@@ -11,11 +11,19 @@
|
|
|
11
11
|
* of all declared agents, teams, and tools without hand-authored
|
|
12
12
|
* protocol text.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
14
|
+
* Wave 2 scope:
|
|
15
15
|
* - Scans project tier only: `<cwd>/.cleo/cant/` (recursive)
|
|
16
16
|
* - Three-tier resolution (global, user, project) is Wave 5
|
|
17
17
|
* - Prompt strategy: APPEND (per ULTRAPLAN L6, never replace)
|
|
18
18
|
*
|
|
19
|
+
* Wave 8 additions (T420):
|
|
20
|
+
* - validate-on-load mental-model injection
|
|
21
|
+
* - When the spawned agent's CANT definition has a `mentalModel` block,
|
|
22
|
+
* fetches prior mental-model observations via memoryFind and injects
|
|
23
|
+
* them into the Pi system prompt with VALIDATE_ON_LOAD_PREAMBLE.
|
|
24
|
+
* - Exports `VALIDATE_ON_LOAD_PREAMBLE` and `buildMentalModelInjection`
|
|
25
|
+
* for testability (T421).
|
|
26
|
+
*
|
|
19
27
|
* Requirements:
|
|
20
28
|
* - `@cleocode/cant` must be installed (provides `compileBundle`)
|
|
21
29
|
* - Pi coding agent runtime (`@mariozechner/pi-coding-agent`)
|
|
@@ -34,6 +42,69 @@ import type {
|
|
|
34
42
|
ExtensionContext,
|
|
35
43
|
} from "@mariozechner/pi-coding-agent";
|
|
36
44
|
|
|
45
|
+
// ============================================================================
|
|
46
|
+
// T420: validate-on-load constants and pure helpers
|
|
47
|
+
// ============================================================================
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Preamble text injected into the Pi system prompt when an agent has a
|
|
51
|
+
* `mental_model:` CANT block. The agent MUST re-evaluate each observation
|
|
52
|
+
* against the current project state before acting.
|
|
53
|
+
*
|
|
54
|
+
* Exported so empirical tests (T421) can assert on its presence.
|
|
55
|
+
*/
|
|
56
|
+
export const VALIDATE_ON_LOAD_PREAMBLE =
|
|
57
|
+
"===== MENTAL MODEL (validate-on-load) =====\n" +
|
|
58
|
+
"These are your prior observations, patterns, and learnings for this project.\n" +
|
|
59
|
+
"Before acting, you MUST re-evaluate each entry against current project state.\n" +
|
|
60
|
+
"If an entry is stale, note it and proceed with fresh understanding.";
|
|
61
|
+
|
|
62
|
+
/** Minimal observation shape returned by memoryFind / searchBrainCompact. */
|
|
63
|
+
export interface MentalModelObservation {
|
|
64
|
+
id: string;
|
|
65
|
+
type: string;
|
|
66
|
+
title: string;
|
|
67
|
+
date?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Build the validate-on-load mental-model injection string.
|
|
72
|
+
*
|
|
73
|
+
* Pure function — no I/O, safe to call in tests without a real DB.
|
|
74
|
+
*
|
|
75
|
+
* @param agentName - Name of the spawned agent (used in the header line).
|
|
76
|
+
* @param observations - Prior mental-model observations to list.
|
|
77
|
+
* @returns System-prompt block containing the preamble and numbered observations,
|
|
78
|
+
* or an empty string when `observations` is empty.
|
|
79
|
+
*/
|
|
80
|
+
export function buildMentalModelInjection(
|
|
81
|
+
agentName: string,
|
|
82
|
+
observations: MentalModelObservation[],
|
|
83
|
+
): string {
|
|
84
|
+
if (observations.length === 0) return "";
|
|
85
|
+
|
|
86
|
+
const lines: string[] = [
|
|
87
|
+
"",
|
|
88
|
+
`// Agent: ${agentName}`,
|
|
89
|
+
VALIDATE_ON_LOAD_PREAMBLE,
|
|
90
|
+
"",
|
|
91
|
+
];
|
|
92
|
+
|
|
93
|
+
for (let i = 0; i < observations.length; i++) {
|
|
94
|
+
const obs = observations[i];
|
|
95
|
+
const datePart = obs.date ? ` [${obs.date}]` : "";
|
|
96
|
+
lines.push(`${i + 1}. [${obs.id}] (${obs.type})${datePart}: ${obs.title}`);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
lines.push("===== END MENTAL MODEL =====");
|
|
100
|
+
|
|
101
|
+
return lines.join("\n");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ============================================================================
|
|
105
|
+
// Internal state
|
|
106
|
+
// ============================================================================
|
|
107
|
+
|
|
37
108
|
/** Cached system prompt addendum from the last session_start compilation. */
|
|
38
109
|
let bundlePrompt: string | null = null;
|
|
39
110
|
|
|
@@ -63,12 +134,80 @@ function discoverCantFiles(dir: string): string[] {
|
|
|
63
134
|
}
|
|
64
135
|
}
|
|
65
136
|
|
|
137
|
+
// ============================================================================
|
|
138
|
+
// T420: mental-model injection helper (async, calls memoryFind)
|
|
139
|
+
// ============================================================================
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Fetch prior mental-model observations for an agent and build the
|
|
143
|
+
* validate-on-load injection block.
|
|
144
|
+
*
|
|
145
|
+
* Called in `before_agent_start` when the agent has a `mentalModel` CANT block.
|
|
146
|
+
* Best-effort: returns empty string on any failure so Pi is never blocked.
|
|
147
|
+
*
|
|
148
|
+
* @param agentName - Name of the spawned agent.
|
|
149
|
+
* @param projectRoot - Project root directory for brain.db access.
|
|
150
|
+
* @returns The validate-on-load system-prompt block, or "" on failure/empty.
|
|
151
|
+
*/
|
|
152
|
+
async function fetchMentalModelInjection(
|
|
153
|
+
agentName: string,
|
|
154
|
+
projectRoot: string,
|
|
155
|
+
): Promise<string> {
|
|
156
|
+
try {
|
|
157
|
+
// Lazy import: @cleocode/core may not be present in all environments.
|
|
158
|
+
// memoryFind is the engine-compat wrapper (T418) that accepts `agent`.
|
|
159
|
+
const coreModule = await import("@cleocode/core") as {
|
|
160
|
+
memoryFind?: (
|
|
161
|
+
params: {
|
|
162
|
+
query: string;
|
|
163
|
+
agent?: string;
|
|
164
|
+
limit?: number;
|
|
165
|
+
tables?: string[];
|
|
166
|
+
},
|
|
167
|
+
projectRoot?: string,
|
|
168
|
+
) => Promise<{
|
|
169
|
+
success: boolean;
|
|
170
|
+
data?: {
|
|
171
|
+
results?: MentalModelObservation[];
|
|
172
|
+
};
|
|
173
|
+
}>;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
if (typeof coreModule.memoryFind !== "function") return "";
|
|
177
|
+
|
|
178
|
+
// Fetch the 10 most recent mental-model observations for this agent.
|
|
179
|
+
// Use tables filter to avoid decisions/patterns/learnings which are
|
|
180
|
+
// not agent-scoped in the current schema.
|
|
181
|
+
const result = await coreModule.memoryFind(
|
|
182
|
+
{
|
|
183
|
+
query: agentName,
|
|
184
|
+
agent: agentName,
|
|
185
|
+
limit: 10,
|
|
186
|
+
tables: ["observations"],
|
|
187
|
+
},
|
|
188
|
+
projectRoot,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
if (!result.success || !result.data?.results?.length) return "";
|
|
192
|
+
|
|
193
|
+
return buildMentalModelInjection(agentName, result.data.results);
|
|
194
|
+
} catch {
|
|
195
|
+
// Best-effort — never crash Pi
|
|
196
|
+
return "";
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// ============================================================================
|
|
201
|
+
// Pi extension factory
|
|
202
|
+
// ============================================================================
|
|
203
|
+
|
|
66
204
|
/**
|
|
67
205
|
* Pi extension factory for the CleoOS CANT bridge.
|
|
68
206
|
*
|
|
69
207
|
* Registers event handlers for `session_start` (compile `.cant` files)
|
|
70
|
-
* and `before_agent_start` (append compiled bundle
|
|
71
|
-
* Also registers a `/cant:bundle-info` command for
|
|
208
|
+
* and `before_agent_start` (append compiled bundle + mental-model injection
|
|
209
|
+
* to system prompt). Also registers a `/cant:bundle-info` command for
|
|
210
|
+
* introspection.
|
|
72
211
|
*
|
|
73
212
|
* @param pi - The Pi extension API instance.
|
|
74
213
|
*/
|
|
@@ -141,16 +280,58 @@ export default function (pi: ExtensionAPI): void {
|
|
|
141
280
|
}
|
|
142
281
|
});
|
|
143
282
|
|
|
144
|
-
// before_agent_start: APPEND compiled bundle prompt
|
|
145
|
-
|
|
146
|
-
|
|
283
|
+
// before_agent_start: APPEND compiled bundle prompt + mental-model injection
|
|
284
|
+
// to system prompt (per ULTRAPLAN L6, never replace)
|
|
285
|
+
pi.on(
|
|
286
|
+
"before_agent_start",
|
|
287
|
+
async (
|
|
288
|
+
event: {
|
|
289
|
+
systemPrompt?: string;
|
|
290
|
+
agentName?: string;
|
|
291
|
+
/** T420: agent CANT definition, if resolved by Pi runtime. */
|
|
292
|
+
agentDef?: {
|
|
293
|
+
/** mentalModel block presence signals validate-on-load injection. */
|
|
294
|
+
mentalModel?: unknown;
|
|
295
|
+
};
|
|
296
|
+
/** Project root injected by Pi when available. */
|
|
297
|
+
projectRoot?: string;
|
|
298
|
+
},
|
|
299
|
+
ctx?: ExtensionContext,
|
|
300
|
+
) => {
|
|
301
|
+
const existingPrompt = event.systemPrompt ?? "";
|
|
302
|
+
let appendix = "";
|
|
147
303
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
304
|
+
// APPEND CANT bundle prompt
|
|
305
|
+
if (bundlePrompt) {
|
|
306
|
+
appendix += "\n\n" + bundlePrompt;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
// T420: validate-on-load mental-model injection.
|
|
310
|
+
// Inject when the agent has a `mentalModel` CANT block.
|
|
311
|
+
const agentName = event.agentName;
|
|
312
|
+
const hasMentalModel =
|
|
313
|
+
agentName !== undefined &&
|
|
314
|
+
agentName !== "" &&
|
|
315
|
+
event.agentDef?.mentalModel !== undefined;
|
|
316
|
+
|
|
317
|
+
if (hasMentalModel && agentName) {
|
|
318
|
+
// Resolve project root: prefer explicit field, fall back to ctx.cwd
|
|
319
|
+
const projectRoot = event.projectRoot ?? ctx?.cwd ?? "";
|
|
320
|
+
if (projectRoot) {
|
|
321
|
+
const mentalModelBlock = await fetchMentalModelInjection(agentName, projectRoot);
|
|
322
|
+
if (mentalModelBlock) {
|
|
323
|
+
appendix += mentalModelBlock;
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
if (!appendix) return {};
|
|
329
|
+
|
|
330
|
+
return {
|
|
331
|
+
systemPrompt: existingPrompt + appendix,
|
|
332
|
+
};
|
|
333
|
+
},
|
|
334
|
+
);
|
|
154
335
|
|
|
155
336
|
// /cant:bundle-info — introspection command
|
|
156
337
|
pi.registerCommand("cant:bundle-info", {
|