@cleocode/cleo 2026.4.21 → 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/cli/index.js +333 -66
- package/dist/cli/index.js.map +4 -4
- package/package.json +7 -7
package/dist/cli/index.js
CHANGED
|
@@ -10836,8 +10836,9 @@ function getProjectRoot(cwd) {
|
|
|
10836
10836
|
if (scope !== void 0) {
|
|
10837
10837
|
return scope.worktreeRoot;
|
|
10838
10838
|
}
|
|
10839
|
-
|
|
10840
|
-
|
|
10839
|
+
const envRoot = process.env["CLEO_ROOT"] ?? process.env["CLEO_PROJECT_ROOT"];
|
|
10840
|
+
if (envRoot) {
|
|
10841
|
+
return envRoot;
|
|
10841
10842
|
}
|
|
10842
10843
|
const cleoDirEnv = process.env["CLEO_DIR"];
|
|
10843
10844
|
if (cleoDirEnv && isAbsolutePath(cleoDirEnv)) {
|
|
@@ -34311,6 +34312,31 @@ function validatePhaseFormat(phase) {
|
|
|
34311
34312
|
);
|
|
34312
34313
|
}
|
|
34313
34314
|
}
|
|
34315
|
+
function throwCombinedValidationError(issues, options) {
|
|
34316
|
+
const summary = issues.length === 1 ? issues[0].message : `${issues.length} validation issues found:
|
|
34317
|
+
${issues.map((i, n) => ` ${n + 1}. ${i.message}`).join("\n")}`;
|
|
34318
|
+
const fixes = issues.map((i) => i.fix).filter(Boolean);
|
|
34319
|
+
const fixSummary = fixes.length === 0 ? void 0 : fixes.length === 1 ? fixes[0] : fixes.map((f2, n) => `${n + 1}. ${f2}`).join("\n");
|
|
34320
|
+
const submittedParams = { title: options.title };
|
|
34321
|
+
if (options.parentId) submittedParams.parent = options.parentId;
|
|
34322
|
+
if (options.type) submittedParams.type = options.type;
|
|
34323
|
+
if (options.priority) submittedParams.priority = options.priority;
|
|
34324
|
+
if (options.size) submittedParams.size = options.size;
|
|
34325
|
+
if (options.description) submittedParams.description = "(provided)";
|
|
34326
|
+
if (options.acceptance?.length)
|
|
34327
|
+
submittedParams.acceptance = `${options.acceptance.length} criteria`;
|
|
34328
|
+
if (options.depends?.length) submittedParams.depends = options.depends;
|
|
34329
|
+
if (options.phase) submittedParams.phase = options.phase;
|
|
34330
|
+
if (options.labels?.length) submittedParams.labels = options.labels;
|
|
34331
|
+
throw new CleoError(6 /* VALIDATION_ERROR */, summary, {
|
|
34332
|
+
fix: fixSummary,
|
|
34333
|
+
details: {
|
|
34334
|
+
field: issues.length === 1 ? issues[0].field : "multiple",
|
|
34335
|
+
issues,
|
|
34336
|
+
submittedParams
|
|
34337
|
+
}
|
|
34338
|
+
});
|
|
34339
|
+
}
|
|
34314
34340
|
function validateDepends(depends, tasks2) {
|
|
34315
34341
|
const existingIds = new Set(tasks2.map((t) => t.id));
|
|
34316
34342
|
for (const depId of depends) {
|
|
@@ -34438,46 +34464,69 @@ function findRecentDuplicate(title, phase, tasks2, windowSeconds = 60) {
|
|
|
34438
34464
|
}
|
|
34439
34465
|
async function addTask(options, cwd, accessor) {
|
|
34440
34466
|
validateTitle(options.title);
|
|
34441
|
-
if (options.description && options.title.trim().toLowerCase() === options.description.trim().toLowerCase()) {
|
|
34442
|
-
throw new CleoError(
|
|
34443
|
-
6 /* VALIDATION_ERROR */,
|
|
34444
|
-
"Title and description must be different (anti-hallucination rule)",
|
|
34445
|
-
{
|
|
34446
|
-
fix: "Provide --desc with a description different from the title",
|
|
34447
|
-
details: { field: "description" }
|
|
34448
|
-
}
|
|
34449
|
-
);
|
|
34450
|
-
}
|
|
34451
34467
|
if (!options.dryRun) {
|
|
34452
34468
|
await requireActiveSession("tasks.add", cwd);
|
|
34453
34469
|
}
|
|
34470
|
+
const issues = [];
|
|
34471
|
+
const warnings = [];
|
|
34472
|
+
if (options.description && options.title.trim().toLowerCase() === options.description.trim().toLowerCase()) {
|
|
34473
|
+
issues.push({
|
|
34474
|
+
field: "description",
|
|
34475
|
+
message: "Title and description must be different (anti-hallucination rule)",
|
|
34476
|
+
fix: "Provide --desc with a description different from the title"
|
|
34477
|
+
});
|
|
34478
|
+
}
|
|
34454
34479
|
const parentId = options.parentId ?? null;
|
|
34455
34480
|
if (!options.dryRun && !parentId && options.type !== "epic") {
|
|
34456
34481
|
const lifecycleMode = await getLifecycleMode(cwd);
|
|
34457
34482
|
if (lifecycleMode === "strict") {
|
|
34458
|
-
|
|
34459
|
-
|
|
34460
|
-
'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".',
|
|
34461
|
-
|
|
34462
|
-
|
|
34463
|
-
|
|
34464
|
-
|
|
34465
|
-
|
|
34466
|
-
command: 'cleo add "Epic title" --type epic --priority high'
|
|
34467
|
-
}
|
|
34468
|
-
]
|
|
34469
|
-
}
|
|
34483
|
+
issues.push({
|
|
34484
|
+
field: "parentId",
|
|
34485
|
+
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".',
|
|
34486
|
+
fix: 'cleo add "Task title" --parent T### --acceptance "AC1|AC2|AC3"'
|
|
34487
|
+
});
|
|
34488
|
+
} else {
|
|
34489
|
+
warnings.push(
|
|
34490
|
+
"Task created without a parent. Use --parent <epicId> to assign to an epic hierarchy."
|
|
34470
34491
|
);
|
|
34471
34492
|
}
|
|
34472
34493
|
}
|
|
34473
34494
|
const dataAccessor = accessor ?? await (await Promise.resolve().then(() => (init_data_accessor(), data_accessor_exports))).getAccessor(cwd);
|
|
34474
34495
|
const status = options.status ?? "pending";
|
|
34475
|
-
|
|
34496
|
+
let priority;
|
|
34497
|
+
try {
|
|
34498
|
+
priority = normalizePriority(options.priority ?? "medium");
|
|
34499
|
+
} catch (err) {
|
|
34500
|
+
if (err instanceof CleoError) {
|
|
34501
|
+
issues.push({ field: "priority", message: err.message, fix: err.fix });
|
|
34502
|
+
}
|
|
34503
|
+
priority = "medium";
|
|
34504
|
+
}
|
|
34476
34505
|
const size = options.size ?? "medium";
|
|
34477
34506
|
let taskType = options.type;
|
|
34478
|
-
|
|
34479
|
-
|
|
34480
|
-
|
|
34507
|
+
try {
|
|
34508
|
+
validateStatus(status);
|
|
34509
|
+
} catch (err) {
|
|
34510
|
+
if (err instanceof CleoError) {
|
|
34511
|
+
issues.push({ field: "status", message: err.message, fix: err.fix });
|
|
34512
|
+
}
|
|
34513
|
+
}
|
|
34514
|
+
try {
|
|
34515
|
+
validateSize(size);
|
|
34516
|
+
} catch (err) {
|
|
34517
|
+
if (err instanceof CleoError) {
|
|
34518
|
+
issues.push({ field: "size", message: err.message, fix: err.fix });
|
|
34519
|
+
}
|
|
34520
|
+
}
|
|
34521
|
+
if (options.labels?.length) {
|
|
34522
|
+
try {
|
|
34523
|
+
validateLabels(options.labels);
|
|
34524
|
+
} catch (err) {
|
|
34525
|
+
if (err instanceof CleoError) {
|
|
34526
|
+
issues.push({ field: "labels", message: err.message, fix: err.fix });
|
|
34527
|
+
}
|
|
34528
|
+
}
|
|
34529
|
+
}
|
|
34481
34530
|
if (!options.dryRun) {
|
|
34482
34531
|
const enforcement = await createAcceptanceEnforcement(cwd);
|
|
34483
34532
|
const acValidation = enforcement.validateCreation({
|
|
@@ -34485,17 +34534,28 @@ async function addTask(options, cwd, accessor) {
|
|
|
34485
34534
|
priority
|
|
34486
34535
|
});
|
|
34487
34536
|
if (!acValidation.valid) {
|
|
34488
|
-
|
|
34537
|
+
issues.push({
|
|
34538
|
+
field: "acceptance",
|
|
34539
|
+
message: acValidation.error,
|
|
34489
34540
|
fix: acValidation.fix
|
|
34490
34541
|
});
|
|
34491
34542
|
}
|
|
34492
34543
|
if (options.type === "epic") {
|
|
34493
|
-
|
|
34494
|
-
|
|
34495
|
-
|
|
34496
|
-
|
|
34544
|
+
try {
|
|
34545
|
+
await validateEpicCreation(
|
|
34546
|
+
{ acceptance: options.acceptance, description: options.description },
|
|
34547
|
+
cwd
|
|
34548
|
+
);
|
|
34549
|
+
} catch (err) {
|
|
34550
|
+
if (err instanceof CleoError) {
|
|
34551
|
+
issues.push({ field: "epic", message: err.message, fix: err.fix });
|
|
34552
|
+
}
|
|
34553
|
+
}
|
|
34497
34554
|
}
|
|
34498
34555
|
}
|
|
34556
|
+
if (issues.length > 0) {
|
|
34557
|
+
throwCombinedValidationError(issues, options);
|
|
34558
|
+
}
|
|
34499
34559
|
if (options.depends?.length) {
|
|
34500
34560
|
for (const depId of options.depends) {
|
|
34501
34561
|
const trimmed = depId.trim();
|
|
@@ -34794,7 +34854,7 @@ async function addTask(options, cwd, accessor) {
|
|
|
34794
34854
|
after: { title: options.title, status, priority }
|
|
34795
34855
|
});
|
|
34796
34856
|
});
|
|
34797
|
-
return { task };
|
|
34857
|
+
return { task, ...warnings.length > 0 && { warnings } };
|
|
34798
34858
|
}
|
|
34799
34859
|
var NUMERIC_PRIORITY_MAP, VALID_PRIORITIES;
|
|
34800
34860
|
var init_add = __esm({
|
|
@@ -38729,10 +38789,10 @@ async function readProjectMeta(projectPath) {
|
|
|
38729
38789
|
}
|
|
38730
38790
|
async function readProjectId(projectPath) {
|
|
38731
38791
|
try {
|
|
38732
|
-
const { readFileSync:
|
|
38792
|
+
const { readFileSync: readFileSync102, existsSync: existsSync131 } = await import("node:fs");
|
|
38733
38793
|
const infoPath = join64(projectPath, ".cleo", "project-info.json");
|
|
38734
38794
|
if (!existsSync131(infoPath)) return "";
|
|
38735
|
-
const data = JSON.parse(
|
|
38795
|
+
const data = JSON.parse(readFileSync102(infoPath, "utf-8"));
|
|
38736
38796
|
return typeof data.projectId === "string" ? data.projectId : "";
|
|
38737
38797
|
} catch {
|
|
38738
38798
|
return "";
|
|
@@ -54949,7 +55009,7 @@ function fuzzyScore(query, text3) {
|
|
|
54949
55009
|
return 0;
|
|
54950
55010
|
}
|
|
54951
55011
|
async function findTasks(options, cwd, accessor) {
|
|
54952
|
-
if (
|
|
55012
|
+
if (options.query == null && !options.id) {
|
|
54953
55013
|
throw new CleoError(2 /* INVALID_INPUT */, "Search query or --id is required", {
|
|
54954
55014
|
fix: 'cleo find "<query>"',
|
|
54955
55015
|
details: { field: "query" }
|
|
@@ -54986,6 +55046,8 @@ async function findTasks(options, cwd, accessor) {
|
|
|
54986
55046
|
priority: t.priority,
|
|
54987
55047
|
type: t.type,
|
|
54988
55048
|
parentId: t.parentId,
|
|
55049
|
+
depends: t.depends ?? [],
|
|
55050
|
+
size: t.size ?? void 0,
|
|
54989
55051
|
score: t.id.toUpperCase() === idQuery ? 100 : t.id.toUpperCase().startsWith(idQuery) ? 80 : 50
|
|
54990
55052
|
}));
|
|
54991
55053
|
} else if (options.exact) {
|
|
@@ -54998,6 +55060,8 @@ async function findTasks(options, cwd, accessor) {
|
|
|
54998
55060
|
priority: t.priority,
|
|
54999
55061
|
type: t.type,
|
|
55000
55062
|
parentId: t.parentId,
|
|
55063
|
+
depends: t.depends ?? [],
|
|
55064
|
+
size: t.size ?? void 0,
|
|
55001
55065
|
score: 100
|
|
55002
55066
|
}));
|
|
55003
55067
|
} else {
|
|
@@ -55016,6 +55080,8 @@ async function findTasks(options, cwd, accessor) {
|
|
|
55016
55080
|
priority: t.priority,
|
|
55017
55081
|
type: t.type,
|
|
55018
55082
|
parentId: t.parentId,
|
|
55083
|
+
depends: t.depends ?? [],
|
|
55084
|
+
size: t.size ?? void 0,
|
|
55019
55085
|
score: Math.round(score)
|
|
55020
55086
|
});
|
|
55021
55087
|
}
|
|
@@ -107789,14 +107855,55 @@ async function taskFind(projectRoot, query, limit, options) {
|
|
|
107789
107855
|
projectRoot,
|
|
107790
107856
|
accessor
|
|
107791
107857
|
);
|
|
107858
|
+
if (options?.verbose) {
|
|
107859
|
+
const fullResults = [];
|
|
107860
|
+
for (const r of findResult.results) {
|
|
107861
|
+
const task = await accessor.loadSingleTask(r.id);
|
|
107862
|
+
if (task) fullResults.push(taskToRecord(task));
|
|
107863
|
+
}
|
|
107864
|
+
return { success: true, data: { results: fullResults, total: findResult.total } };
|
|
107865
|
+
}
|
|
107866
|
+
if (options?.fields) {
|
|
107867
|
+
const extraFields = options.fields.split(",").map((f2) => f2.trim());
|
|
107868
|
+
const extendedResults = [];
|
|
107869
|
+
for (const r of findResult.results) {
|
|
107870
|
+
const base = {
|
|
107871
|
+
id: r.id,
|
|
107872
|
+
title: r.title,
|
|
107873
|
+
status: r.status,
|
|
107874
|
+
priority: r.priority,
|
|
107875
|
+
parentId: r.parentId,
|
|
107876
|
+
depends: r.depends,
|
|
107877
|
+
type: r.type,
|
|
107878
|
+
size: r.size
|
|
107879
|
+
};
|
|
107880
|
+
const task = await accessor.loadSingleTask(r.id);
|
|
107881
|
+
if (task) {
|
|
107882
|
+
const record2 = taskToRecord(task);
|
|
107883
|
+
for (const field of extraFields) {
|
|
107884
|
+
if (field in record2) {
|
|
107885
|
+
base[field] = record2[field];
|
|
107886
|
+
}
|
|
107887
|
+
}
|
|
107888
|
+
}
|
|
107889
|
+
extendedResults.push(base);
|
|
107890
|
+
}
|
|
107891
|
+
return {
|
|
107892
|
+
success: true,
|
|
107893
|
+
data: { results: extendedResults, total: findResult.total }
|
|
107894
|
+
};
|
|
107895
|
+
}
|
|
107792
107896
|
const results = findResult.results.map((r) => ({
|
|
107793
107897
|
id: r.id,
|
|
107794
107898
|
title: r.title,
|
|
107795
107899
|
status: r.status,
|
|
107796
107900
|
priority: r.priority,
|
|
107797
|
-
parentId: r.parentId
|
|
107901
|
+
parentId: r.parentId,
|
|
107902
|
+
depends: r.depends,
|
|
107903
|
+
type: r.type,
|
|
107904
|
+
size: r.size
|
|
107798
107905
|
}));
|
|
107799
|
-
return { success: true, data: { results, total:
|
|
107906
|
+
return { success: true, data: { results, total: findResult.total } };
|
|
107800
107907
|
} catch (err) {
|
|
107801
107908
|
return cleoErrorToEngineError(err, "E_NOT_INITIALIZED", "Task database not initialized");
|
|
107802
107909
|
}
|
|
@@ -107804,11 +107911,37 @@ async function taskFind(projectRoot, query, limit, options) {
|
|
|
107804
107911
|
async function taskCreate(projectRoot, params) {
|
|
107805
107912
|
try {
|
|
107806
107913
|
const accessor = await getAccessor(projectRoot);
|
|
107914
|
+
let resolvedParent = params.parent || null;
|
|
107915
|
+
if (!resolvedParent && params.parentSearch) {
|
|
107916
|
+
const searchResult = await findTasks(
|
|
107917
|
+
{ query: params.parentSearch, limit: 1 },
|
|
107918
|
+
projectRoot,
|
|
107919
|
+
accessor
|
|
107920
|
+
);
|
|
107921
|
+
if (searchResult.results.length > 0) {
|
|
107922
|
+
resolvedParent = searchResult.results[0].id;
|
|
107923
|
+
} else {
|
|
107924
|
+
return cleoErrorToEngineError(
|
|
107925
|
+
new Error(`No task found matching --parent-search "${params.parentSearch}"`),
|
|
107926
|
+
"E_NOT_FOUND",
|
|
107927
|
+
`No task found matching "${params.parentSearch}"`
|
|
107928
|
+
);
|
|
107929
|
+
}
|
|
107930
|
+
}
|
|
107931
|
+
if (!resolvedParent && params.type !== "epic") {
|
|
107932
|
+
try {
|
|
107933
|
+
const session = await getActiveSession(projectRoot);
|
|
107934
|
+
if (session?.scope?.type === "epic" && session.scope.epicId) {
|
|
107935
|
+
resolvedParent = session.scope.epicId;
|
|
107936
|
+
}
|
|
107937
|
+
} catch {
|
|
107938
|
+
}
|
|
107939
|
+
}
|
|
107807
107940
|
const result = await addTask(
|
|
107808
107941
|
{
|
|
107809
107942
|
title: params.title,
|
|
107810
107943
|
description: params.description,
|
|
107811
|
-
parentId:
|
|
107944
|
+
parentId: resolvedParent,
|
|
107812
107945
|
depends: params.depends,
|
|
107813
107946
|
priority: params.priority || "medium",
|
|
107814
107947
|
labels: params.labels,
|
|
@@ -107828,7 +107961,8 @@ async function taskCreate(projectRoot, params) {
|
|
|
107828
107961
|
data: {
|
|
107829
107962
|
task: taskToRecord(result.task),
|
|
107830
107963
|
duplicate: result.duplicate ?? false,
|
|
107831
|
-
dryRun: params.dryRun
|
|
107964
|
+
dryRun: params.dryRun,
|
|
107965
|
+
...result.warnings?.length && { warnings: result.warnings }
|
|
107832
107966
|
}
|
|
107833
107967
|
};
|
|
107834
107968
|
} catch (err) {
|
|
@@ -111605,7 +111739,7 @@ var init_nexus2 = __esm({
|
|
|
111605
111739
|
async function orchestrateClassify(request, context, projectRoot) {
|
|
111606
111740
|
try {
|
|
111607
111741
|
const { getCleoCantWorkflowsDir: getCleoCantWorkflowsDir2 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
111608
|
-
const { readFileSync:
|
|
111742
|
+
const { readFileSync: readFileSync102, readdirSync: readdirSync42, existsSync: existsSync131 } = await import("node:fs");
|
|
111609
111743
|
const { join: join131 } = await import("node:path");
|
|
111610
111744
|
const workflowsDir = getCleoCantWorkflowsDir2();
|
|
111611
111745
|
const combined = `${request} ${context ?? ""}`.toLowerCase();
|
|
@@ -111614,7 +111748,7 @@ async function orchestrateClassify(request, context, projectRoot) {
|
|
|
111614
111748
|
const files = readdirSync42(workflowsDir).filter((f2) => f2.endsWith(".cant"));
|
|
111615
111749
|
for (const file2 of files) {
|
|
111616
111750
|
try {
|
|
111617
|
-
const src =
|
|
111751
|
+
const src = readFileSync102(join131(workflowsDir, file2), "utf-8");
|
|
111618
111752
|
const teamMatch = /^team\s+(\S+):/m.exec(src);
|
|
111619
111753
|
if (!teamMatch) continue;
|
|
111620
111754
|
const teamName = teamMatch[1];
|
|
@@ -111634,7 +111768,7 @@ async function orchestrateClassify(request, context, projectRoot) {
|
|
|
111634
111768
|
const files = readdirSync42(localCantDir).filter((f2) => f2.endsWith(".cant"));
|
|
111635
111769
|
for (const file2 of files) {
|
|
111636
111770
|
try {
|
|
111637
|
-
const src =
|
|
111771
|
+
const src = readFileSync102(join131(localCantDir, file2), "utf-8");
|
|
111638
111772
|
const teamMatch = /^team\s+(\S+):/m.exec(src);
|
|
111639
111773
|
if (!teamMatch) continue;
|
|
111640
111774
|
const teamName = teamMatch[1];
|
|
@@ -113916,7 +114050,9 @@ var init_tasks4 = __esm({
|
|
|
113916
114050
|
exact: params?.exact,
|
|
113917
114051
|
status: params?.status,
|
|
113918
114052
|
includeArchive: params?.includeArchive,
|
|
113919
|
-
offset: params?.offset
|
|
114053
|
+
offset: params?.offset,
|
|
114054
|
+
fields: params?.fields,
|
|
114055
|
+
verbose: params?.verbose
|
|
113920
114056
|
}
|
|
113921
114057
|
);
|
|
113922
114058
|
return wrapResult(result, "query", "tasks", operation, startTime);
|
|
@@ -114067,7 +114203,8 @@ var init_tasks4 = __esm({
|
|
|
114067
114203
|
size: params?.size,
|
|
114068
114204
|
notes: params?.notes,
|
|
114069
114205
|
files: params?.files,
|
|
114070
|
-
dryRun: params?.dryRun
|
|
114206
|
+
dryRun: params?.dryRun,
|
|
114207
|
+
parentSearch: params?.parentSearch
|
|
114071
114208
|
});
|
|
114072
114209
|
return wrapResult(result, "mutate", "tasks", operation, startTime);
|
|
114073
114210
|
}
|
|
@@ -116151,7 +116288,7 @@ var init_cli = __esm({
|
|
|
116151
116288
|
|
|
116152
116289
|
// packages/cleo/src/cli/index.ts
|
|
116153
116290
|
init_internal();
|
|
116154
|
-
import { readFileSync as
|
|
116291
|
+
import { readFileSync as readFileSync101 } from "node:fs";
|
|
116155
116292
|
import { dirname as dirname28, join as join130 } from "node:path";
|
|
116156
116293
|
import { fileURLToPath as fileURLToPath5 } from "node:url";
|
|
116157
116294
|
|
|
@@ -117156,6 +117293,13 @@ var ADD_PARAMS = [
|
|
|
117156
117293
|
required: false,
|
|
117157
117294
|
description: "Position within sibling group",
|
|
117158
117295
|
cli: { flag: "position", parse: parseInt }
|
|
117296
|
+
},
|
|
117297
|
+
{
|
|
117298
|
+
name: "parentSearch",
|
|
117299
|
+
type: "string",
|
|
117300
|
+
required: false,
|
|
117301
|
+
description: "Resolve parent by title substring instead of exact ID (T090)",
|
|
117302
|
+
cli: { flag: "parent-search" }
|
|
117159
117303
|
}
|
|
117160
117304
|
];
|
|
117161
117305
|
function registerAddCommand(program) {
|
|
@@ -117179,18 +117323,37 @@ function registerAddCommand(program) {
|
|
|
117179
117323
|
params["labels"] = opts["labels"].split(",").map((s3) => s3.trim());
|
|
117180
117324
|
if (opts["files"])
|
|
117181
117325
|
params["files"] = opts["files"].split(",").map((s3) => s3.trim());
|
|
117182
|
-
if (opts["acceptance"])
|
|
117183
|
-
|
|
117326
|
+
if (opts["acceptance"]) {
|
|
117327
|
+
const raw = opts["acceptance"];
|
|
117328
|
+
if (raw.trimStart().startsWith("[")) {
|
|
117329
|
+
try {
|
|
117330
|
+
const parsed = JSON.parse(raw);
|
|
117331
|
+
params["acceptance"] = Array.isArray(parsed) ? parsed.map((s3) => String(s3).trim()).filter(Boolean) : [raw];
|
|
117332
|
+
} catch {
|
|
117333
|
+
params["acceptance"] = raw.split("|").map((s3) => s3.trim()).filter(Boolean);
|
|
117334
|
+
}
|
|
117335
|
+
} else {
|
|
117336
|
+
params["acceptance"] = raw.split("|").map((s3) => s3.trim()).filter(Boolean);
|
|
117337
|
+
}
|
|
117338
|
+
}
|
|
117184
117339
|
if (opts["depends"])
|
|
117185
117340
|
params["depends"] = opts["depends"].split(",").map((s3) => s3.trim());
|
|
117186
117341
|
if (opts["notes"] !== void 0) params["notes"] = opts["notes"];
|
|
117187
117342
|
if (opts["position"] !== void 0) params["position"] = opts["position"];
|
|
117188
117343
|
if (opts["dryRun"] !== void 0) params["dryRun"] = opts["dryRun"];
|
|
117344
|
+
if (opts["parentSearch"] !== void 0) params["parentSearch"] = opts["parentSearch"];
|
|
117189
117345
|
const response = await dispatchRaw("mutate", "tasks", "add", params);
|
|
117190
117346
|
if (!response.success) {
|
|
117191
117347
|
handleRawError(response, { command: "add", operation: "tasks.add" });
|
|
117192
117348
|
}
|
|
117193
117349
|
const data = response.data;
|
|
117350
|
+
const dataWarnings = data?.warnings;
|
|
117351
|
+
if (dataWarnings?.length) {
|
|
117352
|
+
for (const w2 of dataWarnings) {
|
|
117353
|
+
process.stderr.write(`\u26A0 ${w2}
|
|
117354
|
+
`);
|
|
117355
|
+
}
|
|
117356
|
+
}
|
|
117194
117357
|
if (data?.duplicate) {
|
|
117195
117358
|
cliOutput(data, {
|
|
117196
117359
|
command: "add",
|
|
@@ -117209,6 +117372,93 @@ function registerAddCommand(program) {
|
|
|
117209
117372
|
});
|
|
117210
117373
|
}
|
|
117211
117374
|
|
|
117375
|
+
// packages/cleo/src/cli/commands/add-batch.ts
|
|
117376
|
+
init_cli();
|
|
117377
|
+
init_renderers();
|
|
117378
|
+
import { readFileSync as readFileSync96 } from "node:fs";
|
|
117379
|
+
function registerAddBatchCommand(program) {
|
|
117380
|
+
program.command("add-batch").description("Create multiple tasks atomically from a JSON file").option("--file <path>", "Path to JSON file (array of task objects). Use - for stdin.").option("--parent <parentId>", "Default parent for all tasks (overridden by per-task parent)").option("--dry-run", "Preview what would be created without making changes").action(async (opts) => {
|
|
117381
|
+
const filePath = opts["file"];
|
|
117382
|
+
const defaultParent = opts["parent"];
|
|
117383
|
+
const dryRun = opts["dryRun"];
|
|
117384
|
+
let raw;
|
|
117385
|
+
if (!filePath || filePath === "-") {
|
|
117386
|
+
const chunks = [];
|
|
117387
|
+
for await (const chunk of process.stdin) {
|
|
117388
|
+
chunks.push(chunk);
|
|
117389
|
+
}
|
|
117390
|
+
raw = Buffer.concat(chunks).toString("utf-8");
|
|
117391
|
+
} else {
|
|
117392
|
+
raw = readFileSync96(filePath, "utf-8");
|
|
117393
|
+
}
|
|
117394
|
+
let tasks2;
|
|
117395
|
+
try {
|
|
117396
|
+
const parsed = JSON.parse(raw);
|
|
117397
|
+
tasks2 = Array.isArray(parsed) ? parsed : [parsed];
|
|
117398
|
+
} catch {
|
|
117399
|
+
process.stderr.write("Error: Invalid JSON input. Expected an array of task objects.\n");
|
|
117400
|
+
process.exit(2);
|
|
117401
|
+
return;
|
|
117402
|
+
}
|
|
117403
|
+
if (tasks2.length === 0) {
|
|
117404
|
+
process.stderr.write("Error: No tasks in input.\n");
|
|
117405
|
+
process.exit(2);
|
|
117406
|
+
return;
|
|
117407
|
+
}
|
|
117408
|
+
const results = [];
|
|
117409
|
+
let failed = 0;
|
|
117410
|
+
for (const task of tasks2) {
|
|
117411
|
+
const params = {
|
|
117412
|
+
title: task.title,
|
|
117413
|
+
...task.description && { description: task.description },
|
|
117414
|
+
parent: task.parent ?? defaultParent,
|
|
117415
|
+
...task.type && { type: task.type },
|
|
117416
|
+
...task.priority && { priority: task.priority },
|
|
117417
|
+
...task.size && { size: task.size },
|
|
117418
|
+
...task.acceptance?.length && { acceptance: task.acceptance },
|
|
117419
|
+
...task.depends?.length && { depends: task.depends },
|
|
117420
|
+
...task.labels?.length && { labels: task.labels },
|
|
117421
|
+
...task.phase && { phase: task.phase },
|
|
117422
|
+
...task.notes && { notes: task.notes },
|
|
117423
|
+
...task.files?.length && { files: task.files },
|
|
117424
|
+
...dryRun && { dryRun: true }
|
|
117425
|
+
};
|
|
117426
|
+
const response = await dispatchRaw("mutate", "tasks", "add", params);
|
|
117427
|
+
if (response.success) {
|
|
117428
|
+
const data = response.data;
|
|
117429
|
+
const taskData = data?.task;
|
|
117430
|
+
results.push({ title: task.title, id: taskData?.id });
|
|
117431
|
+
} else {
|
|
117432
|
+
failed++;
|
|
117433
|
+
results.push({
|
|
117434
|
+
title: task.title,
|
|
117435
|
+
error: response.error?.message ?? "Unknown error"
|
|
117436
|
+
});
|
|
117437
|
+
}
|
|
117438
|
+
}
|
|
117439
|
+
const output = {
|
|
117440
|
+
total: tasks2.length,
|
|
117441
|
+
created: tasks2.length - failed,
|
|
117442
|
+
failed,
|
|
117443
|
+
dryRun: dryRun ?? false,
|
|
117444
|
+
results
|
|
117445
|
+
};
|
|
117446
|
+
if (failed > 0) {
|
|
117447
|
+
cliOutput(output, {
|
|
117448
|
+
command: "add-batch",
|
|
117449
|
+
message: `${failed} of ${tasks2.length} tasks failed`,
|
|
117450
|
+
operation: "tasks.add-batch"
|
|
117451
|
+
});
|
|
117452
|
+
process.exit(1);
|
|
117453
|
+
} else {
|
|
117454
|
+
cliOutput(output, {
|
|
117455
|
+
command: "add-batch",
|
|
117456
|
+
operation: "tasks.add-batch"
|
|
117457
|
+
});
|
|
117458
|
+
}
|
|
117459
|
+
});
|
|
117460
|
+
}
|
|
117461
|
+
|
|
117212
117462
|
// packages/cleo/src/cli/commands/admin.ts
|
|
117213
117463
|
init_cli();
|
|
117214
117464
|
function registerAdminCommand(program) {
|
|
@@ -117496,7 +117746,7 @@ agent ${agentId}:
|
|
|
117496
117746
|
try {
|
|
117497
117747
|
const { AgentRegistryAccessor: AgentRegistryAccessor2, getDb: getDb4 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
117498
117748
|
const { createRuntime } = await import("@cleocode/runtime");
|
|
117499
|
-
const { existsSync: existsSync131, readFileSync:
|
|
117749
|
+
const { existsSync: existsSync131, readFileSync: readFileSync102 } = await import("node:fs");
|
|
117500
117750
|
const { join: join131 } = await import("node:path");
|
|
117501
117751
|
await getDb4();
|
|
117502
117752
|
const registry2 = new AgentRegistryAccessor2(process.cwd());
|
|
@@ -117519,7 +117769,7 @@ agent ${agentId}:
|
|
|
117519
117769
|
let cantValidation = null;
|
|
117520
117770
|
const cantPath = opts["cant"] ?? join131(".cleo", "agents", `${agentId}.cant`);
|
|
117521
117771
|
if (existsSync131(cantPath)) {
|
|
117522
|
-
profile =
|
|
117772
|
+
profile = readFileSync102(cantPath, "utf-8");
|
|
117523
117773
|
try {
|
|
117524
117774
|
const cantModule = await import("@cleocode/cant");
|
|
117525
117775
|
const validate = "validate" in cantModule ? cantModule.validate : null;
|
|
@@ -118559,7 +118809,7 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
118559
118809
|
});
|
|
118560
118810
|
agent.command("install <path>").description("Install an agent from a .cantz archive or agent directory").option("--global", "Install to global tier (~/.local/share/cleo/cant/agents/)").action(async (sourcePath, opts) => {
|
|
118561
118811
|
try {
|
|
118562
|
-
const { existsSync: existsSync131, mkdirSync: mkdirSync31, cpSync, readFileSync:
|
|
118812
|
+
const { existsSync: existsSync131, mkdirSync: mkdirSync31, cpSync, readFileSync: readFileSync102, rmSync: rmSync3, statSync: statSync22 } = await import("node:fs");
|
|
118563
118813
|
const { join: join131, basename: basename19, resolve: resolve16 } = await import("node:path");
|
|
118564
118814
|
const { homedir: homedir7 } = await import("node:os");
|
|
118565
118815
|
const { tmpdir: tmpdir3 } = await import("node:os");
|
|
@@ -118678,7 +118928,7 @@ Task ${taskId} reassigned to you by ${active.agentId}. Run: cleo show ${taskId}
|
|
|
118678
118928
|
}
|
|
118679
118929
|
let registered = false;
|
|
118680
118930
|
try {
|
|
118681
|
-
const persona =
|
|
118931
|
+
const persona = readFileSync102(join131(targetDir, "persona.cant"), "utf-8");
|
|
118682
118932
|
const descMatch = persona.match(/description:\s*"([^"]+)"/);
|
|
118683
118933
|
const displayName = descMatch?.[1] ?? agentName;
|
|
118684
118934
|
const { AgentRegistryAccessor: AgentRegistryAccessor2, getDb: getDb4 } = await Promise.resolve().then(() => (init_internal(), internal_exports));
|
|
@@ -120277,7 +120527,7 @@ function registerBugCommand(program) {
|
|
|
120277
120527
|
|
|
120278
120528
|
// packages/cleo/src/cli/commands/cant.ts
|
|
120279
120529
|
init_renderers();
|
|
120280
|
-
import { existsSync as existsSync128, mkdirSync as mkdirSync29, readFileSync as
|
|
120530
|
+
import { existsSync as existsSync128, mkdirSync as mkdirSync29, readFileSync as readFileSync97, writeFileSync as writeFileSync23 } from "node:fs";
|
|
120281
120531
|
import { dirname as dirname25, isAbsolute as isAbsolute3, join as join124, resolve as resolve15 } from "node:path";
|
|
120282
120532
|
function registerCantCommand(program) {
|
|
120283
120533
|
const cant = program.command("cant").description("CANT DSL tooling");
|
|
@@ -120355,7 +120605,7 @@ function registerCantCommand(program) {
|
|
|
120355
120605
|
}
|
|
120356
120606
|
try {
|
|
120357
120607
|
const mod = await loadMigrateEngine();
|
|
120358
|
-
const content =
|
|
120608
|
+
const content = readFileSync97(filePath, "utf-8");
|
|
120359
120609
|
const result = mod.migrateMarkdown(content, filePath, {
|
|
120360
120610
|
write: isWrite,
|
|
120361
120611
|
verbose: isVerbose,
|
|
@@ -121150,7 +121400,7 @@ function registerDetectCommand(program) {
|
|
|
121150
121400
|
// packages/cleo/src/cli/commands/detect-drift.ts
|
|
121151
121401
|
init_src();
|
|
121152
121402
|
init_renderers();
|
|
121153
|
-
import { existsSync as existsSync129, readdirSync as readdirSync41, readFileSync as
|
|
121403
|
+
import { existsSync as existsSync129, readdirSync as readdirSync41, readFileSync as readFileSync98 } from "node:fs";
|
|
121154
121404
|
import { dirname as dirname26, join as join125 } from "node:path";
|
|
121155
121405
|
function findProjectRoot() {
|
|
121156
121406
|
let currentDir = process.cwd();
|
|
@@ -121170,7 +121420,7 @@ function registerDetectDriftCommand(program) {
|
|
|
121170
121420
|
const isCleoRepo = existsSync129(join125(projectRoot, "src", "cli", "commands")) || existsSync129(join125(projectRoot, "packages", "cleo", "src"));
|
|
121171
121421
|
const safeRead = (filePath) => {
|
|
121172
121422
|
try {
|
|
121173
|
-
return
|
|
121423
|
+
return readFileSync98(filePath, "utf-8");
|
|
121174
121424
|
} catch {
|
|
121175
121425
|
return "";
|
|
121176
121426
|
}
|
|
@@ -122088,6 +122338,20 @@ var FIND_PARAMS = [
|
|
|
122088
122338
|
required: false,
|
|
122089
122339
|
description: "Skip first N results",
|
|
122090
122340
|
cli: { flag: "offset", parse: parseInt }
|
|
122341
|
+
},
|
|
122342
|
+
{
|
|
122343
|
+
name: "fields",
|
|
122344
|
+
type: "string",
|
|
122345
|
+
required: false,
|
|
122346
|
+
description: "Comma-separated additional fields to include (e.g. labels,acceptance,notes,description)",
|
|
122347
|
+
cli: { flag: "fields" }
|
|
122348
|
+
},
|
|
122349
|
+
{
|
|
122350
|
+
name: "verbose",
|
|
122351
|
+
type: "boolean",
|
|
122352
|
+
required: false,
|
|
122353
|
+
description: "Include all task fields (same as cleo list output)",
|
|
122354
|
+
cli: { flag: "verbose", short: "-v" }
|
|
122091
122355
|
}
|
|
122092
122356
|
];
|
|
122093
122357
|
function registerFindCommand(program) {
|
|
@@ -122107,6 +122371,8 @@ function registerFindCommand(program) {
|
|
|
122107
122371
|
if (opts["includeArchive"] !== void 0) params["includeArchive"] = opts["includeArchive"];
|
|
122108
122372
|
if (limit !== void 0) params["limit"] = limit;
|
|
122109
122373
|
if (offset !== void 0) params["offset"] = offset;
|
|
122374
|
+
if (opts["fields"] !== void 0) params["fields"] = opts["fields"];
|
|
122375
|
+
if (opts["verbose"] !== void 0) params["verbose"] = opts["verbose"];
|
|
122110
122376
|
const response = await dispatchRaw("query", "tasks", "find", params);
|
|
122111
122377
|
if (!response.success) {
|
|
122112
122378
|
handleRawError(response, { command: "find", operation: "tasks.find" });
|
|
@@ -122134,12 +122400,12 @@ init_src();
|
|
|
122134
122400
|
init_src2();
|
|
122135
122401
|
init_renderers();
|
|
122136
122402
|
import { execFileSync as execFileSync16 } from "node:child_process";
|
|
122137
|
-
import { existsSync as existsSync130, mkdirSync as mkdirSync30, readFileSync as
|
|
122403
|
+
import { existsSync as existsSync130, mkdirSync as mkdirSync30, readFileSync as readFileSync99, writeFileSync as writeFileSync24 } from "node:fs";
|
|
122138
122404
|
import { dirname as dirname27, join as join127 } from "node:path";
|
|
122139
122405
|
function getChangelogSource(cwd) {
|
|
122140
122406
|
const configPath = getConfigPath(cwd);
|
|
122141
122407
|
try {
|
|
122142
|
-
const config2 = JSON.parse(
|
|
122408
|
+
const config2 = JSON.parse(readFileSync99(configPath, "utf-8"));
|
|
122143
122409
|
return config2?.release?.changelog?.source ?? "CHANGELOG.md";
|
|
122144
122410
|
} catch {
|
|
122145
122411
|
return "CHANGELOG.md";
|
|
@@ -122148,7 +122414,7 @@ function getChangelogSource(cwd) {
|
|
|
122148
122414
|
function getEnabledPlatforms(cwd) {
|
|
122149
122415
|
const configPath = getConfigPath(cwd);
|
|
122150
122416
|
try {
|
|
122151
|
-
const config2 = JSON.parse(
|
|
122417
|
+
const config2 = JSON.parse(readFileSync99(configPath, "utf-8"));
|
|
122152
122418
|
const outputs = config2?.release?.changelog?.outputs ?? [];
|
|
122153
122419
|
return outputs.filter((o) => o.enabled);
|
|
122154
122420
|
} catch {
|
|
@@ -122277,7 +122543,7 @@ function registerGenerateChangelogCommand(program) {
|
|
|
122277
122543
|
if (!existsSync130(sourcePath)) {
|
|
122278
122544
|
throw new CleoError(4 /* NOT_FOUND */, `Changelog source not found: ${sourcePath}`);
|
|
122279
122545
|
}
|
|
122280
|
-
const sourceContent =
|
|
122546
|
+
const sourceContent = readFileSync99(sourcePath, "utf-8");
|
|
122281
122547
|
const repoSlug = getGitHubRepoSlug();
|
|
122282
122548
|
const results = [];
|
|
122283
122549
|
if (targetPlatform) {
|
|
@@ -125333,7 +125599,7 @@ init_src2();
|
|
|
125333
125599
|
init_cli();
|
|
125334
125600
|
init_renderers();
|
|
125335
125601
|
function registerStickyCommand(program) {
|
|
125336
|
-
const sticky = program.command("sticky").
|
|
125602
|
+
const sticky = program.command("sticky").description("Manage sticky notes - quick project-wide ephemeral captures");
|
|
125337
125603
|
sticky.command("add <content>").alias("jot").description("Create a new sticky note").option("--tag <tag>", "Add a tag (can be used multiple times)", collect, []).option("--color <color>", "Sticky color: yellow|blue|green|red|purple", "yellow").option("--priority <priority>", "Priority: low|medium|high", "medium").action(async (content, opts) => {
|
|
125338
125604
|
try {
|
|
125339
125605
|
await dispatchFromCli(
|
|
@@ -125369,7 +125635,7 @@ function registerStickyCommand(program) {
|
|
|
125369
125635
|
return;
|
|
125370
125636
|
}
|
|
125371
125637
|
const data = response.data;
|
|
125372
|
-
if (!data
|
|
125638
|
+
if (!data?.stickies || data.stickies.length === 0) {
|
|
125373
125639
|
cliOutput(
|
|
125374
125640
|
{ stickies: [], total: 0 },
|
|
125375
125641
|
{ command: "sticky list", message: "No sticky notes found", operation: "sticky.list" }
|
|
@@ -125581,11 +125847,11 @@ function registerTestingCommand(program) {
|
|
|
125581
125847
|
init_internal();
|
|
125582
125848
|
init_cli();
|
|
125583
125849
|
init_renderers();
|
|
125584
|
-
import { readFileSync as
|
|
125850
|
+
import { readFileSync as readFileSync100 } from "node:fs";
|
|
125585
125851
|
function readPayload(opts, textKey, fileKey) {
|
|
125586
125852
|
const text3 = opts[textKey];
|
|
125587
125853
|
const file2 = opts[fileKey];
|
|
125588
|
-
if (file2) return
|
|
125854
|
+
if (file2) return readFileSync100(file2, "utf-8");
|
|
125589
125855
|
return text3;
|
|
125590
125856
|
}
|
|
125591
125857
|
function registerTokenCommand(program) {
|
|
@@ -126171,7 +126437,7 @@ var codeCommand = defineCommand({
|
|
|
126171
126437
|
// packages/cleo/src/cli/index.ts
|
|
126172
126438
|
function getPackageVersion() {
|
|
126173
126439
|
const pkgPath = join130(dirname28(fileURLToPath5(import.meta.url)), "../../package.json");
|
|
126174
|
-
const pkg = JSON.parse(
|
|
126440
|
+
const pkg = JSON.parse(readFileSync101(pkgPath, "utf-8"));
|
|
126175
126441
|
return pkg.version;
|
|
126176
126442
|
}
|
|
126177
126443
|
var CLI_VERSION = getPackageVersion();
|
|
@@ -126179,6 +126445,7 @@ var rootShim = new ShimCommand();
|
|
|
126179
126445
|
registerAgentCommand(rootShim);
|
|
126180
126446
|
registerAgentsCommand(rootShim);
|
|
126181
126447
|
registerAddCommand(rootShim);
|
|
126448
|
+
registerAddBatchCommand(rootShim);
|
|
126182
126449
|
registerListCommand(rootShim);
|
|
126183
126450
|
registerShowCommand(rootShim);
|
|
126184
126451
|
registerFindCommand(rootShim);
|