@cleocode/cleo 2026.4.72 → 2026.4.73

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
@@ -91183,7 +91183,6 @@ __export(src_exports, {
91183
91183
  });
91184
91184
  var init_src3 = __esm({
91185
91185
  "packages/core/src/index.ts"() {
91186
- "use strict";
91187
91186
  init_src();
91188
91187
  init_adapters();
91189
91188
  init_admin();
@@ -141639,8 +141638,7 @@ function toHistoryEntry(e) {
141639
141638
  }
141640
141639
  async function taskCompleteStrict(projectRoot, taskId, notes, force) {
141641
141640
  try {
141642
- const { loadConfig: loadConfig4 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
141643
- const config2 = await loadConfig4(projectRoot);
141641
+ const config2 = await loadConfig(projectRoot);
141644
141642
  const lifecycleMode = config2.lifecycle?.mode ?? "strict";
141645
141643
  if (lifecycleMode === "strict") {
141646
141644
  const ivtrState = await getIvtrState(taskId, { cwd: projectRoot });
@@ -141727,6 +141725,81 @@ async function taskCompleteStrict(projectRoot, taskId, notes, force) {
141727
141725
  };
141728
141726
  }
141729
141727
  }
141728
+ if (lifecycleMode === "strict" || lifecycleMode === "advisory") {
141729
+ const accessor = await getAccessor(projectRoot);
141730
+ const task = await accessor.loadSingleTask(taskId);
141731
+ if (task?.parentId) {
141732
+ const parent = await accessor.loadSingleTask(task.parentId);
141733
+ if (parent?.type === "epic") {
141734
+ const earlyStages = /* @__PURE__ */ new Set([
141735
+ "research",
141736
+ "consensus",
141737
+ "architecture_decision",
141738
+ "specification",
141739
+ "decomposition"
141740
+ ]);
141741
+ const epicStage = parent.pipelineStage ?? null;
141742
+ if (epicStage && earlyStages.has(epicStage)) {
141743
+ const msg = `Task ${taskId} cannot complete: parent epic ${task.parentId} is still in '${epicStage}' stage. Advance the epic past decomposition before completing children.`;
141744
+ if (lifecycleMode === "strict" && !force) {
141745
+ return engineError("E_LIFECYCLE_GATE_FAILED", msg, {
141746
+ details: {
141747
+ taskId,
141748
+ parentEpicId: task.parentId,
141749
+ epicStage,
141750
+ requiredStages: ["implementation", "validation", "testing", "release"]
141751
+ },
141752
+ fix: `Advance the parent epic via 'cleo lifecycle complete ${task.parentId} ${epicStage}' and then the next stages, or use '--force' to bypass.`
141753
+ });
141754
+ }
141755
+ getLogger("engine:lifecycle").warn(
141756
+ {
141757
+ taskId,
141758
+ parentEpicId: task.parentId,
141759
+ epicStage,
141760
+ mode: lifecycleMode,
141761
+ forced: force === true
141762
+ },
141763
+ lifecycleMode === "advisory" ? `[ADVISORY] parent-epic lifecycle gate: ${msg}` : `[OWNER WARNING] cleo complete --force bypassed parent-epic lifecycle gate: ${msg}`
141764
+ );
141765
+ if (lifecycleMode === "strict" && force === true) {
141766
+ try {
141767
+ const now2 = (/* @__PURE__ */ new Date()).toISOString();
141768
+ if (!task.verification) {
141769
+ task.verification = {
141770
+ round: 0,
141771
+ gates: {},
141772
+ passed: false,
141773
+ lastAgent: null,
141774
+ lastUpdated: null,
141775
+ failureLog: []
141776
+ };
141777
+ }
141778
+ if (!task.verification.failureLog) {
141779
+ task.verification.failureLog = [];
141780
+ }
141781
+ task.verification.failureLog.push({
141782
+ round: task.verification.round,
141783
+ agent: "owner-forced",
141784
+ reason: `OWNER FORCED cleo complete --force \u2014 parent-epic lifecycle gate bypass. Epic ${task.parentId} at stage='${epicStage}'.`,
141785
+ timestamp: now2
141786
+ });
141787
+ task.updatedAt = now2;
141788
+ await accessor.upsertSingleTask(task);
141789
+ } catch {
141790
+ }
141791
+ const innerResult = await taskComplete(projectRoot, taskId, notes);
141792
+ if (!innerResult.success)
141793
+ return innerResult;
141794
+ return {
141795
+ success: true,
141796
+ data: { ...innerResult.data, lifecycleGateBypassed: true }
141797
+ };
141798
+ }
141799
+ }
141800
+ }
141801
+ }
141802
+ }
141730
141803
  return taskComplete(projectRoot, taskId, notes);
141731
141804
  } catch (err2) {
141732
141805
  return cleoErrorToEngineError(err2, "E_INTERNAL", "Failed to complete task (strict mode)");