@cleocode/core 2026.4.20 → 2026.4.22
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/index.js +101 -35
- package/dist/index.js.map +2 -2
- package/dist/paths.d.ts.map +1 -1
- package/dist/tasks/add.d.ts +2 -0
- package/dist/tasks/add.d.ts.map +1 -1
- package/dist/tasks/find.d.ts +4 -0
- package/dist/tasks/find.d.ts.map +1 -1
- package/package.json +7 -7
- package/src/paths.ts +5 -3
- package/src/tasks/add.ts +141 -39
- package/src/tasks/find.ts +11 -1
package/dist/index.js
CHANGED
|
@@ -10811,8 +10811,9 @@ function getProjectRoot(cwd) {
|
|
|
10811
10811
|
if (scope !== void 0) {
|
|
10812
10812
|
return scope.worktreeRoot;
|
|
10813
10813
|
}
|
|
10814
|
-
|
|
10815
|
-
|
|
10814
|
+
const envRoot = process.env["CLEO_ROOT"] ?? process.env["CLEO_PROJECT_ROOT"];
|
|
10815
|
+
if (envRoot) {
|
|
10816
|
+
return envRoot;
|
|
10816
10817
|
}
|
|
10817
10818
|
const cleoDirEnv = process.env["CLEO_DIR"];
|
|
10818
10819
|
if (cleoDirEnv && isAbsolutePath(cleoDirEnv)) {
|
|
@@ -24715,6 +24716,31 @@ function validatePhaseFormat(phase) {
|
|
|
24715
24716
|
);
|
|
24716
24717
|
}
|
|
24717
24718
|
}
|
|
24719
|
+
function throwCombinedValidationError(issues, options) {
|
|
24720
|
+
const summary = issues.length === 1 ? issues[0].message : `${issues.length} validation issues found:
|
|
24721
|
+
${issues.map((i, n) => ` ${n + 1}. ${i.message}`).join("\n")}`;
|
|
24722
|
+
const fixes = issues.map((i) => i.fix).filter(Boolean);
|
|
24723
|
+
const fixSummary = fixes.length === 0 ? void 0 : fixes.length === 1 ? fixes[0] : fixes.map((f, n) => `${n + 1}. ${f}`).join("\n");
|
|
24724
|
+
const submittedParams = { title: options.title };
|
|
24725
|
+
if (options.parentId) submittedParams.parent = options.parentId;
|
|
24726
|
+
if (options.type) submittedParams.type = options.type;
|
|
24727
|
+
if (options.priority) submittedParams.priority = options.priority;
|
|
24728
|
+
if (options.size) submittedParams.size = options.size;
|
|
24729
|
+
if (options.description) submittedParams.description = "(provided)";
|
|
24730
|
+
if (options.acceptance?.length)
|
|
24731
|
+
submittedParams.acceptance = `${options.acceptance.length} criteria`;
|
|
24732
|
+
if (options.depends?.length) submittedParams.depends = options.depends;
|
|
24733
|
+
if (options.phase) submittedParams.phase = options.phase;
|
|
24734
|
+
if (options.labels?.length) submittedParams.labels = options.labels;
|
|
24735
|
+
throw new CleoError(6 /* VALIDATION_ERROR */, summary, {
|
|
24736
|
+
fix: fixSummary,
|
|
24737
|
+
details: {
|
|
24738
|
+
field: issues.length === 1 ? issues[0].field : "multiple",
|
|
24739
|
+
issues,
|
|
24740
|
+
submittedParams
|
|
24741
|
+
}
|
|
24742
|
+
});
|
|
24743
|
+
}
|
|
24718
24744
|
function validateDepends(depends, tasks2) {
|
|
24719
24745
|
const existingIds = new Set(tasks2.map((t) => t.id));
|
|
24720
24746
|
for (const depId of depends) {
|
|
@@ -24842,46 +24868,69 @@ function findRecentDuplicate(title, phase, tasks2, windowSeconds = 60) {
|
|
|
24842
24868
|
}
|
|
24843
24869
|
async function addTask(options, cwd, accessor) {
|
|
24844
24870
|
validateTitle(options.title);
|
|
24845
|
-
if (options.description && options.title.trim().toLowerCase() === options.description.trim().toLowerCase()) {
|
|
24846
|
-
throw new CleoError(
|
|
24847
|
-
6 /* VALIDATION_ERROR */,
|
|
24848
|
-
"Title and description must be different (anti-hallucination rule)",
|
|
24849
|
-
{
|
|
24850
|
-
fix: "Provide --desc with a description different from the title",
|
|
24851
|
-
details: { field: "description" }
|
|
24852
|
-
}
|
|
24853
|
-
);
|
|
24854
|
-
}
|
|
24855
24871
|
if (!options.dryRun) {
|
|
24856
24872
|
await requireActiveSession("tasks.add", cwd);
|
|
24857
24873
|
}
|
|
24874
|
+
const issues = [];
|
|
24875
|
+
const warnings = [];
|
|
24876
|
+
if (options.description && options.title.trim().toLowerCase() === options.description.trim().toLowerCase()) {
|
|
24877
|
+
issues.push({
|
|
24878
|
+
field: "description",
|
|
24879
|
+
message: "Title and description must be different (anti-hallucination rule)",
|
|
24880
|
+
fix: "Provide --desc with a description different from the title"
|
|
24881
|
+
});
|
|
24882
|
+
}
|
|
24858
24883
|
const parentId = options.parentId ?? null;
|
|
24859
24884
|
if (!options.dryRun && !parentId && options.type !== "epic") {
|
|
24860
24885
|
const lifecycleMode = await getLifecycleMode(cwd);
|
|
24861
24886
|
if (lifecycleMode === "strict") {
|
|
24862
|
-
|
|
24863
|
-
|
|
24864
|
-
'Tasks must have a parent (epic or task) in strict mode. Use --parent <epicId>, --type epic for a root-level epic, or set lifecycle.mode to "advisory".',
|
|
24865
|
-
|
|
24866
|
-
|
|
24867
|
-
|
|
24868
|
-
|
|
24869
|
-
|
|
24870
|
-
command: 'cleo add "Epic title" --type epic --priority high'
|
|
24871
|
-
}
|
|
24872
|
-
]
|
|
24873
|
-
}
|
|
24887
|
+
issues.push({
|
|
24888
|
+
field: "parentId",
|
|
24889
|
+
message: 'Tasks must have a parent (epic or task) in strict mode. Use --parent <epicId>, --type epic for a root-level epic, or set lifecycle.mode to "advisory".',
|
|
24890
|
+
fix: 'cleo add "Task title" --parent T### --acceptance "AC1|AC2|AC3"'
|
|
24891
|
+
});
|
|
24892
|
+
} else {
|
|
24893
|
+
warnings.push(
|
|
24894
|
+
"Task created without a parent. Use --parent <epicId> to assign to an epic hierarchy."
|
|
24874
24895
|
);
|
|
24875
24896
|
}
|
|
24876
24897
|
}
|
|
24877
24898
|
const dataAccessor = accessor ?? await (await Promise.resolve().then(() => (init_data_accessor(), data_accessor_exports))).getAccessor(cwd);
|
|
24878
24899
|
const status = options.status ?? "pending";
|
|
24879
|
-
|
|
24900
|
+
let priority;
|
|
24901
|
+
try {
|
|
24902
|
+
priority = normalizePriority(options.priority ?? "medium");
|
|
24903
|
+
} catch (err) {
|
|
24904
|
+
if (err instanceof CleoError) {
|
|
24905
|
+
issues.push({ field: "priority", message: err.message, fix: err.fix });
|
|
24906
|
+
}
|
|
24907
|
+
priority = "medium";
|
|
24908
|
+
}
|
|
24880
24909
|
const size = options.size ?? "medium";
|
|
24881
24910
|
let taskType = options.type;
|
|
24882
|
-
|
|
24883
|
-
|
|
24884
|
-
|
|
24911
|
+
try {
|
|
24912
|
+
validateStatus(status);
|
|
24913
|
+
} catch (err) {
|
|
24914
|
+
if (err instanceof CleoError) {
|
|
24915
|
+
issues.push({ field: "status", message: err.message, fix: err.fix });
|
|
24916
|
+
}
|
|
24917
|
+
}
|
|
24918
|
+
try {
|
|
24919
|
+
validateSize(size);
|
|
24920
|
+
} catch (err) {
|
|
24921
|
+
if (err instanceof CleoError) {
|
|
24922
|
+
issues.push({ field: "size", message: err.message, fix: err.fix });
|
|
24923
|
+
}
|
|
24924
|
+
}
|
|
24925
|
+
if (options.labels?.length) {
|
|
24926
|
+
try {
|
|
24927
|
+
validateLabels(options.labels);
|
|
24928
|
+
} catch (err) {
|
|
24929
|
+
if (err instanceof CleoError) {
|
|
24930
|
+
issues.push({ field: "labels", message: err.message, fix: err.fix });
|
|
24931
|
+
}
|
|
24932
|
+
}
|
|
24933
|
+
}
|
|
24885
24934
|
if (!options.dryRun) {
|
|
24886
24935
|
const enforcement = await createAcceptanceEnforcement(cwd);
|
|
24887
24936
|
const acValidation = enforcement.validateCreation({
|
|
@@ -24889,17 +24938,28 @@ async function addTask(options, cwd, accessor) {
|
|
|
24889
24938
|
priority
|
|
24890
24939
|
});
|
|
24891
24940
|
if (!acValidation.valid) {
|
|
24892
|
-
|
|
24941
|
+
issues.push({
|
|
24942
|
+
field: "acceptance",
|
|
24943
|
+
message: acValidation.error,
|
|
24893
24944
|
fix: acValidation.fix
|
|
24894
24945
|
});
|
|
24895
24946
|
}
|
|
24896
24947
|
if (options.type === "epic") {
|
|
24897
|
-
|
|
24898
|
-
|
|
24899
|
-
|
|
24900
|
-
|
|
24948
|
+
try {
|
|
24949
|
+
await validateEpicCreation(
|
|
24950
|
+
{ acceptance: options.acceptance, description: options.description },
|
|
24951
|
+
cwd
|
|
24952
|
+
);
|
|
24953
|
+
} catch (err) {
|
|
24954
|
+
if (err instanceof CleoError) {
|
|
24955
|
+
issues.push({ field: "epic", message: err.message, fix: err.fix });
|
|
24956
|
+
}
|
|
24957
|
+
}
|
|
24901
24958
|
}
|
|
24902
24959
|
}
|
|
24960
|
+
if (issues.length > 0) {
|
|
24961
|
+
throwCombinedValidationError(issues, options);
|
|
24962
|
+
}
|
|
24903
24963
|
if (options.depends?.length) {
|
|
24904
24964
|
for (const depId of options.depends) {
|
|
24905
24965
|
const trimmed = depId.trim();
|
|
@@ -25198,7 +25258,7 @@ async function addTask(options, cwd, accessor) {
|
|
|
25198
25258
|
after: { title: options.title, status, priority }
|
|
25199
25259
|
});
|
|
25200
25260
|
});
|
|
25201
|
-
return { task };
|
|
25261
|
+
return { task, ...warnings.length > 0 && { warnings } };
|
|
25202
25262
|
}
|
|
25203
25263
|
var NUMERIC_PRIORITY_MAP, VALID_PRIORITIES;
|
|
25204
25264
|
var init_add = __esm({
|
|
@@ -53219,7 +53279,7 @@ function fuzzyScore(query, text3) {
|
|
|
53219
53279
|
return 0;
|
|
53220
53280
|
}
|
|
53221
53281
|
async function findTasks(options, cwd, accessor) {
|
|
53222
|
-
if (
|
|
53282
|
+
if (options.query == null && !options.id) {
|
|
53223
53283
|
throw new CleoError(2 /* INVALID_INPUT */, "Search query or --id is required", {
|
|
53224
53284
|
fix: 'cleo find "<query>"',
|
|
53225
53285
|
details: { field: "query" }
|
|
@@ -53256,6 +53316,8 @@ async function findTasks(options, cwd, accessor) {
|
|
|
53256
53316
|
priority: t.priority,
|
|
53257
53317
|
type: t.type,
|
|
53258
53318
|
parentId: t.parentId,
|
|
53319
|
+
depends: t.depends ?? [],
|
|
53320
|
+
size: t.size ?? void 0,
|
|
53259
53321
|
score: t.id.toUpperCase() === idQuery ? 100 : t.id.toUpperCase().startsWith(idQuery) ? 80 : 50
|
|
53260
53322
|
}));
|
|
53261
53323
|
} else if (options.exact) {
|
|
@@ -53268,6 +53330,8 @@ async function findTasks(options, cwd, accessor) {
|
|
|
53268
53330
|
priority: t.priority,
|
|
53269
53331
|
type: t.type,
|
|
53270
53332
|
parentId: t.parentId,
|
|
53333
|
+
depends: t.depends ?? [],
|
|
53334
|
+
size: t.size ?? void 0,
|
|
53271
53335
|
score: 100
|
|
53272
53336
|
}));
|
|
53273
53337
|
} else {
|
|
@@ -53286,6 +53350,8 @@ async function findTasks(options, cwd, accessor) {
|
|
|
53286
53350
|
priority: t.priority,
|
|
53287
53351
|
type: t.type,
|
|
53288
53352
|
parentId: t.parentId,
|
|
53353
|
+
depends: t.depends ?? [],
|
|
53354
|
+
size: t.size ?? void 0,
|
|
53289
53355
|
score: Math.round(score)
|
|
53290
53356
|
});
|
|
53291
53357
|
}
|