@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 +76 -3
- package/dist/cli/index.js.map +3 -3
- package/package.json +8 -8
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
|
|
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)");
|