@cleocode/cant 2026.4.85 → 2026.4.87
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/bundle.d.ts +51 -2
- package/dist/bundle.js +260 -1
- package/dist/index.d.ts +4 -3
- package/dist/index.js +4 -1
- package/dist/types.d.ts +100 -0
- package/dist/types.js +26 -0
- package/package.json +4 -4
package/dist/bundle.d.ts
CHANGED
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* ```
|
|
23
23
|
*/
|
|
24
24
|
import type { CantDocumentResult } from './document.js';
|
|
25
|
+
import type { CantAgentV3 } from './types.js';
|
|
25
26
|
/**
|
|
26
27
|
* A single parsed `.cant` document with its source path and diagnostics.
|
|
27
28
|
*
|
|
@@ -80,6 +81,21 @@ export interface AgentEntry {
|
|
|
80
81
|
/** Simplified agent properties (role, tier, prompt, skills, etc.). */
|
|
81
82
|
properties: Record<string, unknown>;
|
|
82
83
|
}
|
|
84
|
+
/**
|
|
85
|
+
* Agent entry extended with a fully-typed {@link CantAgentV3} projection.
|
|
86
|
+
*
|
|
87
|
+
* @remarks
|
|
88
|
+
* T889 Wave 1 (W1-2) surface. `typed` is `null` when the entry could not be
|
|
89
|
+
* mapped to the v3 shape (for example, the AST kind is not `agent` or required
|
|
90
|
+
* fields are missing). When `typed` is present, the entry satisfies the
|
|
91
|
+
* {@link isCantAgentV3} structural guard and carries v1/v2-backward-compatible
|
|
92
|
+
* defaults (`tier: 'mid'`, `contextSources: []`, etc.) merged on top of any
|
|
93
|
+
* values discovered in the `.cant` source.
|
|
94
|
+
*/
|
|
95
|
+
export interface TypedAgentEntry extends AgentEntry {
|
|
96
|
+
/** Typed v3 projection of this agent entry, or `null` when mapping failed. */
|
|
97
|
+
typed: CantAgentV3 | null;
|
|
98
|
+
}
|
|
83
99
|
/**
|
|
84
100
|
* A team declaration extracted from a compiled `.cant` file.
|
|
85
101
|
*
|
|
@@ -123,8 +139,17 @@ export interface ToolEntry {
|
|
|
123
139
|
export interface CompiledBundle {
|
|
124
140
|
/** All successfully parsed documents, keyed by source path. */
|
|
125
141
|
documents: Map<string, ParsedCantDocument>;
|
|
126
|
-
/**
|
|
127
|
-
|
|
142
|
+
/**
|
|
143
|
+
* Agents found across all documents.
|
|
144
|
+
*
|
|
145
|
+
* @remarks
|
|
146
|
+
* Each entry includes a `typed: CantAgentV3 | null` field that carries
|
|
147
|
+
* the fully-typed v3 projection (populated via {@link toCantAgentV3}).
|
|
148
|
+
* Older consumers that only read `name`, `sourcePath`, and `properties`
|
|
149
|
+
* remain source-compatible because {@link TypedAgentEntry} extends
|
|
150
|
+
* {@link AgentEntry}.
|
|
151
|
+
*/
|
|
152
|
+
agents: TypedAgentEntry[];
|
|
128
153
|
/** Teams found across all documents. */
|
|
129
154
|
teams: TeamEntry[];
|
|
130
155
|
/** Tools found across all documents. */
|
|
@@ -136,6 +161,30 @@ export interface CompiledBundle {
|
|
|
136
161
|
/** Render the compiled bundle as a system prompt addendum. */
|
|
137
162
|
renderSystemPrompt(): string;
|
|
138
163
|
}
|
|
164
|
+
/**
|
|
165
|
+
* Project an {@link AgentEntry} into the fully-typed {@link CantAgentV3}
|
|
166
|
+
* surface, filling v1/v2-backward-compatible defaults for fields the source
|
|
167
|
+
* `.cant` file omits.
|
|
168
|
+
*
|
|
169
|
+
* @remarks
|
|
170
|
+
* Defaults applied when the source file does not declare them:
|
|
171
|
+
*
|
|
172
|
+
* - `tier`: `'mid'`
|
|
173
|
+
* - `contextSources`: `[]`
|
|
174
|
+
* - `onOverflow`: `'escalate_tier'`
|
|
175
|
+
* - `mentalModelRef`: `null`
|
|
176
|
+
* - `contracts`: `{ requires: [], ensures: [] }`
|
|
177
|
+
*
|
|
178
|
+
* Returns `null` when `entry.name` is empty (the AST kind wasn't `agent` or
|
|
179
|
+
* the name field was missing), so callers can distinguish "mapped" from
|
|
180
|
+
* "not an agent".
|
|
181
|
+
*
|
|
182
|
+
* @param entry - The {@link AgentEntry} extracted by {@link compileBundle}.
|
|
183
|
+
* @param sourcePath - Absolute path to the source `.cant` file (used to
|
|
184
|
+
* populate {@link CantAgentV3.sourcePath}).
|
|
185
|
+
* @returns A {@link CantAgentV3} projection, or `null` when mapping fails.
|
|
186
|
+
*/
|
|
187
|
+
export declare function toCantAgentV3(entry: AgentEntry, sourcePath: string): CantAgentV3 | null;
|
|
139
188
|
/**
|
|
140
189
|
* Compile a list of `.cant` files into a unified {@link CompiledBundle}.
|
|
141
190
|
*
|
package/dist/bundle.js
CHANGED
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
* ```
|
|
24
24
|
*/
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.toCantAgentV3 = toCantAgentV3;
|
|
26
27
|
exports.compileBundle = compileBundle;
|
|
27
28
|
const document_js_1 = require("./document.js");
|
|
28
29
|
/**
|
|
@@ -121,6 +122,253 @@ function extractAgents(doc, sourcePath) {
|
|
|
121
122
|
}
|
|
122
123
|
return agents;
|
|
123
124
|
}
|
|
125
|
+
/** Valid {@link CantTier} string values. */
|
|
126
|
+
const VALID_TIERS = ['low', 'mid', 'high'];
|
|
127
|
+
/** Valid {@link CantOverflowStrategy} string values. */
|
|
128
|
+
const VALID_OVERFLOW = ['escalate_tier', 'fail'];
|
|
129
|
+
/**
|
|
130
|
+
* Coerce a simplified AST value to a plain string, or `undefined` if the value
|
|
131
|
+
* cannot be safely represented as one. Accepts raw strings, numbers, and the
|
|
132
|
+
* stringified form of booleans; other shapes (objects, arrays) return
|
|
133
|
+
* `undefined`.
|
|
134
|
+
*/
|
|
135
|
+
function coerceString(value) {
|
|
136
|
+
if (typeof value === 'string')
|
|
137
|
+
return value;
|
|
138
|
+
if (typeof value === 'number' || typeof value === 'boolean')
|
|
139
|
+
return String(value);
|
|
140
|
+
return undefined;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Coerce a simplified AST value to an array of strings. Returns an empty array
|
|
144
|
+
* for non-array inputs. Array members are coerced via {@link coerceString} and
|
|
145
|
+
* dropped if they cannot be represented as strings.
|
|
146
|
+
*/
|
|
147
|
+
function coerceStringArray(value) {
|
|
148
|
+
if (!Array.isArray(value))
|
|
149
|
+
return [];
|
|
150
|
+
const out = [];
|
|
151
|
+
for (const item of value) {
|
|
152
|
+
const s = coerceString(item);
|
|
153
|
+
if (typeof s === 'string')
|
|
154
|
+
out.push(s);
|
|
155
|
+
}
|
|
156
|
+
return out;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Map the raw `permissions` property (either a domain-access record or the
|
|
160
|
+
* tool-permissions scalar map) to the flat `Record<string, string>` required
|
|
161
|
+
* by {@link CantAgentV3}. Array access lists are joined with `, ` so downstream
|
|
162
|
+
* consumers keep the v1/v2 "tasks: read, write" wire format.
|
|
163
|
+
*/
|
|
164
|
+
function extractV3Permissions(value) {
|
|
165
|
+
const result = {};
|
|
166
|
+
if (typeof value !== 'object' || value === null)
|
|
167
|
+
return result;
|
|
168
|
+
const rec = value;
|
|
169
|
+
for (const [domain, access] of Object.entries(rec)) {
|
|
170
|
+
if (Array.isArray(access)) {
|
|
171
|
+
const parts = coerceStringArray(access);
|
|
172
|
+
if (parts.length > 0)
|
|
173
|
+
result[domain] = parts.join(', ');
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
const s = coerceString(access);
|
|
177
|
+
if (typeof s === 'string')
|
|
178
|
+
result[domain] = s;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Map the raw `contracts` property to a {@link CantContractBlock}.
|
|
185
|
+
*
|
|
186
|
+
* @remarks
|
|
187
|
+
* The Wave 0 grammar does not yet recognize `contracts:` blocks, so today
|
|
188
|
+
* this helper returns `null` unless the property is already shaped as
|
|
189
|
+
* `{ requires: string[], ensures: string[] }`. When the grammar adds the
|
|
190
|
+
* block, this helper will round-trip the richer shape without breaking
|
|
191
|
+
* existing callers.
|
|
192
|
+
*/
|
|
193
|
+
function extractContracts(value) {
|
|
194
|
+
const empty = { requires: [], ensures: [] };
|
|
195
|
+
if (typeof value !== 'object' || value === null)
|
|
196
|
+
return empty;
|
|
197
|
+
const rec = value;
|
|
198
|
+
const toClauses = (raw) => {
|
|
199
|
+
if (!Array.isArray(raw))
|
|
200
|
+
return [];
|
|
201
|
+
const out = [];
|
|
202
|
+
for (const item of raw) {
|
|
203
|
+
const text = coerceString(item);
|
|
204
|
+
if (typeof text === 'string' && text.length > 0)
|
|
205
|
+
out.push({ text });
|
|
206
|
+
}
|
|
207
|
+
return out;
|
|
208
|
+
};
|
|
209
|
+
return {
|
|
210
|
+
requires: toClauses(rec['requires']),
|
|
211
|
+
ensures: toClauses(rec['ensures']),
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Map the raw `context_sources` property value to an array of
|
|
216
|
+
* {@link CantContextSourceDef}. Supports the list form
|
|
217
|
+
* `[{source, query, max_entries}]` today; dict form (`patterns: {...}`) is
|
|
218
|
+
* flattened by the Wave 0 parser into sibling properties and therefore
|
|
219
|
+
* requires a follow-up grammar pass to reconstruct. Returns an empty array
|
|
220
|
+
* when the value is absent, malformed, or dict-flattened.
|
|
221
|
+
*/
|
|
222
|
+
function extractContextSources(value) {
|
|
223
|
+
if (!Array.isArray(value))
|
|
224
|
+
return [];
|
|
225
|
+
const out = [];
|
|
226
|
+
for (const item of value) {
|
|
227
|
+
if (typeof item !== 'object' || item === null)
|
|
228
|
+
continue;
|
|
229
|
+
const rec = item;
|
|
230
|
+
const source = coerceString(rec['source']);
|
|
231
|
+
const query = coerceString(rec['query']);
|
|
232
|
+
const maxRaw = rec['maxEntries'] ?? rec['max_entries'] ?? rec['max'];
|
|
233
|
+
const maxEntries = typeof maxRaw === 'number'
|
|
234
|
+
? maxRaw
|
|
235
|
+
: typeof maxRaw === 'string'
|
|
236
|
+
? Number.parseInt(maxRaw, 10)
|
|
237
|
+
: Number.NaN;
|
|
238
|
+
if (typeof source === 'string' &&
|
|
239
|
+
typeof query === 'string' &&
|
|
240
|
+
Number.isFinite(maxEntries) &&
|
|
241
|
+
maxEntries > 0) {
|
|
242
|
+
out.push({ source, query, maxEntries });
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return out;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Project an {@link AgentEntry} into the fully-typed {@link CantAgentV3}
|
|
249
|
+
* surface, filling v1/v2-backward-compatible defaults for fields the source
|
|
250
|
+
* `.cant` file omits.
|
|
251
|
+
*
|
|
252
|
+
* @remarks
|
|
253
|
+
* Defaults applied when the source file does not declare them:
|
|
254
|
+
*
|
|
255
|
+
* - `tier`: `'mid'`
|
|
256
|
+
* - `contextSources`: `[]`
|
|
257
|
+
* - `onOverflow`: `'escalate_tier'`
|
|
258
|
+
* - `mentalModelRef`: `null`
|
|
259
|
+
* - `contracts`: `{ requires: [], ensures: [] }`
|
|
260
|
+
*
|
|
261
|
+
* Returns `null` when `entry.name` is empty (the AST kind wasn't `agent` or
|
|
262
|
+
* the name field was missing), so callers can distinguish "mapped" from
|
|
263
|
+
* "not an agent".
|
|
264
|
+
*
|
|
265
|
+
* @param entry - The {@link AgentEntry} extracted by {@link compileBundle}.
|
|
266
|
+
* @param sourcePath - Absolute path to the source `.cant` file (used to
|
|
267
|
+
* populate {@link CantAgentV3.sourcePath}).
|
|
268
|
+
* @returns A {@link CantAgentV3} projection, or `null` when mapping fails.
|
|
269
|
+
*/
|
|
270
|
+
function toCantAgentV3(entry, sourcePath) {
|
|
271
|
+
if (typeof entry.name !== 'string' || entry.name.length === 0)
|
|
272
|
+
return null;
|
|
273
|
+
const props = entry.properties;
|
|
274
|
+
const tierRaw = coerceString(props['tier']);
|
|
275
|
+
const tier = tierRaw !== undefined && VALID_TIERS.includes(tierRaw)
|
|
276
|
+
? tierRaw
|
|
277
|
+
: 'mid';
|
|
278
|
+
const overflowRaw = coerceString(props['on_overflow'] ?? props['onOverflow']);
|
|
279
|
+
const onOverflow = overflowRaw !== undefined && VALID_OVERFLOW.includes(overflowRaw)
|
|
280
|
+
? overflowRaw
|
|
281
|
+
: 'escalate_tier';
|
|
282
|
+
const mentalModelRef = null;
|
|
283
|
+
const version = coerceString(props['version']) ?? '1';
|
|
284
|
+
const role = coerceString(props['role']) ?? '';
|
|
285
|
+
const description = coerceString(props['description']) ?? '';
|
|
286
|
+
const prompt = coerceString(props['prompt']) ?? '';
|
|
287
|
+
const skills = coerceStringArray(props['skills']);
|
|
288
|
+
const permissions = extractV3Permissions(props['permissions']);
|
|
289
|
+
const contextSources = extractContextSources(props['context_sources'] ?? props['contextSources']);
|
|
290
|
+
const contracts = extractContracts(props['contracts']);
|
|
291
|
+
const model = coerceString(props['model']);
|
|
292
|
+
const persistRaw = props['persist'];
|
|
293
|
+
const persist = typeof persistRaw === 'boolean'
|
|
294
|
+
? persistRaw
|
|
295
|
+
: typeof persistRaw === 'string'
|
|
296
|
+
? persistRaw
|
|
297
|
+
: undefined;
|
|
298
|
+
const parent = coerceString(props['parent']);
|
|
299
|
+
const consultWhen = coerceString(props['consult-when'] ?? props['consultWhen']);
|
|
300
|
+
const workers = coerceStringArray(props['workers']);
|
|
301
|
+
const stages = coerceStringArray(props['stages']);
|
|
302
|
+
const deprecatedRaw = props['deprecated'];
|
|
303
|
+
const deprecated = typeof deprecatedRaw === 'boolean' ? deprecatedRaw : undefined;
|
|
304
|
+
const supersededBy = coerceString(props['superseded_by'] ?? props['supersededBy']);
|
|
305
|
+
const typed = {
|
|
306
|
+
name: entry.name,
|
|
307
|
+
sourcePath,
|
|
308
|
+
version,
|
|
309
|
+
role,
|
|
310
|
+
description,
|
|
311
|
+
prompt,
|
|
312
|
+
skills,
|
|
313
|
+
permissions,
|
|
314
|
+
tier,
|
|
315
|
+
contextSources,
|
|
316
|
+
onOverflow,
|
|
317
|
+
mentalModelRef,
|
|
318
|
+
contracts,
|
|
319
|
+
};
|
|
320
|
+
if (model !== undefined)
|
|
321
|
+
typed.model = model;
|
|
322
|
+
if (persist !== undefined)
|
|
323
|
+
typed.persist = persist;
|
|
324
|
+
if (parent !== undefined)
|
|
325
|
+
typed.parent = parent;
|
|
326
|
+
if (consultWhen !== undefined)
|
|
327
|
+
typed.consultWhen = consultWhen;
|
|
328
|
+
if (workers.length > 0)
|
|
329
|
+
typed.workers = workers;
|
|
330
|
+
if (stages.length > 0)
|
|
331
|
+
typed.stages = stages;
|
|
332
|
+
if (deprecated !== undefined)
|
|
333
|
+
typed.deprecated = deprecated;
|
|
334
|
+
if (supersededBy !== undefined)
|
|
335
|
+
typed.supersededBy = supersededBy;
|
|
336
|
+
return typed;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Detect placeholder `TODO` stubs in an agent's behavioral fields.
|
|
340
|
+
*
|
|
341
|
+
* @remarks
|
|
342
|
+
* T889 Wave 1 (W1-4) linter. Emits one {@link BundleDiagnostic} per offending
|
|
343
|
+
* field at severity `'error'` with `ruleId: 'S-TODO-001'`. An agent cannot be
|
|
344
|
+
* spawned while any of its `prompt`, `tone`, or `enforcement` values contain
|
|
345
|
+
* the literal substring `TODO` because the composer would forward placeholder
|
|
346
|
+
* content to the live model. The enclosing `valid` flag on
|
|
347
|
+
* {@link CompiledBundle} flips to `false` when any such diagnostic is raised.
|
|
348
|
+
*
|
|
349
|
+
* @param entry - The {@link AgentEntry} whose raw properties are inspected
|
|
350
|
+
* (not the {@link CantAgentV3} projection, because `tone` and `enforcement`
|
|
351
|
+
* are not part of the typed v3 surface).
|
|
352
|
+
* @param sourcePath - Absolute path to the source `.cant` file for attribution.
|
|
353
|
+
* @returns Zero or more S-TODO-001 diagnostics.
|
|
354
|
+
*/
|
|
355
|
+
function detectTodoStubs(entry, sourcePath) {
|
|
356
|
+
const stubs = [];
|
|
357
|
+
const fields = ['prompt', 'tone', 'enforcement'];
|
|
358
|
+
for (const field of fields) {
|
|
359
|
+
const raw = entry.properties[field];
|
|
360
|
+
const value = coerceString(raw);
|
|
361
|
+
if (value?.includes('TODO')) {
|
|
362
|
+
stubs.push({
|
|
363
|
+
ruleId: 'S-TODO-001',
|
|
364
|
+
message: `Field '${field}' on agent '${entry.name}' contains TODO stub; agent cannot be spawned with placeholder content`,
|
|
365
|
+
severity: 'error',
|
|
366
|
+
sourcePath,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
return stubs;
|
|
371
|
+
}
|
|
124
372
|
/**
|
|
125
373
|
* Extract teams from a parsed document AST.
|
|
126
374
|
*
|
|
@@ -396,7 +644,18 @@ async function compileBundle(filePaths) {
|
|
|
396
644
|
const agents = extractAgents(parseResult.document, filePath);
|
|
397
645
|
const teams = extractTeams(parseResult.document, filePath);
|
|
398
646
|
const tools = extractTools(parseResult.document, filePath);
|
|
399
|
-
|
|
647
|
+
for (const agent of agents) {
|
|
648
|
+
const typed = toCantAgentV3(agent, filePath);
|
|
649
|
+
const typedEntry = { ...agent, typed };
|
|
650
|
+
const todoStubs = detectTodoStubs(agent, filePath);
|
|
651
|
+
if (todoStubs.length > 0) {
|
|
652
|
+
for (const stub of todoStubs) {
|
|
653
|
+
fileDiagnostics.push(stub);
|
|
654
|
+
}
|
|
655
|
+
allValid = false;
|
|
656
|
+
}
|
|
657
|
+
allAgents.push(typedEntry);
|
|
658
|
+
}
|
|
400
659
|
allTeams.push(...teams);
|
|
401
660
|
allTools.push(...tools);
|
|
402
661
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { LAFSEnvelope, LAFSError, LAFSMeta, MVILevel } from '@cleocode/lafs';
|
|
2
|
-
export type { AgentEntry, BundleDiagnostic, CompiledBundle, ParsedCantDocument, TeamEntry, ToolEntry, } from './bundle';
|
|
3
|
-
export { compileBundle } from './bundle';
|
|
2
|
+
export type { AgentEntry, BundleDiagnostic, CompiledBundle, ParsedCantDocument, TeamEntry, ToolEntry, TypedAgentEntry, } from './bundle';
|
|
3
|
+
export { compileBundle, toCantAgentV3 } from './bundle';
|
|
4
4
|
export type { AgentDefinition, ContextProvider, ContextSlice, MentalModelSlice, PathPermissions, SpawnPayload, Tier, } from './composer.js';
|
|
5
5
|
export { composeSpawnPayload, escalateTier, estimateTokens, TIER_CAPS } from './composer.js';
|
|
6
6
|
export { brainContextProvider } from './context-provider-brain.js';
|
|
@@ -16,6 +16,7 @@ export type { NativeDiagnostic, NativeParseDocumentResult, NativeParseError, Nat
|
|
|
16
16
|
export { cantClassifyDirectiveNative, cantExecutePipelineNative, cantExtractAgentProfilesNative, cantParseDocumentNative, cantParseNative, cantValidateDocumentNative, initWasm, isNativeAvailable, isWasmAvailable, } from './native-loader';
|
|
17
17
|
export type { ParsedCANTMessage } from './parse';
|
|
18
18
|
export { initCantParser, parseCANTMessage } from './parse';
|
|
19
|
-
export type { DirectiveType } from './types';
|
|
19
|
+
export type { CantAgentV3, CantContextSourceDef, CantContractBlock, CantContractClause, CantMentalModelRef, CantOverflowStrategy, CantPathPermissions, CantTier, DirectiveType, } from './types';
|
|
20
|
+
export { isCantAgentV3 } from './types';
|
|
20
21
|
export type { MergeResult, WorktreeConfig, WorktreeEntry, WorktreeHandle, WorktreeRequest, } from './worktree.js';
|
|
21
22
|
export { createWorktree, listWorktrees, mergeWorktree, resolveWorktreeRoot, } from './worktree.js';
|
package/dist/index.js
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
// JIT Agent Composer (ULTRAPLAN Wave 5)
|
|
3
3
|
// Wave 7a: BRAIN-backed ContextProvider (T432)
|
|
4
4
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
5
|
-
exports.resolveWorktreeRoot = exports.mergeWorktree = exports.listWorktrees = exports.createWorktree = exports.parseCANTMessage = exports.initCantParser = exports.isWasmAvailable = exports.isNativeAvailable = exports.initWasm = exports.cantValidateDocumentNative = exports.cantParseNative = exports.cantParseDocumentNative = exports.cantExtractAgentProfilesNative = exports.cantExecutePipelineNative = exports.cantClassifyDirectiveNative = exports.showSummary = exports.showDiff = exports.serializeCantDocument = exports.migrateMarkdown = exports.renderMentalModel = exports.harvestObservations = exports.createEmptyModel = exports.consolidate = exports.validateSpawnRequest = exports.ORCHESTRATOR_FORBIDDEN_TOOLS = exports.LEAD_FORBIDDEN_TOOLS = exports.filterToolsForRole = exports.validateDocument = exports.parseDocument = exports.listSections = exports.executePipeline = exports.brainContextProvider = exports.TIER_CAPS = exports.estimateTokens = exports.escalateTier = exports.composeSpawnPayload = exports.compileBundle = void 0;
|
|
5
|
+
exports.resolveWorktreeRoot = exports.mergeWorktree = exports.listWorktrees = exports.createWorktree = exports.isCantAgentV3 = exports.parseCANTMessage = exports.initCantParser = exports.isWasmAvailable = exports.isNativeAvailable = exports.initWasm = exports.cantValidateDocumentNative = exports.cantParseNative = exports.cantParseDocumentNative = exports.cantExtractAgentProfilesNative = exports.cantExecutePipelineNative = exports.cantClassifyDirectiveNative = exports.showSummary = exports.showDiff = exports.serializeCantDocument = exports.migrateMarkdown = exports.renderMentalModel = exports.harvestObservations = exports.createEmptyModel = exports.consolidate = exports.validateSpawnRequest = exports.ORCHESTRATOR_FORBIDDEN_TOOLS = exports.LEAD_FORBIDDEN_TOOLS = exports.filterToolsForRole = exports.validateDocument = exports.parseDocument = exports.listSections = exports.executePipeline = exports.brainContextProvider = exports.TIER_CAPS = exports.estimateTokens = exports.escalateTier = exports.composeSpawnPayload = exports.toCantAgentV3 = exports.compileBundle = void 0;
|
|
6
6
|
// Bundle compiler
|
|
7
7
|
var bundle_1 = require("./bundle");
|
|
8
8
|
Object.defineProperty(exports, "compileBundle", { enumerable: true, get: function () { return bundle_1.compileBundle; } });
|
|
9
|
+
Object.defineProperty(exports, "toCantAgentV3", { enumerable: true, get: function () { return bundle_1.toCantAgentV3; } });
|
|
9
10
|
var composer_js_1 = require("./composer.js");
|
|
10
11
|
Object.defineProperty(exports, "composeSpawnPayload", { enumerable: true, get: function () { return composer_js_1.composeSpawnPayload; } });
|
|
11
12
|
Object.defineProperty(exports, "escalateTier", { enumerable: true, get: function () { return composer_js_1.escalateTier; } });
|
|
@@ -52,6 +53,8 @@ Object.defineProperty(exports, "isWasmAvailable", { enumerable: true, get: funct
|
|
|
52
53
|
var parse_1 = require("./parse");
|
|
53
54
|
Object.defineProperty(exports, "initCantParser", { enumerable: true, get: function () { return parse_1.initCantParser; } });
|
|
54
55
|
Object.defineProperty(exports, "parseCANTMessage", { enumerable: true, get: function () { return parse_1.parseCANTMessage; } });
|
|
56
|
+
var types_1 = require("./types");
|
|
57
|
+
Object.defineProperty(exports, "isCantAgentV3", { enumerable: true, get: function () { return types_1.isCantAgentV3; } });
|
|
55
58
|
// Worktree isolation (ULTRAPLAN Wave 9)
|
|
56
59
|
var worktree_js_1 = require("./worktree.js");
|
|
57
60
|
Object.defineProperty(exports, "createWorktree", { enumerable: true, get: function () { return worktree_js_1.createWorktree; } });
|
package/dist/types.d.ts
CHANGED
|
@@ -8,3 +8,103 @@ export interface ParsedCANTMessage {
|
|
|
8
8
|
header_raw: string;
|
|
9
9
|
body: string;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* A single contract clause — a precondition (requires) or postcondition (ensures)
|
|
13
|
+
* on agent behavior, expressed as OpenProse semiformal text.
|
|
14
|
+
*
|
|
15
|
+
* Syntax in .cant file:
|
|
16
|
+
* contracts:
|
|
17
|
+
* requires:
|
|
18
|
+
* - "Task is in started state before work begins"
|
|
19
|
+
* ensures:
|
|
20
|
+
* - "Output file written to OUTPUT_PATH before return"
|
|
21
|
+
*/
|
|
22
|
+
export interface CantContractClause {
|
|
23
|
+
text: string;
|
|
24
|
+
enforcement?: 'hard' | 'soft';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Paired precondition/postcondition contract block attached to a CANT agent.
|
|
28
|
+
* `requires` clauses MUST hold before agent execution; `ensures` clauses MUST
|
|
29
|
+
* hold on successful return.
|
|
30
|
+
*/
|
|
31
|
+
export interface CantContractBlock {
|
|
32
|
+
requires: CantContractClause[];
|
|
33
|
+
ensures: CantContractClause[];
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Reference to a mental model slice to load into agent context.
|
|
37
|
+
* `scope` selects project-local vs global mental model store; `maxTokens`
|
|
38
|
+
* bounds the rendered slice; `validateOnLoad` enforces schema checks.
|
|
39
|
+
*/
|
|
40
|
+
export interface CantMentalModelRef {
|
|
41
|
+
scope: 'project' | 'global';
|
|
42
|
+
maxTokens: number;
|
|
43
|
+
validateOnLoad: boolean;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Declarative context source binding: a CantContextSourceDef instructs the
|
|
47
|
+
* composer to query `source` with `query` and inject up to `maxEntries`
|
|
48
|
+
* results into the agent's spawn payload context.
|
|
49
|
+
*/
|
|
50
|
+
export interface CantContextSourceDef {
|
|
51
|
+
source: string;
|
|
52
|
+
query: string;
|
|
53
|
+
maxEntries: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Strategy the composer applies when the rendered agent payload exceeds the
|
|
57
|
+
* tier token cap. `escalate_tier` promotes to the next tier; `fail` aborts.
|
|
58
|
+
*/
|
|
59
|
+
export type CantOverflowStrategy = 'escalate_tier' | 'fail';
|
|
60
|
+
/**
|
|
61
|
+
* Agent capability tier. Tier selection drives token budgets, tool
|
|
62
|
+
* allowlists, and hierarchical spawn permissions.
|
|
63
|
+
*/
|
|
64
|
+
export type CantTier = 'low' | 'mid' | 'high';
|
|
65
|
+
/**
|
|
66
|
+
* Filesystem permission ACL for an agent — separate read, write, and execute
|
|
67
|
+
* globs. Paths are evaluated against the spawning project root.
|
|
68
|
+
*/
|
|
69
|
+
export interface CantPathPermissions {
|
|
70
|
+
read?: string[];
|
|
71
|
+
write?: string[];
|
|
72
|
+
execute?: string[];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Fully-typed CANT agent DSL v3 record. Represents the complete parsed shape
|
|
76
|
+
* of an agent declared in a `.cant` file with `kind: agent`. Consumed by the
|
|
77
|
+
* bundle compiler, composer, and spawn pipeline.
|
|
78
|
+
*/
|
|
79
|
+
export interface CantAgentV3 {
|
|
80
|
+
name: string;
|
|
81
|
+
sourcePath: string;
|
|
82
|
+
version: string;
|
|
83
|
+
role: string;
|
|
84
|
+
description: string;
|
|
85
|
+
prompt: string;
|
|
86
|
+
skills: string[];
|
|
87
|
+
permissions: Record<string, string>;
|
|
88
|
+
model?: string;
|
|
89
|
+
persist?: boolean | string;
|
|
90
|
+
parent?: string;
|
|
91
|
+
filePermissions?: CantPathPermissions;
|
|
92
|
+
tier: CantTier;
|
|
93
|
+
contextSources: CantContextSourceDef[];
|
|
94
|
+
onOverflow: CantOverflowStrategy;
|
|
95
|
+
mentalModelRef: CantMentalModelRef | null;
|
|
96
|
+
contracts: CantContractBlock;
|
|
97
|
+
consultWhen?: string;
|
|
98
|
+
workers?: string[];
|
|
99
|
+
stages?: string[];
|
|
100
|
+
tools?: Record<string, string[]>;
|
|
101
|
+
deprecated?: boolean;
|
|
102
|
+
supersededBy?: string;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Structural type guard for `CantAgentV3`. Validates the required surface
|
|
106
|
+
* (name, sourcePath, version, role, description, prompt, skills,
|
|
107
|
+
* permissions, tier, contextSources, contracts). Returns `true` when `x`
|
|
108
|
+
* safely narrows to `CantAgentV3`.
|
|
109
|
+
*/
|
|
110
|
+
export declare function isCantAgentV3(x: unknown): x is CantAgentV3;
|
package/dist/types.js
CHANGED
|
@@ -1,2 +1,28 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isCantAgentV3 = isCantAgentV3;
|
|
4
|
+
/**
|
|
5
|
+
* Structural type guard for `CantAgentV3`. Validates the required surface
|
|
6
|
+
* (name, sourcePath, version, role, description, prompt, skills,
|
|
7
|
+
* permissions, tier, contextSources, contracts). Returns `true` when `x`
|
|
8
|
+
* safely narrows to `CantAgentV3`.
|
|
9
|
+
*/
|
|
10
|
+
function isCantAgentV3(x) {
|
|
11
|
+
if (typeof x !== 'object' || x === null)
|
|
12
|
+
return false;
|
|
13
|
+
const o = x;
|
|
14
|
+
return (typeof o.name === 'string' &&
|
|
15
|
+
typeof o.sourcePath === 'string' &&
|
|
16
|
+
typeof o.version === 'string' &&
|
|
17
|
+
typeof o.role === 'string' &&
|
|
18
|
+
typeof o.description === 'string' &&
|
|
19
|
+
typeof o.prompt === 'string' &&
|
|
20
|
+
Array.isArray(o.skills) &&
|
|
21
|
+
typeof o.permissions === 'object' &&
|
|
22
|
+
o.permissions !== null &&
|
|
23
|
+
typeof o.tier === 'string' &&
|
|
24
|
+
['low', 'mid', 'high'].includes(o.tier) &&
|
|
25
|
+
Array.isArray(o.contextSources) &&
|
|
26
|
+
typeof o.contracts === 'object' &&
|
|
27
|
+
o.contracts !== null);
|
|
28
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/cant",
|
|
3
|
-
"version": "2026.4.
|
|
3
|
+
"version": "2026.4.87",
|
|
4
4
|
"description": "CANT protocol parser and runtime for CLEO — wraps cant-core via napi-rs",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
"napi/"
|
|
10
10
|
],
|
|
11
11
|
"dependencies": {
|
|
12
|
-
"@cleocode/contracts": "2026.4.
|
|
13
|
-
"@cleocode/lafs": "2026.4.
|
|
14
|
-
"@cleocode/core": "2026.4.
|
|
12
|
+
"@cleocode/contracts": "2026.4.87",
|
|
13
|
+
"@cleocode/lafs": "2026.4.87",
|
|
14
|
+
"@cleocode/core": "2026.4.87"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
17
|
"typescript": "^6.0.2",
|