@cleocode/cleo 2026.4.109 → 2026.4.111

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
@@ -698,6 +698,13 @@ var init_validate = __esm({
698
698
  }
699
699
  });
700
700
 
701
+ // packages/contracts/src/operations/variable-substitution.ts
702
+ var init_variable_substitution = __esm({
703
+ "packages/contracts/src/operations/variable-substitution.ts"() {
704
+ "use strict";
705
+ }
706
+ });
707
+
701
708
  // packages/contracts/src/operations/index.ts
702
709
  var init_operations = __esm({
703
710
  "packages/contracts/src/operations/index.ts"() {
@@ -717,6 +724,7 @@ var init_operations = __esm({
717
724
  init_system();
718
725
  init_tasks();
719
726
  init_validate();
727
+ init_variable_substitution();
720
728
  }
721
729
  });
722
730
 
@@ -9374,7 +9382,14 @@ async function orchestrateSpawnExecute(taskId, adapterId, protocolType, projectR
9374
9382
  }
9375
9383
  };
9376
9384
  }
9377
- const rawPrompt = payload.prompt;
9385
+ const templateSubstitution = await applyCantBodySubstitution(payload, cwd, {
9386
+ taskId,
9387
+ sessionId: activeSessionId,
9388
+ protocol: protocolType ?? payload.meta.protocol
9389
+ });
9390
+ const rawPrompt = templateSubstitution.resolvedBody ? `${templateSubstitution.resolvedBody}
9391
+
9392
+ ${payload.prompt}` : payload.prompt;
9378
9393
  const cleoSpawnContext = {
9379
9394
  taskId: payload.taskId,
9380
9395
  protocol: protocolType || payload.meta.protocol,
@@ -9446,7 +9461,17 @@ async function orchestrateSpawnExecute(taskId, adapterId, protocolType, projectR
9446
9461
  timing: result.timing,
9447
9462
  tier: tier ?? null,
9448
9463
  atomicity: payload.atomicity,
9449
- meta: payload.meta,
9464
+ meta: {
9465
+ ...payload.meta,
9466
+ // T1238 — variable substitution diagnostics surfaced for audit.
9467
+ templateSubstitution: {
9468
+ applied: templateSubstitution.applied,
9469
+ resolvedCount: templateSubstitution.resolvedCount,
9470
+ missing: templateSubstitution.missing,
9471
+ projectContextLoaded: templateSubstitution.projectContextLoaded,
9472
+ ...templateSubstitution.reason !== void 0 ? { reason: templateSubstitution.reason } : {}
9473
+ }
9474
+ },
9450
9475
  agentId: payload.agentId,
9451
9476
  role: payload.role,
9452
9477
  harnessHint: payload.harnessHint
@@ -9463,6 +9488,58 @@ async function orchestrateSpawnExecute(taskId, adapterId, protocolType, projectR
9463
9488
  };
9464
9489
  }
9465
9490
  }
9491
+ async function applyCantBodySubstitution(payload, cwd, ctx) {
9492
+ const empty = {
9493
+ applied: false,
9494
+ resolvedCount: 0,
9495
+ missing: [],
9496
+ projectContextLoaded: false,
9497
+ resolvedBody: null
9498
+ };
9499
+ const cantPath = payload.resolvedAgent?.cantPath;
9500
+ if (!cantPath) {
9501
+ return { ...empty, reason: "resolved agent has no cantPath" };
9502
+ }
9503
+ const [{ existsSync: existsSync12, readFileSync: readFileSync15 }, { substituteCantAgentBody }] = await Promise.all([
9504
+ import("node:fs"),
9505
+ import("@cleocode/core/internal")
9506
+ ]);
9507
+ if (!existsSync12(cantPath)) {
9508
+ return { ...empty, reason: `cant file not found at ${cantPath}` };
9509
+ }
9510
+ let body;
9511
+ try {
9512
+ body = readFileSync15(cantPath, "utf-8");
9513
+ } catch (err) {
9514
+ return {
9515
+ ...empty,
9516
+ reason: `Failed to read cant body: ${err instanceof Error ? err.message : String(err)}`
9517
+ };
9518
+ }
9519
+ const sessionContext = {
9520
+ taskId: ctx.taskId,
9521
+ sessionId: ctx.sessionId,
9522
+ protocol: ctx.protocol,
9523
+ agentId: payload.agentId,
9524
+ role: payload.role,
9525
+ tier: payload.tier,
9526
+ harnessHint: payload.harnessHint
9527
+ };
9528
+ if (payload.taskId) sessionContext.spawnTaskId = payload.taskId;
9529
+ const result = substituteCantAgentBody(body, {
9530
+ projectRoot: cwd,
9531
+ sessionContext,
9532
+ env: process.env,
9533
+ options: { strict: false, warnMissing: false }
9534
+ });
9535
+ return {
9536
+ applied: result.resolved.length > 0,
9537
+ resolvedCount: result.resolved.length,
9538
+ missing: result.missing,
9539
+ projectContextLoaded: result.projectContextLoaded,
9540
+ resolvedBody: result.text
9541
+ };
9542
+ }
9466
9543
  async function openSignaldockDbForComposer() {
9467
9544
  await ensureGlobalSignaldockDb();
9468
9545
  const dbPath = getGlobalSignaldockDbPath();