@cleocode/cleo 2026.5.113 → 2026.5.120

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
@@ -1388,6 +1388,40 @@ var init_animation_bridge = __esm({
1388
1388
  }
1389
1389
  });
1390
1390
 
1391
+ // packages/cleo/src/cli/output-context.ts
1392
+ function setOutputMode(mode) {
1393
+ currentMode = mode;
1394
+ }
1395
+ function getOutputMode() {
1396
+ return currentMode;
1397
+ }
1398
+ function isOutputMode(value) {
1399
+ return OUTPUT_MODES.includes(value);
1400
+ }
1401
+ var OUTPUT_MODES, currentMode;
1402
+ var init_output_context = __esm({
1403
+ "packages/cleo/src/cli/output-context.ts"() {
1404
+ "use strict";
1405
+ OUTPUT_MODES = ["envelope", "id", "table", "count", "silent"];
1406
+ currentMode = "envelope";
1407
+ }
1408
+ });
1409
+
1410
+ // packages/cleo/src/cli/summary-context.ts
1411
+ function setSummaryMode(on) {
1412
+ currentSummary = on;
1413
+ }
1414
+ function getSummaryMode() {
1415
+ return currentSummary;
1416
+ }
1417
+ var currentSummary;
1418
+ var init_summary_context = __esm({
1419
+ "packages/cleo/src/cli/summary-context.ts"() {
1420
+ "use strict";
1421
+ currentSummary = false;
1422
+ }
1423
+ });
1424
+
1391
1425
  // packages/contracts/src/acceptance-gate-schema.ts
1392
1426
  import { z } from "zod";
1393
1427
  var gateBaseSchema, fileAssertionSchema, testGateSchema, fileGateSchema, commandGateSchema, lintGateSchema, httpGateSchema, manualGateSchema, acceptanceGateSchema, gateResultDetailsSchema, acceptanceGateResultSchema, acceptanceItemSchema, acceptanceArraySchema;
@@ -4248,6 +4282,39 @@ var init_operations_registry = __esm({
4248
4282
  }
4249
4283
  ]
4250
4284
  },
4285
+ {
4286
+ gateway: "mutate",
4287
+ domain: "tasks",
4288
+ operation: "relates.remove",
4289
+ description: "tasks.relates.remove (mutate) \u2014 delete a relation between two tasks. Pass `type` to scope deletion to a single relation kind; omit to remove any type.",
4290
+ tier: 1,
4291
+ idempotent: true,
4292
+ sessionRequired: false,
4293
+ requiredParams: ["taskId", "relatedId"],
4294
+ params: [
4295
+ {
4296
+ name: "taskId",
4297
+ type: "string",
4298
+ required: true,
4299
+ description: "Source task ID",
4300
+ cli: { positional: true }
4301
+ },
4302
+ {
4303
+ name: "relatedId",
4304
+ type: "string",
4305
+ required: true,
4306
+ description: "Target task ID to remove the relation to",
4307
+ cli: { positional: true }
4308
+ },
4309
+ {
4310
+ name: "type",
4311
+ type: "string",
4312
+ required: false,
4313
+ description: "Optional relation type (blocks|related|duplicates|absorbs|fixes|extends|supersedes). Omit to remove any type.",
4314
+ cli: { flag: "type" }
4315
+ }
4316
+ ]
4317
+ },
4251
4318
  // === saga sub-domain (ADR-073 — above-epic grouping tier) ===
4252
4319
  {
4253
4320
  gateway: "mutate",
@@ -8533,6 +8600,39 @@ var init_operations_registry = __esm({
8533
8600
  }
8534
8601
  ]
8535
8602
  },
8603
+ // ── docs.supersede (T10162) ──────────────────────────────────────────────
8604
+ {
8605
+ gateway: "mutate",
8606
+ domain: "docs",
8607
+ operation: "supersede",
8608
+ description: "docs.supersede (mutate) \u2014 atomically flip an older doc to `superseded` and link both rows via the supersedes/superseded_by self-FK pointers (T10162 \xB7 Saga T9855)",
8609
+ tier: 1,
8610
+ idempotent: true,
8611
+ sessionRequired: false,
8612
+ requiredParams: ["oldSlug", "newSlug"],
8613
+ params: [
8614
+ {
8615
+ name: "oldSlug",
8616
+ type: "string",
8617
+ required: true,
8618
+ description: "Slug of the doc being replaced",
8619
+ cli: { positional: true }
8620
+ },
8621
+ {
8622
+ name: "newSlug",
8623
+ type: "string",
8624
+ required: true,
8625
+ description: "Slug of the doc that replaces oldSlug",
8626
+ cli: { positional: true }
8627
+ },
8628
+ {
8629
+ name: "reason",
8630
+ type: "string",
8631
+ required: false,
8632
+ description: "Optional human-readable reason carried back on the response"
8633
+ }
8634
+ ]
8635
+ },
8536
8636
  // ── docs.generate (T798) ─────────────────────────────────────────────────
8537
8637
  {
8538
8638
  gateway: "query",
@@ -8558,6 +8658,55 @@ var init_operations_registry = __esm({
8558
8658
  }
8559
8659
  ]
8560
8660
  },
8661
+ // ── docs.update (T10161 — Epic T10157 / Saga T9855) ──────────────────────
8662
+ {
8663
+ gateway: "mutate",
8664
+ domain: "docs",
8665
+ operation: "update",
8666
+ description: "docs.update (mutate) \u2014 replace blob content for an existing slug while preserving the slug. New sha256 + new attachment row; the old row stays reachable by ID for history. NO supersession edge (use `cleo docs supersede` for that). Audit log entry appended to .cleo/audit/docs-versioning.jsonl (squashed within a 5-min window).",
8667
+ tier: 1,
8668
+ idempotent: false,
8669
+ sessionRequired: false,
8670
+ requiredParams: ["slug"],
8671
+ params: [
8672
+ {
8673
+ name: "slug",
8674
+ type: "string",
8675
+ required: true,
8676
+ description: "Slug of the existing attachment to update"
8677
+ },
8678
+ {
8679
+ name: "file",
8680
+ type: "string",
8681
+ required: false,
8682
+ description: "Path to a local file containing the new content"
8683
+ },
8684
+ {
8685
+ name: "content",
8686
+ type: "string",
8687
+ required: false,
8688
+ description: "Inline UTF-8 content (mutually exclusive with file)"
8689
+ },
8690
+ {
8691
+ name: "message",
8692
+ type: "string",
8693
+ required: false,
8694
+ description: "One-line summary describing the change (recorded in the audit log)"
8695
+ },
8696
+ {
8697
+ name: "status",
8698
+ type: "string",
8699
+ required: false,
8700
+ description: 'Override the new lifecycle status. Defaults to "draft" on every update. Valid: draft|proposed|accepted|superseded|archived|deprecated.'
8701
+ },
8702
+ {
8703
+ name: "attachedBy",
8704
+ type: "string",
8705
+ required: false,
8706
+ description: 'Agent identity that performed the update (defaults to "human")'
8707
+ }
8708
+ ]
8709
+ },
8561
8710
  // ── playbook.* HITL CLI surface (T935) ───────────────────────────────────
8562
8711
  {
8563
8712
  gateway: "mutate",
@@ -12317,6 +12466,7 @@ var init_src2 = __esm({
12317
12466
  init_operations();
12318
12467
  init_nexus_scope_map();
12319
12468
  init_params();
12469
+ init_tasks();
12320
12470
  init_peer();
12321
12471
  init_evidence_atoms();
12322
12472
  init_plan();
@@ -12519,6 +12669,174 @@ var init_normalizer = __esm({
12519
12669
  }
12520
12670
  });
12521
12671
 
12672
+ // packages/cleo/src/cli/renderers/output-mode.ts
12673
+ function extractIds(data) {
12674
+ if (data === null || typeof data !== "object") return [];
12675
+ const rec = data;
12676
+ const task = rec["task"];
12677
+ if (task && typeof task === "object") {
12678
+ const id2 = task["id"];
12679
+ if (typeof id2 === "string") return [id2];
12680
+ }
12681
+ const tasks = rec["tasks"];
12682
+ if (Array.isArray(tasks)) {
12683
+ return tasks.map((t) => t && typeof t === "object" ? t["id"] : void 0).filter((id2) => typeof id2 === "string");
12684
+ }
12685
+ const items = rec["items"];
12686
+ if (Array.isArray(items)) {
12687
+ return items.map((t) => t && typeof t === "object" ? t["id"] : void 0).filter((id2) => typeof id2 === "string");
12688
+ }
12689
+ const id = rec["id"];
12690
+ if (typeof id === "string") return [id];
12691
+ return [];
12692
+ }
12693
+ function extractCount(data) {
12694
+ if (data === null || typeof data !== "object") return 0;
12695
+ const rec = data;
12696
+ const total = rec["total"];
12697
+ if (typeof total === "number" && Number.isFinite(total)) return total;
12698
+ const tasks = rec["tasks"];
12699
+ if (Array.isArray(tasks)) return tasks.length;
12700
+ const items = rec["items"];
12701
+ if (Array.isArray(items)) return items.length;
12702
+ if (rec["task"] && typeof rec["task"] === "object") return 1;
12703
+ if (typeof rec["id"] === "string") return 1;
12704
+ return 0;
12705
+ }
12706
+ function truncate(value, max) {
12707
+ if (value.length <= max) return value;
12708
+ return value.slice(0, Math.max(0, max - 1)) + "\u2026";
12709
+ }
12710
+ function renderTableList(tasks) {
12711
+ if (tasks.length === 0) return "No rows.";
12712
+ const COL_TITLE_MAX = 60;
12713
+ const rows = tasks.map((t) => ({
12714
+ id: typeof t["id"] === "string" ? t["id"] : "",
12715
+ status: typeof t["status"] === "string" ? t["status"] : "",
12716
+ priority: typeof t["priority"] === "string" ? t["priority"] : "",
12717
+ title: truncate(typeof t["title"] === "string" ? t["title"] : "", COL_TITLE_MAX)
12718
+ }));
12719
+ const widths = {
12720
+ id: Math.max(2, ...rows.map((r) => r.id.length)),
12721
+ status: Math.max(6, ...rows.map((r) => r.status.length)),
12722
+ priority: Math.max(8, ...rows.map((r) => r.priority.length)),
12723
+ title: Math.max(5, ...rows.map((r) => r.title.length))
12724
+ };
12725
+ const pad = (s, w) => s + " ".repeat(Math.max(0, w - s.length));
12726
+ const header = `${pad("id", widths.id)} ${pad("status", widths.status)} ${pad(
12727
+ "priority",
12728
+ widths.priority
12729
+ )} ${pad("title", widths.title)}`;
12730
+ const sep2 = `${"-".repeat(widths.id)} ${"-".repeat(widths.status)} ${"-".repeat(
12731
+ widths.priority
12732
+ )} ${"-".repeat(widths.title)}`;
12733
+ const body = rows.map(
12734
+ (r) => `${pad(r.id, widths.id)} ${pad(r.status, widths.status)} ${pad(
12735
+ r.priority,
12736
+ widths.priority
12737
+ )} ${pad(r.title, widths.title)}`
12738
+ ).join("\n");
12739
+ return `${header}
12740
+ ${sep2}
12741
+ ${body}`;
12742
+ }
12743
+ function renderTableGeneric(data) {
12744
+ const entries = Object.entries(data);
12745
+ if (entries.length === 0) return "(empty)";
12746
+ const rows = entries.map(([k, v]) => ({
12747
+ field: k,
12748
+ value: v === null || v === void 0 ? "" : typeof v === "object" ? JSON.stringify(v) : String(v)
12749
+ }));
12750
+ const VAL_MAX = 80;
12751
+ for (const r of rows) r.value = truncate(r.value, VAL_MAX);
12752
+ const widths = {
12753
+ field: Math.max(5, ...rows.map((r) => r.field.length)),
12754
+ value: Math.max(5, ...rows.map((r) => r.value.length))
12755
+ };
12756
+ const pad = (s, w) => s + " ".repeat(Math.max(0, w - s.length));
12757
+ const header = `${pad("field", widths.field)} ${pad("value", widths.value)}`;
12758
+ const sep2 = `${"-".repeat(widths.field)} ${"-".repeat(widths.value)}`;
12759
+ const body = rows.map((r) => `${pad(r.field, widths.field)} ${pad(r.value, widths.value)}`).join("\n");
12760
+ return `${header}
12761
+ ${sep2}
12762
+ ${body}`;
12763
+ }
12764
+ function renderSummary2(data) {
12765
+ if (data === null || typeof data !== "object") {
12766
+ return { text: "" };
12767
+ }
12768
+ const rec = data;
12769
+ const tasks = rec["tasks"];
12770
+ if (Array.isArray(tasks)) {
12771
+ return { text: renderSummaryList(tasks) };
12772
+ }
12773
+ const items = rec["items"];
12774
+ if (Array.isArray(items)) {
12775
+ return { text: renderSummaryList(items) };
12776
+ }
12777
+ const task = rec["task"];
12778
+ if (task && typeof task === "object") {
12779
+ return { text: renderSummaryRow(task) };
12780
+ }
12781
+ if (typeof rec["id"] === "string") {
12782
+ return { text: renderSummaryRow(rec) };
12783
+ }
12784
+ return { text: "" };
12785
+ }
12786
+ function renderSummaryRow(record) {
12787
+ const id = typeof record["id"] === "string" ? record["id"] : "";
12788
+ const status = typeof record["status"] === "string" ? record["status"] : "";
12789
+ const title = truncate(typeof record["title"] === "string" ? record["title"] : "", 60);
12790
+ return `${id} [${status}] ${title}`;
12791
+ }
12792
+ function renderSummaryList(rows) {
12793
+ if (rows.length === 0) return "No rows.";
12794
+ const lines = [];
12795
+ for (const row of rows) {
12796
+ if (!row || typeof row !== "object") continue;
12797
+ const rec = row;
12798
+ if (typeof rec["id"] !== "string") continue;
12799
+ lines.push(renderSummaryRow(rec));
12800
+ }
12801
+ return lines.length === 0 ? "No rows." : lines.join("\n");
12802
+ }
12803
+ function renderOutputMode(mode, data) {
12804
+ switch (mode) {
12805
+ case "id": {
12806
+ const ids = extractIds(data);
12807
+ return { text: ids.length === 0 ? "" : ids.join("\n") };
12808
+ }
12809
+ case "count": {
12810
+ return { text: String(extractCount(data)) };
12811
+ }
12812
+ case "table": {
12813
+ if (data && typeof data === "object") {
12814
+ const rec = data;
12815
+ const tasks = rec["tasks"];
12816
+ if (Array.isArray(tasks)) {
12817
+ return { text: renderTableList(tasks) };
12818
+ }
12819
+ const items = rec["items"];
12820
+ if (Array.isArray(items)) {
12821
+ return { text: renderTableList(items) };
12822
+ }
12823
+ return { text: renderTableGeneric(rec) };
12824
+ }
12825
+ return { text: data === null || data === void 0 ? "(empty)" : String(data) };
12826
+ }
12827
+ case "silent": {
12828
+ return { text: null };
12829
+ }
12830
+ case "envelope":
12831
+ throw new Error("renderOutputMode: envelope mode must be handled by caller");
12832
+ }
12833
+ }
12834
+ var init_output_mode = __esm({
12835
+ "packages/cleo/src/cli/renderers/output-mode.ts"() {
12836
+ "use strict";
12837
+ }
12838
+ });
12839
+
12522
12840
  // packages/cleo/src/cli/renderers/index.ts
12523
12841
  var renderers_exports = {};
12524
12842
  __export(renderers_exports, {
@@ -12534,7 +12852,9 @@ __export(renderers_exports, {
12534
12852
  import { randomUUID } from "node:crypto";
12535
12853
  import {
12536
12854
  drainWarnings,
12855
+ extractByJsonPointer,
12537
12856
  formatSuccess,
12857
+ isJsonPointer,
12538
12858
  metaFooter,
12539
12859
  pagerFooter,
12540
12860
  renderAuditReconstruct,
@@ -12592,7 +12912,8 @@ import {
12592
12912
  renderStop,
12593
12913
  renderTree as renderTree2,
12594
12914
  renderVersion,
12595
- renderWaves
12915
+ renderWaves,
12916
+ serializePointerValue
12596
12917
  } from "@cleocode/core";
12597
12918
  import { applyFieldFilter, extractFieldFromResult } from "@cleocode/lafs";
12598
12919
  import {
@@ -12614,11 +12935,60 @@ function pickDecoratorMetaExtensionsLocal(responseMeta) {
12614
12935
  const out = {};
12615
12936
  if (responseMeta["_nexus"] !== void 0) out["_nexus"] = responseMeta["_nexus"];
12616
12937
  if (responseMeta["deprecated"] !== void 0) out["deprecated"] = responseMeta["deprecated"];
12938
+ if (responseMeta["suggestedNext"] !== void 0) {
12939
+ out["suggestedNext"] = responseMeta["suggestedNext"];
12940
+ }
12941
+ if (responseMeta["projection"] !== void 0) {
12942
+ out["projection"] = responseMeta["projection"];
12943
+ }
12617
12944
  return out;
12618
12945
  }
12946
+ function buildEnvelopeForPointer(data, opts) {
12947
+ const decoratorExt = pickDecoratorMetaExtensionsLocal(opts.responseMeta);
12948
+ const meta = {
12949
+ ...decoratorExt,
12950
+ ...opts.extensions ?? {},
12951
+ operation: opts.operation ?? "cli.output"
12952
+ };
12953
+ if (opts.message) meta["message"] = opts.message;
12954
+ const envelope = {
12955
+ success: true,
12956
+ data,
12957
+ meta
12958
+ };
12959
+ if (opts.page) envelope["page"] = opts.page;
12960
+ return envelope;
12961
+ }
12619
12962
  function cliOutput(data, opts) {
12620
12963
  const ctx = getFormatContext();
12621
12964
  const fieldCtx = getFieldContext();
12965
+ const outputMode = getOutputMode();
12966
+ const summary = getSummaryMode();
12967
+ if (outputMode !== "envelope" && !fieldCtx.field) {
12968
+ const out = renderOutputMode(outputMode, data);
12969
+ if (out.text !== null && out.text.length > 0) {
12970
+ process.stdout.write(out.text + "\n");
12971
+ }
12972
+ return;
12973
+ }
12974
+ if (summary && !fieldCtx.field) {
12975
+ const out = renderSummary2(data);
12976
+ if (out.text !== null && out.text.length > 0) {
12977
+ process.stdout.write(out.text + "\n");
12978
+ }
12979
+ return;
12980
+ }
12981
+ if (fieldCtx.field && isJsonPointer(fieldCtx.field)) {
12982
+ const envelope = buildEnvelopeForPointer(data, opts);
12983
+ const value = extractByJsonPointer(envelope, fieldCtx.field);
12984
+ if (value === void 0) {
12985
+ cliError(`Pointer "${fieldCtx.field}" did not resolve`, 4, { name: "E_FIELD_NOT_FOUND" });
12986
+ process.exit(4);
12987
+ }
12988
+ process.stdout.write(`${serializePointerValue(value)}
12989
+ `);
12990
+ return;
12991
+ }
12622
12992
  if (ctx.format === "human") {
12623
12993
  let dataToRender = data;
12624
12994
  let fieldExtracted = false;
@@ -12768,6 +13138,12 @@ function isHumanOutput() {
12768
13138
  }
12769
13139
  function cliError(message, code, details, meta) {
12770
13140
  const ctx = getFormatContext();
13141
+ const outputMode = getOutputMode();
13142
+ if (outputMode === "silent") {
13143
+ process.stderr.write(`Error: ${message}${code ? ` (${code})` : ""}
13144
+ `);
13145
+ return;
13146
+ }
12771
13147
  if (ctx.format === "human") {
12772
13148
  process.stderr.write(`Error: ${message}${code ? ` (${code})` : ""}
12773
13149
  `);
@@ -12810,8 +13186,11 @@ var init_renderers = __esm({
12810
13186
  "use strict";
12811
13187
  init_field_context();
12812
13188
  init_format_context();
13189
+ init_output_context();
13190
+ init_summary_context();
12813
13191
  init_lafs_validator();
12814
13192
  init_normalizer();
13193
+ init_output_mode();
12815
13194
  renderers = {
12816
13195
  // Task CRUD
12817
13196
  show: renderShow,
@@ -17004,18 +17383,25 @@ import { resolve as resolve2 } from "node:path";
17004
17383
  import { pushWarning } from "@cleocode/core";
17005
17384
  import {
17006
17385
  AUTO_TOKEN,
17386
+ allocateAdrSlug,
17007
17387
  allocateAutoSlugForDispatch,
17388
+ consumeReservedSlug,
17008
17389
  createAttachmentStore,
17009
17390
  createAttachmentStoreV2,
17010
17391
  generateDocsLlmsTxt,
17011
17392
  getCleoDirAbsolute,
17012
17393
  getProjectRoot as getProjectRoot5,
17394
+ isLifecycleStatus,
17013
17395
  memoryObserve as memoryObserve2,
17014
17396
  parseChangesetFrontmatter,
17015
17397
  releaseReservedSlug,
17016
17398
  reserveSlugForDispatch,
17017
17399
  resolveAttachmentBackend,
17018
17400
  SlugCollisionError,
17401
+ SUPERSEDE_NOT_FOUND_CODE,
17402
+ SUPERSEDE_SAME_SLUG_CODE,
17403
+ supersedeDoc,
17404
+ updateDocBySlug,
17019
17405
  validateDocBody,
17020
17406
  writeChangesetEntry
17021
17407
  } from "@cleocode/core/internal";
@@ -17493,6 +17879,7 @@ var init_docs2 = __esm({
17493
17879
  labels: rawLabels,
17494
17880
  attachedBy: rawAttachedBy,
17495
17881
  slug: rawSlug,
17882
+ title: rawTitle,
17496
17883
  type: rawType,
17497
17884
  strict: strictMode
17498
17885
  } = params;
@@ -17600,6 +17987,19 @@ var init_docs2 = __esm({
17600
17987
  if (err.code === "E_FILE_WRITE_FAILED") {
17601
17988
  return lafsError("E_FILE_ERROR", err.message, "add");
17602
17989
  }
17990
+ if (err.code === "E_SLUG_RESERVED") {
17991
+ return {
17992
+ success: false,
17993
+ error: {
17994
+ code: "E_SLUG_RESERVED",
17995
+ message: err.message,
17996
+ details: {
17997
+ suggestions: err.suggestions,
17998
+ aliases: err.aliases
17999
+ }
18000
+ }
18001
+ };
18002
+ }
17603
18003
  return lafsError("E_SSOT_WRITE_FAILED", err.message, "add");
17604
18004
  }
17605
18005
  const changesetPayload = {
@@ -17632,14 +18032,31 @@ var init_docs2 = __esm({
17632
18032
  "add"
17633
18033
  );
17634
18034
  }
18035
+ let adrNumber;
18036
+ if (type2 === "adr" && slug === void 0) {
18037
+ if (typeof rawTitle !== "string" || rawTitle.trim().length === 0) {
18038
+ return lafsError(
18039
+ "E_VALIDATION",
18040
+ "title is required when type=adr and slug is omitted \u2014 the allocator needs a title to assemble adr-NNN-<kebab-title>",
18041
+ "add"
18042
+ );
18043
+ }
18044
+ const allocation = await allocateAdrSlug(getProjectRoot5(), { title: rawTitle });
18045
+ if (!allocation.ok) {
18046
+ return lafsError(allocation.code, allocation.message, "add");
18047
+ }
18048
+ slug = allocation.slug;
18049
+ adrNumber = allocation.number;
18050
+ }
17635
18051
  if (type2 !== void 0 && slug !== void 0) {
17636
18052
  const patternCheck = getDocKindRegistry().validateSlug(type2, slug);
17637
18053
  if (!patternCheck.ok) {
18054
+ if (adrNumber !== void 0) releaseReservedSlug(slug);
17638
18055
  const exampleHint = patternCheck.example ? ` (example: ${patternCheck.example})` : "";
17639
18056
  return lafsError("E_SLUG_PATTERN_MISMATCH", `${patternCheck.error}${exampleHint}`, "add");
17640
18057
  }
17641
18058
  }
17642
- if (slug !== void 0) {
18059
+ if (slug !== void 0 && adrNumber === void 0) {
17643
18060
  const reservation = await reserveSlugForDispatch(getProjectRoot5(), {
17644
18061
  kind: type2 ?? "",
17645
18062
  slug
@@ -17740,6 +18157,7 @@ var init_docs2 = __esm({
17740
18157
  }
17741
18158
  throw err;
17742
18159
  }
18160
+ if (adrNumber !== void 0 && slug !== void 0) consumeReservedSlug(slug);
17743
18161
  let backend = "legacy";
17744
18162
  try {
17745
18163
  const v2 = createAttachmentStoreV2(getProjectRoot5());
@@ -17781,7 +18199,8 @@ var init_docs2 = __esm({
17781
18199
  // Cast: core returns 'llmtxt'|'legacy'; contracts uses 'legacy'|'llmstxt-v2' (T1529)
17782
18200
  attachmentBackend: backend,
17783
18201
  ...slug !== void 0 ? { slug } : {},
17784
- ...type2 !== void 0 ? { type: type2 } : {}
18202
+ ...type2 !== void 0 ? { type: type2 } : {},
18203
+ ...adrNumber !== void 0 ? { adrNumber } : {}
17785
18204
  },
17786
18205
  "add"
17787
18206
  );
@@ -17822,6 +18241,7 @@ var init_docs2 = __esm({
17822
18241
  }
17823
18242
  throw err;
17824
18243
  }
18244
+ if (adrNumber !== void 0 && slug !== void 0) consumeReservedSlug(slug);
17825
18245
  import("@cleocode/core/internal").then(
17826
18246
  ({ ensureLlmtxtNode }) => ensureLlmtxtNode(getProjectRoot5(), meta.sha256, `${ownerType}:${ownerId}`, url)
17827
18247
  ).catch(() => {
@@ -17848,7 +18268,8 @@ var init_docs2 = __esm({
17848
18268
  // Cast: core returns 'llmtxt'|'legacy'; contracts uses 'legacy'|'llmstxt-v2' (T1529)
17849
18269
  attachmentBackend: backend,
17850
18270
  ...slug !== void 0 ? { slug } : {},
17851
- ...type2 !== void 0 ? { type: type2 } : {}
18271
+ ...type2 !== void 0 ? { type: type2 } : {},
18272
+ ...adrNumber !== void 0 ? { adrNumber } : {}
17852
18273
  },
17853
18274
  "add"
17854
18275
  );
@@ -17906,10 +18327,90 @@ var init_docs2 = __esm({
17906
18327
  },
17907
18328
  "remove"
17908
18329
  );
18330
+ },
18331
+ // ── docs.update (T10161 — E12.C4 / Saga T9855) ─────────────────────────────
18332
+ update: async (params) => {
18333
+ const { slug: rawSlug, file: filePath, content: inlineContent, status: rawStatus } = params;
18334
+ if (typeof rawSlug !== "string" || rawSlug.length === 0) {
18335
+ return lafsError("E_INVALID_INPUT", "slug is required", "update");
18336
+ }
18337
+ const hasFile = typeof filePath === "string" && filePath.length > 0;
18338
+ const hasContent = typeof inlineContent === "string";
18339
+ if (hasFile === hasContent) {
18340
+ return lafsError(
18341
+ "E_INVALID_INPUT",
18342
+ "Provide exactly one of --file <path> or --content <text>",
18343
+ "update",
18344
+ 'Use `cleo docs update <slug> --file ./new.md` OR `cleo docs update <slug> --content "..."`.'
18345
+ );
18346
+ }
18347
+ if (rawStatus !== void 0 && !isLifecycleStatus(rawStatus)) {
18348
+ return lafsError(
18349
+ "E_INVALID_INPUT",
18350
+ `status must be one of: draft|proposed|accepted|superseded|archived|deprecated \u2014 got '${String(rawStatus)}'`,
18351
+ "update"
18352
+ );
18353
+ }
18354
+ const projectRoot = getProjectRoot5();
18355
+ const resolvedParams = hasFile ? { ...params, file: resolve2(filePath) } : params;
18356
+ const outcome = await updateDocBySlug(projectRoot, resolvedParams);
18357
+ if (!outcome.ok) {
18358
+ return lafsError(outcome.error.code, outcome.error.message, "update");
18359
+ }
18360
+ return lafsSuccess(
18361
+ {
18362
+ slug: outcome.result.slug,
18363
+ ...outcome.result.type !== null ? { type: outcome.result.type } : {},
18364
+ attachmentId: outcome.result.attachmentId,
18365
+ previousAttachmentId: outcome.result.previousAttachmentId,
18366
+ sha256: outcome.result.sha256,
18367
+ previousSha256: outcome.result.previousSha256,
18368
+ changed: outcome.result.changed,
18369
+ lifecycleStatus: outcome.result.lifecycleStatus,
18370
+ updatedAt: outcome.result.updatedAt,
18371
+ version: outcome.result.version,
18372
+ squashed: outcome.result.squashed
18373
+ },
18374
+ "update"
18375
+ );
18376
+ },
18377
+ // ── docs.supersede ─────────────────────────────────────────────────────────
18378
+ supersede: async (params) => {
18379
+ const { oldSlug, newSlug, reason } = params;
18380
+ if (typeof oldSlug !== "string" || oldSlug.length === 0) {
18381
+ return lafsError("E_INVALID_INPUT", "<oldSlug> is required", "supersede");
18382
+ }
18383
+ if (typeof newSlug !== "string" || newSlug.length === 0) {
18384
+ return lafsError("E_INVALID_INPUT", "<newSlug> is required", "supersede");
18385
+ }
18386
+ try {
18387
+ const result = await supersedeDoc(getProjectRoot5(), {
18388
+ oldSlug,
18389
+ newSlug,
18390
+ ...typeof reason === "string" && reason.length > 0 ? { reason } : {}
18391
+ });
18392
+ const payload = {
18393
+ oldSlug: result.oldSlug,
18394
+ newSlug: result.newSlug,
18395
+ oldAttachmentId: result.oldAttachmentId,
18396
+ newAttachmentId: result.newAttachmentId,
18397
+ supersededAt: result.supersededAt,
18398
+ edgeId: result.edgeId,
18399
+ ...result.reason !== void 0 ? { reason: result.reason } : {}
18400
+ };
18401
+ return lafsSuccess(payload, "supersede");
18402
+ } catch (err) {
18403
+ const code = err && typeof err === "object" && "code" in err && typeof err.code === "number" ? (
18404
+ // Map ExitCode (number) → stable LAFS string code expected by callers.
18405
+ err.code === 4 ? SUPERSEDE_NOT_FOUND_CODE : err.code === 6 ? SUPERSEDE_SAME_SLUG_CODE : "E_INTERNAL"
18406
+ ) : "E_INTERNAL";
18407
+ const message = err instanceof Error ? err.message : "supersede failed";
18408
+ return lafsError(code, message, "supersede");
18409
+ }
17909
18410
  }
17910
18411
  });
17911
18412
  QUERY_OPS3 = /* @__PURE__ */ new Set(["list", "fetch", "generate"]);
17912
- MUTATE_OPS3 = /* @__PURE__ */ new Set(["add", "remove"]);
18413
+ MUTATE_OPS3 = /* @__PURE__ */ new Set(["add", "remove", "update", "supersede"]);
17913
18414
  DocsHandler = class {
17914
18415
  // -----------------------------------------------------------------------
17915
18416
  // Query
@@ -17968,7 +18469,7 @@ var init_docs2 = __esm({
17968
18469
  getSupportedOperations() {
17969
18470
  return {
17970
18471
  query: ["list", "fetch", "generate"],
17971
- mutate: ["add", "remove"]
18472
+ mutate: ["add", "remove", "update", "supersede"]
17972
18473
  };
17973
18474
  }
17974
18475
  };
@@ -20429,6 +20930,9 @@ function pickDecoratorMetaExtensions(responseMeta) {
20429
20930
  const out = {};
20430
20931
  if (responseMeta["_nexus"] !== void 0) out["_nexus"] = responseMeta["_nexus"];
20431
20932
  if (responseMeta["deprecated"] !== void 0) out["deprecated"] = responseMeta["deprecated"];
20933
+ if (responseMeta["suggestedNext"] !== void 0) {
20934
+ out["suggestedNext"] = responseMeta["suggestedNext"];
20935
+ }
20432
20936
  return out;
20433
20937
  }
20434
20938
  function buildNexusMetaExtensions(operation, params = {}) {
@@ -26224,8 +26728,8 @@ async function loadPlaybookByName(name) {
26224
26728
  return null;
26225
26729
  }
26226
26730
  try {
26227
- const { getProjectRoot: getProjectRoot53 } = await import("@cleocode/core/internal");
26228
- const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot53();
26731
+ const { getProjectRoot: getProjectRoot54 } = await import("@cleocode/core/internal");
26732
+ const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot54();
26229
26733
  const resolved = resolvePlaybook(name, {
26230
26734
  projectRoot,
26231
26735
  globalPlaybooksDir: __playbookRuntimeOverrides.globalPlaybooksDir,
@@ -26269,8 +26773,8 @@ async function acquireDb() {
26269
26773
  async function buildDefaultDispatcher() {
26270
26774
  if (__playbookRuntimeOverrides.dispatcher) return __playbookRuntimeOverrides.dispatcher;
26271
26775
  const { orchestrateSpawnExecute: orchestrateSpawnExecute2 } = await Promise.resolve().then(() => (init_engine(), engine_exports));
26272
- const { getProjectRoot: getProjectRoot53 } = await import("@cleocode/core/internal");
26273
- const projectRoot = getProjectRoot53();
26776
+ const { getProjectRoot: getProjectRoot54 } = await import("@cleocode/core/internal");
26777
+ const projectRoot = getProjectRoot54();
26274
26778
  return {
26275
26779
  async dispatch(input2) {
26276
26780
  try {
@@ -26460,8 +26964,8 @@ var init_playbook2 = __esm({
26460
26964
  projectRoot = __playbookRuntimeOverrides.projectRoot;
26461
26965
  } else {
26462
26966
  try {
26463
- const { getProjectRoot: getProjectRoot53 } = await import("@cleocode/core/internal");
26464
- projectRoot = getProjectRoot53();
26967
+ const { getProjectRoot: getProjectRoot54 } = await import("@cleocode/core/internal");
26968
+ projectRoot = getProjectRoot54();
26465
26969
  } catch {
26466
26970
  projectRoot = void 0;
26467
26971
  }
@@ -26525,14 +27029,14 @@ var init_playbook2 = __esm({
26525
27029
  const dispatcher = await buildDefaultDispatcher();
26526
27030
  let result;
26527
27031
  try {
26528
- const { getProjectRoot: getProjectRoot53 } = await import("@cleocode/core/internal");
27032
+ const { getProjectRoot: getProjectRoot54 } = await import("@cleocode/core/internal");
26529
27033
  const opts = {
26530
27034
  db,
26531
27035
  playbook: parsed.definition,
26532
27036
  playbookHash: parsed.sourceHash,
26533
27037
  initialContext,
26534
27038
  dispatcher,
26535
- projectRoot: getProjectRoot53()
27039
+ projectRoot: getProjectRoot54()
26536
27040
  };
26537
27041
  if (__playbookRuntimeOverrides.approvalSecret !== void 0) {
26538
27042
  opts.approvalSecret = __playbookRuntimeOverrides.approvalSecret;
@@ -26816,7 +27320,8 @@ async function orchestrateSpawnOp(params) {
26816
27320
  getProjectRoot11(),
26817
27321
  params.tier,
26818
27322
  params.noWorktree,
26819
- params.spawnScope
27323
+ params.spawnScope,
27324
+ params.atomicityScope
26820
27325
  );
26821
27326
  }
26822
27327
  async function orchestrateHandoffOp(params) {
@@ -26896,16 +27401,16 @@ async function orchestrateRejectOp(params) {
26896
27401
  async function orchestrateClassify(request, context, projectRoot) {
26897
27402
  try {
26898
27403
  const { getCleoCantWorkflowsDir } = await import("@cleocode/core/internal");
26899
- const { readFileSync: readFileSync18, readdirSync: readdirSync3, existsSync: existsSync17 } = await import("node:fs");
26900
- const { join: join34 } = await import("node:path");
27404
+ const { readFileSync: readFileSync21, readdirSync: readdirSync3, existsSync: existsSync19 } = await import("node:fs");
27405
+ const { join: join37 } = await import("node:path");
26901
27406
  const workflowsDir = getCleoCantWorkflowsDir();
26902
27407
  const combined = `${request} ${context ?? ""}`.toLowerCase();
26903
27408
  const matches = [];
26904
- if (existsSync17(workflowsDir)) {
27409
+ if (existsSync19(workflowsDir)) {
26905
27410
  const files = readdirSync3(workflowsDir).filter((f) => f.endsWith(".cant"));
26906
27411
  for (const file of files) {
26907
27412
  try {
26908
- const src = readFileSync18(join34(workflowsDir, file), "utf-8");
27413
+ const src = readFileSync21(join37(workflowsDir, file), "utf-8");
26909
27414
  const teamMatch = /^team\s+(\S+):/m.exec(src);
26910
27415
  if (!teamMatch) continue;
26911
27416
  const teamName = teamMatch[1];
@@ -26920,12 +27425,12 @@ async function orchestrateClassify(request, context, projectRoot) {
26920
27425
  }
26921
27426
  }
26922
27427
  }
26923
- const localCantDir = join34(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
26924
- if (existsSync17(localCantDir)) {
27428
+ const localCantDir = join37(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
27429
+ if (existsSync19(localCantDir)) {
26925
27430
  const files = readdirSync3(localCantDir).filter((f) => f.endsWith(".cant"));
26926
27431
  for (const file of files) {
26927
27432
  try {
26928
- const src = readFileSync18(join34(localCantDir, file), "utf-8");
27433
+ const src = readFileSync21(join37(localCantDir, file), "utf-8");
26929
27434
  const teamMatch = /^team\s+(\S+):/m.exec(src);
26930
27435
  if (!teamMatch) continue;
26931
27436
  const teamName = teamMatch[1];
@@ -27117,11 +27622,11 @@ async function orchestrateAnalyzeParallelSafety(taskIds, projectRoot) {
27117
27622
  };
27118
27623
  }
27119
27624
  }
27120
- async function handleWorktreeComplete(taskId, projectRoot, resolve7) {
27625
+ async function handleWorktreeComplete(taskId, projectRoot, resolve8) {
27121
27626
  try {
27122
27627
  const { completeWorktreeForTask } = await import("@cleocode/core/internal");
27123
27628
  const result = completeWorktreeForTask(taskId, projectRoot, {
27124
- resolve: resolve7 ?? "auto"
27629
+ resolve: resolve8 ?? "auto"
27125
27630
  });
27126
27631
  if (result.outcome === "conflict") {
27127
27632
  return {
@@ -27653,12 +28158,15 @@ var init_orchestrate2 = __esm({
27653
28158
  );
27654
28159
  const tierRaw = params.tier;
27655
28160
  const tier = tierRaw === 0 || tierRaw === 1 || tierRaw === 2 ? tierRaw : void 0;
28161
+ const atomicityScopeRaw = params.atomicityScope;
28162
+ const atomicityScope = atomicityScopeRaw === "orchestrator-defer" ? "orchestrator-defer" : void 0;
27656
28163
  const p = {
27657
28164
  taskId: params.taskId,
27658
28165
  protocolType: params.protocolType,
27659
28166
  tier,
27660
28167
  noWorktree: params.noWorktree,
27661
- spawnScope: params.spawnScope
28168
+ spawnScope: params.spawnScope,
28169
+ ...atomicityScope ? { atomicityScope } : {}
27662
28170
  };
27663
28171
  return wrapResult(await coreOps2.spawn(p), "mutate", "orchestrate", operation, startTime);
27664
28172
  }
@@ -27798,10 +28306,10 @@ var init_orchestrate2 = __esm({
27798
28306
  startTime
27799
28307
  );
27800
28308
  const rawResolve = params.resolve;
27801
- const resolve7 = rawResolve === "manual" ? "manual" : rawResolve === "auto" ? "auto" : void 0;
28309
+ const resolve8 = rawResolve === "manual" ? "manual" : rawResolve === "auto" ? "auto" : void 0;
27802
28310
  const p = {
27803
28311
  taskId: params.taskId,
27804
- ...resolve7 !== void 0 ? { resolve: resolve7 } : {}
28312
+ ...resolve8 !== void 0 ? { resolve: resolve8 } : {}
27805
28313
  };
27806
28314
  return wrapResult(
27807
28315
  await coreOps2["worktree.complete"](p),
@@ -30091,7 +30599,7 @@ var init_sticky2 = __esm({
30091
30599
  });
30092
30600
 
30093
30601
  // packages/cleo/src/dispatch/domains/tasks.ts
30094
- import { getLogger as getLogger15, getProjectRoot as getProjectRoot18 } from "@cleocode/core";
30602
+ import { getLogger as getLogger15, getProjectRoot as getProjectRoot18, TASKS_SUGGESTED_NEXT_BUILDERS } from "@cleocode/core";
30095
30603
  import { createAttachmentStore as createAttachmentStore4 } from "@cleocode/core/internal";
30096
30604
  import {
30097
30605
  sagaAdd as coreSagaAdd,
@@ -30169,6 +30677,25 @@ async function sagaReconcile(params) {
30169
30677
  "saga.reconcile"
30170
30678
  );
30171
30679
  }
30680
+ function stampSuggestedNext(response, operation, params) {
30681
+ if (!response.success) return response;
30682
+ const builder = TASKS_SUGGESTED_NEXT_BUILDERS[operation];
30683
+ if (!builder) return response;
30684
+ let suggestions;
30685
+ try {
30686
+ suggestions = builder(params, response.data);
30687
+ } catch {
30688
+ return response;
30689
+ }
30690
+ if (suggestions.length === 0) return response;
30691
+ return {
30692
+ ...response,
30693
+ meta: {
30694
+ ...response.meta,
30695
+ suggestedNext: suggestions
30696
+ }
30697
+ };
30698
+ }
30172
30699
  var _tasksTypedHandler, QUERY_OPS11, MUTATE_OPS10, TasksHandler;
30173
30700
  var init_tasks2 = __esm({
30174
30701
  "packages/cleo/src/dispatch/domains/tasks.ts"() {
@@ -30240,7 +30767,9 @@ var init_tasks2 = __esm({
30240
30767
  fields: params.fields,
30241
30768
  verbose: params.verbose,
30242
30769
  // T944/T9072: kind filter
30243
- kind: params.kind
30770
+ kind: params.kind,
30771
+ // T9905: unified urgency surface
30772
+ urgent: params.urgent
30244
30773
  }),
30245
30774
  "find"
30246
30775
  );
@@ -30683,7 +31212,14 @@ var init_tasks2 = __esm({
30683
31212
  operation,
30684
31213
  params ?? {}
30685
31214
  );
30686
- return wrapResult(envelopeToEngineResult(envelope), "query", "tasks", operation, startTime);
31215
+ const response = wrapResult(
31216
+ envelopeToEngineResult(envelope),
31217
+ "query",
31218
+ "tasks",
31219
+ operation,
31220
+ startTime
31221
+ );
31222
+ return stampSuggestedNext(response, operation, params ?? {});
30687
31223
  } catch (error) {
30688
31224
  getLogger15("domain:tasks").error(
30689
31225
  { gateway: "query", domain: "tasks", operation, err: error },
@@ -30770,7 +31306,14 @@ var init_tasks2 = __esm({
30770
31306
  operation,
30771
31307
  params ?? {}
30772
31308
  );
30773
- return wrapResult(envelopeToEngineResult(envelope), "mutate", "tasks", operation, startTime);
31309
+ const response = wrapResult(
31310
+ envelopeToEngineResult(envelope),
31311
+ "mutate",
31312
+ "tasks",
31313
+ operation,
31314
+ startTime
31315
+ );
31316
+ return stampSuggestedNext(response, operation, params ?? {});
30774
31317
  } catch (error) {
30775
31318
  getLogger15("domain:tasks").error(
30776
31319
  { gateway: "mutate", domain: "tasks", operation, err: error },
@@ -32295,6 +32838,88 @@ var init_field_filter = __esm({
32295
32838
  }
32296
32839
  });
32297
32840
 
32841
+ // packages/cleo/src/cli/projection-context.ts
32842
+ function setProjectionOptOut(optOut) {
32843
+ currentOptOut = optOut;
32844
+ }
32845
+ function getProjectionOptOut() {
32846
+ return currentOptOut;
32847
+ }
32848
+ var currentOptOut;
32849
+ var init_projection_context = __esm({
32850
+ "packages/cleo/src/cli/projection-context.ts"() {
32851
+ "use strict";
32852
+ currentOptOut = false;
32853
+ }
32854
+ });
32855
+
32856
+ // packages/cleo/src/dispatch/middleware/mutate-minimal-envelope.ts
32857
+ import {
32858
+ applyMutateProjection,
32859
+ MUTATE_PROJECTION_PLANS,
32860
+ resolveProjectionMode
32861
+ } from "@cleocode/core";
32862
+ function resolveModeFor(req) {
32863
+ const override = req.params?.["_projection"];
32864
+ if (override === "full" || override === "mvi") return override;
32865
+ return resolveProjectionMode(getProjectionOptOut() || void 0);
32866
+ }
32867
+ function createMutateMinimalEnvelope() {
32868
+ return async (req, next) => {
32869
+ const mode = resolveModeFor(req);
32870
+ const opKey = `${req.domain}.${req.operation}`;
32871
+ const hasPlan = MUTATE_PROJECTION_PLANS[opKey] !== void 0;
32872
+ const response = await next();
32873
+ if (!hasPlan) return response;
32874
+ if (response.success && response.data !== void 0) {
32875
+ response.data = applyMutateProjection(response.data, opKey, mode);
32876
+ }
32877
+ response.meta.mutateProjection = mode;
32878
+ return response;
32879
+ };
32880
+ }
32881
+ var init_mutate_minimal_envelope = __esm({
32882
+ "packages/cleo/src/dispatch/middleware/mutate-minimal-envelope.ts"() {
32883
+ "use strict";
32884
+ init_projection_context();
32885
+ }
32886
+ });
32887
+
32888
+ // packages/cleo/src/dispatch/middleware/mvi-record-projection.ts
32889
+ import {
32890
+ applyProjectionPlan,
32891
+ PROJECTION_PLANS,
32892
+ resolveProjectionMode as resolveProjectionMode2
32893
+ } from "@cleocode/core";
32894
+ function resolveModeFor2(req) {
32895
+ const override = req.params?.["_projection"];
32896
+ if (override === "full" || override === "mvi") return override;
32897
+ return resolveProjectionMode2(getProjectionOptOut() || void 0);
32898
+ }
32899
+ function createMviRecordProjection() {
32900
+ return async (req, next) => {
32901
+ const mode = resolveModeFor2(req);
32902
+ if (req.params && "_projection" in req.params) {
32903
+ delete req.params["_projection"];
32904
+ }
32905
+ const opKey = `${req.domain}.${req.operation}`;
32906
+ const hasPlan = PROJECTION_PLANS[opKey] !== void 0;
32907
+ const response = await next();
32908
+ if (!hasPlan) return response;
32909
+ if (response.success && response.data !== void 0) {
32910
+ response.data = applyProjectionPlan(response.data, opKey, mode);
32911
+ }
32912
+ response.meta.projection = mode;
32913
+ return response;
32914
+ };
32915
+ }
32916
+ var init_mvi_record_projection = __esm({
32917
+ "packages/cleo/src/dispatch/middleware/mvi-record-projection.ts"() {
32918
+ "use strict";
32919
+ init_projection_context();
32920
+ }
32921
+ });
32922
+
32298
32923
  // packages/cleo/src/dispatch/lib/security.ts
32299
32924
  import {
32300
32925
  ALL_VALID_STATUSES,
@@ -32320,11 +32945,11 @@ var init_security = __esm({
32320
32945
  });
32321
32946
 
32322
32947
  // packages/cleo/src/dispatch/middleware/sanitizer.ts
32323
- function createSanitizer(getProjectRoot53) {
32948
+ function createSanitizer(getProjectRoot54) {
32324
32949
  return async (req, next) => {
32325
32950
  if (req.params) {
32326
32951
  try {
32327
- const root = getProjectRoot53 ? getProjectRoot53() : void 0;
32952
+ const root = getProjectRoot54 ? getProjectRoot54() : void 0;
32328
32953
  req.params = sanitizeParams(req.params, root, {
32329
32954
  domain: req.domain,
32330
32955
  operation: req.operation
@@ -32502,6 +33127,15 @@ function createCliDispatcher() {
32502
33127
  // T4959: session identity first
32503
33128
  createSanitizer(() => getProjectRoot22()),
32504
33129
  createFieldFilter(),
33130
+ // T9922 (Saga T9855 / E8.3): MVI record projection default for read ops.
33131
+ // Runs AFTER the domain handler returns so it can trim the data payload
33132
+ // before audit + telemetry record byte sizes. Sits before audit so the
33133
+ // audit trail captures the projected (final) bytes.
33134
+ createMviRecordProjection(),
33135
+ // T9931 (Saga T9855 / E9.4): minimal envelopes for mutate ops. Mirror
33136
+ // policy to the read-side projection — sits in the same pre-audit slot
33137
+ // so audit/telemetry record the trimmed bytes.
33138
+ createMutateMinimalEnvelope(),
32505
33139
  createAudit(),
32506
33140
  // T4959: CLI now gets audit trail
32507
33141
  createTelemetry()
@@ -32668,6 +33302,8 @@ var init_cli = __esm({
32668
33302
  init_domains();
32669
33303
  init_audit();
32670
33304
  init_field_filter();
33305
+ init_mutate_minimal_envelope();
33306
+ init_mvi_record_projection();
32671
33307
  init_sanitizer();
32672
33308
  init_session_resolver();
32673
33309
  init_telemetry();
@@ -32857,18 +33493,77 @@ var init_adapter = __esm({
32857
33493
  }
32858
33494
  });
32859
33495
 
33496
+ // packages/cleo/src/cli/lib/collect-input.ts
33497
+ import { readFile as readFile2 } from "node:fs/promises";
33498
+ function wrapParseError(rawInput, parseErr, sourceLabel) {
33499
+ const snippet2 = rawInput.length > PARSE_ERROR_SNIPPET_MAX_LENGTH ? `${rawInput.slice(0, PARSE_ERROR_SNIPPET_MAX_LENGTH)}\u2026` : rawInput;
33500
+ return new Error(`Invalid JSON in ${sourceLabel}: ${parseErr.message} (got: ${snippet2})`);
33501
+ }
33502
+ function readStdinJson(stdin2) {
33503
+ return new Promise((resolve8, reject) => {
33504
+ const chunks = [];
33505
+ stdin2.on("data", (chunk) => {
33506
+ chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
33507
+ });
33508
+ stdin2.on("error", (err) => {
33509
+ reject(err);
33510
+ });
33511
+ stdin2.on("end", () => {
33512
+ const raw = Buffer.concat(chunks).toString("utf8");
33513
+ try {
33514
+ resolve8(JSON.parse(raw));
33515
+ } catch (err) {
33516
+ reject(wrapParseError(raw, err, "stdin"));
33517
+ }
33518
+ });
33519
+ });
33520
+ }
33521
+ async function collectMutateInput(args, stdin2) {
33522
+ if (typeof args.params === "string" && args.params.length > 0) {
33523
+ try {
33524
+ return JSON.parse(args.params);
33525
+ } catch (err) {
33526
+ throw wrapParseError(args.params, err, "--params");
33527
+ }
33528
+ }
33529
+ if (typeof args.file === "string" && args.file.length > 0) {
33530
+ const raw = await readFile2(args.file, "utf8");
33531
+ try {
33532
+ return JSON.parse(raw);
33533
+ } catch (err) {
33534
+ throw wrapParseError(raw, err, `--file ${args.file}`);
33535
+ }
33536
+ }
33537
+ if (stdin2.isTTY !== true) {
33538
+ return readStdinJson(stdin2);
33539
+ }
33540
+ if (args.positional !== void 0 && args.positional.length > 0) {
33541
+ return args.positional;
33542
+ }
33543
+ return void 0;
33544
+ }
33545
+ var PARSE_ERROR_SNIPPET_MAX_LENGTH;
33546
+ var init_collect_input = __esm({
33547
+ "packages/cleo/src/cli/lib/collect-input.ts"() {
33548
+ "use strict";
33549
+ PARSE_ERROR_SNIPPET_MAX_LENGTH = 80;
33550
+ }
33551
+ });
33552
+
32860
33553
  // packages/cleo/src/cli/commands/add-batch.ts
32861
33554
  var add_batch_exports = {};
32862
33555
  __export(add_batch_exports, {
32863
33556
  addBatchCommand: () => addBatchCommand
32864
33557
  });
32865
- import { existsSync as existsSync6, readFileSync as readFileSync8 } from "node:fs";
33558
+ import { INPUT_CONTRACTS, validateOperationInput } from "@cleocode/core";
32866
33559
  var addBatchCommand;
32867
33560
  var init_add_batch = __esm({
32868
33561
  "packages/cleo/src/cli/commands/add-batch.ts"() {
32869
33562
  "use strict";
33563
+ init_src2();
32870
33564
  init_dist();
32871
33565
  init_cli();
33566
+ init_collect_input();
32872
33567
  init_renderers();
32873
33568
  addBatchCommand = defineCommand({
32874
33569
  meta: {
@@ -32876,9 +33571,13 @@ var init_add_batch = __esm({
32876
33571
  description: "Create multiple tasks in a single atomic transaction from a JSON file"
32877
33572
  },
32878
33573
  args: {
33574
+ params: {
33575
+ type: "string",
33576
+ description: 'Inline JSON object: { "tasks": [...], "defaultParent"?: "...", "dryRun"?: bool } (T9917)'
33577
+ },
32879
33578
  file: {
32880
33579
  type: "string",
32881
- description: "Path to JSON file (array of task objects). Use - for stdin."
33580
+ description: "Path to JSON file (array of task objects, or full payload). Use - for stdin."
32882
33581
  },
32883
33582
  parent: {
32884
33583
  type: "string",
@@ -32890,66 +33589,86 @@ var init_add_batch = __esm({
32890
33589
  }
32891
33590
  },
32892
33591
  async run({ args }) {
32893
- const filePath = args.file;
32894
33592
  const defaultParent = args.parent;
32895
- const dryRun = args["dry-run"];
33593
+ const dryRunFlag = args["dry-run"];
33594
+ const paramsArg = args.params;
33595
+ const fileArg = args.file;
33596
+ const collectArgs = {};
33597
+ if (paramsArg !== void 0) collectArgs.params = paramsArg;
33598
+ if (fileArg !== void 0 && fileArg !== "-") collectArgs.file = fileArg;
32896
33599
  let raw;
32897
- if (!filePath || filePath === "-") {
32898
- const chunks = [];
32899
- for await (const chunk of process.stdin) chunks.push(chunk);
32900
- raw = Buffer.concat(chunks).toString("utf-8");
32901
- if (!raw.trim()) {
32902
- cliError(
32903
- "No input provided. Pass --file <path> or pipe JSON to stdin.",
32904
- "E_VALIDATION",
32905
- { name: "E_VALIDATION", fix: "cleo add-batch --file tasks.json" },
32906
- { operation: "tasks.add-batch" }
32907
- );
32908
- process.exitCode = 2;
32909
- return;
32910
- }
33600
+ try {
33601
+ raw = await collectMutateInput(
33602
+ collectArgs,
33603
+ process.stdin
33604
+ );
33605
+ } catch (err) {
33606
+ cliError(
33607
+ err.message,
33608
+ 6 /* VALIDATION_ERROR */,
33609
+ {
33610
+ name: "E_VALIDATION_FAILED",
33611
+ fix: "Verify the JSON syntax of your --params / --file / stdin input"
33612
+ },
33613
+ { operation: "tasks.add-batch" }
33614
+ );
33615
+ process.exitCode = 6 /* VALIDATION_ERROR */;
33616
+ return;
33617
+ }
33618
+ if (raw === void 0) {
33619
+ cliError(
33620
+ "No input provided. Pass --params <json>, --file <path>, or pipe JSON to stdin.",
33621
+ 6 /* VALIDATION_ERROR */,
33622
+ {
33623
+ name: "E_VALIDATION_FAILED",
33624
+ fix: "cleo add-batch --file tasks.json"
33625
+ },
33626
+ { operation: "tasks.add-batch" }
33627
+ );
33628
+ process.exitCode = 6 /* VALIDATION_ERROR */;
33629
+ return;
33630
+ }
33631
+ let payload;
33632
+ if (Array.isArray(raw)) {
33633
+ payload = { tasks: raw };
33634
+ } else if (raw !== null && typeof raw === "object" && Array.isArray(raw["tasks"])) {
33635
+ payload = { ...raw };
32911
33636
  } else {
32912
- if (!existsSync6(filePath)) {
32913
- cliError(
32914
- `File not found: ${filePath}`,
32915
- "E_NOT_FOUND",
32916
- { name: "E_NOT_FOUND", fix: `Verify the file path exists: ${filePath}` },
32917
- { operation: "tasks.add-batch" }
32918
- );
32919
- process.exitCode = 2;
32920
- return;
32921
- }
32922
- raw = readFileSync8(filePath, "utf-8");
33637
+ payload = { tasks: [raw] };
32923
33638
  }
32924
- let tasks;
32925
- try {
32926
- const parsed = JSON.parse(raw);
32927
- tasks = Array.isArray(parsed) ? parsed : [parsed];
32928
- } catch {
33639
+ if (defaultParent !== void 0 && payload["defaultParent"] === void 0) {
33640
+ payload["defaultParent"] = defaultParent;
33641
+ }
33642
+ if (dryRunFlag === true && payload["dryRun"] === void 0) {
33643
+ payload["dryRun"] = true;
33644
+ }
33645
+ const contract = INPUT_CONTRACTS["tasks.add-batch"];
33646
+ if (!contract) {
32929
33647
  cliError(
32930
- "Invalid JSON input. Expected an array of task objects.",
32931
- "E_VALIDATION",
32932
- { name: "E_VALIDATION", fix: "Ensure the input is a valid JSON array of task objects" },
33648
+ "tasks.add-batch contract missing from INPUT_CONTRACTS registry",
33649
+ 1 /* GENERAL_ERROR */,
33650
+ { name: "E_INTERNAL", fix: "This is a CLI bug \u2014 file an issue" },
32933
33651
  { operation: "tasks.add-batch" }
32934
33652
  );
32935
- process.exitCode = 2;
33653
+ process.exitCode = 1 /* GENERAL_ERROR */;
32936
33654
  return;
32937
33655
  }
32938
- if (tasks.length === 0) {
33656
+ const result = validateOperationInput(contract, payload);
33657
+ if (!result.ok) {
32939
33658
  cliError(
32940
- "No tasks in input.",
32941
- "E_VALIDATION",
32942
- { name: "E_VALIDATION", fix: "Provide at least one task object in the JSON array" },
33659
+ "tasks.add-batch failed: validation",
33660
+ 6 /* VALIDATION_ERROR */,
33661
+ {
33662
+ name: "E_VALIDATION_FAILED",
33663
+ fix: result.errors[0]?.fix ?? "Inspect the errors[] payload and correct the input",
33664
+ details: { errors: result.errors }
33665
+ },
32943
33666
  { operation: "tasks.add-batch" }
32944
33667
  );
32945
- process.exitCode = 2;
33668
+ process.exitCode = 6 /* VALIDATION_ERROR */;
32946
33669
  return;
32947
33670
  }
32948
- const response = await dispatchRaw("mutate", "tasks", "add-batch", {
32949
- tasks,
32950
- ...defaultParent && { defaultParent },
32951
- ...dryRun && { dryRun: true }
32952
- });
33671
+ const response = await dispatchRaw("mutate", "tasks", "add-batch", payload);
32953
33672
  if (!response.success) {
32954
33673
  cliError(
32955
33674
  response.error?.message ?? "Batch creation failed",
@@ -32977,7 +33696,9 @@ __export(add_exports, {
32977
33696
  import {
32978
33697
  appendSignedSeverityAttestation,
32979
33698
  getProjectRoot as getProjectRoot23,
32980
- inferTaskAddParams
33699
+ INPUT_CONTRACTS as INPUT_CONTRACTS2,
33700
+ inferTaskAddParams,
33701
+ validateOperationInput as validateOperationInput2
32981
33702
  } from "@cleocode/core";
32982
33703
  var addCommand;
32983
33704
  var init_add = __esm({
@@ -32986,6 +33707,7 @@ var init_add = __esm({
32986
33707
  init_src2();
32987
33708
  init_dist();
32988
33709
  init_cli();
33710
+ init_collect_input();
32989
33711
  init_renderers();
32990
33712
  addCommand = defineCommand({
32991
33713
  meta: {
@@ -32994,6 +33716,28 @@ var init_add = __esm({
32994
33716
  For 2+ tasks at once: cleo add-batch --file tasks.json (single transaction, atomic rollback)`
32995
33717
  },
32996
33718
  args: {
33719
+ /**
33720
+ * Schema-first input — supersedes all flag-based args when present.
33721
+ *
33722
+ * Accepts a JSON object that matches `INPUT_CONTRACTS['tasks.add']`.
33723
+ * When provided, the command short-circuits the flag-mapping path
33724
+ * entirely and goes straight to validate→dispatch.
33725
+ *
33726
+ * @task T9917
33727
+ */
33728
+ params: {
33729
+ type: "string",
33730
+ description: 'Inline JSON object matching INPUT_CONTRACTS["tasks.add"] (T9917). Overrides positional + flags.'
33731
+ },
33732
+ /**
33733
+ * Schema-first input from a JSON file. Same semantics as --params.
33734
+ *
33735
+ * @task T9917
33736
+ */
33737
+ "params-file": {
33738
+ type: "string",
33739
+ description: 'Path to JSON file matching INPUT_CONTRACTS["tasks.add"] (T9917).'
33740
+ },
32997
33741
  title: {
32998
33742
  type: "positional",
32999
33743
  description: "Task title (3\u2013500 characters)",
@@ -33156,6 +33900,72 @@ For 2+ tasks at once: cleo add-batch --file tasks.json (single transaction, atom
33156
33900
  }
33157
33901
  },
33158
33902
  async run({ args, cmd }) {
33903
+ const paramsArg = args.params;
33904
+ const paramsFileArg = args["params-file"];
33905
+ if (paramsArg !== void 0 || paramsFileArg !== void 0) {
33906
+ const collectArgs = {};
33907
+ if (paramsArg !== void 0) collectArgs.params = paramsArg;
33908
+ if (paramsFileArg !== void 0) collectArgs.file = paramsFileArg;
33909
+ let raw;
33910
+ try {
33911
+ raw = await collectMutateInput(
33912
+ collectArgs,
33913
+ process.stdin
33914
+ );
33915
+ } catch (err) {
33916
+ cliError(
33917
+ err.message,
33918
+ 6 /* VALIDATION_ERROR */,
33919
+ {
33920
+ name: "E_VALIDATION_FAILED",
33921
+ fix: "Verify the JSON syntax of your --params / --params-file input"
33922
+ },
33923
+ { operation: "tasks.add" }
33924
+ );
33925
+ process.exit(6 /* VALIDATION_ERROR */);
33926
+ return;
33927
+ }
33928
+ const contract = INPUT_CONTRACTS2["tasks.add"];
33929
+ if (!contract) {
33930
+ cliError(
33931
+ "tasks.add contract missing from INPUT_CONTRACTS registry",
33932
+ 1 /* GENERAL_ERROR */,
33933
+ { name: "E_INTERNAL", fix: "This is a CLI bug \u2014 file an issue" },
33934
+ { operation: "tasks.add" }
33935
+ );
33936
+ process.exit(1 /* GENERAL_ERROR */);
33937
+ return;
33938
+ }
33939
+ const validation = validateOperationInput2(contract, raw);
33940
+ if (!validation.ok) {
33941
+ cliError(
33942
+ "tasks.add failed: validation",
33943
+ 6 /* VALIDATION_ERROR */,
33944
+ {
33945
+ name: "E_VALIDATION_FAILED",
33946
+ fix: validation.errors[0]?.fix ?? "Inspect errors[] and correct the input",
33947
+ details: { errors: validation.errors }
33948
+ },
33949
+ { operation: "tasks.add" }
33950
+ );
33951
+ process.exit(6 /* VALIDATION_ERROR */);
33952
+ return;
33953
+ }
33954
+ const validatedPayload = raw;
33955
+ const response2 = await dispatchRaw("mutate", "tasks", "add", validatedPayload);
33956
+ if (!response2.success) {
33957
+ handleRawError(response2, { command: "add", operation: "tasks.add" });
33958
+ }
33959
+ const data2 = response2.data;
33960
+ const dataWarnings2 = data2?.warnings;
33961
+ if (dataWarnings2?.length) {
33962
+ for (const w of dataWarnings2) {
33963
+ humanWarn(`\u26A0 ${w}`);
33964
+ }
33965
+ }
33966
+ cliOutput(data2, { command: "add", operation: "tasks.add" });
33967
+ return;
33968
+ }
33159
33969
  if (!args.title) {
33160
33970
  await showUsage(cmd);
33161
33971
  return;
@@ -33930,13 +34740,13 @@ var init_agent = __esm({
33930
34740
  transportConfig: {},
33931
34741
  isActive: true
33932
34742
  });
33933
- const { existsSync: existsSync17, mkdirSync: mkdirSync5, writeFileSync: writeFileSync5 } = await import("node:fs");
33934
- const { join: join34 } = await import("node:path");
33935
- const cantDir = join34(CLEO_DIR_NAME, AGENTS_SUBDIR);
33936
- const cantPath = join34(cantDir, `${agentId}.cant`);
34743
+ const { existsSync: existsSync19, mkdirSync: mkdirSync7, writeFileSync: writeFileSync7 } = await import("node:fs");
34744
+ const { join: join37 } = await import("node:path");
34745
+ const cantDir = join37(CLEO_DIR_NAME, AGENTS_SUBDIR);
34746
+ const cantPath = join37(cantDir, `${agentId}.cant`);
33937
34747
  let cantScaffolded = false;
33938
- if (!existsSync17(cantPath)) {
33939
- mkdirSync5(cantDir, { recursive: true });
34748
+ if (!existsSync19(cantPath)) {
34749
+ mkdirSync7(cantDir, { recursive: true });
33940
34750
  const role = classification ?? "specialist";
33941
34751
  const cantContent = `---
33942
34752
  kind: agent
@@ -33986,7 +34796,7 @@ agent ${agentId}:
33986
34796
  enforcement:
33987
34797
  1: TODO \u2014 what does this agent push back on?
33988
34798
  `;
33989
- writeFileSync5(cantPath, cantContent, "utf-8");
34799
+ writeFileSync7(cantPath, cantContent, "utf-8");
33990
34800
  cantScaffolded = true;
33991
34801
  }
33992
34802
  cliOutput(
@@ -33995,7 +34805,7 @@ agent ${agentId}:
33995
34805
  data: {
33996
34806
  agentId: credential.agentId,
33997
34807
  displayName: credential.displayName,
33998
- cantFile: cantScaffolded ? cantPath : existsSync17(cantPath) ? cantPath : null,
34808
+ cantFile: cantScaffolded ? cantPath : existsSync19(cantPath) ? cantPath : null,
33999
34809
  cantScaffolded
34000
34810
  }
34001
34811
  },
@@ -34114,8 +34924,8 @@ agent ${agentId}:
34114
34924
  try {
34115
34925
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
34116
34926
  const { createRuntime } = await import("@cleocode/runtime");
34117
- const { existsSync: existsSync17, readFileSync: readFileSync18 } = await import("node:fs");
34118
- const { join: join34 } = await import("node:path");
34927
+ const { existsSync: existsSync19, readFileSync: readFileSync21 } = await import("node:fs");
34928
+ const { join: join37 } = await import("node:path");
34119
34929
  await openCleoDb("tasks");
34120
34930
  const registry = new AgentRegistryAccessor(getProjectRoot24());
34121
34931
  const credential = await registry.get(args.agentId);
@@ -34135,9 +34945,9 @@ agent ${agentId}:
34135
34945
  }
34136
34946
  let profile = null;
34137
34947
  let cantValidation = null;
34138
- const cantPath = args.cant ?? join34(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
34139
- if (existsSync17(cantPath)) {
34140
- profile = readFileSync18(cantPath, "utf-8");
34948
+ const cantPath = args.cant ?? join37(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
34949
+ if (existsSync19(cantPath)) {
34950
+ profile = readFileSync21(cantPath, "utf-8");
34141
34951
  try {
34142
34952
  const cantModule = await import("@cleocode/cant");
34143
34953
  const validate = "validate" in cantModule ? cantModule.validate : null;
@@ -34660,8 +35470,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34660
35470
  try {
34661
35471
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
34662
35472
  const { createRuntime } = await import("@cleocode/runtime");
34663
- const { existsSync: existsSync17 } = await import("node:fs");
34664
- const { join: join34 } = await import("node:path");
35473
+ const { existsSync: existsSync19 } = await import("node:fs");
35474
+ const { join: join37 } = await import("node:path");
34665
35475
  await openCleoDb("tasks");
34666
35476
  const registry = new AgentRegistryAccessor(getProjectRoot24());
34667
35477
  const credential = await registry.get(args.agentId);
@@ -34678,8 +35488,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34678
35488
  }
34679
35489
  await registry.update(args.agentId, { isActive: true });
34680
35490
  await registry.markUsed(args.agentId);
34681
- const cantPath = join34(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
34682
- const hasProfile = existsSync17(cantPath);
35491
+ const cantPath = join37(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
35492
+ const hasProfile = existsSync19(cantPath);
34683
35493
  const runtime = await createRuntime(registry, {
34684
35494
  agentId: args.agentId,
34685
35495
  pollIntervalMs: 5e3,
@@ -35475,10 +36285,10 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35475
36285
  async run({ args }) {
35476
36286
  let tempDir = null;
35477
36287
  try {
35478
- const { existsSync: existsSync17 } = await import("node:fs");
35479
- const { basename, resolve: resolve7 } = await import("node:path");
35480
- const resolvedPath = resolve7(args.path);
35481
- if (!existsSync17(resolvedPath)) {
36288
+ const { existsSync: existsSync19 } = await import("node:fs");
36289
+ const { basename, resolve: resolve8 } = await import("node:path");
36290
+ const resolvedPath = resolve8(args.path);
36291
+ if (!existsSync19(resolvedPath)) {
35482
36292
  cliOutput(
35483
36293
  {
35484
36294
  success: false,
@@ -35603,11 +36413,11 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35603
36413
  },
35604
36414
  async run({ args }) {
35605
36415
  try {
35606
- const { existsSync: existsSync17, statSync } = await import("node:fs");
35607
- const { resolve: resolve7, basename, dirname: dirname10 } = await import("node:path");
35608
- const { execFileSync: execFileSync4 } = await import("node:child_process");
35609
- const resolvedDir = resolve7(args.dir);
35610
- if (!existsSync17(resolvedDir) || !statSync(resolvedDir).isDirectory()) {
36416
+ const { existsSync: existsSync19, statSync } = await import("node:fs");
36417
+ const { resolve: resolve8, basename, dirname: dirname12 } = await import("node:path");
36418
+ const { execFileSync: execFileSync5 } = await import("node:child_process");
36419
+ const resolvedDir = resolve8(args.dir);
36420
+ if (!existsSync19(resolvedDir) || !statSync(resolvedDir).isDirectory()) {
35611
36421
  cliOutput(
35612
36422
  {
35613
36423
  success: false,
@@ -35621,9 +36431,9 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35621
36431
  process.exitCode = 4;
35622
36432
  return;
35623
36433
  }
35624
- const { join: join34 } = await import("node:path");
35625
- const personaPath = join34(resolvedDir, "persona.cant");
35626
- if (!existsSync17(personaPath)) {
36434
+ const { join: join37 } = await import("node:path");
36435
+ const personaPath = join37(resolvedDir, "persona.cant");
36436
+ if (!existsSync19(personaPath)) {
35627
36437
  cliOutput(
35628
36438
  {
35629
36439
  success: false,
@@ -35639,10 +36449,10 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35639
36449
  }
35640
36450
  const agentName = basename(resolvedDir);
35641
36451
  const archiveName = `${agentName}.cantz`;
35642
- const archivePath = resolve7(archiveName);
35643
- const parentDir = dirname10(resolvedDir);
36452
+ const archivePath = resolve8(archiveName);
36453
+ const parentDir = dirname12(resolvedDir);
35644
36454
  try {
35645
- execFileSync4("zip", ["-r", archivePath, agentName], {
36455
+ execFileSync5("zip", ["-r", archivePath, agentName], {
35646
36456
  cwd: parentDir,
35647
36457
  encoding: "utf-8",
35648
36458
  timeout: 3e4
@@ -35670,7 +36480,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35670
36480
  if (entry.isFile()) {
35671
36481
  fileCount++;
35672
36482
  } else if (entry.isDirectory()) {
35673
- countFiles(join34(dirPath, entry.name));
36483
+ countFiles(join37(dirPath, entry.name));
35674
36484
  }
35675
36485
  }
35676
36486
  };
@@ -35918,18 +36728,18 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35918
36728
  },
35919
36729
  async run({ args }) {
35920
36730
  try {
35921
- const { existsSync: existsSync17, readFileSync: readFileSync18, mkdirSync: mkdirSync5 } = await import("node:fs");
35922
- const { resolve: resolve7, join: join34 } = await import("node:path");
35923
- const specPath = resolve7(args.spec);
35924
- if (!existsSync17(specPath)) {
36731
+ const { existsSync: existsSync19, readFileSync: readFileSync21, mkdirSync: mkdirSync7 } = await import("node:fs");
36732
+ const { resolve: resolve8, join: join37 } = await import("node:path");
36733
+ const specPath = resolve8(args.spec);
36734
+ if (!existsSync19(specPath)) {
35925
36735
  cliError(`spec file not found: ${specPath}`, 4, { name: "E_NOT_FOUND" });
35926
36736
  process.exitCode = 4;
35927
36737
  return;
35928
36738
  }
35929
- const specContent = readFileSync18(specPath, "utf-8");
36739
+ const specContent = readFileSync21(specPath, "utf-8");
35930
36740
  const projectRoot = getProjectRoot24();
35931
- const outputDir = args["output-dir"] ? resolve7(args["output-dir"]) : join34(projectRoot, ".cleo", "cant", "agents");
35932
- mkdirSync5(outputDir, { recursive: true });
36741
+ const outputDir = args["output-dir"] ? resolve8(args["output-dir"]) : join37(projectRoot, ".cleo", "cant", "agents");
36742
+ mkdirSync7(outputDir, { recursive: true });
35933
36743
  if (args["dry-run"]) {
35934
36744
  cliOutput(
35935
36745
  {
@@ -36529,7 +37339,7 @@ var init_consent = __esm({
36529
37339
  });
36530
37340
 
36531
37341
  // packages/cleo/src/cli/commands/auth/list.ts
36532
- import { existsSync as existsSync7 } from "node:fs";
37342
+ import { existsSync as existsSync6 } from "node:fs";
36533
37343
  import { homedir as homedir2 } from "node:os";
36534
37344
  import { join as join9 } from "node:path";
36535
37345
  function formatExpiry(expiresAt) {
@@ -36609,7 +37419,7 @@ var init_list2 = __esm({
36609
37419
  return p !== 0 ? p : a2.label.localeCompare(b.label);
36610
37420
  });
36611
37421
  const claudeCredsPath = join9(homedir2(), ".claude", ".credentials.json");
36612
- const hint = existsSync7(claudeCredsPath) && entries.every((e) => e.source !== "claude-code") ? "Hint: Claude Code OAuth detected at ~/.claude/.credentials.json but consent is off. Run `cleo auth consent --enable-claude-code` to seed it into the pool." : null;
37422
+ const hint = existsSync6(claudeCredsPath) && entries.every((e) => e.source !== "claude-code") ? "Hint: Claude Code OAuth detected at ~/.claude/.credentials.json but consent is off. Run `cleo auth consent --enable-claude-code` to seed it into the pool." : null;
36613
37423
  cliOutput(
36614
37424
  { entries, ...hint !== null ? { hint } : {} },
36615
37425
  {
@@ -36623,7 +37433,7 @@ var init_list2 = __esm({
36623
37433
  });
36624
37434
 
36625
37435
  // packages/cleo/src/cli/commands/auth/migrate-project-secrets.ts
36626
- import { existsSync as existsSync8, readFileSync as readFileSync9, writeFileSync as writeFileSync2 } from "node:fs";
37436
+ import { existsSync as existsSync7, readFileSync as readFileSync8, writeFileSync as writeFileSync2 } from "node:fs";
36627
37437
  import { join as join10 } from "node:path";
36628
37438
  import { createInterface } from "node:readline";
36629
37439
  function resolveProjectRootArg(arg) {
@@ -36679,8 +37489,8 @@ function detectAuthType(provider, token) {
36679
37489
  async function promptYesNo(question) {
36680
37490
  const rl = createInterface({ input: process.stdin, output: process.stderr });
36681
37491
  try {
36682
- const answer = await new Promise((resolve7) => {
36683
- rl.question(question, (a) => resolve7(a));
37492
+ const answer = await new Promise((resolve8) => {
37493
+ rl.question(question, (a) => resolve8(a));
36684
37494
  });
36685
37495
  const clean = answer.trim().toLowerCase();
36686
37496
  return clean === "y" || clean === "yes";
@@ -36690,7 +37500,7 @@ async function promptYesNo(question) {
36690
37500
  }
36691
37501
  async function runMigrateProjectSecrets(opts) {
36692
37502
  const configPath = projectConfigPath(opts.projectRoot);
36693
- if (!existsSync8(configPath)) {
37503
+ if (!existsSync7(configPath)) {
36694
37504
  return {
36695
37505
  configPath,
36696
37506
  backupPath: null,
@@ -36699,7 +37509,7 @@ async function runMigrateProjectSecrets(opts) {
36699
37509
  dryRun: opts.dryRun
36700
37510
  };
36701
37511
  }
36702
- const raw = readFileSync9(configPath, "utf-8");
37512
+ const raw = readFileSync8(configPath, "utf-8");
36703
37513
  let parsed;
36704
37514
  try {
36705
37515
  parsed = JSON.parse(raw);
@@ -37616,12 +38426,12 @@ async function promptPassphrase() {
37616
38426
  "Cannot prompt for passphrase: stdin is not a TTY. Set the CLEO_BACKUP_PASSPHRASE environment variable for non-interactive use."
37617
38427
  );
37618
38428
  }
37619
- return new Promise((resolve7) => {
38429
+ return new Promise((resolve8) => {
37620
38430
  process.stdout.write("Passphrase: ");
37621
38431
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
37622
38432
  rl.question("", (answer) => {
37623
38433
  rl.close();
37624
- resolve7(answer.trim());
38434
+ resolve8(answer.trim());
37625
38435
  });
37626
38436
  });
37627
38437
  }
@@ -37757,9 +38567,9 @@ var init_backup = __esm({
37757
38567
  async run({ args }) {
37758
38568
  const scope = args.scope;
37759
38569
  const { packBundle } = await import("@cleocode/core/store/backup-pack.js");
37760
- const { getProjectRoot: getProjectRoot53 } = await import("@cleocode/core");
38570
+ const { getProjectRoot: getProjectRoot54 } = await import("@cleocode/core");
37761
38571
  const includesProject = scope === "project" || scope === "all";
37762
- const projectRoot = includesProject ? getProjectRoot53() : void 0;
38572
+ const projectRoot = includesProject ? getProjectRoot54() : void 0;
37763
38573
  let passphrase;
37764
38574
  if (args.encrypt === true) {
37765
38575
  passphrase = process.env["CLEO_BACKUP_PASSPHRASE"];
@@ -37835,12 +38645,12 @@ var init_backup = __esm({
37835
38645
  },
37836
38646
  async run({ args }) {
37837
38647
  const bundlePath = args.bundle;
37838
- const { getProjectRoot: getProjectRoot53, getCleoHome: getCleoHome6, getCleoVersion } = await import("@cleocode/core");
38648
+ const { getProjectRoot: getProjectRoot54, getCleoHome: getCleoHome6, getCleoVersion } = await import("@cleocode/core");
37839
38649
  const { BundleError, cleanupStaging, unpackBundle } = await import("@cleocode/core/store/backup-unpack.js");
37840
38650
  const { regenerateConfigJson, regenerateProjectContextJson, regenerateProjectInfoJson } = await import("@cleocode/core/store/regenerators.js");
37841
38651
  const { regenerateAndCompare } = await import("@cleocode/core/store/restore-json-merge.js");
37842
38652
  const { buildConflictReport, writeConflictReport } = await import("@cleocode/core/store/restore-conflict-report.js");
37843
- const projectRoot = getProjectRoot53();
38653
+ const projectRoot = getProjectRoot54();
37844
38654
  if (args.force !== true) {
37845
38655
  const existing = checkForExistingData(projectRoot, getCleoHome6());
37846
38656
  if (existing.length > 0) {
@@ -38442,7 +39252,7 @@ var briefing_exports = {};
38442
39252
  __export(briefing_exports, {
38443
39253
  briefingCommand: () => briefingCommand
38444
39254
  });
38445
- import { existsSync as existsSync9, readFileSync as readFileSync10 } from "node:fs";
39255
+ import { existsSync as existsSync8, readFileSync as readFileSync9 } from "node:fs";
38446
39256
  import { join as join11 } from "node:path";
38447
39257
  import { pushWarning as pushWarning2 } from "@cleocode/core";
38448
39258
  import { resolveLegacyCleoDir } from "@cleocode/paths";
@@ -38475,7 +39285,7 @@ function renderForAdapter(sectionName, content, format) {
38475
39285
  }
38476
39286
  async function runBriefingInject(sectionName, formatStr) {
38477
39287
  const templatePath = resolveInjectionTemplatePath();
38478
- if (!existsSync9(templatePath)) {
39288
+ if (!existsSync8(templatePath)) {
38479
39289
  pushWarning2({
38480
39290
  code: "W_TEMPLATE_INJECT_FAILED",
38481
39291
  message: `CLEO-INJECTION.md not found at ${templatePath}`
@@ -38492,7 +39302,7 @@ async function runBriefingInject(sectionName, formatStr) {
38492
39302
  process.exitCode = 1;
38493
39303
  return;
38494
39304
  }
38495
- const content = readFileSync10(templatePath, "utf-8");
39305
+ const content = readFileSync9(templatePath, "utf-8");
38496
39306
  const section = extractSection(content, sectionName);
38497
39307
  if (section === null) {
38498
39308
  const available = INJECTION_SECTION_NAMES.join(", ");
@@ -38731,15 +39541,15 @@ var init_caamp = __esm({
38731
39541
  }
38732
39542
  if (args["dry-run"]) {
38733
39543
  const { parseCaampBlocks } = await import("@cleocode/caamp");
38734
- const { existsSync: existsSync17 } = await import("node:fs");
38735
- const { readFile: readFile7 } = await import("node:fs/promises");
39544
+ const { existsSync: existsSync19 } = await import("node:fs");
39545
+ const { readFile: readFile8 } = await import("node:fs/promises");
38736
39546
  const dryResults = [];
38737
39547
  for (const filePath of filePaths) {
38738
- if (!existsSync17(filePath)) {
39548
+ if (!existsSync19(filePath)) {
38739
39549
  dryResults.push({ filePath, exists: false, blockCount: 0, wouldRemove: 0 });
38740
39550
  continue;
38741
39551
  }
38742
- const content = await readFile7(filePath, "utf-8");
39552
+ const content = await readFile8(filePath, "utf-8");
38743
39553
  const blocks = parseCaampBlocks(content);
38744
39554
  const uniqueContents = new Set(blocks.map((b) => b.content));
38745
39555
  const wouldRemove = blocks.length - uniqueContents.size;
@@ -38833,13 +39643,13 @@ var cant_exports = {};
38833
39643
  __export(cant_exports, {
38834
39644
  cantCommand: () => cantCommand
38835
39645
  });
38836
- import { existsSync as existsSync10, mkdirSync as mkdirSync2, readFileSync as readFileSync11, writeFileSync as writeFileSync3 } from "node:fs";
39646
+ import { existsSync as existsSync9, mkdirSync as mkdirSync2, readFileSync as readFileSync10, writeFileSync as writeFileSync3 } from "node:fs";
38837
39647
  import { dirname as dirname4, isAbsolute, join as join13, resolve as resolve3 } from "node:path";
38838
39648
  function resolveFilePath(file) {
38839
39649
  return isAbsolute(file) ? file : resolve3(process.cwd(), file);
38840
39650
  }
38841
39651
  function ensureExists(filePath, operation) {
38842
- if (existsSync10(filePath)) return true;
39652
+ if (existsSync9(filePath)) return true;
38843
39653
  cliError(`File not found: ${filePath}`, "E_FILE_READ");
38844
39654
  process.exitCode = 3;
38845
39655
  if (process.env["CLEO_DEBUG"]) humanWarn(`(operation: ${operation})`);
@@ -38989,7 +39799,7 @@ var init_cant = __esm({
38989
39799
  if (!ensureExists(filePath, "cant.migrate")) return;
38990
39800
  try {
38991
39801
  const mod = await loadMigrateEngine();
38992
- const content = readFileSync11(filePath, "utf-8");
39802
+ const content = readFileSync10(filePath, "utf-8");
38993
39803
  const result = mod.migrateMarkdown(content, filePath, {
38994
39804
  write: isWrite,
38995
39805
  verbose: isVerbose,
@@ -39055,7 +39865,7 @@ var chain_exports = {};
39055
39865
  __export(chain_exports, {
39056
39866
  chainCommand: () => chainCommand
39057
39867
  });
39058
- import { readFileSync as readFileSync12 } from "node:fs";
39868
+ import { readFileSync as readFileSync11 } from "node:fs";
39059
39869
  var showCommand3, listCommand5, addCommand3, instantiateCommand, advanceCommand, chainCommand;
39060
39870
  var init_chain = __esm({
39061
39871
  "packages/cleo/src/cli/commands/chain.ts"() {
@@ -39097,7 +39907,7 @@ var init_chain = __esm({
39097
39907
  }
39098
39908
  },
39099
39909
  async run({ args }) {
39100
- const chainJson = JSON.parse(readFileSync12(args.file, "utf-8"));
39910
+ const chainJson = JSON.parse(readFileSync11(args.file, "utf-8"));
39101
39911
  await dispatchFromCli(
39102
39912
  "mutate",
39103
39913
  "pipeline",
@@ -39178,7 +39988,7 @@ var changeset_exports = {};
39178
39988
  __export(changeset_exports, {
39179
39989
  changesetCommand: () => changesetCommand
39180
39990
  });
39181
- import { existsSync as existsSync11 } from "node:fs";
39991
+ import { existsSync as existsSync10 } from "node:fs";
39182
39992
  import { join as join14 } from "node:path";
39183
39993
  import {
39184
39994
  changesets,
@@ -39305,7 +40115,7 @@ var init_changeset = __esm({
39305
40115
  });
39306
40116
  if (!outcome.ok) {
39307
40117
  const err = outcome.error;
39308
- const hint = err.code === "E_SLUG_PATTERN_MISMATCH" && err.example ? `example slug: ${err.example}` : void 0;
40118
+ const hint = err.code === "E_SLUG_PATTERN_MISMATCH" && err.example ? `example slug: ${err.example}` : err.code === "E_SLUG_RESERVED" ? `try: ${err.suggestions.join(", ")}` : void 0;
39309
40119
  cliError(err.message, 6 /* VALIDATION_ERROR */, {
39310
40120
  name: err.code,
39311
40121
  ...hint ? { fix: hint } : {}
@@ -39327,7 +40137,7 @@ var init_changeset = __esm({
39327
40137
  async run() {
39328
40138
  const projectRoot = getProjectRoot30();
39329
40139
  const dir = join14(projectRoot, ".changeset");
39330
- if (!existsSync11(dir)) {
40140
+ if (!existsSync10(dir)) {
39331
40141
  const empty = { entries: [], count: 0, dir, note: "no .changeset/ dir" };
39332
40142
  if (isHumanOutput()) {
39333
40143
  humanLine("No changeset entries found (.changeset/ directory absent).");
@@ -39497,10 +40307,10 @@ var init_check2 = __esm({
39497
40307
  }
39498
40308
  },
39499
40309
  async run({ args }) {
39500
- const { readFileSync: readFileSync18 } = await import("node:fs");
40310
+ const { readFileSync: readFileSync21 } = await import("node:fs");
39501
40311
  let chain;
39502
40312
  try {
39503
- chain = JSON.parse(readFileSync18(args.file, "utf8"));
40313
+ chain = JSON.parse(readFileSync21(args.file, "utf8"));
39504
40314
  } catch (err) {
39505
40315
  const message = err instanceof Error ? err.message : String(err);
39506
40316
  cliError(`Failed to read or parse chain file: ${message}`, 2, {
@@ -39790,11 +40600,11 @@ var init_check2 = __esm({
39790
40600
  },
39791
40601
  async run({ args }) {
39792
40602
  const { spawnSync } = await import("node:child_process");
39793
- const { existsSync: existsSync17 } = await import("node:fs");
39794
- const { join: join34, resolve: resolve7 } = await import("node:path");
40603
+ const { existsSync: existsSync19 } = await import("node:fs");
40604
+ const { join: join37, resolve: resolve8 } = await import("node:path");
39795
40605
  const strict = Boolean(args.strict);
39796
40606
  const jsonOnly = Boolean(args.json);
39797
- const repoRoot = resolve7(process.cwd());
40607
+ const repoRoot = resolve8(process.cwd());
39798
40608
  const gates = [
39799
40609
  {
39800
40610
  id: "gate-1",
@@ -39831,8 +40641,8 @@ var init_check2 = __esm({
39831
40641
  const results = [];
39832
40642
  let anyFailed = false;
39833
40643
  for (const gate of gates) {
39834
- const scriptPath = join34(repoRoot, gate.script);
39835
- if (!existsSync17(scriptPath)) {
40644
+ const scriptPath = join37(repoRoot, gate.script);
40645
+ if (!existsSync19(scriptPath)) {
39836
40646
  results.push({
39837
40647
  id: gate.id,
39838
40648
  task: gate.task,
@@ -40147,9 +40957,9 @@ var init_code = __esm({
40147
40957
  async run({ args }) {
40148
40958
  await requireTreeSitter();
40149
40959
  const { smartOutline } = await import("@cleocode/core/internal");
40150
- const { join: join34 } = await import("node:path");
40960
+ const { join: join37 } = await import("node:path");
40151
40961
  const root = process.cwd();
40152
- const absPath = args.file.startsWith("/") ? args.file : join34(root, args.file);
40962
+ const absPath = args.file.startsWith("/") ? args.file : join37(root, args.file);
40153
40963
  const result = smartOutline(absPath, root);
40154
40964
  if (result.errors.length > 0 && result.symbols.length === 0) {
40155
40965
  cliError(result.errors.join(", "), 1, { name: "E_OUTLINE_FAILED" });
@@ -40240,9 +41050,9 @@ var init_code = __esm({
40240
41050
  async run({ args }) {
40241
41051
  await requireTreeSitter();
40242
41052
  const { smartUnfold } = await import("@cleocode/core/internal");
40243
- const { join: join34 } = await import("node:path");
41053
+ const { join: join37 } = await import("node:path");
40244
41054
  const root = process.cwd();
40245
- const absPath = args.file.startsWith("/") ? args.file : join34(root, args.file);
41055
+ const absPath = args.file.startsWith("/") ? args.file : join37(root, args.file);
40246
41056
  const result = smartUnfold(absPath, args.symbol, root);
40247
41057
  if (!result.found) {
40248
41058
  const errs = result.errors.length > 0 ? `: ${result.errors.join(", ")}` : "";
@@ -41924,7 +42734,7 @@ var daemon_exports = {};
41924
42734
  __export(daemon_exports, {
41925
42735
  daemonCommand: () => daemonCommand
41926
42736
  });
41927
- import { existsSync as existsSync12 } from "node:fs";
42737
+ import { existsSync as existsSync11 } from "node:fs";
41928
42738
  import { join as join16 } from "node:path";
41929
42739
  import { fileURLToPath as fileURLToPath3 } from "node:url";
41930
42740
  import { getGCDaemonStatus, spawnGCDaemon, stopGCDaemon } from "@cleocode/core/gc/daemon.js";
@@ -41992,7 +42802,7 @@ async function showDaemonStatus(cleoDir, projectRoot) {
41992
42802
  function resolveDaemonInstallerScript() {
41993
42803
  const filePath = fileURLToPath3(import.meta.url);
41994
42804
  const candidate1 = join16(filePath, "..", "..", "..", "scripts", "install-daemon-service.mjs");
41995
- if (existsSync12(candidate1)) return candidate1;
42805
+ if (existsSync11(candidate1)) return candidate1;
41996
42806
  const candidate2 = join16(
41997
42807
  filePath,
41998
42808
  "..",
@@ -42913,12 +43723,12 @@ var detect_drift_exports = {};
42913
43723
  __export(detect_drift_exports, {
42914
43724
  detectDriftCommand: () => detectDriftCommand
42915
43725
  });
42916
- import { existsSync as existsSync13, readdirSync, readFileSync as readFileSync13 } from "node:fs";
43726
+ import { existsSync as existsSync12, readdirSync, readFileSync as readFileSync12 } from "node:fs";
42917
43727
  import { dirname as dirname5, join as join17 } from "node:path";
42918
43728
  function findProjectRoot() {
42919
43729
  let currentDir = process.cwd();
42920
43730
  while (currentDir !== "/") {
42921
- if (existsSync13(join17(currentDir, "package.json"))) {
43731
+ if (existsSync12(join17(currentDir, "package.json"))) {
42922
43732
  return currentDir;
42923
43733
  }
42924
43734
  const parent = dirname5(currentDir);
@@ -42942,11 +43752,11 @@ var init_detect_drift = __esm({
42942
43752
  },
42943
43753
  async run() {
42944
43754
  const projectRoot = findProjectRoot();
42945
- const isCleoRepo = existsSync13(join17(projectRoot, "packages", "cleo", "src"));
43755
+ const isCleoRepo = existsSync12(join17(projectRoot, "packages", "cleo", "src"));
42946
43756
  const cleoSrcRoot = isCleoRepo ? join17(projectRoot, "packages", "cleo", "src") : join17(projectRoot, "src");
42947
43757
  const safeRead = (filePath) => {
42948
43758
  try {
42949
- return readFileSync13(filePath, "utf-8");
43759
+ return readFileSync12(filePath, "utf-8");
42950
43760
  } catch {
42951
43761
  return "";
42952
43762
  }
@@ -42958,7 +43768,7 @@ var init_detect_drift = __esm({
42958
43768
  recommendations: []
42959
43769
  };
42960
43770
  const injPath = join17(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
42961
- if (existsSync13(injPath)) {
43771
+ if (existsSync12(injPath)) {
42962
43772
  const content = safeRead(injPath);
42963
43773
  userResult.checks.push({
42964
43774
  name: "Agent injection",
@@ -43012,7 +43822,7 @@ var init_detect_drift = __esm({
43012
43822
  const specPath = join17(projectRoot, "docs", "specs", "CLEO-OPERATION-CONSTITUTION.md");
43013
43823
  const registryPath = join17(cleoSrcRoot, "dispatch", "registry.ts");
43014
43824
  const dispatchDomainsDir = join17(cleoSrcRoot, "dispatch", "domains");
43015
- if (!existsSync13(specPath)) {
43825
+ if (!existsSync12(specPath)) {
43016
43826
  addCheck("Gateway-to-spec sync", "fail", "CLEO-OPERATION-CONSTITUTION.md missing", [
43017
43827
  {
43018
43828
  severity: "error",
@@ -43022,7 +43832,7 @@ var init_detect_drift = __esm({
43022
43832
  recommendation: "Create docs/specs/CLEO-OPERATION-CONSTITUTION.md with canonical operation definitions"
43023
43833
  }
43024
43834
  ]);
43025
- } else if (!existsSync13(registryPath) || !existsSync13(dispatchDomainsDir)) {
43835
+ } else if (!existsSync12(registryPath) || !existsSync12(dispatchDomainsDir)) {
43026
43836
  addCheck("Gateway-to-spec sync", "fail", "Dispatch registry or domains missing", [
43027
43837
  {
43028
43838
  severity: "error",
@@ -43082,7 +43892,7 @@ var init_detect_drift = __esm({
43082
43892
  try {
43083
43893
  const cliDir = join17(cleoSrcRoot, "cli", "commands");
43084
43894
  const coreDir = isCleoRepo ? join17(projectRoot, "packages", "core", "src") : join17(projectRoot, "src", "core");
43085
- if (!existsSync13(cliDir)) {
43895
+ if (!existsSync12(cliDir)) {
43086
43896
  addCheck("CLI-to-core sync", "fail", "CLI commands directory missing", [
43087
43897
  {
43088
43898
  severity: "error",
@@ -43091,7 +43901,7 @@ var init_detect_drift = __esm({
43091
43901
  recommendation: "Verify TypeScript source structure is intact"
43092
43902
  }
43093
43903
  ]);
43094
- } else if (!existsSync13(coreDir)) {
43904
+ } else if (!existsSync12(coreDir)) {
43095
43905
  addCheck("CLI-to-core sync", "fail", "Core directory missing", [
43096
43906
  {
43097
43907
  severity: "error",
@@ -43109,7 +43919,7 @@ var init_detect_drift = __esm({
43109
43919
  }
43110
43920
  try {
43111
43921
  const domainsDir = join17(cleoSrcRoot, "dispatch", "domains");
43112
- if (!existsSync13(domainsDir)) {
43922
+ if (!existsSync12(domainsDir)) {
43113
43923
  addCheck("Domain handler coverage", "fail", "Dispatch domains directory missing", [
43114
43924
  {
43115
43925
  severity: "error",
@@ -43127,7 +43937,7 @@ var init_detect_drift = __esm({
43127
43937
  }
43128
43938
  try {
43129
43939
  const matrixPath = join17(cleoSrcRoot, "dispatch", "lib", "capability-matrix.ts");
43130
- if (!existsSync13(matrixPath)) {
43940
+ if (!existsSync12(matrixPath)) {
43131
43941
  addCheck("Capability matrix", "fail", "Capability matrix missing", [
43132
43942
  {
43133
43943
  severity: "error",
@@ -43144,7 +43954,7 @@ var init_detect_drift = __esm({
43144
43954
  }
43145
43955
  try {
43146
43956
  const schemaPath = join17(projectRoot, "src", "store", "schema.ts");
43147
- if (!existsSync13(schemaPath)) {
43957
+ if (!existsSync12(schemaPath)) {
43148
43958
  addCheck("Schema validation", "fail", "Schema definition missing", [
43149
43959
  {
43150
43960
  severity: "error",
@@ -43181,7 +43991,7 @@ var init_detect_drift = __esm({
43181
43991
  const visionPath = join17(projectRoot, "docs", "concepts", "CLEO-VISION.md");
43182
43992
  const specPath = join17(projectRoot, "docs", "specs", "CLEO-PORTABLE-PROJECT-BRAIN-SPEC.md");
43183
43993
  const issues = [];
43184
- if (!existsSync13(visionPath)) {
43994
+ if (!existsSync12(visionPath)) {
43185
43995
  issues.push({
43186
43996
  severity: "error",
43187
43997
  category: "vision",
@@ -43190,7 +44000,7 @@ var init_detect_drift = __esm({
43190
44000
  recommendation: "Create docs/concepts/CLEO-VISION.md with project vision"
43191
44001
  });
43192
44002
  }
43193
- if (!existsSync13(specPath)) {
44003
+ if (!existsSync12(specPath)) {
43194
44004
  issues.push({
43195
44005
  severity: "error",
43196
44006
  category: "spec",
@@ -43235,7 +44045,7 @@ var init_detect_drift = __esm({
43235
44045
  }
43236
44046
  try {
43237
44047
  const injectionPath = join17(projectRoot, CLEO_DIR_NAME, TEMPLATES_SUBDIR, CLEO_INJECTION_MD);
43238
- if (!existsSync13(injectionPath)) {
44048
+ if (!existsSync12(injectionPath)) {
43239
44049
  addCheck("Agent injection", "fail", "Agent injection template missing", [
43240
44050
  {
43241
44051
  severity: "error",
@@ -43265,7 +44075,7 @@ var init_detect_drift = __esm({
43265
44075
  }
43266
44076
  try {
43267
44077
  const exitCodesPath = join17(cleoSrcRoot, "dispatch", "lib", "exit-codes.ts");
43268
- if (!existsSync13(exitCodesPath)) {
44078
+ if (!existsSync12(exitCodesPath)) {
43269
44079
  addCheck("Exit codes", "fail", "Exit codes definition missing", [
43270
44080
  {
43271
44081
  severity: "error",
@@ -43611,8 +44421,96 @@ var init_strict_args = __esm({
43611
44421
  }
43612
44422
  });
43613
44423
 
44424
+ // packages/cleo/src/cli/commands/docs/graph.ts
44425
+ import {
44426
+ buildDocProvenanceGraph,
44427
+ DocProvenanceRootNotFoundError,
44428
+ renderProvenanceGraphAsDot
44429
+ } from "@cleocode/core/internal";
44430
+ function parseDepth(raw) {
44431
+ if (raw === void 0 || raw === null || raw === "") return 2;
44432
+ const parsed = Number.parseInt(String(raw), 10);
44433
+ if (!Number.isInteger(parsed) || parsed < 0) {
44434
+ cliError(
44435
+ `--depth must be a non-negative integer (got '${String(raw)}')`,
44436
+ 6 /* VALIDATION_ERROR */,
44437
+ { name: "E_VALIDATION" }
44438
+ );
44439
+ process.exit(6 /* VALIDATION_ERROR */);
44440
+ }
44441
+ return parsed;
44442
+ }
44443
+ function parseFormat(raw) {
44444
+ if (raw === void 0 || raw === null || raw === "") return "json";
44445
+ const candidate = String(raw);
44446
+ if (candidate !== "json" && candidate !== "dot") {
44447
+ cliError(`--format must be one of: json|dot \u2014 got '${candidate}'`, 6 /* VALIDATION_ERROR */, {
44448
+ name: "E_VALIDATION"
44449
+ });
44450
+ process.exit(6 /* VALIDATION_ERROR */);
44451
+ }
44452
+ return candidate;
44453
+ }
44454
+ var graphCommand;
44455
+ var init_graph2 = __esm({
44456
+ "packages/cleo/src/cli/commands/docs/graph.ts"() {
44457
+ "use strict";
44458
+ init_src2();
44459
+ init_define_cli_command();
44460
+ init_renderers();
44461
+ graphCommand = defineCommand({
44462
+ meta: {
44463
+ name: "graph",
44464
+ description: "Traverse the docs provenance graph from a root (slug or task ID) and return a typed DocProvenanceResponse envelope. Walks supersedes/superseded-by chains plus cross-entity edges to owning + related tasks. Default depth=2. Pass --format dot for Graphviz output (still wrapped in the envelope under data.dot)."
44465
+ },
44466
+ args: {
44467
+ root: {
44468
+ type: "string",
44469
+ description: "Root identifier \u2014 a canonical doc slug (e.g. adr-078-docs-provenance) or a CLEO task ID (T####). Required.",
44470
+ required: true
44471
+ },
44472
+ depth: {
44473
+ type: "string",
44474
+ description: "Maximum BFS hops from the root (default: 2; minimum: 0)."
44475
+ },
44476
+ format: {
44477
+ type: "string",
44478
+ description: "Output format: json (default) | dot."
44479
+ }
44480
+ },
44481
+ async run({ args }) {
44482
+ const root = String(args.root);
44483
+ const depth = parseDepth(args.depth);
44484
+ const format = parseFormat(args.format);
44485
+ try {
44486
+ const graph = await buildDocProvenanceGraph({ root, depth });
44487
+ const payload = { ...graph };
44488
+ if (format === "dot") {
44489
+ payload["dot"] = renderProvenanceGraphAsDot(graph);
44490
+ }
44491
+ cliOutput(payload, { command: "docs graph", operation: "docs.graph" });
44492
+ } catch (err) {
44493
+ if (err instanceof DocProvenanceRootNotFoundError) {
44494
+ cliError(err.message, 4 /* NOT_FOUND */, {
44495
+ name: "E_DOC_PROVENANCE_ROOT_NOT_FOUND",
44496
+ fix: "Verify the root with `cleo docs list --project --type adr` (or your kind) and pass an existing slug or task ID. Slugs and task IDs are matched against attachments.slug and attachment_refs.owner_id respectively.",
44497
+ details: { root }
44498
+ });
44499
+ process.exit(4 /* NOT_FOUND */);
44500
+ }
44501
+ const message = err instanceof Error ? err.message : String(err);
44502
+ cliError(`docs graph failed: ${message}`, 1 /* GENERAL_ERROR */, {
44503
+ name: "E_DOCS_GRAPH_FAILED"
44504
+ });
44505
+ process.exit(1 /* GENERAL_ERROR */);
44506
+ }
44507
+ }
44508
+ });
44509
+ }
44510
+ });
44511
+
43614
44512
  // packages/cleo/src/viewer/pidfile.ts
43615
- import { mkdir, readFile as readFile2, unlink, writeFile } from "node:fs/promises";
44513
+ import { mkdir, readFile as readFile3, unlink, writeFile } from "node:fs/promises";
43616
44514
  import { dirname as dirname6, join as join18 } from "node:path";
43617
44515
  import { getCleoHome as getCleoHome2 } from "@cleocode/core/internal";
43618
44516
  function viewerPidFilePath() {
@@ -43626,7 +44524,7 @@ async function writeViewerPidFile(record) {
43626
44524
  }
43627
44525
  async function readViewerPidFile() {
43628
44526
  try {
43629
- const raw = await readFile2(viewerPidFilePath(), "utf8");
44527
+ const raw = await readFile3(viewerPidFilePath(), "utf8");
43630
44528
  const parsed = JSON.parse(raw);
43631
44529
  if (typeof parsed.pid === "number" && typeof parsed.port === "number" && typeof parsed.host === "string" && typeof parsed.projectRoot === "string" && typeof parsed.startedAt === "number") {
43632
44530
  return parsed;
@@ -44436,10 +45334,9 @@ var docs_exports = {};
44436
45334
  __export(docs_exports, {
44437
45335
  docsCommand: () => docsCommand
44438
45336
  });
44439
- import { appendFile, mkdir as mkdir2, readdir, readFile as readFile3, writeFile as writeFile2 } from "node:fs/promises";
45337
+ import { appendFile, mkdir as mkdir2, readdir, readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
44440
45338
  import { dirname as dirname8, isAbsolute as isAbsolute2, join as join21, resolve as resolve5 } from "node:path";
44441
45339
  import {
44442
- buildDocsGraph,
44443
45340
  CleoError as CleoError3,
44444
45341
  CounterMismatchError,
44445
45342
  checkSlugSimilarity,
@@ -44448,6 +45345,7 @@ import {
44448
45345
  DEFAULT_SIMILARITY_THRESHOLD,
44449
45346
  detectStrayCleoDb as detectStrayCleoDb2,
44450
45347
  exportDocument,
45348
+ findSimilarDocs,
44451
45349
  getAgentOutputsAbsolute,
44452
45350
  getProjectRoot as getProjectRoot38,
44453
45351
  listDocVersions,
@@ -44510,7 +45408,7 @@ async function runGapCheck(_projectRoot, filterId) {
44510
45408
  for (const file of reviewFiles) {
44511
45409
  if (filterId && !file.includes(filterId)) continue;
44512
45410
  const filePath = join21(reviewDir, file);
44513
- const content = await readFile3(filePath, "utf-8");
45411
+ const content = await readFile4(filePath, "utf-8");
44514
45412
  const taskMatch = file.match(/^(T\d+)/);
44515
45413
  const taskId = taskMatch ? taskMatch[1] : "UNKNOWN";
44516
45414
  const gaps = [];
@@ -44553,7 +45451,7 @@ function loadCliRegistry(projectRoot) {
44553
45451
  throw err;
44554
45452
  }
44555
45453
  }
44556
- var addCommand5, listCommand8, fetchCommand, removeCommand2, generateCommand, exportCommand4, searchCommand, mergeCommand, graphCommand, rankCommand, versionsCommand, publishCommand2, publishPrCommand, syncCommand3, statusCommand7, gapCheckCommand, importCommand2, schemaCommand, listTypesCommand, docsCommand;
45454
+ var addCommand5, listCommand8, fetchCommand, removeCommand2, supersedeCommandArgs, supersedeCommand, generateCommand, exportCommand4, searchCommand, findCommand3, mergeCommand, rankCommand, updateCommand, versionsCommand, publishCommand2, publishPrCommand, syncCommand3, statusCommand7, gapCheckCommand, importCommand2, schemaCommand, listTypesCommand, docsCommand;
44557
45455
  var init_docs3 = __esm({
44558
45456
  "packages/cleo/src/cli/commands/docs.ts"() {
44559
45457
  "use strict";
@@ -44563,11 +45461,12 @@ var init_docs3 = __esm({
44563
45461
  init_canon_docs();
44564
45462
  init_strict_args();
44565
45463
  init_renderers();
45464
+ init_graph2();
44566
45465
  init_docs_viewer();
44567
45466
  addCommand5 = defineCommand({
44568
45467
  meta: {
44569
45468
  name: "add",
44570
- description: 'Attach a local file or remote URL to a CLEO entity (task, session, observation). Owner type is inferred from the ID prefix: T### \u2192 task, ses_* \u2192 session, O-* \u2192 observation. Use --slug to set a human-friendly alias (unique per project) (T9636).\n\nPositional arguments:\n <owner-id> Owner entity ID (T###, ses_*, O-*) \u2014 required\n [file] Local file path to attach \u2014 optional when --url is set\n\nNamed arguments:\n --url <url> Remote URL to attach (instead of a local file)\n --desc <text> Free-text description of this attachment\n --labels <csv> Comma-separated labels (e.g. rfc,spec)\n --attached-by <name> Agent identity that created the attachment (default: "human")\n --slug <kebab> Human-friendly alias, unique per project (T9636)\n --type <kind> Taxonomy classification \u2014 run `cleo docs list-types` for kinds\n\nUnknown flags are rejected with E_UNKNOWN_FLAG + did-you-mean suggestions (T10359).'
45469
+ description: 'Attach a local file or remote URL to a CLEO entity (task, session, observation). Owner type is inferred from the ID prefix: T### \u2192 task, ses_* \u2192 session, O-* \u2192 observation. Use --slug to set a human-friendly alias (unique per project) (T9636).\n\nPositional arguments:\n <owner-id> Owner entity ID (T###, ses_*, O-*) \u2014 required\n [file] Local file path to attach \u2014 optional when --url is set\n\nNamed arguments:\n --url <url> Remote URL to attach (instead of a local file)\n --desc <text> Free-text description of this attachment\n --labels <csv> Comma-separated labels (e.g. rfc,spec)\n --attached-by <name> Agent identity that created the attachment (default: "human")\n --slug <kebab> Human-friendly alias, unique per project (T9636)\n --title <text> Human-readable title \u2014 REQUIRED for --type adr when --slug is omitted (T10360)\n --type <kind> Taxonomy classification \u2014 run `cleo docs list-types` for kinds\n --allow-similar Bypass the slug-similarity warn \u2014 every bypass is audited\n to .cleo/audit/similar-bypass.jsonl (T10361)\n --strict Enforce body-schema (requiredSections) \u2014 fail with\n E_DOC_SCHEMA_MISMATCH instead of warning (T10160)\n\nValidation behaviors:\n \u2022 Unknown flags \u2192 E_UNKNOWN_FLAG with did-you-mean suggestions (T10359)\n \u2022 Slug collision \u2192 E_SLUG_RESERVED + 3 alternative slugs (T10386)\n \u2022 Near-duplicate slug \u2192 W_SLUG_SIMILAR warning unless --allow-similar (T10361)\n \u2022 For --type adr without --slug, slug auto-allocates as `adr-NNN-<kebab-title>` via the\n central allocator (T10360 \u2014 closes T10153). --title is required in this case.'
44571
45470
  },
44572
45471
  args: {
44573
45472
  "owner-id": {
@@ -44600,6 +45499,10 @@ var init_docs3 = __esm({
44600
45499
  type: "string",
44601
45500
  description: "Human-friendly kebab-case alias for the attachment, unique per project (T9636). Collision returns E_SLUG_RESERVED with 3 alternative suggestions (legacy E_SLUG_TAKEN aliased under details.aliases for one release \u2014 T10386)."
44602
45501
  },
45502
+ title: {
45503
+ type: "string",
45504
+ description: "Human-readable title used to derive the kebab-slug tail when auto-allocating an ADR slug. REQUIRED when --type adr is set AND --slug is omitted. Slugified via the shared kebabize helper (lowercase, hyphen-separated, diacritics stripped) (T10360)."
45505
+ },
44603
45506
  type: {
44604
45507
  type: "string",
44605
45508
  description: "Taxonomy classification \u2014 run `cleo docs list-types` to enumerate registered kinds (T9637 / T9788)"
@@ -44639,6 +45542,17 @@ var init_docs3 = __esm({
44639
45542
  });
44640
45543
  process.exit(6);
44641
45544
  }
45545
+ if (args.type === "adr" && !args.slug && !args.title) {
45546
+ cliError(
45547
+ "--title <text> is required when --type adr is used without --slug \u2014 the allocator needs a title to assemble adr-NNN-<kebab-title>",
45548
+ 6,
45549
+ {
45550
+ name: "E_VALIDATION",
45551
+ fix: 'Re-run with --title "Adopt Drizzle v1 beta" (or pass --slug adr-042-explicit-name to bypass auto-allocation).'
45552
+ }
45553
+ );
45554
+ process.exit(6);
45555
+ }
44642
45556
  let resolvedFile;
44643
45557
  if (fileArg) {
44644
45558
  const routing = resolveWorktreeRouting2();
@@ -44751,6 +45665,7 @@ var init_docs3 = __esm({
44751
45665
  ...args.labels ? { labels: args.labels } : {},
44752
45666
  ...args["attached-by"] ? { attachedBy: args["attached-by"] } : {},
44753
45667
  ...args.slug ? { slug: args.slug } : {},
45668
+ ...args.title ? { title: args.title } : {},
44754
45669
  ...args.type ? { type: args.type } : {},
44755
45670
  ...args.strict === true ? { strict: true } : {}
44756
45671
  },
@@ -44791,6 +45706,15 @@ var init_docs3 = __esm({
44791
45706
  orderBy: {
44792
45707
  type: "string",
44793
45708
  description: "Sort key: newest (default \u2014 most recent first), sha (ascending hex), slug (alphabetical, slug-less rows last) (T9792)."
45709
+ },
45710
+ // T9922 — MVI record projection opt-out flags (surfaced for --help).
45711
+ verbose: {
45712
+ type: "boolean",
45713
+ description: "Return full attachment records instead of the MVI projection (id + slug + type + kind + sha + size + createdAt). T9922."
45714
+ },
45715
+ full: {
45716
+ type: "boolean",
45717
+ description: "Alias for --verbose. T9922."
44794
45718
  }
44795
45719
  },
44796
45720
  async run({ args }) {
@@ -44857,6 +45781,15 @@ var init_docs3 = __esm({
44857
45781
  type: "positional",
44858
45782
  description: "Attachment ID (att_*) or SHA-256 hex",
44859
45783
  required: true
45784
+ },
45785
+ // T9922 — MVI record projection opt-out flags (surfaced for --help).
45786
+ verbose: {
45787
+ type: "boolean",
45788
+ description: "Return the full attachment metadata block instead of the MVI projection. The byte payload is always returned. T9922."
45789
+ },
45790
+ full: {
45791
+ type: "boolean",
45792
+ description: "Alias for --verbose. T9922."
44860
45793
  }
44861
45794
  },
44862
45795
  async run({ args }) {
@@ -44900,6 +45833,54 @@ var init_docs3 = __esm({
44900
45833
  );
44901
45834
  }
44902
45835
  });
45836
+ supersedeCommandArgs = {
45837
+ oldSlug: {
45838
+ type: "positional",
45839
+ description: "Slug of the doc being replaced",
45840
+ required: true
45841
+ },
45842
+ newSlug: {
45843
+ type: "positional",
45844
+ description: "Slug of the doc that replaces oldSlug",
45845
+ required: true
45846
+ },
45847
+ reason: {
45848
+ type: "string",
45849
+ description: "Optional human-readable reason carried back on the response envelope"
45850
+ }
45851
+ };
45852
+ supersedeCommand = defineCommand({
45853
+ meta: {
45854
+ name: "supersede",
45855
+ description: "Atomically supersede an older doc with a newer one: flips lifecycle_status to 'superseded' on the old row and links both rows via the supersedes/superseded_by FK pointers. All writes commit in a single SQLite transaction."
45856
+ },
45857
+ args: supersedeCommandArgs,
45858
+ async run({ args, rawArgs }) {
45859
+ try {
45860
+ assertKnownFlags(rawArgs, supersedeCommandArgs, "docs supersede");
45861
+ } catch (err) {
45862
+ if (err instanceof UnknownFlagError) {
45863
+ cliError(err.message, 6 /* VALIDATION_ERROR */, { name: "E_VALIDATION" });
45864
+ process.exit(6 /* VALIDATION_ERROR */);
45865
+ }
45866
+ throw err;
45867
+ }
45868
+ const oldSlug = args.oldSlug;
45869
+ const newSlug = args.newSlug;
45870
+ const reason = typeof args.reason === "string" && args.reason.length > 0 ? args.reason : void 0;
45871
+ await dispatchFromCli(
45872
+ "mutate",
45873
+ "docs",
45874
+ "supersede",
45875
+ {
45876
+ oldSlug,
45877
+ newSlug,
45878
+ ...reason !== void 0 ? { reason } : {}
45879
+ },
45880
+ { command: "docs supersede" }
45881
+ );
45882
+ }
45883
+ });
44903
45884
  generateCommand = defineCommand({
44904
45885
  meta: {
44905
45886
  name: "generate",
@@ -45051,6 +46032,102 @@ var init_docs3 = __esm({
45051
46032
  }
45052
46033
  }
45053
46034
  });
46035
+ findCommand3 = defineCommand({
46036
+ meta: {
46037
+ name: "find",
46038
+ description: "Find docs similar to a seed slug via llmtxt/similarity.rankBySimilarity. Pass --similar <slug>; results default to the same DocKind as the seed. Use --all-kinds to rank cross-kind, --threshold to set the minimum cosine score, and --limit to cap the number of returned hits.\n\nNamed arguments:\n --similar <slug> Slug of the seed doc to anchor similarity against (required for now)\n --limit <n> Maximum number of hits to return (default 10)\n --threshold <0..1> Minimum cosine score, hits below are dropped (default 0.5)\n --all-kinds Disable the same-kind filter and rank cross-kind\n --json Emit LAFS JSON envelope (default for non-TTY)"
46039
+ },
46040
+ args: {
46041
+ similar: {
46042
+ type: "string",
46043
+ description: "Slug of the seed doc to anchor similarity against"
46044
+ },
46045
+ limit: {
46046
+ type: "string",
46047
+ description: "Maximum number of hits to return (default: 10)"
46048
+ },
46049
+ threshold: {
46050
+ type: "string",
46051
+ description: "Minimum cosine similarity score in [0, 1] (default: 0.5)"
46052
+ },
46053
+ "all-kinds": {
46054
+ type: "boolean",
46055
+ description: "Disable the same-kind filter and rank across every DocKind"
46056
+ },
46057
+ json: {
46058
+ type: "boolean",
46059
+ description: "Emit LAFS JSON envelope instead of human-readable output"
46060
+ }
46061
+ },
46062
+ async run({ args, rawArgs }) {
46063
+ try {
46064
+ assertKnownFlags(rawArgs, findCommand3.args, "docs find");
46065
+ } catch (err) {
46066
+ if (err instanceof UnknownFlagError) {
46067
+ cliError(err.message, 6 /* VALIDATION_ERROR */, {
46068
+ name: err.code,
46069
+ fix: err.fix,
46070
+ alternatives: err.suggestions.map((s) => ({ action: s, command: s })),
46071
+ details: { flag: err.flag, knownFlags: err.knownFlags }
46072
+ });
46073
+ process.exit(6 /* VALIDATION_ERROR */);
46074
+ }
46075
+ throw err;
46076
+ }
46077
+ const similarSlug = typeof args.similar === "string" ? args.similar.trim() : "";
46078
+ if (similarSlug.length === 0) {
46079
+ cliError("--similar <slug> is required", 6 /* VALIDATION_ERROR */, {
46080
+ name: "E_VALIDATION",
46081
+ fix: "Example: `cleo docs find --similar adr-073-above-epic-naming --limit 5`."
46082
+ });
46083
+ process.exit(6 /* VALIDATION_ERROR */);
46084
+ }
46085
+ let limit;
46086
+ if (typeof args.limit === "string") {
46087
+ const parsed = Number.parseInt(args.limit, 10);
46088
+ if (!Number.isFinite(parsed) || parsed <= 0) {
46089
+ cliError(
46090
+ `--limit must be a positive integer (got "${args.limit}")`,
46091
+ 6 /* VALIDATION_ERROR */,
46092
+ {
46093
+ name: "E_VALIDATION"
46094
+ }
46095
+ );
46096
+ process.exit(6 /* VALIDATION_ERROR */);
46097
+ }
46098
+ limit = parsed;
46099
+ }
46100
+ let threshold;
46101
+ if (typeof args.threshold === "string") {
46102
+ const parsed = Number.parseFloat(args.threshold);
46103
+ if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
46104
+ cliError(
46105
+ `--threshold must be a number in [0, 1] (got "${args.threshold}")`,
46106
+ 6 /* VALIDATION_ERROR */,
46107
+ { name: "E_VALIDATION" }
46108
+ );
46109
+ process.exit(6 /* VALIDATION_ERROR */);
46110
+ }
46111
+ threshold = parsed;
46112
+ }
46113
+ const allKinds = args["all-kinds"] === true;
46114
+ const projectRoot = getProjectRoot38();
46115
+ try {
46116
+ const result = await findSimilarDocs(similarSlug, {
46117
+ ...limit !== void 0 ? { limit } : {},
46118
+ ...threshold !== void 0 ? { threshold } : {},
46119
+ allKinds,
46120
+ projectRoot
46121
+ });
46122
+ cliOutput(result, { command: "docs find", operation: "docs.find" });
46123
+ } catch (err) {
46124
+ const code = err instanceof Error && typeof err.code === "string" ? err.code : "E_DOCS_FIND_FAILED";
46125
+ const message = err instanceof Error ? err.message : String(err);
46126
+ cliError(`docs find failed: ${message}`, 1 /* GENERAL_ERROR */, { name: code });
46127
+ process.exit(1 /* GENERAL_ERROR */);
46128
+ }
46129
+ }
46130
+ });
45054
46131
  mergeCommand = defineCommand({
45055
46132
  meta: {
45056
46133
  name: "merge",
@@ -45109,10 +46186,10 @@ var init_docs3 = __esm({
45109
46186
  }
45110
46187
  }
45111
46188
  });
45112
- graphCommand = defineCommand({
46189
+ rankCommand = defineCommand({
45113
46190
  meta: {
45114
- name: "graph",
45115
- description: "Build a document relationship graph for an entity using llmtxt/graph.buildGraph. Output formats: mermaid (default), dot, json."
46191
+ name: "rank",
46192
+ description: "Rank attachments for an entity by relevance using llmtxt/similarity.rankBySimilarity. Pass --query to use a custom query; otherwise the entity ID anchors the ranking."
45116
46193
  },
45117
46194
  args: {
45118
46195
  for: {
@@ -45120,13 +46197,9 @@ var init_docs3 = __esm({
45120
46197
  description: "Owner entity ID (T###, ses_*, O-*)",
45121
46198
  required: true
45122
46199
  },
45123
- format: {
45124
- type: "string",
45125
- description: "Output format: mermaid | dot | json (default: mermaid)"
45126
- },
45127
- out: {
46200
+ query: {
45128
46201
  type: "string",
45129
- description: "Write graph to this file path"
46202
+ description: "Optional free-text query to rank against (default: owner ID)"
45130
46203
  },
45131
46204
  json: {
45132
46205
  type: "boolean",
@@ -45135,89 +46208,105 @@ var init_docs3 = __esm({
45135
46208
  },
45136
46209
  async run({ args }) {
45137
46210
  const projectRoot = getProjectRoot38();
45138
- const fmt = args.format ?? "mermaid";
45139
46211
  try {
45140
- const result = await buildDocsGraph({ ownerId: String(args.for), projectRoot });
45141
- let output2;
45142
- if (fmt === "dot") {
45143
- const dotLines = ["digraph docs {"];
45144
- for (const node of result.nodes) {
45145
- dotLines.push(` "${node.id}" [label="${node.label}"];`);
45146
- }
45147
- for (const edge of result.edges) {
45148
- dotLines.push(` "${edge.source}" -> "${edge.target}" [label="${edge.relation}"];`);
45149
- }
45150
- dotLines.push("}");
45151
- output2 = dotLines.join("\n");
45152
- } else if (fmt === "json") {
45153
- output2 = JSON.stringify(result, null, 2);
45154
- } else {
45155
- const lines = ["graph LR"];
45156
- for (const edge of result.edges) {
45157
- lines.push(` ${edge.source} -->|${edge.relation}| ${edge.target}`);
45158
- }
45159
- if (result.edges.length === 0) {
45160
- for (const node of result.nodes) {
45161
- lines.push(` ${node.id}["${node.label}"]`);
45162
- }
45163
- }
45164
- output2 = lines.join("\n");
45165
- }
45166
- if (typeof args.out === "string" && args.out.length > 0) {
45167
- const outPath = isAbsolute2(args.out) ? args.out : resolve5(projectRoot, args.out);
45168
- await mkdir2(dirname8(outPath), { recursive: true });
45169
- await writeFile2(outPath, output2, "utf8");
45170
- humanInfo(`Wrote graph to ${outPath}`);
45171
- }
45172
- cliOutput(
45173
- { format: fmt, nodeCount: result.nodes.length, edgeCount: result.edges.length, output: output2 },
45174
- { command: "docs graph", operation: "docs.graph" }
45175
- );
46212
+ const result = await rankDocs({
46213
+ ownerId: String(args.for),
46214
+ query: args.query ?? void 0,
46215
+ projectRoot
46216
+ });
46217
+ cliOutput(result, { command: "docs rank", operation: "docs.rank" });
45176
46218
  } catch (err) {
45177
46219
  const message = err instanceof Error ? err.message : String(err);
45178
- cliError(`docs graph failed: ${message}`, 1 /* GENERAL_ERROR */, {
45179
- name: "E_DOCS_GRAPH_FAILED"
46220
+ cliError(`docs rank failed: ${message}`, 1 /* GENERAL_ERROR */, {
46221
+ name: "E_DOCS_RANK_FAILED"
45180
46222
  });
45181
46223
  process.exit(1 /* GENERAL_ERROR */);
45182
46224
  }
45183
46225
  }
45184
46226
  });
45185
- rankCommand = defineCommand({
46227
+ updateCommand = defineCommand({
45186
46228
  meta: {
45187
- name: "rank",
45188
- description: "Rank attachments for an entity by relevance using llmtxt/similarity.rankBySimilarity. Pass --query to use a custom query; otherwise the entity ID anchors the ranking."
46229
+ name: "update",
46230
+ description: 'Replace blob content for an existing slug while preserving the slug. Pass --file <path> OR --content <text> (exactly one). Defaults --status to "draft" on every update so explicit `accepted` docs get back-pressured to draft on edit. Audit log entry appended to .cleo/audit/docs-versioning.jsonl (squashed within 5 min).\n\nPositional arguments:\n <slug> Slug of the attachment to update (required)\n\nNamed arguments:\n --file <path> Local file containing the new content\n --content <text> Inline UTF-8 content (mutually exclusive with --file)\n --message <text> One-line summary of the change (audit log)\n --status <status> Override lifecycle status \u2014 default "draft"\n --attached-by <name> Agent identity for this revision (default "human")'
45189
46231
  },
45190
46232
  args: {
45191
- for: {
45192
- type: "string",
45193
- description: "Owner entity ID (T###, ses_*, O-*)",
46233
+ slug: {
46234
+ type: "positional",
46235
+ description: "Slug of the attachment to update",
45194
46236
  required: true
45195
46237
  },
45196
- query: {
46238
+ file: {
45197
46239
  type: "string",
45198
- description: "Optional free-text query to rank against (default: owner ID)"
46240
+ description: "Local file containing the new content"
45199
46241
  },
45200
- json: {
45201
- type: "boolean",
45202
- description: "Emit LAFS JSON envelope"
46242
+ content: {
46243
+ type: "string",
46244
+ description: "Inline UTF-8 content (mutually exclusive with --file)"
46245
+ },
46246
+ message: {
46247
+ type: "string",
46248
+ description: "One-line summary of the change (recorded in the audit log)"
46249
+ },
46250
+ status: {
46251
+ type: "string",
46252
+ description: "Lifecycle status to set on the new row. Valid: draft|proposed|accepted|superseded|archived|deprecated. Default: draft."
46253
+ },
46254
+ "attached-by": {
46255
+ type: "string",
46256
+ description: 'Agent identity that performed the update (default: "human")'
45203
46257
  }
45204
46258
  },
45205
- async run({ args }) {
45206
- const projectRoot = getProjectRoot38();
46259
+ async run({ args, rawArgs }) {
45207
46260
  try {
45208
- const result = await rankDocs({
45209
- ownerId: String(args.for),
45210
- query: args.query ?? void 0,
45211
- projectRoot
45212
- });
45213
- cliOutput(result, { command: "docs rank", operation: "docs.rank" });
46261
+ assertKnownFlags(rawArgs, updateCommand.args, "docs update");
45214
46262
  } catch (err) {
45215
- const message = err instanceof Error ? err.message : String(err);
45216
- cliError(`docs rank failed: ${message}`, 1 /* GENERAL_ERROR */, {
45217
- name: "E_DOCS_RANK_FAILED"
46263
+ if (err instanceof UnknownFlagError) {
46264
+ cliError(err.message, 6 /* VALIDATION_ERROR */, {
46265
+ name: err.code,
46266
+ fix: err.fix,
46267
+ alternatives: err.suggestions.map((s) => ({ action: s, command: s })),
46268
+ details: { flag: err.flag, knownFlags: err.knownFlags }
46269
+ });
46270
+ process.exit(6 /* VALIDATION_ERROR */);
46271
+ }
46272
+ throw err;
46273
+ }
46274
+ const slug = String(args.slug);
46275
+ const filePath = typeof args.file === "string" ? args.file : void 0;
46276
+ const inlineContent = typeof args.content === "string" ? args.content : void 0;
46277
+ if (filePath !== void 0 && inlineContent !== void 0) {
46278
+ cliError("--file and --content are mutually exclusive", 6 /* VALIDATION_ERROR */, {
46279
+ name: "E_VALIDATION",
46280
+ fix: "Use `cleo docs update <slug> --file <path>` OR `--content <text>` (not both)."
45218
46281
  });
45219
- process.exit(1 /* GENERAL_ERROR */);
46282
+ process.exit(6 /* VALIDATION_ERROR */);
45220
46283
  }
46284
+ if (filePath === void 0 && inlineContent === void 0) {
46285
+ cliError("provide --file <path> OR --content <text>", 6 /* VALIDATION_ERROR */, {
46286
+ name: "E_VALIDATION",
46287
+ fix: 'Example: `cleo docs update my-doc --file ./new.md` OR `cleo docs update my-doc --content "..."`.'
46288
+ });
46289
+ process.exit(6 /* VALIDATION_ERROR */);
46290
+ }
46291
+ let resolvedFile;
46292
+ if (filePath !== void 0) {
46293
+ const routing = resolveWorktreeRouting2();
46294
+ resolvedFile = resolveWorktreeFilePath(filePath, routing);
46295
+ }
46296
+ await dispatchFromCli(
46297
+ "mutate",
46298
+ "docs",
46299
+ "update",
46300
+ {
46301
+ slug,
46302
+ ...resolvedFile !== void 0 ? { file: resolvedFile } : {},
46303
+ ...inlineContent !== void 0 ? { content: inlineContent } : {},
46304
+ ...typeof args.message === "string" ? { message: args.message } : {},
46305
+ ...typeof args.status === "string" ? { status: args.status } : {},
46306
+ ...typeof args["attached-by"] === "string" ? { attachedBy: args["attached-by"] } : {}
46307
+ },
46308
+ { command: "docs update" }
46309
+ );
45221
46310
  }
45222
46311
  });
45223
46312
  versionsCommand = defineCommand({
@@ -45726,13 +46815,17 @@ var init_docs3 = __esm({
45726
46815
  },
45727
46816
  subCommands: {
45728
46817
  add: addCommand5,
46818
+ update: updateCommand,
45729
46819
  list: listCommand8,
45730
46820
  fetch: fetchCommand,
45731
46821
  remove: removeCommand2,
46822
+ supersede: supersedeCommand,
45732
46823
  generate: generateCommand,
45733
46824
  export: exportCommand4,
46825
+ find: findCommand3,
45734
46826
  search: searchCommand,
45735
46827
  merge: mergeCommand,
46828
+ // T10164 — DocProvenanceResponse-typed graph (`--root <slug>|<taskId>`).
45736
46829
  graph: graphCommand,
45737
46830
  rank: rankCommand,
45738
46831
  versions: versionsCommand,
@@ -46174,6 +47267,7 @@ var ProgressTracker;
46174
47267
  var init_progress = __esm({
46175
47268
  "packages/cleo/src/cli/progress.ts"() {
46176
47269
  "use strict";
47270
+ init_format_context();
46177
47271
  ProgressTracker = class {
46178
47272
  enabled;
46179
47273
  prefix;
@@ -46190,7 +47284,7 @@ var init_progress = __esm({
46190
47284
  * Start the progress tracker.
46191
47285
  */
46192
47286
  start() {
46193
- if (!this.enabled) return;
47287
+ if (!this.enabled || isQuiet()) return;
46194
47288
  this.currentStep = 0;
46195
47289
  stderr.write(`
46196
47290
  ${this.prefix}: Starting...
@@ -46200,7 +47294,7 @@ ${this.prefix}: Starting...
46200
47294
  * Update to a specific step.
46201
47295
  */
46202
47296
  step(index, message) {
46203
- if (!this.enabled) return;
47297
+ if (!this.enabled || isQuiet()) return;
46204
47298
  this.currentStep = index;
46205
47299
  const stepName = this.steps[index] ?? message ?? "Working...";
46206
47300
  const progress = `[${index + 1}/${this.totalSteps}]`;
@@ -46222,7 +47316,7 @@ ${this.prefix}: Starting...
46222
47316
  * one JSON object per CLI invocation (ADR-039 / T927).
46223
47317
  */
46224
47318
  complete(summary) {
46225
- if (!this.enabled) return;
47319
+ if (!this.enabled || isQuiet()) return;
46226
47320
  if (summary) {
46227
47321
  stderr.write(`
46228
47322
  ${this.prefix}: \u2713 ${summary}
@@ -46239,7 +47333,7 @@ ${this.prefix}: \u2713 Complete
46239
47333
  * Report an error.
46240
47334
  */
46241
47335
  error(message) {
46242
- if (!this.enabled) return;
47336
+ if (!this.enabled || isQuiet()) return;
46243
47337
  stderr.write(`
46244
47338
  ${this.prefix}: \u2717 ${message}
46245
47339
 
@@ -46259,7 +47353,7 @@ __export(migrate_agents_v2_exports, {
46259
47353
  walkAgentsDir: () => walkAgentsDir
46260
47354
  });
46261
47355
  import { createHash as createHash2 } from "node:crypto";
46262
- import { appendFileSync as appendFileSync2, existsSync as existsSync14, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync14 } from "node:fs";
47356
+ import { appendFileSync as appendFileSync2, existsSync as existsSync13, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync13 } from "node:fs";
46263
47357
  import { join as join22 } from "node:path";
46264
47358
  import { getProjectRoot as getProjectRoot41, installAgentFromCant } from "@cleocode/core/internal";
46265
47359
  import { openCleoDb as openCleoDb2 } from "@cleocode/core/store/open-cleo-db";
@@ -46282,13 +47376,13 @@ function extractAgentName(source) {
46282
47376
  function appendAuditLog(projectRoot, entry) {
46283
47377
  const auditPath = join22(projectRoot, AUDIT_LOG_RELATIVE);
46284
47378
  const auditDir = join22(auditPath, "..");
46285
- if (!existsSync14(auditDir)) {
47379
+ if (!existsSync13(auditDir)) {
46286
47380
  mkdirSync3(auditDir, { recursive: true });
46287
47381
  }
46288
47382
  appendFileSync2(auditPath, JSON.stringify(entry) + "\n", "utf8");
46289
47383
  }
46290
47384
  function walkAgentsDir(db, scanDir, projectRoot, summary, verbose) {
46291
- if (!existsSync14(scanDir)) return;
47385
+ if (!existsSync13(scanDir)) return;
46292
47386
  let files;
46293
47387
  try {
46294
47388
  files = readdirSync2(scanDir).filter((f) => f.endsWith(".cant"));
@@ -46304,7 +47398,7 @@ function walkAgentsDir(db, scanDir, projectRoot, summary, verbose) {
46304
47398
  let sourceBytes;
46305
47399
  let sourceText;
46306
47400
  try {
46307
- sourceBytes = readFileSync14(cantPath);
47401
+ sourceBytes = readFileSync13(cantPath);
46308
47402
  sourceText = sourceBytes.toString("utf8");
46309
47403
  } catch (err) {
46310
47404
  const msg = err instanceof Error ? err.message : String(err);
@@ -46407,10 +47501,10 @@ async function runMigrateAgentsV2(projectRoot, verbose = true) {
46407
47501
  }
46408
47502
  function readMigrationConflicts(projectRoot) {
46409
47503
  const auditPath = join22(projectRoot, AUDIT_LOG_RELATIVE);
46410
- if (!existsSync14(auditPath)) return [];
47504
+ if (!existsSync13(auditPath)) return [];
46411
47505
  let raw;
46412
47506
  try {
46413
- raw = readFileSync14(auditPath, "utf8");
47507
+ raw = readFileSync13(auditPath, "utf8");
46414
47508
  } catch {
46415
47509
  return [];
46416
47510
  }
@@ -47439,8 +48533,8 @@ var init_event = __esm({
47439
48533
  }
47440
48534
  for (const file of filesToTail) {
47441
48535
  const agentId = file.replace(".jsonl", "");
47442
- const { readFileSync: readFileSync18 } = await import("node:fs");
47443
- const content = readFileSync18(join24(eventsDir, file), "utf-8");
48536
+ const { readFileSync: readFileSync21 } = await import("node:fs");
48537
+ const content = readFileSync21(join24(eventsDir, file), "utf-8");
47444
48538
  const eventLines = content.trim().split("\n").filter(Boolean);
47445
48539
  const tail = eventLines.slice(-lines);
47446
48540
  if (jsonMode) {
@@ -47535,8 +48629,8 @@ var init_event = __esm({
47535
48629
  const printAgentLog = async (file) => {
47536
48630
  const agentId = file.replace(".jsonl", "");
47537
48631
  try {
47538
- const { readFileSync: readFileSync18 } = await import("node:fs");
47539
- const content = readFileSync18(join24(eventsDir, file), "utf-8");
48632
+ const { readFileSync: readFileSync21 } = await import("node:fs");
48633
+ const content = readFileSync21(join24(eventsDir, file), "utf-8");
47540
48634
  const eventLines = content.trim().split("\n").filter(Boolean);
47541
48635
  const tail = eventLines.slice(-lines);
47542
48636
  if (jsonMode) {
@@ -47954,10 +49048,10 @@ var init_federation = __esm({
47954
49048
  // packages/cleo/src/cli/commands/find.ts
47955
49049
  var find_exports = {};
47956
49050
  __export(find_exports, {
47957
- findCommand: () => findCommand3
49051
+ findCommand: () => findCommand4
47958
49052
  });
47959
49053
  import { createPage } from "@cleocode/core";
47960
- var findCommand3;
49054
+ var findCommand4;
47961
49055
  var init_find = __esm({
47962
49056
  "packages/cleo/src/cli/commands/find.ts"() {
47963
49057
  "use strict";
@@ -47965,7 +49059,7 @@ var init_find = __esm({
47965
49059
  init_dist();
47966
49060
  init_cli();
47967
49061
  init_renderers();
47968
- findCommand3 = defineCommand({
49062
+ findCommand4 = defineCommand({
47969
49063
  meta: { name: "find", description: "Fuzzy search tasks by title/description" },
47970
49064
  args: {
47971
49065
  query: {
@@ -47984,7 +49078,16 @@ var init_find = __esm({
47984
49078
  limit: { type: "string", description: "Max results (default: 20)" },
47985
49079
  offset: { type: "string", description: "Skip first N results" },
47986
49080
  fields: { type: "string", description: "Comma-separated additional fields to include" },
47987
- verbose: { type: "boolean", description: "Include all task fields", alias: "v" },
49081
+ verbose: {
49082
+ type: "boolean",
49083
+ description: "Return full task records instead of the MVI projection (id + title + status + key metadata). T9922.",
49084
+ alias: "v"
49085
+ },
49086
+ // T9922 — MVI record projection opt-out alias (surfaced for --help).
49087
+ full: {
49088
+ type: "boolean",
49089
+ description: "Alias for --verbose. T9922."
49090
+ },
47988
49091
  /**
47989
49092
  * Filter by task kind axis (T944/T9072).
47990
49093
  * Values: work | research | experiment | bug | spike | release
@@ -47992,6 +49095,20 @@ var init_find = __esm({
47992
49095
  kind: {
47993
49096
  type: "string",
47994
49097
  description: "Filter by kind axis (work|research|experiment|bug|spike|release) \u2014 T944"
49098
+ },
49099
+ /**
49100
+ * Unified urgency surface (T9905).
49101
+ *
49102
+ * Selects tasks where
49103
+ * priority IN ('critical','high') OR severity IN ('P0','P1')
49104
+ *
49105
+ * Combines the two orthogonal urgency axes (priority + severity) into a
49106
+ * single filter so agents don't have to query each axis separately.
49107
+ */
49108
+ urgent: {
49109
+ type: "boolean",
49110
+ description: "Surface urgent work across both axes: priority IN (critical,high) OR severity IN (P0,P1) (T9905)",
49111
+ alias: "u"
47995
49112
  }
47996
49113
  },
47997
49114
  async run({ args }) {
@@ -48009,6 +49126,7 @@ var init_find = __esm({
48009
49126
  if (args.fields !== void 0) params["fields"] = args.fields;
48010
49127
  if (args.verbose !== void 0) params["verbose"] = args.verbose;
48011
49128
  if (args.kind !== void 0) params["kind"] = args.kind;
49129
+ if (args.urgent !== void 0) params["urgent"] = args.urgent;
48012
49130
  const response = await dispatchRaw("query", "tasks", "find", params);
48013
49131
  if (!response.success) {
48014
49132
  handleRawError(response, { command: "find", operation: "tasks.find" });
@@ -48365,7 +49483,7 @@ function applyJsonFlag(jsonFlag) {
48365
49483
  }
48366
49484
  }
48367
49485
  var statusCommand9, resolveCommand, depsCommand2, rawCommand, discoverCommand, searchCommand2, augmentCommand, contextCommand2, impactCommand2, impactFullCommand, clustersCommand, flowsCommand, diffCommand, routeMapCommand, shapeCheckCommand, searchCodeCommand, wikiCommand, hotPathsCommand, hotNodesCommand, coldSymbolsCommand, orphansCommand, queryCommand, initCommand, syncCommand4, reconcileCommand, livingFullContextCommand, livingTaskFootprintCommand, livingBrainAnchorsCommand, livingWhyCommand, livingConduitScanCommand, livingCommand, graphCommand2;
48368
- var init_graph2 = __esm({
49486
+ var init_graph3 = __esm({
48369
49487
  "packages/cleo/src/cli/commands/graph.ts"() {
48370
49488
  "use strict";
48371
49489
  init_dist();
@@ -49424,25 +50542,26 @@ __export(init_exports, {
49424
50542
  getWorkflowTemplatesDir: () => getWorkflowTemplatesDir2,
49425
50543
  initCommand: () => initCommand2
49426
50544
  });
49427
- import { existsSync as existsSync15, readFileSync as readFileSync15 } from "node:fs";
50545
+ import { existsSync as existsSync14, readFileSync as readFileSync14 } from "node:fs";
49428
50546
  import { join as join26 } from "node:path";
49429
50547
  import { fileURLToPath as fileURLToPath6 } from "node:url";
49430
50548
  import {
49431
50549
  CleoError as CleoError4,
49432
- formatError as formatError4,
49433
50550
  getWorkflowTemplatesDir as getCoreWorkflowTemplatesDir,
49434
50551
  initProject as initProject2,
50552
+ pushWarning as pushWarning5,
49435
50553
  scaffoldWorkflows
49436
50554
  } from "@cleocode/core";
50555
+ import { getTemplatesByKind } from "@cleocode/core/templates/registry";
49437
50556
  function getGitignoreTemplate() {
49438
50557
  try {
49439
50558
  const thisFile = fileURLToPath6(import.meta.url);
49440
50559
  const packageRoot = join26(thisFile, "..", "..", "..", "..");
49441
50560
  const localTemplatePath = join26(packageRoot, "templates", "cleo-gitignore");
49442
50561
  const monorepoTemplatePath = join26(packageRoot, "..", "..", "templates", "cleo-gitignore");
49443
- const templatePath = existsSync15(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
49444
- if (existsSync15(templatePath)) {
49445
- return readFileSync15(templatePath, "utf-8");
50562
+ const templatePath = existsSync14(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
50563
+ if (existsSync14(templatePath)) {
50564
+ return readFileSync14(templatePath, "utf-8");
49446
50565
  }
49447
50566
  } catch {
49448
50567
  }
@@ -49451,6 +50570,9 @@ function getGitignoreTemplate() {
49451
50570
  function getWorkflowTemplatesDir2() {
49452
50571
  return getCoreWorkflowTemplatesDir();
49453
50572
  }
50573
+ function isWorkflowName(id) {
50574
+ return id === "release-prepare" || id === "release-publish" || id === "release-fanout" || id === "release-rollback";
50575
+ }
49454
50576
  var initCommand2;
49455
50577
  var init_init = __esm({
49456
50578
  "packages/cleo/src/cli/commands/init.ts"() {
@@ -49491,7 +50613,11 @@ var init_init = __esm({
49491
50613
  },
49492
50614
  workflows: {
49493
50615
  type: "boolean",
49494
- description: "Scaffold the release-prepare.yml workflow into .github/workflows/ (T9531).",
50616
+ /**
50617
+ * @deprecated Use `cleo templates install --kind workflow` instead
50618
+ * (T9886 / Saga T9855). Removal target: v2026.7.0. T9888.
50619
+ */
50620
+ description: "[DEPRECATED \u2014 use `cleo templates install --kind workflow`] Scaffold release workflows into .github/workflows/. Will be removed in v2026.7.0.",
49495
50621
  default: false
49496
50622
  },
49497
50623
  "dry-run": {
@@ -49503,11 +50629,23 @@ var init_init = __esm({
49503
50629
  async run({ args }) {
49504
50630
  try {
49505
50631
  if (args.workflows) {
50632
+ pushWarning5({
50633
+ code: "W_INIT_WORKFLOWS_DEPRECATED",
50634
+ message: "[deprecated] cleo init --workflows: use `cleo templates install --kind workflow` instead. This alias will be removed in v2026.7.0.",
50635
+ severity: "warn",
50636
+ deprecated: "cleo init --workflows",
50637
+ replacement: "cleo templates install --kind workflow",
50638
+ removeBy: "v2026.7.0",
50639
+ context: { task: "T9888", saga: "T9855" }
50640
+ });
49506
50641
  const projectRoot = process.cwd();
49507
50642
  const templatesDir = getWorkflowTemplatesDir2();
50643
+ const workflowEntries = getTemplatesByKind("workflow");
50644
+ const templates2 = workflowEntries.map((entry) => entry.id).filter((id) => isWorkflowName(id));
49508
50645
  const result2 = await scaffoldWorkflows({
49509
50646
  projectRoot,
49510
50647
  templatesDir,
50648
+ ...templates2.length > 0 ? { templates: templates2 } : {},
49511
50649
  dryRun: !!args["dry-run"],
49512
50650
  force: !!args.force
49513
50651
  });
@@ -49549,7 +50687,7 @@ var init_init = __esm({
49549
50687
  );
49550
50688
  } catch (err) {
49551
50689
  if (err instanceof CleoError4) {
49552
- cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
50690
+ cliError(`init failed: ${err.message}`, err.code, { name: "E_INTERNAL" });
49553
50691
  process.exit(err.code);
49554
50692
  }
49555
50693
  throw err;
@@ -50320,6 +51458,20 @@ var init_list3 = __esm({
50320
51458
  "parent-id": {
50321
51459
  type: "string",
50322
51460
  description: "Alias for --parent (legacy parentId compatibility)"
51461
+ },
51462
+ // T9922 — MVI record projection opt-out flags (surfaced for --help).
51463
+ verbose: {
51464
+ type: "boolean",
51465
+ description: "Return full task records instead of the MVI projection (id + title + status + key metadata). T9922."
51466
+ },
51467
+ full: {
51468
+ type: "boolean",
51469
+ description: "Alias for --verbose. T9922."
51470
+ },
51471
+ // T9932 — 1-line-per-record summary render. Global flag; parsed by cli/index.ts.
51472
+ summary: {
51473
+ type: "boolean",
51474
+ description: 'Render each task as a single line "<id> [<status>] <title-truncated-60>". Composes with --output: --output {id|table|count|silent} wins. T9932.'
50323
51475
  }
50324
51476
  };
50325
51477
  listCommand11 = defineCommand({
@@ -50552,7 +51704,7 @@ async function resolveDefaultModel(provider) {
50552
51704
  return profile?.defaultModel ?? IMPLICIT_FALLBACK_MODEL;
50553
51705
  }
50554
51706
  async function runLlmStream(opts) {
50555
- const stdout = opts.stdout ?? process.stdout;
51707
+ const stdout2 = opts.stdout ?? process.stdout;
50556
51708
  const stderr2 = opts.stderr ?? process.stderr;
50557
51709
  const session = opts._sessionOverride ?? await buildSession(opts.provider, opts.model ?? await resolveDefaultModel(opts.provider));
50558
51710
  const sendOpts = {
@@ -50563,7 +51715,7 @@ async function runLlmStream(opts) {
50563
51715
  const stream = session.stream(messages, sendOpts);
50564
51716
  for await (const delta of stream) {
50565
51717
  if (delta.text) {
50566
- stdout.write(delta.text);
51718
+ stdout2.write(delta.text);
50567
51719
  }
50568
51720
  if (delta.reasoning && opts.showThink) {
50569
51721
  stderr2.write(delta.reasoning);
@@ -50808,7 +51960,7 @@ async function _headlessPkceFlow(provider, authUrl) {
50808
51960
  ` After approving, paste the full redirect URL (http://localhost?code=\u2026&state=\u2026):
50809
51961
  `
50810
51962
  );
50811
- return new Promise((resolve7, reject) => {
51963
+ return new Promise((resolve8, reject) => {
50812
51964
  let buf = "";
50813
51965
  process.stdin.setEncoding("utf8");
50814
51966
  process.stdin.once("data", (chunk) => {
@@ -50820,7 +51972,7 @@ async function _headlessPkceFlow(provider, authUrl) {
50820
51972
  reject(new Error('Redirect URL is missing the "code" parameter'));
50821
51973
  return;
50822
51974
  }
50823
- resolve7(code);
51975
+ resolve8(code);
50824
51976
  } catch {
50825
51977
  reject(new Error(`Invalid redirect URL: ${buf}`));
50826
51978
  }
@@ -50828,7 +51980,7 @@ async function _headlessPkceFlow(provider, authUrl) {
50828
51980
  });
50829
51981
  }
50830
51982
  async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
50831
- return new Promise((resolve7) => {
51983
+ return new Promise((resolve8) => {
50832
51984
  const server = createServer2((req, res) => {
50833
51985
  const url = new URL(req.url ?? "/", `http://localhost:${port}`);
50834
51986
  const code = url.searchParams.get("code");
@@ -50838,7 +51990,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
50838
51990
  if (error) {
50839
51991
  res.end(`<h1>Authorization failed</h1><p>${error}</p><p>You may close this tab.</p>`);
50840
51992
  server.close();
50841
- resolve7({
51993
+ resolve8({
50842
51994
  error: {
50843
51995
  code: "E_PKCE_AUTH_DENIED",
50844
51996
  codeName: "E_PKCE_AUTH_DENIED",
@@ -50850,7 +52002,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
50850
52002
  if (!code || state !== expectedState) {
50851
52003
  res.end("<h1>Invalid callback</h1><p>You may close this tab.</p>");
50852
52004
  server.close();
50853
- resolve7({
52005
+ resolve8({
50854
52006
  error: {
50855
52007
  code: "E_PKCE_INVALID_CALLBACK",
50856
52008
  codeName: "E_PKCE_INVALID_CALLBACK",
@@ -50861,7 +52013,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
50861
52013
  }
50862
52014
  res.end("<h1>Authorized</h1><p>You may close this tab and return to your terminal.</p>");
50863
52015
  server.close();
50864
- resolve7({ code });
52016
+ resolve8({ code });
50865
52017
  });
50866
52018
  server.listen(port, "localhost", () => {
50867
52019
  process.stderr.write("\n");
@@ -50994,7 +52146,7 @@ function _generateState() {
50994
52146
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
50995
52147
  }
50996
52148
  function _findFreePort() {
50997
- return new Promise((resolve7, reject) => {
52149
+ return new Promise((resolve8, reject) => {
50998
52150
  const srv = createServer2();
50999
52151
  srv.listen(0, "localhost", () => {
51000
52152
  const addr = srv.address();
@@ -51004,7 +52156,7 @@ function _findFreePort() {
51004
52156
  return;
51005
52157
  }
51006
52158
  const port = addr.port;
51007
- srv.close(() => resolve7(port));
52159
+ srv.close(() => resolve8(port));
51008
52160
  });
51009
52161
  srv.on("error", reject);
51010
52162
  });
@@ -51078,7 +52230,7 @@ var llm_exports = {};
51078
52230
  __export(llm_exports, {
51079
52231
  llmCommand: () => llmCommand
51080
52232
  });
51081
- import { pushWarning as pushWarning5 } from "@cleocode/core";
52233
+ import { pushWarning as pushWarning6 } from "@cleocode/core";
51082
52234
  async function getListProviders() {
51083
52235
  const { listProviders } = await import(
51084
52236
  /* webpackIgnore: true */
@@ -51209,7 +52361,7 @@ var init_llm3 = __esm({
51209
52361
  apiKey = envValue;
51210
52362
  source = "env";
51211
52363
  } else if (typeof a["api-key"] === "string" && a["api-key"]) {
51212
- pushWarning5({
52364
+ pushWarning6({
51213
52365
  code: "W_DEPRECATED_FLAG",
51214
52366
  message: API_KEY_FLAG_DEPRECATION,
51215
52367
  deprecated: "--api-key=<value>",
@@ -51626,19 +52778,19 @@ async function readStdin() {
51626
52778
  if (process.stdin.isTTY) {
51627
52779
  return "";
51628
52780
  }
51629
- return new Promise((resolve7, reject) => {
52781
+ return new Promise((resolve8, reject) => {
51630
52782
  let data = "";
51631
52783
  process.stdin.setEncoding("utf-8");
51632
52784
  process.stdin.on("data", (chunk) => {
51633
52785
  data += chunk;
51634
52786
  });
51635
52787
  process.stdin.on("end", () => {
51636
- resolve7(data.trim());
52788
+ resolve8(data.trim());
51637
52789
  });
51638
52790
  process.stdin.on("error", reject);
51639
52791
  });
51640
52792
  }
51641
- var showCommand7, listCommand13, findCommand4, statsCommand3, appendCommand, archiveCommand2, manifestCommand;
52793
+ var showCommand7, listCommand13, findCommand5, statsCommand3, appendCommand, archiveCommand2, manifestCommand;
51642
52794
  var init_manifest3 = __esm({
51643
52795
  "packages/cleo/src/cli/commands/manifest.ts"() {
51644
52796
  "use strict";
@@ -51724,7 +52876,7 @@ var init_manifest3 = __esm({
51724
52876
  );
51725
52877
  }
51726
52878
  });
51727
- findCommand4 = defineCommand({
52879
+ findCommand5 = defineCommand({
51728
52880
  meta: {
51729
52881
  name: "find",
51730
52882
  description: "Full-text search manifest entries"
@@ -51933,7 +53085,7 @@ var init_manifest3 = __esm({
51933
53085
  subCommands: {
51934
53086
  show: showCommand7,
51935
53087
  list: listCommand13,
51936
- find: findCommand4,
53088
+ find: findCommand5,
51937
53089
  stats: statsCommand3,
51938
53090
  append: appendCommand,
51939
53091
  archive: archiveCommand2
@@ -52013,7 +53165,7 @@ function makeMemorySubcommand(opts) {
52013
53165
  }
52014
53166
  });
52015
53167
  }
52016
- var storeCommand, findCommand5, statsCommand4, observeCommand, timelineCommand, fetchCommand2, decisionFindCommand, decisionStoreCommand, linkCommand, traceCommand, relatedCommand, contextCommand3, graphStatsCommand, graphShowCommand, graphNeighborsCommand, graphAddCommand, graphRemoveCommand, reasonWhyCommand, reasonSimilarCommand, searchHybridCommand, codeLinksCommand, codeAutoLinkCommand, codeMemoriesForCodeCommand, codeForMemoryCommand, consolidateCommand, dreamCommand, reflectCommand, dedupScanCommand, importCommand4, doctorCommand3, llmStatusCommand, verifyCommand, pendingVerifyCommand, tierStatsCommand, tierPromoteCommand, tierDemoteCommand, precompactFlushCommand, backfillRunCommand, backfillApproveCommand, backfillRollbackCommand, backfillCommand2, digestCommand, recentCommand, diaryReadCommand, diaryWriteCommand, diaryCommand, watchCommand2, tierCommand, sweepCommand, memoryCommand;
53168
+ var storeCommand, findCommand6, statsCommand4, observeCommand, timelineCommand, fetchCommand2, decisionFindCommand, decisionStoreCommand, linkCommand, traceCommand, relatedCommand, contextCommand3, graphStatsCommand, graphShowCommand, graphNeighborsCommand, graphAddCommand, graphRemoveCommand, reasonWhyCommand, reasonSimilarCommand, searchHybridCommand, codeLinksCommand, codeAutoLinkCommand, codeMemoriesForCodeCommand, codeForMemoryCommand, consolidateCommand, dreamCommand, reflectCommand, dedupScanCommand, importCommand4, doctorCommand3, llmStatusCommand, verifyCommand, pendingVerifyCommand, tierStatsCommand, tierPromoteCommand, tierDemoteCommand, precompactFlushCommand, backfillRunCommand, backfillApproveCommand, backfillRollbackCommand, backfillCommand2, digestCommand, recentCommand, diaryReadCommand, diaryWriteCommand, diaryCommand, watchCommand2, tierCommand, sweepCommand, memoryCommand;
52017
53169
  var init_memory3 = __esm({
52018
53170
  "packages/cleo/src/cli/commands/memory.ts"() {
52019
53171
  "use strict";
@@ -52105,7 +53257,7 @@ var init_memory3 = __esm({
52105
53257
  }
52106
53258
  }
52107
53259
  });
52108
- findCommand5 = defineCommand({
53260
+ findCommand6 = defineCommand({
52109
53261
  meta: {
52110
53262
  name: "find",
52111
53263
  description: "Search BRAIN memory (all tables, or filter by --type pattern|learning)"
@@ -53718,7 +54870,7 @@ data: ${JSON.stringify({ ts: item.ts })}
53718
54870
  meta: { name: "memory", description: "BRAIN memory operations (patterns, learnings)" },
53719
54871
  subCommands: {
53720
54872
  store: storeCommand,
53721
- find: findCommand5,
54873
+ find: findCommand6,
53722
54874
  stats: statsCommand4,
53723
54875
  observe: observeCommand,
53724
54876
  timeline: timelineCommand,
@@ -55200,15 +56352,15 @@ var init_nexus3 = __esm({
55200
56352
  return;
55201
56353
  }
55202
56354
  if (!skipPrompt) {
55203
- const { createInterface: createInterface4 } = await import("node:readline");
55204
- const rl = createInterface4({ input: process.stdin, output: process.stdout });
55205
- const confirmed = await new Promise((resolve7) => {
56355
+ const { createInterface: createInterface5 } = await import("node:readline");
56356
+ const rl = createInterface5({ input: process.stdin, output: process.stdout });
56357
+ const confirmed = await new Promise((resolve8) => {
55206
56358
  rl.question(
55207
56359
  `
55208
56360
  [nexus] Delete ${matchCount} project(s) from the registry? [y/N] `,
55209
56361
  (answer) => {
55210
56362
  rl.close();
55211
- resolve7(answer.trim().toLowerCase() === "y");
56363
+ resolve8(answer.trim().toLowerCase() === "y");
55212
56364
  }
55213
56365
  );
55214
56366
  });
@@ -55358,8 +56510,8 @@ var init_nexus3 = __esm({
55358
56510
  projectFilter
55359
56511
  });
55360
56512
  if (outputFile) {
55361
- const { writeFileSync: writeFileSync5 } = await import("node:fs");
55362
- writeFileSync5(outputFile, result.content, "utf-8");
56513
+ const { writeFileSync: writeFileSync7 } = await import("node:fs");
56514
+ writeFileSync7(outputFile, result.content, "utf-8");
55363
56515
  const durationMs = Date.now() - startTime;
55364
56516
  cliOutput(
55365
56517
  { outputFile, nodeCount: result.nodeCount, edgeCount: result.edgeCount },
@@ -56507,7 +57659,9 @@ __export(orchestrate_exports, {
56507
57659
  formatRollupTable: () => formatRollupTable,
56508
57660
  orchestrateCommand: () => orchestrateCommand
56509
57661
  });
57662
+ import { execFileSync as execFileSync3 } from "node:child_process";
56510
57663
  import { orchestration } from "@cleocode/core";
57664
+ import { BUILD_CONFIG as BUILD_CONFIG2 } from "@cleocode/core/internal";
56511
57665
  function formatRollupTable(rollup) {
56512
57666
  const waves = "waves" in rollup ? rollup.waves : [rollup];
56513
57667
  const lines = [];
@@ -56600,9 +57754,34 @@ var init_orchestrate3 = __esm({
56600
57754
  epic: {
56601
57755
  type: "string",
56602
57756
  description: "Epic ID to scope status to"
57757
+ },
57758
+ "merge-queue": {
57759
+ type: "boolean",
57760
+ description: "Show GitHub merge queue depth instead of epic status (T10445)"
56603
57761
  }
56604
57762
  },
56605
57763
  async run({ args }) {
57764
+ if (args["merge-queue"]) {
57765
+ const repo = BUILD_CONFIG2.repository.fullName;
57766
+ let queueDepth = 0;
57767
+ let estimatedWaitMinutes = 0;
57768
+ let blocked = false;
57769
+ let note = "merge queue not enabled";
57770
+ try {
57771
+ const raw = execFileSync3(
57772
+ "gh",
57773
+ ["api", `repos/${repo}/merge-queue`, "--jq", ".entries | length"],
57774
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 15e3 }
57775
+ );
57776
+ queueDepth = Number(raw.trim()) || 0;
57777
+ estimatedWaitMinutes = queueDepth * 5;
57778
+ blocked = queueDepth > 10;
57779
+ note = queueDepth > 0 ? "active" : "empty";
57780
+ } catch {
57781
+ }
57782
+ cliOutput({ queueDepth, estimatedWaitMinutes, blocked, note }, { command: "orchestrate" });
57783
+ return;
57784
+ }
56606
57785
  await dispatchFromCli(
56607
57786
  "query",
56608
57787
  "orchestrate",
@@ -56772,6 +57951,10 @@ var init_orchestrate3 = __esm({
56772
57951
  scope: {
56773
57952
  type: "string",
56774
57953
  description: "T9807 sparse-checkout scope: directory prefix to check out in the worktree (cone mode). Example: --scope packages/cleo creates a worktree with only that subtree checked out. Reduces disk usage and checkout time for tasks scoped to a single package."
57954
+ },
57955
+ "orchestrator-defer": {
57956
+ type: "boolean",
57957
+ description: "T9214 atomicity waiver: defer worker file-scope declaration to commit time. Tier-1+ orchestrators only \u2014 records auditable atomicity_waiver in the spawn manifest. Bypasses E_ATOMICITY_NO_SCOPE for worker tasks without explicit AC.files."
56775
57958
  }
56776
57959
  },
56777
57960
  async run({ args }) {
@@ -56782,6 +57965,7 @@ var init_orchestrate3 = __esm({
56782
57965
  tier = parsed;
56783
57966
  }
56784
57967
  }
57968
+ const atomicityScope = args["orchestrator-defer"] ? "orchestrator-defer" : void 0;
56785
57969
  await dispatchFromCli(
56786
57970
  "mutate",
56787
57971
  "orchestrate",
@@ -56791,7 +57975,8 @@ var init_orchestrate3 = __esm({
56791
57975
  protocolType: args.protocol,
56792
57976
  tier,
56793
57977
  noWorktree: args["no-worktree"] === true,
56794
- ...args.scope ? { spawnScope: args.scope } : {}
57978
+ ...args.scope ? { spawnScope: args.scope } : {},
57979
+ ...atomicityScope ? { atomicityScope } : {}
56795
57980
  },
56796
57981
  { command: "orchestrate" }
56797
57982
  );
@@ -57410,7 +58595,7 @@ __export(otel_exports, {
57410
58595
  import {
57411
58596
  CleoError as CleoError5,
57412
58597
  clearOtelData,
57413
- formatError as formatError5,
58598
+ formatError as formatError4,
57414
58599
  getOtelSessions,
57415
58600
  getOtelSpawns,
57416
58601
  getOtelStatus,
@@ -57431,7 +58616,7 @@ var init_otel = __esm({
57431
58616
  cliOutput(result, { command: "otel" });
57432
58617
  } catch (err) {
57433
58618
  if (err instanceof CleoError5) {
57434
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
58619
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57435
58620
  process.exit(err.code);
57436
58621
  }
57437
58622
  throw err;
@@ -57446,7 +58631,7 @@ var init_otel = __esm({
57446
58631
  cliOutput(result, { command: "otel" });
57447
58632
  } catch (err) {
57448
58633
  if (err instanceof CleoError5) {
57449
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
58634
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57450
58635
  process.exit(err.code);
57451
58636
  }
57452
58637
  throw err;
@@ -57474,7 +58659,7 @@ var init_otel = __esm({
57474
58659
  cliOutput(result, { command: "otel" });
57475
58660
  } catch (err) {
57476
58661
  if (err instanceof CleoError5) {
57477
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
58662
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57478
58663
  process.exit(err.code);
57479
58664
  }
57480
58665
  throw err;
@@ -57502,7 +58687,7 @@ var init_otel = __esm({
57502
58687
  cliOutput(result, { command: "otel" });
57503
58688
  } catch (err) {
57504
58689
  if (err instanceof CleoError5) {
57505
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
58690
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57506
58691
  process.exit(err.code);
57507
58692
  }
57508
58693
  throw err;
@@ -57530,7 +58715,7 @@ var init_otel = __esm({
57530
58715
  cliOutput(result, { command: "otel" });
57531
58716
  } catch (err) {
57532
58717
  if (err instanceof CleoError5) {
57533
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
58718
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57534
58719
  process.exit(err.code);
57535
58720
  }
57536
58721
  throw err;
@@ -57545,7 +58730,7 @@ var init_otel = __esm({
57545
58730
  cliOutput(result, { command: "otel" });
57546
58731
  } catch (err) {
57547
58732
  if (err instanceof CleoError5) {
57548
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
58733
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57549
58734
  process.exit(err.code);
57550
58735
  }
57551
58736
  throw err;
@@ -59654,7 +60839,7 @@ __export(research_exports, {
59654
60839
  function generateResearchId() {
59655
60840
  return `res_${Date.now()}`;
59656
60841
  }
59657
- var addCommand10, showCommand11, listCommand21, pendingCommand2, linkCommand2, updateCommand, statsCommand5, linksCommand, archiveCommand3, manifestCommand2, researchCommand;
60842
+ var addCommand10, showCommand11, listCommand21, pendingCommand2, linkCommand2, updateCommand2, statsCommand5, linksCommand, archiveCommand3, manifestCommand2, researchCommand;
59658
60843
  var init_research2 = __esm({
59659
60844
  "packages/cleo/src/cli/commands/research.ts"() {
59660
60845
  "use strict";
@@ -59821,7 +61006,7 @@ var init_research2 = __esm({
59821
61006
  );
59822
61007
  }
59823
61008
  });
59824
- updateCommand = defineCommand({
61009
+ updateCommand2 = defineCommand({
59825
61010
  meta: { name: "update", description: "Update research findings" },
59826
61011
  args: {
59827
61012
  id: {
@@ -59975,7 +61160,7 @@ var init_research2 = __esm({
59975
61160
  list: listCommand21,
59976
61161
  pending: pendingCommand2,
59977
61162
  link: linkCommand2,
59978
- update: updateCommand,
61163
+ update: updateCommand2,
59979
61164
  stats: statsCommand5,
59980
61165
  links: linksCommand,
59981
61166
  archive: archiveCommand3,
@@ -60386,7 +61571,7 @@ var revert_exports = {};
60386
61571
  __export(revert_exports, {
60387
61572
  revertCommand: () => revertCommand
60388
61573
  });
60389
- import { readFile as readFile4 } from "node:fs/promises";
61574
+ import { readFile as readFile5 } from "node:fs/promises";
60390
61575
  import { join as join27 } from "node:path";
60391
61576
  import { cwd as processCwd2 } from "node:process";
60392
61577
  import { E_RECEIPT_NOT_FOUND } from "@cleocode/core/sentient/chain-walker.js";
@@ -60412,7 +61597,7 @@ async function loadOwnerAttestation(attestationFilePath) {
60412
61597
  let raw;
60413
61598
  if (attestationFilePath) {
60414
61599
  try {
60415
- raw = await readFile4(attestationFilePath, "utf-8");
61600
+ raw = await readFile5(attestationFilePath, "utf-8");
60416
61601
  } catch (err) {
60417
61602
  const message = err instanceof Error ? err.message : String(err);
60418
61603
  throw new Error(`Failed to read attestation file "${attestationFilePath}": ${message}`);
@@ -60442,7 +61627,7 @@ async function loadOwnerAttestation(attestationFilePath) {
60442
61627
  async function loadOwnerPubkeys(projectRoot) {
60443
61628
  const path6 = join27(projectRoot, OWNER_PUBKEYS_FILE);
60444
61629
  try {
60445
- const raw = await readFile4(path6, "utf-8");
61630
+ const raw = await readFile5(path6, "utf-8");
60446
61631
  const parsed = JSON.parse(raw);
60447
61632
  if (Array.isArray(parsed)) {
60448
61633
  return new Set(parsed.filter((k) => typeof k === "string"));
@@ -61110,12 +62295,12 @@ __export(self_update_exports, {
61110
62295
  selfUpdateCommand: () => selfUpdateCommand
61111
62296
  });
61112
62297
  import { execFile } from "node:child_process";
61113
- import { readFile as readFile5 } from "node:fs/promises";
62298
+ import { readFile as readFile6 } from "node:fs/promises";
61114
62299
  import { join as join28 } from "node:path";
61115
62300
  import * as readline2 from "node:readline";
61116
62301
  import { promisify } from "node:util";
61117
62302
  import {
61118
- BUILD_CONFIG as BUILD_CONFIG2,
62303
+ BUILD_CONFIG as BUILD_CONFIG3,
61119
62304
  CleoError as CleoError8,
61120
62305
  checkAllRegisteredProjects as checkAllRegisteredProjects2,
61121
62306
  checkStorageMigration,
@@ -61126,7 +62311,7 @@ import {
61126
62311
  async function getCurrentVersion() {
61127
62312
  const cleoHome = getCleoHome4();
61128
62313
  try {
61129
- const content = await readFile5(join28(cleoHome, "VERSION"), "utf-8");
62314
+ const content = await readFile6(join28(cleoHome, "VERSION"), "utf-8");
61130
62315
  return (content.split("\n")[0] ?? "unknown").trim();
61131
62316
  } catch {
61132
62317
  return "unknown";
@@ -61134,14 +62319,14 @@ async function getCurrentVersion() {
61134
62319
  }
61135
62320
  async function getNpmInstalledVersion() {
61136
62321
  try {
61137
- const { stdout } = await execAsync("npm", [
62322
+ const { stdout: stdout2 } = await execAsync("npm", [
61138
62323
  "ls",
61139
62324
  "-g",
61140
62325
  "@cleocode/cleo",
61141
62326
  "--depth=0",
61142
62327
  "--json"
61143
62328
  ]);
61144
- const data = JSON.parse(stdout);
62329
+ const data = JSON.parse(stdout2);
61145
62330
  return data.dependencies?.["@cleocode/cleo"]?.version ?? null;
61146
62331
  } catch {
61147
62332
  return null;
@@ -61149,19 +62334,19 @@ async function getNpmInstalledVersion() {
61149
62334
  }
61150
62335
  async function getDistTagVersion(tag) {
61151
62336
  try {
61152
- const { stdout } = await execAsync("npm", ["view", `@cleocode/cleo@${tag}`, "version"]);
61153
- const v = stdout.trim();
62337
+ const { stdout: stdout2 } = await execAsync("npm", ["view", `@cleocode/cleo@${tag}`, "version"]);
62338
+ const v = stdout2.trim();
61154
62339
  return v || null;
61155
62340
  } catch {
61156
62341
  if (tag === "latest") {
61157
62342
  try {
61158
- const { stdout } = await execAsync("curl", [
62343
+ const { stdout: stdout2 } = await execAsync("curl", [
61159
62344
  "-sL",
61160
62345
  "--max-time",
61161
62346
  "10",
61162
62347
  `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`
61163
62348
  ]);
61164
- const data = JSON.parse(stdout);
62349
+ const data = JSON.parse(stdout2);
61165
62350
  return data.tag_name?.replace(/^v/, "") ?? null;
61166
62351
  } catch {
61167
62352
  return null;
@@ -61218,11 +62403,11 @@ async function runPostUpdateDiagnostics(opts) {
61218
62403
  input: process.stdin,
61219
62404
  output: process.stdout
61220
62405
  });
61221
- shouldMigrate = await new Promise((resolve7) => {
62406
+ shouldMigrate = await new Promise((resolve8) => {
61222
62407
  rl.question(" Do you want to run the upgrade now? [Y/n] ", (answer) => {
61223
62408
  rl.close();
61224
62409
  const clean = answer.trim().toLowerCase();
61225
- resolve7(clean === "" || clean === "y" || clean === "yes");
62410
+ resolve8(clean === "" || clean === "y" || clean === "yes");
61226
62411
  });
61227
62412
  });
61228
62413
  }
@@ -61362,7 +62547,7 @@ var init_self_update = __esm({
61362
62547
  init_progress();
61363
62548
  init_renderers();
61364
62549
  execAsync = promisify(execFile);
61365
- GITHUB_REPO = BUILD_CONFIG2.repository.fullName;
62550
+ GITHUB_REPO = BUILD_CONFIG3.repository.fullName;
61366
62551
  selfUpdateCommand = defineCommand({
61367
62552
  meta: {
61368
62553
  name: "self-update",
@@ -61589,10 +62774,13 @@ var init_self_update = __esm({
61589
62774
  // packages/cleo/src/cli/commands/sentient.ts
61590
62775
  var sentient_exports = {};
61591
62776
  __export(sentient_exports, {
62777
+ __setPromptAcceptExecutionForTest: () => __setPromptAcceptExecutionForTest,
62778
+ promptAcceptExecution: () => promptAcceptExecution,
61592
62779
  sentientCommand: () => sentientCommand
61593
62780
  });
61594
62781
  import { join as join29 } from "node:path";
61595
- import { cwd as processCwd3 } from "node:process";
62782
+ import { cwd as processCwd3, stdin, stdout } from "node:process";
62783
+ import { createInterface as createInterface3 } from "node:readline/promises";
61596
62784
  import {
61597
62785
  getSentientDaemonStatus as getSentientDaemonStatus2,
61598
62786
  monitorWorkers,
@@ -61603,6 +62791,12 @@ import {
61603
62791
  stopSentientDaemon,
61604
62792
  WORKER_BUDGET_MS
61605
62793
  } from "@cleocode/core/sentient/daemon.js";
62794
+ import {
62795
+ appendSentientExecuteAudit,
62796
+ executeFixAction,
62797
+ extractFixActionFromNotesJson,
62798
+ parseFixAction
62799
+ } from "@cleocode/core/sentient/execute-action.js";
61606
62800
  import { safeRunProposeTick } from "@cleocode/core/sentient/propose-tick.js";
61607
62801
  import { patchSentientState, readSentientState as readSentientState2 } from "@cleocode/core/sentient/state.js";
61608
62802
  import { safeRunTick } from "@cleocode/core/sentient/tick.js";
@@ -61622,7 +62816,14 @@ function emitFailure3(code, message, _jsonMode, operation) {
61622
62816
  cliError(message, code, { name: code }, operation ? { operation } : void 0);
61623
62817
  process.exit(1);
61624
62818
  }
61625
- var projectArgs2, startSub, stopSub, statusSub, resumeSub, tickSub, proposeListSub, proposeAcceptSub, proposeRejectSub, proposeDiffSub, proposeRunSub, proposeEnableSub, proposeDisableSub, proposeSub, baselineCaptureSub, baselineSub, allowlistListSub, allowlistAddSub, allowlistRemoveSub, allowlistSub, monitorSub, reviewStatusListSub, reviewStatusShowSub, reviewStatusAcceptSub, reviewStatusRejectSub, reviewStatusSub, sentientCommand;
62819
+ function __setPromptAcceptExecutionForTest(next) {
62820
+ const prev = promptAcceptExecution;
62821
+ promptAcceptExecution = next;
62822
+ return () => {
62823
+ promptAcceptExecution = prev;
62824
+ };
62825
+ }
62826
+ var projectArgs2, startSub, stopSub, statusSub, resumeSub, tickSub, proposeListSub, promptAcceptExecution, proposeAcceptSub, proposeRejectSub, proposeDiffSub, proposeRunSub, proposeEnableSub, proposeDisableSub, proposeSub, baselineCaptureSub, baselineSub, allowlistListSub, allowlistAddSub, allowlistRemoveSub, allowlistSub, monitorSub, reviewStatusListSub, reviewStatusShowSub, reviewStatusAcceptSub, reviewStatusRejectSub, reviewStatusSub, sentientCommand;
61626
62827
  var init_sentient3 = __esm({
61627
62828
  "packages/cleo/src/cli/commands/sentient.ts"() {
61628
62829
  "use strict";
@@ -61820,19 +63021,42 @@ Logs: ${logPath}`
61820
63021
  }
61821
63022
  }
61822
63023
  });
63024
+ promptAcceptExecution = async (fixAction) => {
63025
+ const rl = createInterface3({ input: stdin, output: stdout });
63026
+ try {
63027
+ stdout.write(`[sentient] Proposal accepted. fixAction:
63028
+ $ ${fixAction}
63029
+ `);
63030
+ const answer = await rl.question("Execute now? [y/N] ");
63031
+ const normalised = answer.trim().toLowerCase();
63032
+ return normalised === "y" || normalised === "yes";
63033
+ } finally {
63034
+ rl.close();
63035
+ }
63036
+ };
61823
63037
  proposeAcceptSub = defineCommand({
61824
63038
  meta: {
61825
63039
  name: "accept",
61826
- description: "Accept a proposal \u2014 transition proposed \u2192 pending"
63040
+ description: "Accept a proposal \u2014 transition proposed \u2192 pending, optionally execute its fixAction"
61827
63041
  },
61828
63042
  args: {
61829
63043
  ...projectArgs2,
61830
- id: { type: "positional", description: "Proposal task ID", required: true }
63044
+ id: { type: "positional", description: "Proposal task ID", required: true },
63045
+ execute: {
63046
+ type: "boolean",
63047
+ description: "Execute proposal.fixAction without prompting"
63048
+ },
63049
+ "no-execute": {
63050
+ type: "boolean",
63051
+ description: "Skip fixAction execution even if the proposal carries one"
63052
+ }
61831
63053
  },
61832
63054
  async run({ args }) {
61833
63055
  const projectRoot = resolveProjectRoot6(args.project);
61834
63056
  const jsonMode = args.json === true;
61835
63057
  const id = args.id;
63058
+ const forceExecute = args.execute === true;
63059
+ const skipExecute = args["no-execute"] === true;
61836
63060
  try {
61837
63061
  const { getDb: getDb3 } = await import("@cleocode/core/store/sqlite.js");
61838
63062
  const { tasks } = await import("@cleocode/core/store/tasks-schema");
@@ -61859,10 +63083,54 @@ Logs: ${logPath}`
61859
63083
  proposalsAccepted: state.tier2Stats.proposalsAccepted + 1
61860
63084
  }
61861
63085
  });
63086
+ const fixAction = extractFixActionFromNotesJson(existing.notesJson ?? null);
63087
+ let shouldExecute = false;
63088
+ if (fixAction && !skipExecute) {
63089
+ if (forceExecute) {
63090
+ shouldExecute = true;
63091
+ } else {
63092
+ shouldExecute = await promptAcceptExecution(fixAction);
63093
+ }
63094
+ }
63095
+ if (!shouldExecute) {
63096
+ emitSuccess2(
63097
+ {
63098
+ id,
63099
+ status: "pending",
63100
+ acceptedAt: now,
63101
+ executed: false,
63102
+ fixAction: fixAction ?? null
63103
+ },
63104
+ jsonMode,
63105
+ `Proposal ${id} accepted \u2192 pending`
63106
+ );
63107
+ return;
63108
+ }
63109
+ const parsed = parseFixAction(fixAction);
63110
+ if (!parsed.ok) {
63111
+ emitFailure3(parsed.code, parsed.reason, jsonMode);
63112
+ return;
63113
+ }
63114
+ const result = await executeFixAction(parsed, { cwd: projectRoot });
63115
+ await appendSentientExecuteAudit(projectRoot, {
63116
+ proposalId: id,
63117
+ fixAction,
63118
+ exitCode: result.exitCode,
63119
+ durationMs: result.durationMs,
63120
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
63121
+ });
61862
63122
  emitSuccess2(
61863
- { id, status: "pending", acceptedAt: now },
63123
+ {
63124
+ id,
63125
+ status: "pending",
63126
+ acceptedAt: now,
63127
+ executed: true,
63128
+ exitCode: result.exitCode,
63129
+ stderrSnippet: result.stderrSnippet,
63130
+ fixAction
63131
+ },
61864
63132
  jsonMode,
61865
- `Proposal ${id} accepted \u2192 pending`
63133
+ `Proposal ${id} accepted \u2192 pending (fixAction exit=${result.exitCode})`
61866
63134
  );
61867
63135
  } catch (err) {
61868
63136
  const message = err instanceof Error ? err.message : String(err);
@@ -62658,15 +63926,15 @@ async function promptOwnerAuthPassword(sessionName) {
62658
63926
  );
62659
63927
  return null;
62660
63928
  }
62661
- const { createInterface: createInterface4 } = await import("node:readline");
63929
+ const { createInterface: createInterface5 } = await import("node:readline");
62662
63930
  const { deriveOwnerAuthToken } = await import("@cleocode/core/internal");
62663
- const rl = createInterface4({
63931
+ const rl = createInterface5({
62664
63932
  input: process.stdin,
62665
63933
  output: process.stderr,
62666
63934
  terminal: true
62667
63935
  });
62668
63936
  process.stderr.write(`[cleo] Enter owner-auth password for session "${sessionName}": `);
62669
- const password = await new Promise((resolve7) => {
63937
+ const password = await new Promise((resolve8) => {
62670
63938
  if (process.stdin.setRawMode) {
62671
63939
  process.stdin.setRawMode(
62672
63940
  true
@@ -62684,10 +63952,10 @@ async function promptOwnerAuthPassword(sessionName) {
62684
63952
  );
62685
63953
  }
62686
63954
  process.stderr.write("\n");
62687
- resolve7(pw);
63955
+ resolve8(pw);
62688
63956
  } else if (ch === "") {
62689
63957
  process.stderr.write("\n[cleo] Cancelled.\n");
62690
- resolve7("");
63958
+ resolve8("");
62691
63959
  } else if (ch === "\x7F" || ch === "\b") {
62692
63960
  pw = pw.slice(0, -1);
62693
63961
  } else {
@@ -62701,7 +63969,7 @@ async function promptOwnerAuthPassword(sessionName) {
62701
63969
  const token = deriveOwnerAuthToken(sessionName, password);
62702
63970
  return token;
62703
63971
  }
62704
- var startCommand7, endCommand, handoffCommand2, statusCommand14, resumeCommand2, findCommand6, listCommand23, gcCommand2, showCommand13, driftCommand, contextDriftCommand, suspendCommand, recordAssumptionCommand, recordDecisionCommand, decisionLogCommand, adoptCommand, lintCommand, sessionCommand;
63972
+ var startCommand7, endCommand, handoffCommand2, statusCommand14, resumeCommand2, findCommand7, listCommand23, gcCommand2, showCommand13, driftCommand, contextDriftCommand, suspendCommand, recordAssumptionCommand, recordDecisionCommand, decisionLogCommand, adoptCommand, lintCommand, sessionCommand;
62705
63973
  var init_session4 = __esm({
62706
63974
  "packages/cleo/src/cli/commands/session.ts"() {
62707
63975
  "use strict";
@@ -62931,7 +64199,7 @@ var init_session4 = __esm({
62931
64199
  );
62932
64200
  }
62933
64201
  });
62934
- findCommand6 = defineCommand({
64202
+ findCommand7 = defineCommand({
62935
64203
  meta: {
62936
64204
  name: "find",
62937
64205
  description: "Find sessions (lightweight discovery \u2014 minimal fields, low context cost)"
@@ -63067,8 +64335,8 @@ var init_session4 = __esm({
63067
64335
  "audit-scope": { type: "string", description: "Audit log scope (global|local)" }
63068
64336
  },
63069
64337
  async run({ args }) {
63070
- const { detectSessionDrift, getProjectRoot: getProjectRoot53 } = await import("@cleocode/core");
63071
- const projectRoot = await getProjectRoot53();
64338
+ const { detectSessionDrift, getProjectRoot: getProjectRoot54 } = await import("@cleocode/core");
64339
+ const projectRoot = await getProjectRoot54();
63072
64340
  const scope = args["audit-scope"] === "local" ? "local" : "global";
63073
64341
  const report = await detectSessionDrift({ projectRoot, auditScope: scope });
63074
64342
  cliOutput(report, { command: "session drift", operation: "session.drift" });
@@ -63294,7 +64562,7 @@ var init_session4 = __esm({
63294
64562
  handoff: handoffCommand2,
63295
64563
  status: statusCommand14,
63296
64564
  resume: resumeCommand2,
63297
- find: findCommand6,
64565
+ find: findCommand7,
63298
64566
  list: listCommand23,
63299
64567
  gc: gcCommand2,
63300
64568
  show: showCommand13,
@@ -63779,9 +65047,27 @@ var init_show2 = __esm({
63779
65047
  showCommand14 = defineCommand({
63780
65048
  meta: {
63781
65049
  name: "show",
63782
- description: "Show full task details by ID (returns complete task record with metadata, verification, lifecycle)"
65050
+ description: "Show task details by ID. MVI-projected (id + title + status + key metadata) by default; pass --verbose / --full to receive the complete record with description, acceptance, verification, evidence, etc. (T9922)"
65051
+ },
65052
+ args: {
65053
+ ...paramsToCittyArgs(getOperationParams("query", "tasks", "show")),
65054
+ // T9922 — MVI record projection opt-out flags. The global parser in
65055
+ // cli/index.ts reads these too; the declarations here surface them in
65056
+ // `cleo show --help` and document the contract for agents.
65057
+ verbose: {
65058
+ type: "boolean",
65059
+ description: "Return the full task record (description, acceptance, verification, evidence) instead of the MVI projection. T9922."
65060
+ },
65061
+ full: {
65062
+ type: "boolean",
65063
+ description: "Alias for --verbose. T9922."
65064
+ },
65065
+ // T9932 — 1-line summary render. Global flag; parsed by cli/index.ts.
65066
+ summary: {
65067
+ type: "boolean",
65068
+ description: 'Render the task as a single line "<id> [<status>] <title-truncated-60>". Composes with --output: --output {id|table|count|silent} wins. T9932.'
65069
+ }
63783
65070
  },
63784
- args: paramsToCittyArgs(getOperationParams("query", "tasks", "show")),
63785
65071
  async run({ args }) {
63786
65072
  await dispatchFromCli(
63787
65073
  "query",
@@ -63903,7 +65189,7 @@ function buildSkillsDoctorAdoptAdapters() {
63903
65189
  }
63904
65190
  };
63905
65191
  }
63906
- var listCommand24, searchCommand4, findCommand7, validateCommand8, infoCommand, installCommand3, uninstallCommand2, enableCommand2, disableCommand2, refreshCommand, dispatchCommand, catalogCommand, precedenceCommand, depsCommand4, doctorBridgeCommand, doctorAdoptOrphansCommand, statsCommand6, importHermesCommand, migrateCommand2, pruneTelemetryCommand, spawnProvidersCommand, doctorDiagnoseCommand, doctorCommand4, proposePatchCommand, skillsCommand2;
65192
+ var listCommand24, searchCommand4, findCommand8, validateCommand8, infoCommand, installCommand3, uninstallCommand2, enableCommand2, disableCommand2, refreshCommand, dispatchCommand, catalogCommand, precedenceCommand, depsCommand4, doctorBridgeCommand, doctorAdoptOrphansCommand, statsCommand6, importHermesCommand, migrateCommand2, pruneTelemetryCommand, spawnProvidersCommand, doctorDiagnoseCommand, doctorCommand4, proposePatchCommand, skillsCommand2;
63907
65193
  var init_skills2 = __esm({
63908
65194
  "packages/cleo/src/cli/commands/skills.ts"() {
63909
65195
  "use strict";
@@ -63961,7 +65247,7 @@ var init_skills2 = __esm({
63961
65247
  );
63962
65248
  }
63963
65249
  });
63964
- findCommand7 = defineCommand({
65250
+ findCommand8 = defineCommand({
63965
65251
  meta: {
63966
65252
  name: "find",
63967
65253
  description: "Federated skill search across local, canonical, and federation peers"
@@ -64646,7 +65932,7 @@ var init_skills2 = __esm({
64646
65932
  subCommands: {
64647
65933
  list: listCommand24,
64648
65934
  search: searchCommand4,
64649
- find: findCommand7,
65935
+ find: findCommand8,
64650
65936
  validate: validateCommand8,
64651
65937
  info: infoCommand,
64652
65938
  install: installCommand3,
@@ -64712,8 +65998,8 @@ var init_snapshot = __esm({
64712
65998
  handleRawError(response, { command: "snapshot", operation: "admin.export" });
64713
65999
  const data = response.data;
64714
66000
  if (data?.outputPath) {
64715
- const { readFile: readFile7 } = await import("node:fs/promises");
64716
- const content = await readFile7(data.outputPath, "utf-8");
66001
+ const { readFile: readFile8 } = await import("node:fs/promises");
66002
+ const content = await readFile8(data.outputPath, "utf-8");
64717
66003
  process.stdout.write(content);
64718
66004
  if (!content.endsWith("\n")) process.stdout.write("\n");
64719
66005
  }
@@ -65444,10 +66730,10 @@ var init_sync = __esm({
65444
66730
  }
65445
66731
  },
65446
66732
  async run({ args }) {
65447
- const { readFileSync: readFileSync18 } = await import("node:fs");
66733
+ const { readFileSync: readFileSync21 } = await import("node:fs");
65448
66734
  let externalTasks;
65449
66735
  try {
65450
- externalTasks = JSON.parse(readFileSync18(args.file, "utf8"));
66736
+ externalTasks = JSON.parse(readFileSync21(args.file, "utf8"));
65451
66737
  } catch (err) {
65452
66738
  const message = err instanceof Error ? err.message : String(err);
65453
66739
  cliError(`Failed to read or parse external tasks file: ${message}`, 2, {
@@ -65702,6 +66988,667 @@ var init_telemetry2 = __esm({
65702
66988
  }
65703
66989
  });
65704
66990
 
66991
+ // packages/cleo/src/cli/commands/templates/lib.ts
66992
+ import { readFileSync as readFileSync15 } from "node:fs";
66993
+ import { isAbsolute as isAbsolute3, resolve as resolve6 } from "node:path";
66994
+ import { getProjectRoot as getProjectRoot50 } from "@cleocode/core";
66995
+ import { resolveSourcePathAbsolute } from "@cleocode/core/templates/registry";
66996
+ function resolveProjectRoot7(raw) {
66997
+ if (typeof raw === "string" && raw.length > 0) {
66998
+ return isAbsolute3(raw) ? raw : resolve6(process.cwd(), raw);
66999
+ }
67000
+ return getProjectRoot50();
67001
+ }
67002
+ function readTemplateSource(entry) {
67003
+ const sourceAbsolute = resolveSourcePathAbsolute(entry);
67004
+ return readFileSync15(sourceAbsolute, "utf8");
67005
+ }
67006
+ function applySubstitution(entry, source) {
67007
+ if (entry.substitution === "static") {
67008
+ return { rendered: source, substituted: false };
67009
+ }
67010
+ return { rendered: source, substituted: false };
67011
+ }
67012
+ var init_lib = __esm({
67013
+ "packages/cleo/src/cli/commands/templates/lib.ts"() {
67014
+ "use strict";
67015
+ }
67016
+ });
67017
+
67018
+ // packages/cleo/src/cli/commands/templates/diff.ts
67019
+ import { existsSync as existsSync15, readFileSync as readFileSync16 } from "node:fs";
67020
+ import { join as join30 } from "node:path";
67021
+ import { getTemplateById } from "@cleocode/core/templates/registry";
67022
+ function unifiedDiff(a, b) {
67023
+ const aLines = a.length === 0 ? [] : a.split("\n");
67024
+ const bLines = b.length === 0 ? [] : b.split("\n");
67025
+ const out = [];
67026
+ const max = Math.max(aLines.length, bLines.length);
67027
+ for (let i = 0; i < max; i += 1) {
67028
+ const av = aLines[i];
67029
+ const bv = bLines[i];
67030
+ if (av === bv) {
67031
+ if (av !== void 0) out.push(` ${av}`);
67032
+ continue;
67033
+ }
67034
+ if (av !== void 0) out.push(`-${av}`);
67035
+ if (bv !== void 0) out.push(`+${bv}`);
67036
+ }
67037
+ return out.join("\n");
67038
+ }
67039
+ var templatesDiffCommand;
67040
+ var init_diff = __esm({
67041
+ "packages/cleo/src/cli/commands/templates/diff.ts"() {
67042
+ "use strict";
67043
+ init_src2();
67044
+ init_define_cli_command();
67045
+ init_renderers();
67046
+ init_lib();
67047
+ templatesDiffCommand = defineCommand({
67048
+ meta: {
67049
+ name: "diff",
67050
+ description: "Diff a template against its installed copy (exit 0 same, 1 different)"
67051
+ },
67052
+ args: {
67053
+ id: {
67054
+ type: "positional",
67055
+ required: true,
67056
+ description: "Template id (kebab-case)"
67057
+ },
67058
+ project: {
67059
+ type: "string",
67060
+ description: "Project root to diff against (default: detected project root)"
67061
+ },
67062
+ json: {
67063
+ type: "boolean",
67064
+ description: "Output as JSON"
67065
+ }
67066
+ },
67067
+ async run({ args }) {
67068
+ const id = String(args["id"] ?? "").trim();
67069
+ if (id.length === 0) {
67070
+ cliError(`templates diff failed: <id> is required`, 2 /* INVALID_INPUT */, {
67071
+ name: "E_TEMPLATES_DIFF_FAILED"
67072
+ });
67073
+ process.exit(2 /* INVALID_INPUT */);
67074
+ return;
67075
+ }
67076
+ const entry = getTemplateById(id);
67077
+ if (entry === void 0) {
67078
+ cliError(`templates diff failed: id "${id}" not found`, 4 /* NOT_FOUND */, {
67079
+ name: "E_NOT_FOUND",
67080
+ details: { id }
67081
+ });
67082
+ process.exit(4 /* NOT_FOUND */);
67083
+ return;
67084
+ }
67085
+ let projectRoot;
67086
+ let installPath;
67087
+ let rendered;
67088
+ try {
67089
+ projectRoot = resolveProjectRoot7(args["project"]);
67090
+ installPath = join30(projectRoot, entry.installPath);
67091
+ const source = readTemplateSource(entry);
67092
+ rendered = applySubstitution(entry, source).rendered;
67093
+ } catch (err) {
67094
+ const message = err instanceof Error ? err.message : String(err);
67095
+ cliError(`templates diff failed: ${message}`, 1 /* GENERAL_ERROR */, {
67096
+ name: "E_TEMPLATES_DIFF_FAILED"
67097
+ });
67098
+ process.exit(1 /* GENERAL_ERROR */);
67099
+ return;
67100
+ }
67101
+ if (!existsSync15(installPath)) {
67102
+ const missingResult = {
67103
+ id,
67104
+ installPath,
67105
+ same: false,
67106
+ missing: true,
67107
+ diff: `--- (missing) ${installPath}
67108
+ +++ (rendered) ${id}
67109
+ ${unifiedDiff("", rendered)}`
67110
+ };
67111
+ cliOutput(missingResult, {
67112
+ command: "templates-diff",
67113
+ operation: "templates.diff"
67114
+ });
67115
+ process.exit(1 /* GENERAL_ERROR */);
67116
+ return;
67117
+ }
67118
+ const current = readFileSync16(installPath, "utf8");
67119
+ const same = current === rendered;
67120
+ const result = {
67121
+ id,
67122
+ installPath,
67123
+ same,
67124
+ missing: false,
67125
+ diff: same ? "" : unifiedDiff(current, rendered)
67126
+ };
67127
+ cliOutput(result, {
67128
+ command: "templates-diff",
67129
+ operation: "templates.diff"
67130
+ });
67131
+ if (!same) {
67132
+ process.exit(1 /* GENERAL_ERROR */);
67133
+ }
67134
+ }
67135
+ });
67136
+ }
67137
+ });
67138
+
67139
+ // packages/cleo/src/cli/commands/templates/install.ts
67140
+ import { existsSync as existsSync16, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync5 } from "node:fs";
67141
+ import { dirname as dirname9, join as join31 } from "node:path";
67142
+ import { getTemplateById as getTemplateById2 } from "@cleocode/core/templates/registry";
67143
+ var templatesInstallCommand;
67144
+ var init_install = __esm({
67145
+ "packages/cleo/src/cli/commands/templates/install.ts"() {
67146
+ "use strict";
67147
+ init_src2();
67148
+ init_define_cli_command();
67149
+ init_renderers();
67150
+ init_lib();
67151
+ templatesInstallCommand = defineCommand({
67152
+ meta: {
67153
+ name: "install",
67154
+ description: "Install a template into a project root (default: current project), idempotent"
67155
+ },
67156
+ args: {
67157
+ id: {
67158
+ type: "positional",
67159
+ required: true,
67160
+ description: "Template id (kebab-case)"
67161
+ },
67162
+ project: {
67163
+ type: "string",
67164
+ description: "Project root to install into (default: detected project root)"
67165
+ },
67166
+ json: {
67167
+ type: "boolean",
67168
+ description: "Output as JSON"
67169
+ }
67170
+ },
67171
+ async run({ args }) {
67172
+ const id = String(args["id"] ?? "").trim();
67173
+ if (id.length === 0) {
67174
+ cliError(`templates install failed: <id> is required`, 2 /* INVALID_INPUT */, {
67175
+ name: "E_TEMPLATES_INSTALL_FAILED"
67176
+ });
67177
+ process.exit(2 /* INVALID_INPUT */);
67178
+ return;
67179
+ }
67180
+ const entry = getTemplateById2(id);
67181
+ if (entry === void 0) {
67182
+ cliError(`templates install failed: id "${id}" not found`, 4 /* NOT_FOUND */, {
67183
+ name: "E_NOT_FOUND",
67184
+ details: { id }
67185
+ });
67186
+ process.exit(4 /* NOT_FOUND */);
67187
+ return;
67188
+ }
67189
+ let projectRoot;
67190
+ let installPath;
67191
+ let rendered;
67192
+ let substituted;
67193
+ try {
67194
+ projectRoot = resolveProjectRoot7(args["project"]);
67195
+ installPath = join31(projectRoot, entry.installPath);
67196
+ const source = readTemplateSource(entry);
67197
+ const sub = applySubstitution(entry, source);
67198
+ rendered = sub.rendered;
67199
+ substituted = sub.substituted;
67200
+ } catch (err) {
67201
+ const message = err instanceof Error ? err.message : String(err);
67202
+ cliError(`templates install failed: ${message}`, 1 /* GENERAL_ERROR */, {
67203
+ name: "E_TEMPLATES_INSTALL_FAILED"
67204
+ });
67205
+ process.exit(1 /* GENERAL_ERROR */);
67206
+ return;
67207
+ }
67208
+ if (existsSync16(installPath)) {
67209
+ const current = readFileSync17(installPath, "utf8");
67210
+ if (current === rendered) {
67211
+ const noopResult = {
67212
+ id,
67213
+ installPath,
67214
+ installed: false,
67215
+ noop: true,
67216
+ substituted
67217
+ };
67218
+ cliOutput(noopResult, {
67219
+ command: "templates-install",
67220
+ operation: "templates.install"
67221
+ });
67222
+ return;
67223
+ }
67224
+ }
67225
+ try {
67226
+ mkdirSync5(dirname9(installPath), { recursive: true });
67227
+ writeFileSync5(installPath, rendered, "utf8");
67228
+ } catch (err) {
67229
+ const message = err instanceof Error ? err.message : String(err);
67230
+ cliError(`templates install failed: ${message}`, 1 /* GENERAL_ERROR */, {
67231
+ name: "E_TEMPLATES_INSTALL_FAILED"
67232
+ });
67233
+ process.exit(1 /* GENERAL_ERROR */);
67234
+ return;
67235
+ }
67236
+ const result = {
67237
+ id,
67238
+ installPath,
67239
+ installed: true,
67240
+ noop: false,
67241
+ substituted
67242
+ };
67243
+ cliOutput(result, {
67244
+ command: "templates-install",
67245
+ operation: "templates.install"
67246
+ });
67247
+ }
67248
+ });
67249
+ }
67250
+ });
67251
+
67252
+ // packages/cleo/src/cli/commands/templates/list.ts
67253
+ import { getTemplateManifest, getTemplatesByKind as getTemplatesByKind2 } from "@cleocode/core/templates/registry";
67254
+ function parseTemplateKind(raw) {
67255
+ if (raw === void 0 || raw === "") return null;
67256
+ return TEMPLATE_KINDS.includes(raw) ? raw : null;
67257
+ }
67258
+ var templatesListCommand;
67259
+ var init_list4 = __esm({
67260
+ "packages/cleo/src/cli/commands/templates/list.ts"() {
67261
+ "use strict";
67262
+ init_src2();
67263
+ init_define_cli_command();
67264
+ init_renderers();
67265
+ templatesListCommand = defineCommand({
67266
+ meta: {
67267
+ name: "list",
67268
+ description: "List every template the registry knows about (optionally filtered by --kind)"
67269
+ },
67270
+ args: {
67271
+ kind: {
67272
+ type: "string",
67273
+ description: `Optional kind filter: ${TEMPLATE_KINDS.join(" | ")}`
67274
+ },
67275
+ json: {
67276
+ type: "boolean",
67277
+ description: "Output as JSON"
67278
+ }
67279
+ },
67280
+ async run({ args }) {
67281
+ const rawKind = args["kind"];
67282
+ const kind = parseTemplateKind(typeof rawKind === "string" ? rawKind : void 0);
67283
+ if (kind === null && rawKind !== void 0 && rawKind !== "") {
67284
+ cliError(
67285
+ `templates list failed: invalid --kind (must be ${TEMPLATE_KINDS.join("|")})`,
67286
+ 2 /* INVALID_INPUT */,
67287
+ { name: "E_TEMPLATES_LIST_FAILED" }
67288
+ );
67289
+ process.exit(2 /* INVALID_INPUT */);
67290
+ return;
67291
+ }
67292
+ const entries = kind === null ? getTemplateManifest() : getTemplatesByKind2(kind);
67293
+ const result = { kind, entries };
67294
+ cliOutput(result, {
67295
+ command: "templates-list",
67296
+ operation: "templates.list"
67297
+ });
67298
+ }
67299
+ });
67300
+ }
67301
+ });
67302
+
67303
+ // packages/cleo/src/cli/commands/templates/show.ts
67304
+ import { getTemplateById as getTemplateById3 } from "@cleocode/core/templates/registry";
67305
+ var templatesShowCommand;
67306
+ var init_show3 = __esm({
67307
+ "packages/cleo/src/cli/commands/templates/show.ts"() {
67308
+ "use strict";
67309
+ init_src2();
67310
+ init_define_cli_command();
67311
+ init_renderers();
67312
+ templatesShowCommand = defineCommand({
67313
+ meta: {
67314
+ name: "show",
67315
+ description: "Print a single template manifest entry by id"
67316
+ },
67317
+ args: {
67318
+ id: {
67319
+ type: "positional",
67320
+ required: true,
67321
+ description: "Template id (kebab-case)"
67322
+ },
67323
+ json: {
67324
+ type: "boolean",
67325
+ description: "Output as JSON"
67326
+ }
67327
+ },
67328
+ async run({ args }) {
67329
+ const id = String(args["id"] ?? "").trim();
67330
+ if (id.length === 0) {
67331
+ cliError(`templates show failed: <id> is required`, 2 /* INVALID_INPUT */, {
67332
+ name: "E_TEMPLATES_SHOW_FAILED"
67333
+ });
67334
+ process.exit(2 /* INVALID_INPUT */);
67335
+ return;
67336
+ }
67337
+ const entry = getTemplateById3(id);
67338
+ if (entry === void 0) {
67339
+ cliError(`templates show failed: id "${id}" not found`, 4 /* NOT_FOUND */, {
67340
+ name: "E_NOT_FOUND",
67341
+ details: { id }
67342
+ });
67343
+ process.exit(4 /* NOT_FOUND */);
67344
+ return;
67345
+ }
67346
+ const result = { id, entry };
67347
+ cliOutput(result, {
67348
+ command: "templates-show",
67349
+ operation: "templates.show"
67350
+ });
67351
+ }
67352
+ });
67353
+ }
67354
+ });
67355
+
67356
+ // packages/cleo/src/cli/commands/templates/upgrade.ts
67357
+ import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync18, writeFileSync as writeFileSync6 } from "node:fs";
67358
+ import { dirname as dirname10, join as join32 } from "node:path";
67359
+ import { getTemplateById as getTemplateById4 } from "@cleocode/core/templates/registry";
67360
+ var templatesUpgradeCommand;
67361
+ var init_upgrade2 = __esm({
67362
+ "packages/cleo/src/cli/commands/templates/upgrade.ts"() {
67363
+ "use strict";
67364
+ init_src2();
67365
+ init_define_cli_command();
67366
+ init_renderers();
67367
+ init_diff();
67368
+ init_lib();
67369
+ templatesUpgradeCommand = defineCommand({
67370
+ meta: {
67371
+ name: "upgrade",
67372
+ description: "Re-install a template respecting its updateStrategy (overwrite | diff-prompt | immutable | manifest-merge)"
67373
+ },
67374
+ args: {
67375
+ id: {
67376
+ type: "positional",
67377
+ required: true,
67378
+ description: "Template id (kebab-case)"
67379
+ },
67380
+ project: {
67381
+ type: "string",
67382
+ description: "Project root to upgrade against (default: detected project root)"
67383
+ },
67384
+ diff: {
67385
+ type: "boolean",
67386
+ description: "Preview-only \u2014 print the diff without writing"
67387
+ },
67388
+ accept: {
67389
+ type: "boolean",
67390
+ description: "Apply when strategy is diff-prompt (no-op otherwise)"
67391
+ },
67392
+ json: {
67393
+ type: "boolean",
67394
+ description: "Output as JSON"
67395
+ }
67396
+ },
67397
+ async run({ args }) {
67398
+ const id = String(args["id"] ?? "").trim();
67399
+ if (id.length === 0) {
67400
+ cliError(`templates upgrade failed: <id> is required`, 2 /* INVALID_INPUT */, {
67401
+ name: "E_TEMPLATES_UPGRADE_FAILED"
67402
+ });
67403
+ process.exit(2 /* INVALID_INPUT */);
67404
+ return;
67405
+ }
67406
+ const entry = getTemplateById4(id);
67407
+ if (entry === void 0) {
67408
+ cliError(`templates upgrade failed: id "${id}" not found`, 4 /* NOT_FOUND */, {
67409
+ name: "E_NOT_FOUND",
67410
+ details: { id }
67411
+ });
67412
+ process.exit(4 /* NOT_FOUND */);
67413
+ return;
67414
+ }
67415
+ let projectRoot;
67416
+ let installPath;
67417
+ let rendered;
67418
+ try {
67419
+ projectRoot = resolveProjectRoot7(args["project"]);
67420
+ installPath = join32(projectRoot, entry.installPath);
67421
+ const source = readTemplateSource(entry);
67422
+ rendered = applySubstitution(entry, source).rendered;
67423
+ } catch (err) {
67424
+ const message = err instanceof Error ? err.message : String(err);
67425
+ cliError(`templates upgrade failed: ${message}`, 1 /* GENERAL_ERROR */, {
67426
+ name: "E_TEMPLATES_UPGRADE_FAILED"
67427
+ });
67428
+ process.exit(1 /* GENERAL_ERROR */);
67429
+ return;
67430
+ }
67431
+ const previewOnly = args["diff"] === true;
67432
+ const accept = args["accept"] === true;
67433
+ const current = existsSync17(installPath) ? readFileSync18(installPath, "utf8") : null;
67434
+ const diffBody = current === null ? "" : current === rendered ? "" : unifiedDiff(current, rendered);
67435
+ let outcome;
67436
+ let reason;
67437
+ let shouldWrite = false;
67438
+ if (entry.updateStrategy === "manifest-merge") {
67439
+ outcome = "not-supported";
67440
+ reason = "manifest-merge upgrade is not yet supported (T9886-followup)";
67441
+ } else if (entry.updateStrategy === "immutable") {
67442
+ outcome = "skipped";
67443
+ reason = current === null ? "immutable: not installed yet \u2014 use `install`" : "immutable: skipped per strategy";
67444
+ } else if (current !== null && current === rendered) {
67445
+ outcome = "noop";
67446
+ reason = "already current";
67447
+ } else if (entry.updateStrategy === "overwrite-on-bump") {
67448
+ if (previewOnly) {
67449
+ outcome = "skipped";
67450
+ reason = "preview-only (--diff)";
67451
+ } else {
67452
+ outcome = "overwritten";
67453
+ reason = current === null ? "fresh install" : "overwrite-on-bump";
67454
+ shouldWrite = true;
67455
+ }
67456
+ } else {
67457
+ if (previewOnly || !accept) {
67458
+ outcome = "skipped";
67459
+ reason = previewOnly ? "preview-only (--diff)" : "diff-prompt: pass --accept to apply";
67460
+ } else {
67461
+ outcome = "overwritten";
67462
+ reason = "diff-prompt: accepted";
67463
+ shouldWrite = true;
67464
+ }
67465
+ }
67466
+ if (shouldWrite) {
67467
+ try {
67468
+ mkdirSync6(dirname10(installPath), { recursive: true });
67469
+ writeFileSync6(installPath, rendered, "utf8");
67470
+ } catch (err) {
67471
+ const message = err instanceof Error ? err.message : String(err);
67472
+ cliError(`templates upgrade failed: ${message}`, 1 /* GENERAL_ERROR */, {
67473
+ name: "E_TEMPLATES_UPGRADE_FAILED"
67474
+ });
67475
+ process.exit(1 /* GENERAL_ERROR */);
67476
+ return;
67477
+ }
67478
+ }
67479
+ const result = {
67480
+ id,
67481
+ installPath,
67482
+ updateStrategy: entry.updateStrategy,
67483
+ outcome,
67484
+ reason,
67485
+ diff: diffBody
67486
+ };
67487
+ cliOutput(result, {
67488
+ command: "templates-upgrade",
67489
+ operation: "templates.upgrade"
67490
+ });
67491
+ }
67492
+ });
67493
+ }
67494
+ });
67495
+
67496
+ // packages/cleo/src/cli/commands/templates/validate.ts
67497
+ import {
67498
+ getInstalledStatus,
67499
+ getTemplateById as getTemplateById5,
67500
+ getTemplateManifest as getTemplateManifest2,
67501
+ resolveSourcePathAbsolute as resolveSourcePathAbsolute2
67502
+ } from "@cleocode/core/templates/registry";
67503
+ var templatesValidateCommand;
67504
+ var init_validate3 = __esm({
67505
+ "packages/cleo/src/cli/commands/templates/validate.ts"() {
67506
+ "use strict";
67507
+ init_src2();
67508
+ init_define_cli_command();
67509
+ init_renderers();
67510
+ init_lib();
67511
+ templatesValidateCommand = defineCommand({
67512
+ meta: {
67513
+ name: "validate",
67514
+ description: "Validate every registry entry (or one --id) against the live filesystem"
67515
+ },
67516
+ args: {
67517
+ id: {
67518
+ type: "string",
67519
+ description: "Validate a single entry by id (default: walk every entry)"
67520
+ },
67521
+ project: {
67522
+ type: "string",
67523
+ description: "Project root to probe install status against (default: detected)"
67524
+ },
67525
+ json: {
67526
+ type: "boolean",
67527
+ description: "Output as JSON"
67528
+ }
67529
+ },
67530
+ async run({ args }) {
67531
+ let projectRoot;
67532
+ try {
67533
+ projectRoot = resolveProjectRoot7(args["project"]);
67534
+ } catch (err) {
67535
+ const message = err instanceof Error ? err.message : String(err);
67536
+ cliError(`templates validate failed: ${message}`, 1 /* GENERAL_ERROR */, {
67537
+ name: "E_TEMPLATES_VALIDATE_FAILED"
67538
+ });
67539
+ process.exit(1 /* GENERAL_ERROR */);
67540
+ return;
67541
+ }
67542
+ const idFilter = typeof args["id"] === "string" && args["id"].length > 0 ? args["id"] : null;
67543
+ let targets;
67544
+ if (idFilter === null) {
67545
+ targets = getTemplateManifest2();
67546
+ } else {
67547
+ const entry = getTemplateById5(idFilter);
67548
+ if (entry === void 0) {
67549
+ cliError(`templates validate failed: id "${idFilter}" not found`, 4 /* NOT_FOUND */, {
67550
+ name: "E_NOT_FOUND",
67551
+ details: { id: idFilter }
67552
+ });
67553
+ process.exit(4 /* NOT_FOUND */);
67554
+ return;
67555
+ }
67556
+ targets = [entry];
67557
+ }
67558
+ const entries = targets.map((entry) => {
67559
+ const issues = [];
67560
+ let sourcePath = null;
67561
+ let sourceExists = false;
67562
+ try {
67563
+ sourcePath = resolveSourcePathAbsolute2(entry);
67564
+ sourceExists = true;
67565
+ } catch (err) {
67566
+ issues.push(`source: ${err instanceof Error ? err.message : String(err)}`);
67567
+ }
67568
+ let installed = false;
67569
+ let installPath = null;
67570
+ try {
67571
+ const status = getInstalledStatus(entry.id, projectRoot);
67572
+ installed = status.installed;
67573
+ installPath = status.path;
67574
+ } catch (err) {
67575
+ issues.push(`install: ${err instanceof Error ? err.message : String(err)}`);
67576
+ }
67577
+ return {
67578
+ id: entry.id,
67579
+ kind: entry.kind,
67580
+ sourceExists,
67581
+ sourcePath,
67582
+ installed,
67583
+ installPath,
67584
+ issues
67585
+ };
67586
+ });
67587
+ const ok = entries.every((e) => e.issues.length === 0);
67588
+ const result = {
67589
+ ok,
67590
+ count: entries.length,
67591
+ entries
67592
+ };
67593
+ cliOutput(result, {
67594
+ command: "templates-validate",
67595
+ operation: "templates.validate"
67596
+ });
67597
+ if (!ok) {
67598
+ process.exit(6 /* VALIDATION_ERROR */);
67599
+ }
67600
+ }
67601
+ });
67602
+ }
67603
+ });
67604
+
67605
+ // packages/cleo/src/cli/commands/templates/index.ts
67606
+ var init_templates = __esm({
67607
+ "packages/cleo/src/cli/commands/templates/index.ts"() {
67608
+ "use strict";
67609
+ init_diff();
67610
+ init_install();
67611
+ init_list4();
67612
+ init_show3();
67613
+ init_upgrade2();
67614
+ init_validate3();
67615
+ }
67616
+ });
67617
+
67618
+ // packages/cleo/src/cli/commands/templates.ts
67619
+ var templates_exports = {};
67620
+ __export(templates_exports, {
67621
+ templatesCommand: () => templatesCommand
67622
+ });
67623
+ var templatesCommand;
67624
+ var init_templates2 = __esm({
67625
+ "packages/cleo/src/cli/commands/templates.ts"() {
67626
+ "use strict";
67627
+ init_dist();
67628
+ init_define_cli_command();
67629
+ init_templates();
67630
+ templatesCommand = defineCommand({
67631
+ meta: {
67632
+ name: "templates",
67633
+ description: "TemplateManifest SSoT registry surface (list, show, install, upgrade, diff, validate)"
67634
+ },
67635
+ subCommands: {
67636
+ list: templatesListCommand,
67637
+ show: templatesShowCommand,
67638
+ install: templatesInstallCommand,
67639
+ upgrade: templatesUpgradeCommand,
67640
+ diff: templatesDiffCommand,
67641
+ validate: templatesValidateCommand
67642
+ },
67643
+ async run({ cmd, rawArgs }) {
67644
+ const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
67645
+ if (firstArg && cmd.subCommands && firstArg in cmd.subCommands) return;
67646
+ await showUsage(cmd);
67647
+ }
67648
+ });
67649
+ }
67650
+ });
67651
+
65705
67652
  // packages/cleo/src/cli/commands/testing.ts
65706
67653
  var testing_exports = {};
65707
67654
  __export(testing_exports, {
@@ -65833,12 +67780,12 @@ var token_exports = {};
65833
67780
  __export(token_exports, {
65834
67781
  tokenCommand: () => tokenCommand
65835
67782
  });
65836
- import { readFileSync as readFileSync16 } from "node:fs";
65837
- import { getProjectRoot as getProjectRoot50, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
67783
+ import { readFileSync as readFileSync19 } from "node:fs";
67784
+ import { getProjectRoot as getProjectRoot51, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
65838
67785
  function readPayload(args, textKey, fileKey) {
65839
67786
  const text = args[textKey];
65840
67787
  const file = args[fileKey];
65841
- if (file) return readFileSync16(file, "utf-8");
67788
+ if (file) return readFileSync19(file, "utf-8");
65842
67789
  return text;
65843
67790
  }
65844
67791
  var filterArgs, summaryCommand3, listCommand26, showCommand16, deleteCommand3, clearCommand2, estimateCommand, tokenCommand;
@@ -65998,7 +67945,7 @@ var init_token = __esm({
65998
67945
  domain: args.domain,
65999
67946
  operation: args.operation
66000
67947
  };
66001
- const result = args.record ? await recordTokenExchange2(getProjectRoot50(), input2) : await measureTokenExchange(input2);
67948
+ const result = args.record ? await recordTokenExchange2(getProjectRoot51(), input2) : await measureTokenExchange(input2);
66002
67949
  cliOutput(result, {
66003
67950
  command: "token",
66004
67951
  operation: args.record ? "admin.token.record" : "token.estimate"
@@ -66033,8 +67980,8 @@ __export(transcript_exports, {
66033
67980
  transcriptCommand: () => transcriptCommand
66034
67981
  });
66035
67982
  import { homedir as homedir6 } from "node:os";
66036
- import { join as join30 } from "node:path";
66037
- import { getProjectRoot as getProjectRoot51 } from "@cleocode/core";
67983
+ import { join as join33 } from "node:path";
67984
+ import { getProjectRoot as getProjectRoot52 } from "@cleocode/core";
66038
67985
  import {
66039
67986
  parseDurationMs,
66040
67987
  pruneTranscripts,
@@ -66064,7 +68011,7 @@ var init_transcript = __esm({
66064
68011
  async run({ args }) {
66065
68012
  if (args.pending) {
66066
68013
  try {
66067
- const projectRoot = getProjectRoot51();
68014
+ const projectRoot = getProjectRoot52();
66068
68015
  const { scanPendingTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
66069
68016
  const pending = await scanPendingTranscripts(projectRoot);
66070
68017
  cliOutput(
@@ -66087,7 +68034,7 @@ var init_transcript = __esm({
66087
68034
  }
66088
68035
  return;
66089
68036
  }
66090
- const projectsDir = args["projects-dir"] ?? join30(homedir6(), ".claude", "projects");
68037
+ const projectsDir = args["projects-dir"] ?? join33(homedir6(), ".claude", "projects");
66091
68038
  try {
66092
68039
  const result = await scanTranscripts(projectsDir);
66093
68040
  cliOutput(
@@ -66161,7 +68108,7 @@ var init_transcript = __esm({
66161
68108
  async run({ args }) {
66162
68109
  const tier = args.tier ?? "warm";
66163
68110
  const dryRun = args["dry-run"] ?? false;
66164
- const projectRoot = getProjectRoot51();
68111
+ const projectRoot = getProjectRoot52();
66165
68112
  try {
66166
68113
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
66167
68114
  const { findSessionTranscriptPath, listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -66273,7 +68220,7 @@ var init_transcript = __esm({
66273
68220
  const dryRun = args["dry-run"] ?? false;
66274
68221
  const olderThanHours = args["older-than-hours"] ? Number.parseInt(args["older-than-hours"], 10) : 24;
66275
68222
  const limit = args.limit ? Number.parseInt(args.limit, 10) : void 0;
66276
- const projectRoot = getProjectRoot51();
68223
+ const projectRoot = getProjectRoot52();
66277
68224
  try {
66278
68225
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
66279
68226
  const { listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -66393,7 +68340,7 @@ var init_transcript = __esm({
66393
68340
  process.exit(2);
66394
68341
  return;
66395
68342
  }
66396
- const projectsDir = args["projects-dir"] ?? join30(homedir6(), ".claude", "projects");
68343
+ const projectsDir = args["projects-dir"] ?? join33(homedir6(), ".claude", "projects");
66397
68344
  try {
66398
68345
  const pruneResult = await pruneTranscripts({
66399
68346
  olderThanMs,
@@ -66450,29 +68397,54 @@ var init_transcript = __esm({
66450
68397
  // packages/cleo/src/cli/commands/update.ts
66451
68398
  var update_exports = {};
66452
68399
  __export(update_exports, {
66453
- updateCommand: () => updateCommand2
68400
+ updateCommand: () => updateCommand3
66454
68401
  });
66455
68402
  import {
66456
68403
  appendSignedSeverityAttestation as appendSignedSeverityAttestation2,
68404
+ INPUT_CONTRACTS as INPUT_CONTRACTS3,
66457
68405
  isPipelineTransitionForward,
66458
68406
  isValidPipelineStage,
66459
68407
  parseAcceptanceCriteria as parseAcceptanceCriteria2,
66460
- TASK_PIPELINE_STAGES
68408
+ TASK_PIPELINE_STAGES,
68409
+ validateOperationInput as validateOperationInput3
66461
68410
  } from "@cleocode/core";
66462
- var updateCommand2;
68411
+ var updateCommand3;
66463
68412
  var init_update = __esm({
66464
68413
  "packages/cleo/src/cli/commands/update.ts"() {
66465
68414
  "use strict";
66466
68415
  init_src2();
66467
68416
  init_dist();
66468
68417
  init_cli();
68418
+ init_collect_input();
66469
68419
  init_renderers();
66470
- updateCommand2 = defineCommand({
68420
+ updateCommand3 = defineCommand({
66471
68421
  meta: {
66472
68422
  name: "update",
66473
68423
  description: "Update a task. Safe under concurrent invocation \u2014 retries on SQLITE_BUSY up to 4 attempts (gh#391)."
66474
68424
  },
66475
68425
  args: {
68426
+ /**
68427
+ * Schema-first input — supersedes all flag-based args when present.
68428
+ *
68429
+ * Accepts a JSON object matching `INPUT_CONTRACTS['tasks.update']`.
68430
+ * The `taskId` MUST be present in the JSON payload (positional
68431
+ * `taskId` arg is ignored in this path).
68432
+ *
68433
+ * @task T9917
68434
+ */
68435
+ params: {
68436
+ type: "string",
68437
+ description: 'Inline JSON object matching INPUT_CONTRACTS["tasks.update"] (T9917). Overrides positional + flags.'
68438
+ },
68439
+ /**
68440
+ * Schema-first input from a JSON file. Same semantics as --params.
68441
+ *
68442
+ * @task T9917
68443
+ */
68444
+ "params-file": {
68445
+ type: "string",
68446
+ description: 'Path to JSON file matching INPUT_CONTRACTS["tasks.update"] (T9917).'
68447
+ },
66476
68448
  taskId: {
66477
68449
  type: "positional",
66478
68450
  description: "Task ID to update",
@@ -66489,7 +68461,7 @@ var init_update = __esm({
66489
68461
  },
66490
68462
  priority: {
66491
68463
  type: "string",
66492
- description: "New priority (critical|high|medium|low)",
68464
+ description: "New priority (critical|high|medium|low). Orthogonal to --severity \u2014 see `cleo find --urgent` for the unified surface (T9905).",
66493
68465
  alias: "p"
66494
68466
  },
66495
68467
  type: {
@@ -66613,7 +68585,7 @@ var init_update = __esm({
66613
68585
  */
66614
68586
  severity: {
66615
68587
  type: "string",
66616
- description: "Severity level (P0|P1|P2|P3) \u2014 valid for any --role (T9073). Orthogonal to priority. Appends signed attestation."
68588
+ description: "Severity level (P0|P1|P2|P3) \u2014 valid for any --kind (T9073). Orthogonal to --priority \u2014 does NOT auto-map (a P0 with priority=medium stays medium). Use `cleo find --urgent` for the unified surface (T9905). Appends signed attestation."
66617
68589
  },
66618
68590
  /**
66619
68591
  * Operator-supplied justification required to override the
@@ -66671,6 +68643,78 @@ var init_update = __esm({
66671
68643
  }
66672
68644
  },
66673
68645
  async run({ args, cmd }) {
68646
+ const paramsArg = args.params;
68647
+ const paramsFileArg = args["params-file"];
68648
+ if (paramsArg !== void 0 || paramsFileArg !== void 0) {
68649
+ const collectArgs = {};
68650
+ if (paramsArg !== void 0) collectArgs.params = paramsArg;
68651
+ if (paramsFileArg !== void 0) collectArgs.file = paramsFileArg;
68652
+ let raw;
68653
+ try {
68654
+ raw = await collectMutateInput(
68655
+ collectArgs,
68656
+ process.stdin
68657
+ );
68658
+ } catch (err) {
68659
+ cliError(
68660
+ err.message,
68661
+ 6 /* VALIDATION_ERROR */,
68662
+ {
68663
+ name: "E_VALIDATION_FAILED",
68664
+ fix: "Verify the JSON syntax of your --params / --params-file input"
68665
+ },
68666
+ { operation: "tasks.update" }
68667
+ );
68668
+ process.exit(6 /* VALIDATION_ERROR */);
68669
+ return;
68670
+ }
68671
+ if (raw !== null && typeof raw === "object" && !Array.isArray(raw) && raw["taskId"] === void 0 && args.taskId !== void 0) {
68672
+ raw["taskId"] = args.taskId;
68673
+ }
68674
+ const contract = INPUT_CONTRACTS3["tasks.update"];
68675
+ if (!contract) {
68676
+ cliError(
68677
+ "tasks.update contract missing from INPUT_CONTRACTS registry",
68678
+ 1 /* GENERAL_ERROR */,
68679
+ { name: "E_INTERNAL", fix: "This is a CLI bug \u2014 file an issue" },
68680
+ { operation: "tasks.update" }
68681
+ );
68682
+ process.exit(1 /* GENERAL_ERROR */);
68683
+ return;
68684
+ }
68685
+ const validation = validateOperationInput3(contract, raw);
68686
+ if (!validation.ok) {
68687
+ cliError(
68688
+ "tasks.update failed: validation",
68689
+ 6 /* VALIDATION_ERROR */,
68690
+ {
68691
+ name: "E_VALIDATION_FAILED",
68692
+ fix: validation.errors[0]?.fix ?? "Inspect errors[] and correct the input",
68693
+ details: { errors: validation.errors }
68694
+ },
68695
+ { operation: "tasks.update" }
68696
+ );
68697
+ process.exit(6 /* VALIDATION_ERROR */);
68698
+ return;
68699
+ }
68700
+ const validatedPayload = raw;
68701
+ const response = await dispatchRaw("mutate", "tasks", "update", validatedPayload);
68702
+ if (!response.success) {
68703
+ cliError(
68704
+ response.error?.message ?? "Update failed",
68705
+ response.error?.code ?? "E_UPDATE_FAILED",
68706
+ {
68707
+ name: response.error?.code ?? "E_UPDATE_FAILED",
68708
+ fix: response.error?.fix ?? "Check task fields and try again"
68709
+ },
68710
+ { operation: "tasks.update" }
68711
+ );
68712
+ process.exit(1);
68713
+ return;
68714
+ }
68715
+ cliOutput(response.data, { command: "update", operation: "tasks.update" });
68716
+ return;
68717
+ }
66674
68718
  if (!args.taskId) {
66675
68719
  await showUsage(cmd);
66676
68720
  return;
@@ -66828,10 +68872,10 @@ var upgrade_exports = {};
66828
68872
  __export(upgrade_exports, {
66829
68873
  upgradeCommand: () => upgradeCommand
66830
68874
  });
66831
- import { resolve as resolve6 } from "node:path";
68875
+ import { resolve as resolve7 } from "node:path";
66832
68876
  import { CleoError as CleoError10, diagnoseUpgrade, runUpgrade as runUpgrade2, upgradeWorkflows as upgradeWorkflows2 } from "@cleocode/core/internal";
66833
68877
  var workflowsSubcommand, upgradeCommand;
66834
- var init_upgrade2 = __esm({
68878
+ var init_upgrade3 = __esm({
66835
68879
  "packages/cleo/src/cli/commands/upgrade.ts"() {
66836
68880
  "use strict";
66837
68881
  init_dist();
@@ -66868,7 +68912,7 @@ var init_upgrade2 = __esm({
66868
68912
  const dryRun = args["dry-run"] === true || args.check === true;
66869
68913
  const force = args.force === true && !dryRun;
66870
68914
  const result = await upgradeWorkflows2({
66871
- projectRoot: resolve6(process.cwd()),
68915
+ projectRoot: resolve7(process.cwd()),
66872
68916
  templatesDir: getWorkflowTemplatesDir2(),
66873
68917
  dryRun,
66874
68918
  force
@@ -67127,17 +69171,17 @@ var web_exports = {};
67127
69171
  __export(web_exports, {
67128
69172
  webCommand: () => webCommand
67129
69173
  });
67130
- import { execFileSync as execFileSync3, spawn as spawn3 } from "node:child_process";
67131
- import { mkdir as mkdir4, open, readFile as readFile6, rm, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
67132
- import { join as join31 } from "node:path";
67133
- import { CleoError as CleoError11, formatError as formatError6, getCleoHome as getCleoHome5 } from "@cleocode/core";
69174
+ import { execFileSync as execFileSync4, spawn as spawn3 } from "node:child_process";
69175
+ import { mkdir as mkdir4, open, readFile as readFile7, rm, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
69176
+ import { join as join34 } from "node:path";
69177
+ import { CleoError as CleoError11, formatError as formatError5, getCleoHome as getCleoHome5 } from "@cleocode/core";
67134
69178
  function getWebPaths() {
67135
69179
  const cleoHome = getCleoHome5();
67136
69180
  return {
67137
- pidFile: join31(cleoHome, "web-server.pid"),
67138
- configFile: join31(cleoHome, "web-server.json"),
67139
- logDir: join31(cleoHome, "logs"),
67140
- logFile: join31(cleoHome, "logs", "web-server.log")
69181
+ pidFile: join34(cleoHome, "web-server.pid"),
69182
+ configFile: join34(cleoHome, "web-server.json"),
69183
+ logDir: join34(cleoHome, "logs"),
69184
+ logFile: join34(cleoHome, "logs", "web-server.log")
67141
69185
  };
67142
69186
  }
67143
69187
  function isProcessRunning(pid) {
@@ -67151,7 +69195,7 @@ function isProcessRunning(pid) {
67151
69195
  async function getStatus() {
67152
69196
  const { pidFile, configFile } = getWebPaths();
67153
69197
  try {
67154
- const pidStr = (await readFile6(pidFile, "utf-8")).trim();
69198
+ const pidStr = (await readFile7(pidFile, "utf-8")).trim();
67155
69199
  const pid = Number.parseInt(pidStr, 10);
67156
69200
  if (Number.isNaN(pid) || !isProcessRunning(pid)) {
67157
69201
  return { running: false, pid: null, port: null, host: null, url: null };
@@ -67159,7 +69203,7 @@ async function getStatus() {
67159
69203
  let port = DEFAULT_PORT;
67160
69204
  let host = DEFAULT_HOST;
67161
69205
  try {
67162
- const config = JSON.parse(await readFile6(configFile, "utf-8"));
69206
+ const config = JSON.parse(await readFile7(configFile, "utf-8"));
67163
69207
  port = config.port ?? DEFAULT_PORT;
67164
69208
  host = config.host ?? DEFAULT_HOST;
67165
69209
  } catch {
@@ -67176,7 +69220,7 @@ async function startWebServer(port, host) {
67176
69220
  throw new CleoError11(1 /* GENERAL_ERROR */, `Server already running (PID: ${status.pid})`);
67177
69221
  }
67178
69222
  const projectRoot = process.env["CLEO_ROOT"] ?? process.cwd();
67179
- const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join31(projectRoot, "packages", "studio", "build");
69223
+ const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join34(projectRoot, "packages", "studio", "build");
67180
69224
  await mkdir4(logDir, { recursive: true });
67181
69225
  await writeFile3(
67182
69226
  configFile,
@@ -67186,12 +69230,12 @@ async function startWebServer(port, host) {
67186
69230
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
67187
69231
  })
67188
69232
  );
67189
- const webIndexPath = join31(studioDir, "index.js");
69233
+ const webIndexPath = join34(studioDir, "index.js");
67190
69234
  try {
67191
69235
  await stat2(webIndexPath);
67192
69236
  } catch {
67193
69237
  try {
67194
- execFileSync3("pnpm", ["--filter", "@cleocode/studio", "run", "build"], {
69238
+ execFileSync4("pnpm", ["--filter", "@cleocode/studio", "run", "build"], {
67195
69239
  cwd: projectRoot,
67196
69240
  stdio: "ignore"
67197
69241
  });
@@ -67234,7 +69278,7 @@ Logs: ${logFile}`
67234
69278
  }
67235
69279
  } catch {
67236
69280
  }
67237
- await new Promise((resolve7) => setTimeout(resolve7, 500));
69281
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
67238
69282
  }
67239
69283
  if (!started) {
67240
69284
  try {
@@ -67283,7 +69327,7 @@ var init_web = __esm({
67283
69327
  await startWebServer(Number.parseInt(args.port, 10), args.host);
67284
69328
  } catch (err) {
67285
69329
  if (err instanceof CleoError11) {
67286
- console.error(formatError6(err));
69330
+ console.error(formatError5(err));
67287
69331
  process.exit(err.code);
67288
69332
  }
67289
69333
  throw err;
@@ -67311,7 +69355,7 @@ var init_web = __esm({
67311
69355
  }
67312
69356
  for (let i = 0; i < 60; i++) {
67313
69357
  if (!isProcessRunning(status.pid)) break;
67314
- await new Promise((resolve7) => setTimeout(resolve7, 500));
69358
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
67315
69359
  }
67316
69360
  if (isProcessRunning(status.pid)) {
67317
69361
  try {
@@ -67327,7 +69371,7 @@ var init_web = __esm({
67327
69371
  cliOutput({ stopped: true }, { command: "web", message: "CLEO Web UI stopped" });
67328
69372
  } catch (err) {
67329
69373
  if (err instanceof CleoError11) {
67330
- console.error(formatError6(err));
69374
+ console.error(formatError5(err));
67331
69375
  process.exit(err.code);
67332
69376
  }
67333
69377
  throw err;
@@ -67363,7 +69407,7 @@ var init_web = __esm({
67363
69407
  }
67364
69408
  for (let i = 0; i < 60; i++) {
67365
69409
  if (!isProcessRunning(status.pid)) break;
67366
- await new Promise((resolve7) => setTimeout(resolve7, 500));
69410
+ await new Promise((resolve8) => setTimeout(resolve8, 500));
67367
69411
  }
67368
69412
  if (isProcessRunning(status.pid)) {
67369
69413
  try {
@@ -67380,7 +69424,7 @@ var init_web = __esm({
67380
69424
  await startWebServer(Number.parseInt(args.port, 10), args.host);
67381
69425
  } catch (err) {
67382
69426
  if (err instanceof CleoError11) {
67383
- console.error(formatError6(err));
69427
+ console.error(formatError5(err));
67384
69428
  process.exit(err.code);
67385
69429
  }
67386
69430
  throw err;
@@ -67395,7 +69439,7 @@ var init_web = __esm({
67395
69439
  cliOutput(status, { command: "web" });
67396
69440
  } catch (err) {
67397
69441
  if (err instanceof CleoError11) {
67398
- console.error(formatError6(err));
69442
+ console.error(formatError5(err));
67399
69443
  process.exit(err.code);
67400
69444
  }
67401
69445
  throw err;
@@ -67428,7 +69472,7 @@ var init_web = __esm({
67428
69472
  cliOutput({ url }, { command: "web", message: `Open browser to: ${url}` });
67429
69473
  } catch (err) {
67430
69474
  if (err instanceof CleoError11) {
67431
- console.error(formatError6(err));
69475
+ console.error(formatError5(err));
67432
69476
  process.exit(err.code);
67433
69477
  }
67434
69478
  throw err;
@@ -67459,14 +69503,14 @@ __export(worktree_exports, {
67459
69503
  worktreeCommand: () => worktreeCommand
67460
69504
  });
67461
69505
  import readline4 from "node:readline";
67462
- import { getProjectRoot as getProjectRoot52, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
69506
+ import { getProjectRoot as getProjectRoot53, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
67463
69507
  async function promptYesNo2(question) {
67464
- return new Promise((resolve7) => {
69508
+ return new Promise((resolve8) => {
67465
69509
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
67466
69510
  rl.question(`${question} [y/N]: `, (answer) => {
67467
69511
  rl.close();
67468
69512
  const trimmed = answer.trim().toLowerCase();
67469
- resolve7(trimmed === "y" || trimmed === "yes");
69513
+ resolve8(trimmed === "y" || trimmed === "yes");
67470
69514
  });
67471
69515
  });
67472
69516
  }
@@ -67564,7 +69608,7 @@ var init_worktree3 = __esm({
67564
69608
  const staleDays = staleDaysRaw !== void 0 ? Number.parseInt(staleDaysRaw, 10) : void 0;
67565
69609
  const idleDaysRaw = typeof args["idle-days"] === "string" ? args["idle-days"] : void 0;
67566
69610
  const idleDays = idleDaysRaw !== void 0 ? Number.parseInt(idleDaysRaw, 10) : void 0;
67567
- const projectRoot = getProjectRoot52();
69611
+ const projectRoot = getProjectRoot53();
67568
69612
  const listResult = await listWorktrees2({
67569
69613
  projectRoot,
67570
69614
  ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
@@ -67799,8 +69843,8 @@ var init_worktree3 = __esm({
67799
69843
  init_dist();
67800
69844
  init_field_context();
67801
69845
  init_format_context();
67802
- import { readFileSync as readFileSync17 } from "node:fs";
67803
- import { dirname as dirname9, join as join33 } from "node:path";
69846
+ import { readFileSync as readFileSync20 } from "node:fs";
69847
+ import { dirname as dirname11, join as join36 } from "node:path";
67804
69848
  import { fileURLToPath as fileURLToPath7 } from "node:url";
67805
69849
 
67806
69850
  // packages/cleo/src/cli/generated/command-manifest.ts
@@ -68193,7 +70237,7 @@ var COMMAND_MANIFEST = [
68193
70237
  exportName: "graphCommand",
68194
70238
  name: "graph",
68195
70239
  description: "Project-scoped code intelligence: symbol graph, impact analysis, clusters, flows",
68196
- load: async () => (await Promise.resolve().then(() => (init_graph2(), graph_exports))).graphCommand
70240
+ load: async () => (await Promise.resolve().then(() => (init_graph3(), graph_exports))).graphCommand
68197
70241
  },
68198
70242
  {
68199
70243
  exportName: "historyCommand",
@@ -68528,7 +70572,7 @@ var COMMAND_MANIFEST = [
68528
70572
  {
68529
70573
  exportName: "showCommand",
68530
70574
  name: "show",
68531
- description: "Show full task details by ID (returns complete task record with metadata, verification, lifecycle)",
70575
+ description: "Show task details by ID. MVI-projected (id + title + status + key metadata) by default; pass --verbose / --full to receive the complete record with description, acceptance, verification, evidence, etc. (T9922)",
68532
70576
  load: async () => (await Promise.resolve().then(() => (init_show2(), show_exports))).showCommand
68533
70577
  },
68534
70578
  {
@@ -68597,6 +70641,12 @@ var COMMAND_MANIFEST = [
68597
70641
  description: "Manage anonymous skills-usage telemetry (enable/disable/status)",
68598
70642
  load: async () => (await Promise.resolve().then(() => (init_telemetry2(), telemetry_exports))).telemetryCommand
68599
70643
  },
70644
+ {
70645
+ exportName: "templatesCommand",
70646
+ name: "templates",
70647
+ description: "TemplateManifest SSoT registry surface (list, show, install, upgrade, diff, validate)",
70648
+ load: async () => (await Promise.resolve().then(() => (init_templates2(), templates_exports))).templatesCommand
70649
+ },
68600
70650
  {
68601
70651
  exportName: "testingCommand",
68602
70652
  name: "testing",
@@ -68625,7 +70675,7 @@ var COMMAND_MANIFEST = [
68625
70675
  exportName: "upgradeCommand",
68626
70676
  name: "upgrade",
68627
70677
  description: "Unified project maintenance (storage migration, schema repair, structural fixes, doc refresh)",
68628
- load: async () => (await Promise.resolve().then(() => (init_upgrade2(), upgrade_exports))).upgradeCommand
70678
+ load: async () => (await Promise.resolve().then(() => (init_upgrade3(), upgrade_exports))).upgradeCommand
68629
70679
  },
68630
70680
  {
68631
70681
  exportName: "verifyCommand",
@@ -68808,14 +70858,14 @@ function lazyCommand(meta, loader2) {
68808
70858
  init_did_you_mean();
68809
70859
 
68810
70860
  // packages/cleo/src/cli/lib/first-run-detection.ts
68811
- import { existsSync as existsSync16 } from "node:fs";
68812
- import { join as join32 } from "node:path";
70861
+ import { existsSync as existsSync18 } from "node:fs";
70862
+ import { join as join35 } from "node:path";
68813
70863
  async function detectFirstRun() {
68814
70864
  const envKey = process.env["ANTHROPIC_API_KEY"];
68815
70865
  if (typeof envKey === "string" && envKey.length > 0) return false;
68816
70866
  const { getCleoPlatformPaths } = await import("@cleocode/paths");
68817
- const configPath = join32(getCleoPlatformPaths().config, "config.json");
68818
- if (existsSync16(configPath)) return false;
70867
+ const configPath = join35(getCleoPlatformPaths().config, "config.json");
70868
+ if (existsSync18(configPath)) return false;
68819
70869
  try {
68820
70870
  const { getCredentialPool } = await import("@cleocode/core/llm/credential-pool.js");
68821
70871
  const pool = getCredentialPool();
@@ -68826,7 +70876,7 @@ async function detectFirstRun() {
68826
70876
  return true;
68827
70877
  }
68828
70878
  function waitForEnterOrTimeout(timeoutMs) {
68829
- return new Promise((resolve7) => {
70879
+ return new Promise((resolve8) => {
68830
70880
  let resolved = false;
68831
70881
  const finish = () => {
68832
70882
  if (resolved) return;
@@ -68838,7 +70888,7 @@ function waitForEnterOrTimeout(timeoutMs) {
68838
70888
  process.stdin.pause();
68839
70889
  } catch {
68840
70890
  }
68841
- resolve7();
70891
+ resolve8();
68842
70892
  };
68843
70893
  const onData = (chunk) => {
68844
70894
  const s = typeof chunk === "string" ? chunk : chunk.toString("utf8");
@@ -68880,6 +70930,10 @@ function resolveFormat(opts, defaults) {
68880
70930
  return resolveOutputFormat(input2);
68881
70931
  }
68882
70932
 
70933
+ // packages/cleo/src/cli/index.ts
70934
+ init_output_context();
70935
+ init_projection_context();
70936
+
68883
70937
  // packages/cleo/src/cli/resolve-subcommand.ts
68884
70938
  async function resolveLazyValue(input2) {
68885
70939
  if (typeof input2 === "function") {
@@ -68907,6 +70961,7 @@ async function resolveSubCommandForHelp(cmd, rawArgs) {
68907
70961
  }
68908
70962
 
68909
70963
  // packages/cleo/src/cli/index.ts
70964
+ init_summary_context();
68910
70965
  {
68911
70966
  const [major] = process.versions.node.split(".").map(Number);
68912
70967
  if (typeof major !== "number" || major < 24) {
@@ -68929,8 +70984,8 @@ Or via NodeSource: https://github.com/nodesource/distributions
68929
70984
  }
68930
70985
  }
68931
70986
  function getPackageVersion() {
68932
- const pkgPath = join33(dirname9(fileURLToPath7(import.meta.url)), "../../package.json");
68933
- const pkg = JSON.parse(readFileSync17(pkgPath, "utf-8"));
70987
+ const pkgPath = join36(dirname11(fileURLToPath7(import.meta.url)), "../../package.json");
70988
+ const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
68934
70989
  return pkg.version;
68935
70990
  }
68936
70991
  var CLI_VERSION = getPackageVersion();
@@ -68965,6 +71020,9 @@ alias("pipeline", "phaseCommand");
68965
71020
  async function startCli() {
68966
71021
  const argv = process.argv.slice(2);
68967
71022
  const rawOpts = {};
71023
+ let verboseFlag = false;
71024
+ let outputModeRaw;
71025
+ let summaryFlag = false;
68968
71026
  for (let i = 0; i < argv.length; i++) {
68969
71027
  const arg = argv[i];
68970
71028
  if (arg === "--json") rawOpts["json"] = true;
@@ -68973,6 +71031,9 @@ async function startCli() {
68973
71031
  else if (arg === "--field" && i + 1 < argv.length) rawOpts["field"] = argv[++i];
68974
71032
  else if (arg === "--fields" && i + 1 < argv.length) rawOpts["fields"] = argv[++i];
68975
71033
  else if (arg === "--mvi" && i + 1 < argv.length) rawOpts["mvi"] = argv[++i];
71034
+ else if (arg === "--verbose" || arg === "--full") verboseFlag = true;
71035
+ else if (arg === "--output" && i + 1 < argv.length) outputModeRaw = argv[++i];
71036
+ else if (arg === "--summary") summaryFlag = true;
68976
71037
  }
68977
71038
  const formatResolution = resolveFormat(rawOpts);
68978
71039
  setFormatContext(formatResolution);
@@ -68981,6 +71042,19 @@ async function startCli() {
68981
71042
  fieldResolution.mvi = "minimal";
68982
71043
  }
68983
71044
  setFieldContext(fieldResolution);
71045
+ setProjectionOptOut(verboseFlag || formatResolution.format === "human");
71046
+ if (outputModeRaw !== void 0) {
71047
+ if (!isOutputMode(outputModeRaw)) {
71048
+ process.stderr.write(
71049
+ `Error: invalid --output mode "${outputModeRaw}"
71050
+ Valid modes: envelope, id, table, count, silent
71051
+ `
71052
+ );
71053
+ process.exit(2);
71054
+ }
71055
+ setOutputMode(outputModeRaw);
71056
+ }
71057
+ setSummaryMode(summaryFlag);
68984
71058
  const isHelpOrVersion = argv.length === 0 || argv[0] === "--help" || argv[0] === "-h" || argv[0] === "--version" || argv[0] === "-V" || argv[0] === "help";
68985
71059
  if (argv[0] === "--version" || argv[0] === "-V") {
68986
71060
  const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
@@ -68988,6 +71062,10 @@ async function startCli() {
68988
71062
  return;
68989
71063
  }
68990
71064
  if (!isHelpOrVersion) {
71065
+ if (rawOpts["quiet"] === true) {
71066
+ const { setLoggerQuiet } = await import("@cleocode/core/internal");
71067
+ setLoggerQuiet(true);
71068
+ }
68991
71069
  await runStartupMaintenance();
68992
71070
  }
68993
71071
  if (!isHelpOrVersion) {
@@ -69082,7 +71160,7 @@ async function runStartupMaintenance() {
69082
71160
  detectAndRemoveStrayProjectNexus,
69083
71161
  getGlobalSalt,
69084
71162
  getLogger: getLogger21,
69085
- getProjectRoot: getProjectRoot53,
71163
+ getProjectRoot: getProjectRoot54,
69086
71164
  isCleanupMarkerSet,
69087
71165
  migrateSignaldockToConduit,
69088
71166
  needsSignaldockToConduitMigration,
@@ -69091,7 +71169,7 @@ async function runStartupMaintenance() {
69091
71169
  } = await import("@cleocode/core/internal");
69092
71170
  let projectRootForCleanup = "";
69093
71171
  try {
69094
- projectRootForCleanup = getProjectRoot53();
71172
+ projectRootForCleanup = getProjectRoot54();
69095
71173
  } catch {
69096
71174
  }
69097
71175
  if (!isCleanupMarkerSet(CLI_VERSION, projectRootForCleanup)) {
@@ -69111,7 +71189,7 @@ async function runStartupMaintenance() {
69111
71189
  const isInitInvocation = process.argv.slice(2).some((a) => a === "init");
69112
71190
  if (!isInitInvocation) {
69113
71191
  try {
69114
- const _projectRootForMigration = getProjectRoot53();
71192
+ const _projectRootForMigration = getProjectRoot54();
69115
71193
  if (needsSignaldockToConduitMigration(_projectRootForMigration)) {
69116
71194
  const migrationResult = migrateSignaldockToConduit(_projectRootForMigration);
69117
71195
  if (migrationResult.status === "failed") {