@cleocode/cleo 2026.4.111 → 2026.4.113

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
@@ -1037,6 +1037,27 @@ var init_normalizer = __esm({
1037
1037
  }
1038
1038
  });
1039
1039
 
1040
+ // packages/cleo/src/cli/tree-context.ts
1041
+ function setTreeContext(ctx) {
1042
+ currentContext2 = {
1043
+ withDeps: ctx.withDeps ?? false,
1044
+ withBlockers: ctx.withBlockers ?? false
1045
+ };
1046
+ }
1047
+ function getTreeContext() {
1048
+ return currentContext2;
1049
+ }
1050
+ var currentContext2;
1051
+ var init_tree_context = __esm({
1052
+ "packages/cleo/src/cli/tree-context.ts"() {
1053
+ "use strict";
1054
+ currentContext2 = {
1055
+ withDeps: false,
1056
+ withBlockers: false
1057
+ };
1058
+ }
1059
+ });
1060
+
1040
1061
  // packages/cleo/src/cli/renderers/colors.ts
1041
1062
  function ansi2(code) {
1042
1063
  return colorsEnabled ? code : "";
@@ -1154,6 +1175,31 @@ var init_colors = __esm({
1154
1175
  });
1155
1176
 
1156
1177
  // packages/cleo/src/cli/renderers/system.ts
1178
+ import { formatTree, formatWaves } from "@cleocode/core/formatters";
1179
+ function cliColorize(text, style) {
1180
+ switch (style) {
1181
+ case "bold":
1182
+ return `${BOLD}${text}${NC}`;
1183
+ case "dim":
1184
+ return `${DIM}${text}${NC}`;
1185
+ case "red":
1186
+ return `${RED}${text}${NC}`;
1187
+ case "green":
1188
+ return `${GREEN}${text}${NC}`;
1189
+ case "yellow":
1190
+ return `${YELLOW}${text}${NC}`;
1191
+ case "blue":
1192
+ return `${BLUE}${text}${NC}`;
1193
+ case "magenta":
1194
+ return `${MAGENTA}${text}${NC}`;
1195
+ case "cyan":
1196
+ return `${CYAN}${text}${NC}`;
1197
+ case "reset":
1198
+ return `${NC}${text}`;
1199
+ default:
1200
+ return text;
1201
+ }
1202
+ }
1157
1203
  function renderDoctor(data, quiet) {
1158
1204
  const healthy = data["healthy"];
1159
1205
  const errors = data["errors"];
@@ -1256,11 +1302,37 @@ function renderBlockers(data, quiet) {
1256
1302
  }
1257
1303
  return lines.join("\n");
1258
1304
  }
1305
+ function renderWaves(data, opts) {
1306
+ return formatWaves(data, {
1307
+ mode: opts?.mode ?? "rich",
1308
+ colorize: cliColorize
1309
+ });
1310
+ }
1259
1311
  function renderTree(data, quiet) {
1312
+ const waves = data["waves"];
1260
1313
  const tree = data["tree"];
1261
1314
  const tasks = data["tasks"];
1315
+ if (waves) {
1316
+ const epicId = data["epicId"];
1317
+ const totalWaves = data["totalWaves"];
1318
+ const totalTasks = data["totalTasks"];
1319
+ if (quiet) {
1320
+ return renderWaves(data, { mode: "quiet" });
1321
+ }
1322
+ const header = epicId ? `${BOLD}Waves for ${epicId}${NC} ${DIM}(${totalWaves ?? waves.length} waves, ${totalTasks ?? "?"} tasks)${NC}` : `${BOLD}Execution Waves${NC}`;
1323
+ const body = renderWaves(data, { mode: "rich", epicId, totalWaves, totalTasks });
1324
+ return `${header}
1325
+
1326
+ ${body}`;
1327
+ }
1262
1328
  if (tree) {
1263
- return renderTreeNodes(tree, "", quiet);
1329
+ const { withDeps, withBlockers } = getTreeContext();
1330
+ return formatTree(tree, {
1331
+ mode: quiet ? "quiet" : "rich",
1332
+ colorize: cliColorize,
1333
+ withDeps,
1334
+ withBlockers
1335
+ });
1264
1336
  }
1265
1337
  if (tasks) {
1266
1338
  if (quiet) return tasks.map((t) => t.id).join("\n");
@@ -1271,29 +1343,6 @@ function renderTree(data, quiet) {
1271
1343
  }
1272
1344
  return quiet ? "" : "No tree data.";
1273
1345
  }
1274
- function renderTreeNodes(nodes, prefix, quiet) {
1275
- const lines = [];
1276
- for (let i = 0; i < nodes.length; i++) {
1277
- const node = nodes[i];
1278
- const isLast = i === nodes.length - 1;
1279
- const connector = isLast ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
1280
- const childPrefix = isLast ? " " : "\u2502 ";
1281
- const id = String(node["id"] ?? "");
1282
- const title = String(node["title"] ?? "");
1283
- const status = String(node["status"] ?? "");
1284
- const sSym = statusSymbol(status);
1285
- if (quiet) {
1286
- lines.push(`${prefix}${id}`);
1287
- } else {
1288
- lines.push(`${prefix}${connector}${sSym} ${BOLD}${id}${NC} ${title}`);
1289
- }
1290
- const children = node["children"];
1291
- if (children?.length) {
1292
- lines.push(renderTreeNodes(children, prefix + childPrefix, quiet));
1293
- }
1294
- }
1295
- return lines.join("\n");
1296
- }
1297
1346
  function renderStart(data, quiet) {
1298
1347
  const task = data["task"];
1299
1348
  const taskId = data["taskId"];
@@ -1487,6 +1536,7 @@ function formatLabel(key) {
1487
1536
  var init_system2 = __esm({
1488
1537
  "packages/cleo/src/cli/renderers/system.ts"() {
1489
1538
  "use strict";
1539
+ init_tree_context();
1490
1540
  init_colors();
1491
1541
  }
1492
1542
  });
@@ -1731,7 +1781,8 @@ var init_tasks2 = __esm({
1731
1781
  var renderers_exports = {};
1732
1782
  __export(renderers_exports, {
1733
1783
  cliError: () => cliError,
1734
- cliOutput: () => cliOutput
1784
+ cliOutput: () => cliOutput,
1785
+ renderWaves: () => renderWaves
1735
1786
  });
1736
1787
  import { randomUUID } from "node:crypto";
1737
1788
  import { formatSuccess } from "@cleocode/core";
@@ -1908,6 +1959,9 @@ var init_renderers = __esm({
1908
1959
  tree: renderTree,
1909
1960
  depends: renderTree,
1910
1961
  deps: renderTree,
1962
+ // Orchestration — `cleo orchestrate waves` emits { waves, epicId, ... }
1963
+ // which renderTree handles via its data.waves branch (T1194/T1195).
1964
+ orchestrate: renderTree,
1911
1965
  session: renderSession,
1912
1966
  version: renderVersion
1913
1967
  };
@@ -4903,7 +4957,7 @@ var init_registry = __esm({
4903
4957
  gateway: "mutate",
4904
4958
  domain: "pipeline",
4905
4959
  operation: "manifest.append",
4906
- description: "pipeline.manifest.append (mutate) \u2014 append entry to MANIFEST.jsonl",
4960
+ description: "pipeline.manifest.append (mutate) \u2014 append entry to pipeline_manifest (SQLite table per ADR-027)",
4907
4961
  tier: 1,
4908
4962
  idempotent: false,
4909
4963
  sessionRequired: false,
@@ -12785,9 +12839,9 @@ async function taskBlockers(projectRoot, params) {
12785
12839
  return engineError("E_NOT_INITIALIZED", "Task database not initialized");
12786
12840
  }
12787
12841
  }
12788
- async function taskTree(projectRoot, taskId) {
12842
+ async function taskTree(projectRoot, taskId, withBlockers) {
12789
12843
  try {
12790
- const result = await coreTaskTree(projectRoot, taskId);
12844
+ const result = await coreTaskTree(projectRoot, taskId, withBlockers);
12791
12845
  return { success: true, data: result };
12792
12846
  } catch (err) {
12793
12847
  return cleoErrorToEngineError(err, "E_NOT_FOUND", "Task not found");
@@ -28805,7 +28859,8 @@ var init_tasks3 = __esm({
28805
28859
  }
28806
28860
  case "tree": {
28807
28861
  const taskId = params?.taskId;
28808
- const result = await taskTree(projectRoot, taskId);
28862
+ const withBlockers = params?.withBlockers;
28863
+ const result = await taskTree(projectRoot, taskId, withBlockers);
28809
28864
  return wrapResult(result, "query", "tasks", operation, startTime);
28810
28865
  }
28811
28866
  case "blockers": {
@@ -39170,6 +39225,7 @@ init_src();
39170
39225
  import { depsCriticalPath, resolveProjectRoot as resolveProjectRoot5 } from "@cleocode/core/internal";
39171
39226
  init_cli();
39172
39227
  init_renderers();
39228
+ init_tree_context();
39173
39229
  var overviewCommand = defineCommand({
39174
39230
  meta: { name: "overview", description: "Overview of all dependencies" },
39175
39231
  async run() {
@@ -39311,14 +39367,25 @@ var treeCommand = defineCommand({
39311
39367
  type: "positional",
39312
39368
  description: "Root task ID (optional)",
39313
39369
  required: false
39370
+ },
39371
+ withDeps: {
39372
+ type: "boolean",
39373
+ description: "Inline dependency chain below each task that has deps",
39374
+ default: false
39375
+ },
39376
+ blockers: {
39377
+ type: "boolean",
39378
+ description: "Render transitive blocker chain and leaf blockers below each blocked task",
39379
+ default: false
39314
39380
  }
39315
39381
  },
39316
39382
  async run({ args }) {
39383
+ setTreeContext({ withDeps: args.withDeps, withBlockers: args.blockers });
39317
39384
  await dispatchFromCli(
39318
39385
  "query",
39319
39386
  "tasks",
39320
39387
  "tree",
39321
- { taskId: args.rootId },
39388
+ { taskId: args.rootId, withBlockers: args.blockers },
39322
39389
  { command: "tree", operation: "tasks.tree" }
39323
39390
  );
39324
39391
  }
@@ -42654,6 +42721,7 @@ var logCommand2 = defineCommand({
42654
42721
  });
42655
42722
 
42656
42723
  // packages/cleo/src/cli/commands/manifest.ts
42724
+ import { buildManifestEntryFromShorthand } from "@cleocode/core/memory/manifest-builder.js";
42657
42725
  init_cli();
42658
42726
  var showCommand7 = defineCommand({
42659
42727
  meta: {
@@ -42796,24 +42864,32 @@ var statsCommand3 = defineCommand({
42796
42864
  var appendCommand = defineCommand({
42797
42865
  meta: {
42798
42866
  name: "append",
42799
- description: "Append a new manifest entry"
42867
+ description: "Append a new manifest entry (pipeline_manifest table). Accepts either a full --entry JSON blob / --file / stdin, OR the shorthand --task + --type + --content flags which build a valid entry with sensible defaults for id/file/title/date/etc."
42800
42868
  },
42801
42869
  args: {
42802
42870
  entry: {
42803
42871
  type: "string",
42804
- description: "JSON string of entry fields"
42872
+ description: "JSON string of entry fields (full ManifestEntry shape)"
42805
42873
  },
42806
42874
  task: {
42807
42875
  type: "string",
42808
- description: "Task ID to associate (shorthand for entry.task_id)"
42876
+ description: "Task ID to associate \u2014 becomes linked_tasks[0] + id prefix (shorthand)"
42809
42877
  },
42810
42878
  type: {
42811
42879
  type: "string",
42812
- description: "Entry type (shorthand for entry.type)"
42880
+ description: "Entry type \u2014 becomes agent_type (e.g. research, implementation, decomposition) (shorthand)"
42813
42881
  },
42814
42882
  content: {
42815
42883
  type: "string",
42816
- description: "Entry content string (shorthand for entry.content)"
42884
+ description: "One-paragraph summary \u2014 becomes key_findings[0] and title (first line) (shorthand)"
42885
+ },
42886
+ title: {
42887
+ type: "string",
42888
+ description: "Explicit title override for shorthand mode"
42889
+ },
42890
+ status: {
42891
+ type: "string",
42892
+ description: "Entry status: completed (default) | partial | blocked (shorthand)"
42817
42893
  },
42818
42894
  file: {
42819
42895
  type: "string",
@@ -42822,6 +42898,7 @@ var appendCommand = defineCommand({
42822
42898
  },
42823
42899
  async run({ args }) {
42824
42900
  let entry;
42901
+ const hasShorthand = Boolean(args.task || args.type || args.content);
42825
42902
  if (args.entry) {
42826
42903
  try {
42827
42904
  entry = JSON.parse(args.entry);
@@ -42838,10 +42915,22 @@ var appendCommand = defineCommand({
42838
42915
  console.error(`Error: failed to read or parse ${args.file}`);
42839
42916
  process.exit(1);
42840
42917
  }
42918
+ } else if (hasShorthand) {
42919
+ entry = {
42920
+ ...buildManifestEntryFromShorthand({
42921
+ task: args.task,
42922
+ type: args.type,
42923
+ content: args.content,
42924
+ title: args.title,
42925
+ status: args.status
42926
+ })
42927
+ };
42841
42928
  } else {
42842
42929
  const stdinData = await readStdin();
42843
42930
  if (!stdinData) {
42844
- console.error("Error: must provide --entry, --file, or stdin with JSON entry data");
42931
+ console.error(
42932
+ "Error: must provide --entry JSON, --file path, stdin, or shorthand (--task + --type + --content)"
42933
+ );
42845
42934
  process.exit(1);
42846
42935
  }
42847
42936
  try {
@@ -42851,14 +42940,22 @@ var appendCommand = defineCommand({
42851
42940
  process.exit(1);
42852
42941
  }
42853
42942
  }
42854
- if (args.task) {
42855
- entry.task_id = args.task;
42856
- }
42857
- if (args.type) {
42858
- entry.type = args.type;
42859
- }
42860
- if (args.content) {
42861
- entry.content = args.content;
42943
+ if ((args.entry || args.file) && hasShorthand) {
42944
+ if (args.task) {
42945
+ entry.linked_tasks = Array.isArray(entry.linked_tasks) ? [args.task, ...entry.linked_tasks.filter((t) => t !== args.task)] : [args.task];
42946
+ }
42947
+ if (args.type) {
42948
+ entry.agent_type = args.type;
42949
+ }
42950
+ if (args.content && !entry.key_findings) {
42951
+ entry.key_findings = [args.content];
42952
+ }
42953
+ if (args.title) {
42954
+ entry.title = args.title;
42955
+ }
42956
+ if (args.status) {
42957
+ entry.status = args.status;
42958
+ }
42862
42959
  }
42863
42960
  await dispatchFromCli(
42864
42961
  "mutate",
@@ -52681,7 +52778,7 @@ var archiveCommand3 = defineCommand({
52681
52778
  }
52682
52779
  });
52683
52780
  var manifestCommand2 = defineCommand({
52684
- meta: { name: "manifest", description: "Query MANIFEST.jsonl entries" },
52781
+ meta: { name: "manifest", description: "Query pipeline_manifest entries" },
52685
52782
  args: {
52686
52783
  status: {
52687
52784
  type: "string",