@cleocode/cleo 2026.3.30 → 2026.3.31

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/mcp/index.js CHANGED
@@ -8584,28 +8584,25 @@ async function ensureInjection(projectRoot) {
8584
8584
  }
8585
8585
  const { getInstalledProviders: getInstalledProviders2, inject, injectAll: injectAll2, buildInjectionContent: buildInjectionContent2 } = caamp;
8586
8586
  const providers = getInstalledProviders2();
8587
- if (providers.length === 0) {
8588
- return {
8589
- action: "skipped",
8590
- path: join26(projectRoot, "AGENTS.md"),
8591
- details: "No AI agent providers detected, skipping injection"
8592
- };
8593
- }
8594
8587
  const actions = [];
8595
- for (const provider of providers) {
8596
- const instructFile = join26(projectRoot, provider.pathProject, provider.instructFile);
8597
- await stripCLEOBlocks(instructFile);
8598
- }
8599
- await stripCLEOBlocks(join26(projectRoot, "AGENTS.md"));
8600
- const removedStale = await removeStaleAgentInjection(projectRoot);
8601
- if (removedStale) {
8602
- actions.push("removed deprecated AGENT-INJECTION.md");
8603
- }
8604
- const injectionContent = buildInjectionContent2({ references: ["@AGENTS.md"] });
8605
- const results = await injectAll2(providers, projectRoot, "project", injectionContent);
8606
- for (const [filePath, action] of results) {
8607
- const fileName = basename3(filePath);
8608
- actions.push(`${fileName} (${action})`);
8588
+ if (providers.length === 0) {
8589
+ actions.push("No providers detected (AGENTS.md created without provider injection)");
8590
+ } else {
8591
+ for (const provider of providers) {
8592
+ const instructFile = join26(projectRoot, provider.pathProject, provider.instructFile);
8593
+ await stripCLEOBlocks(instructFile);
8594
+ }
8595
+ await stripCLEOBlocks(join26(projectRoot, "AGENTS.md"));
8596
+ const removedStale = await removeStaleAgentInjection(projectRoot);
8597
+ if (removedStale) {
8598
+ actions.push("removed deprecated AGENT-INJECTION.md");
8599
+ }
8600
+ const injectionContent = buildInjectionContent2({ references: ["@AGENTS.md"] });
8601
+ const results = await injectAll2(providers, projectRoot, "project", injectionContent);
8602
+ for (const [filePath, action] of results) {
8603
+ const fileName = basename3(filePath);
8604
+ actions.push(`${fileName} (${action})`);
8605
+ }
8609
8606
  }
8610
8607
  const agentsMdPath = join26(projectRoot, "AGENTS.md");
8611
8608
  const agentsMdLines = ["@~/.cleo/templates/CLEO-INJECTION.md"];
@@ -14961,7 +14958,7 @@ async function loadCompletionEnforcement(cwd) {
14961
14958
  const lifecycleModeRaw = await getRawConfigValue("lifecycle.mode", cwd);
14962
14959
  const acceptanceMode = modeRaw === "off" || modeRaw === "warn" || modeRaw === "block" ? modeRaw : "warn";
14963
14960
  const acceptanceRequiredForPriorities = Array.isArray(prioritiesRaw) ? prioritiesRaw.filter((p) => typeof p === "string") : ["critical", "high"];
14964
- const verificationEnabled = verificationEnabledRaw !== false;
14961
+ const verificationEnabled = verificationEnabledRaw === true;
14965
14962
  const verificationRequiredGates = Array.isArray(verificationRequiredGatesRaw) ? verificationRequiredGatesRaw.filter((g) => typeof g === "string").filter(isVerificationGate) : DEFAULT_VERIFICATION_REQUIRED_GATES;
14966
14963
  const verificationMaxRounds = typeof verificationMaxRoundsRaw === "number" && Number.isInteger(verificationMaxRoundsRaw) ? verificationMaxRoundsRaw : 5;
14967
14964
  const lifecycleMode = lifecycleModeRaw === "strict" || lifecycleModeRaw === "warn" || lifecycleModeRaw === "advisory" || lifecycleModeRaw === "none" || lifecycleModeRaw === "off" ? lifecycleModeRaw : "off";
@@ -22676,6 +22673,14 @@ async function initProject(opts = {}) {
22676
22673
  } catch (err) {
22677
22674
  warnings.push(`Project detection failed: ${err instanceof Error ? err.message : String(err)}`);
22678
22675
  }
22676
+ try {
22677
+ const bridgeResult = await writeMemoryBridge(projRoot);
22678
+ if (bridgeResult.written) {
22679
+ created.push("memory-bridge.md");
22680
+ }
22681
+ } catch (err) {
22682
+ warnings.push(`Memory bridge: ${err instanceof Error ? err.message : String(err)}`);
22683
+ }
22679
22684
  try {
22680
22685
  const injectionResult = await ensureInjection(projRoot);
22681
22686
  if (injectionResult.action !== "skipped") {
@@ -22729,14 +22734,6 @@ async function initProject(opts = {}) {
22729
22734
  } catch (err) {
22730
22735
  warnings.push(`Adapter discovery: ${err instanceof Error ? err.message : String(err)}`);
22731
22736
  }
22732
- try {
22733
- const bridgeResult = await writeMemoryBridge(projRoot);
22734
- if (bridgeResult.written) {
22735
- created.push("memory-bridge.md");
22736
- }
22737
- } catch (err) {
22738
- warnings.push(`Memory bridge: ${err instanceof Error ? err.message : String(err)}`);
22739
- }
22740
22737
  const rootGitignoreResult = await removeCleoFromRootGitignore(projRoot);
22741
22738
  if (rootGitignoreResult.removed) {
22742
22739
  warnings.push(
@@ -24836,6 +24833,7 @@ function injectContext(protocolType, params, projectRoot) {
24836
24833
  // src/dispatch/engines/session-engine.ts
24837
24834
  init_handoff();
24838
24835
  init_sessions();
24836
+ init_sessions();
24839
24837
 
24840
24838
  // src/core/sessions/session-id.ts
24841
24839
  import { randomBytes as randomBytes9 } from "node:crypto";
@@ -25125,29 +25123,31 @@ async function sessionStart(projectRoot, params) {
25125
25123
  try {
25126
25124
  let accessor = await getAccessor(projectRoot);
25127
25125
  let taskData = await accessor.loadTaskFile();
25126
+ let scope;
25127
+ try {
25128
+ scope = parseScope2(params.scope);
25129
+ } catch (err) {
25130
+ return engineError("E_INVALID_INPUT", err instanceof Error ? err.message : "Invalid scope");
25131
+ }
25132
+ if (scope.type !== "global") {
25133
+ const rootTask = taskData.tasks?.find((t) => t.id === scope.rootTaskId);
25134
+ if (!rootTask) {
25135
+ return engineError("E_NOT_FOUND", `Root task '${scope.rootTaskId}' not found`);
25136
+ }
25137
+ }
25128
25138
  const activeSessionId = taskData._meta?.activeSession;
25129
25139
  if (activeSessionId) {
25130
25140
  await sessionEnd(projectRoot);
25131
25141
  accessor = await getAccessor(projectRoot);
25132
25142
  taskData = await accessor.loadTaskFile();
25133
25143
  }
25134
- const scopeParts = params.scope.split(":");
25135
- const scopeType = scopeParts[0] || "task";
25136
- const rootTaskId = scopeParts[1] || "";
25137
- if (!rootTaskId) {
25138
- return engineError("E_INVALID_INPUT", "Scope must include a task ID (e.g., epic:T001)");
25139
- }
25140
- const rootTask = taskData.tasks?.find((t) => t.id === rootTaskId);
25141
- if (!rootTask) {
25142
- return engineError("E_NOT_FOUND", `Root task '${rootTaskId}' not found`);
25143
- }
25144
25144
  const now2 = (/* @__PURE__ */ new Date()).toISOString();
25145
25145
  const sessionId = generateSessionId2();
25146
25146
  let previousSessionId = null;
25147
25147
  {
25148
25148
  const sessions2 = await accessor.loadSessions();
25149
25149
  const sameScope = sessions2.filter(
25150
- (s) => s.status === "ended" && s.endedAt && s.scope?.rootTaskId === rootTaskId && s.scope?.type === scopeType
25150
+ (s) => s.status === "ended" && s.endedAt && s.scope?.type === scope.type && (scope.type === "global" || s.scope?.rootTaskId === scope.rootTaskId)
25151
25151
  ).sort(
25152
25152
  (a, b) => new Date(b.endedAt).getTime() - new Date(a.endedAt).getTime()
25153
25153
  );
@@ -25156,16 +25156,13 @@ async function sessionStart(projectRoot, params) {
25156
25156
  }
25157
25157
  }
25158
25158
  const agentIdentifier = params.agentIdentifier ?? process.env.CLEO_AGENT_ID ?? null;
25159
- const startingTaskId = params.startTask || (params.autoStart ? rootTaskId : null);
25159
+ const rootTaskId = scope.type !== "global" ? scope.rootTaskId : void 0;
25160
+ const startingTaskId = params.startTask || (params.autoStart && rootTaskId ? rootTaskId : null);
25160
25161
  const newSession = {
25161
25162
  id: sessionId,
25162
25163
  status: "active",
25163
25164
  name: params.name || `session-${sessionId}`,
25164
- scope: {
25165
- type: scopeType,
25166
- rootTaskId,
25167
- includeDescendants: true
25168
- },
25165
+ scope: scope.type === "global" ? { type: "global" } : { type: scope.type, rootTaskId: scope.rootTaskId, includeDescendants: true },
25169
25166
  taskWork: {
25170
25167
  taskId: startingTaskId,
25171
25168
  setAt: now2
@@ -25196,7 +25193,7 @@ async function sessionStart(projectRoot, params) {
25196
25193
  const startingTask = params.startTask;
25197
25194
  if (startingTask) {
25198
25195
  taskData.focus.currentTask = startingTask;
25199
- } else if (params.autoStart) {
25196
+ } else if (params.autoStart && rootTaskId) {
25200
25197
  taskData.focus.currentTask = rootTaskId;
25201
25198
  }
25202
25199
  if (taskData._meta) {