@cleocode/cleo 2026.5.114 → 2026.5.121

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;
@@ -1696,7 +1730,7 @@ var init_branch_lock = __esm({
1696
1730
 
1697
1731
  // packages/contracts/src/changesets.ts
1698
1732
  import { z as z3 } from "zod";
1699
- var CHANGESET_KINDS, TASK_ID_RE, ChangesetEntrySchema;
1733
+ var CHANGESET_KINDS, CHANGESET_RELEASE_NOTE_SECTIONS, CHANGESET_RELEASE_NOTE_AUDIENCES, CHANGESET_RELEASE_NOTE_SCOPES, nonEmptyReleaseNoteText, nonEmptyReleaseNoteList, ChangesetReleaseNotesMetadataSchema, TASK_ID_RE, ChangesetEntrySchema;
1700
1734
  var init_changesets = __esm({
1701
1735
  "packages/contracts/src/changesets.ts"() {
1702
1736
  "use strict";
@@ -1710,10 +1744,60 @@ var init_changesets = __esm({
1710
1744
  "chore",
1711
1745
  "breaking"
1712
1746
  ];
1747
+ CHANGESET_RELEASE_NOTE_SECTIONS = [
1748
+ "added",
1749
+ "changed",
1750
+ "fixed",
1751
+ "deprecated",
1752
+ "removed",
1753
+ "security",
1754
+ "breaking"
1755
+ ];
1756
+ CHANGESET_RELEASE_NOTE_AUDIENCES = [
1757
+ "users",
1758
+ "operators",
1759
+ "developers",
1760
+ "maintainers"
1761
+ ];
1762
+ CHANGESET_RELEASE_NOTE_SCOPES = [
1763
+ "project",
1764
+ "package",
1765
+ "component",
1766
+ "docs",
1767
+ "ops",
1768
+ "security"
1769
+ ];
1770
+ nonEmptyReleaseNoteText = z3.string().min(1, "release-note metadata text must be non-empty");
1771
+ nonEmptyReleaseNoteList = z3.array(nonEmptyReleaseNoteText).min(1, "release-note metadata list must contain at least one item");
1772
+ ChangesetReleaseNotesMetadataSchema = z3.object({
1773
+ /** Keep-a-Changelog style section/category override. */
1774
+ section: z3.enum(CHANGESET_RELEASE_NOTE_SECTIONS).optional(),
1775
+ /** Intended readers for the note. */
1776
+ audience: z3.array(z3.enum(CHANGESET_RELEASE_NOTE_AUDIENCES)).min(1).optional(),
1777
+ /** Release-note scope. */
1778
+ scope: z3.enum(CHANGESET_RELEASE_NOTE_SCOPES).optional(),
1779
+ /** Package/project/component targets affected by this entry. */
1780
+ targets: nonEmptyReleaseNoteList.optional(),
1781
+ /** User- or operator-visible impact statement. */
1782
+ impact: nonEmptyReleaseNoteText.optional(),
1783
+ /** Deterministic migration/action text, separate from breaking changes. */
1784
+ migration: nonEmptyReleaseNoteText.optional(),
1785
+ /** Deprecation detail for Deprecated sections. */
1786
+ deprecation: nonEmptyReleaseNoteText.optional(),
1787
+ /** Security detail for Security sections. */
1788
+ security: nonEmptyReleaseNoteText.optional(),
1789
+ /** Operator-facing rollout/verification note. */
1790
+ operatorNotes: nonEmptyReleaseNoteText.optional(),
1791
+ /** Explicit inclusion toggle for future release-scope filters. */
1792
+ includeInChangelog: z3.boolean().optional()
1793
+ }).strict();
1713
1794
  TASK_ID_RE = /^(T\d+(-[A-Z][A-Za-z0-9]*)?|E-\d+(-[A-Z][A-Za-z0-9]*)?)$/;
1714
1795
  ChangesetEntrySchema = z3.object({
1715
- /** Filename slug (without the `.md` extension). */
1716
- id: z3.string().min(1, "id must be non-empty").regex(/^[a-z0-9][a-z0-9-]*$/, "id must be kebab-case (lowercase, digits, hyphens)"),
1796
+ /** Filename identifier (without the `.md` extension); lowercase kebab-case for new files, legacy uppercase task IDs accepted. */
1797
+ id: z3.string().min(1, "id must be non-empty").regex(
1798
+ /^[A-Za-z0-9][A-Za-z0-9-]*$/,
1799
+ "id must contain only ASCII letters, digits, and hyphens"
1800
+ ),
1717
1801
  /** One or more CLEO task IDs this change is anchored to. */
1718
1802
  tasks: z3.array(z3.string().regex(TASK_ID_RE, "task ID must match T#### or E-#### format")).min(1, "tasks must contain at least one task ID"),
1719
1803
  /** Type of change. */
@@ -1725,7 +1809,9 @@ var init_changesets = __esm({
1725
1809
  /** Markdown body — longer-form explanation. */
1726
1810
  notes: z3.string().optional(),
1727
1811
  /** Migration note. Required iff `kind === 'breaking'`. */
1728
- breaking: z3.string().optional()
1812
+ breaking: z3.string().optional(),
1813
+ /** Structured author-provided metadata for deterministic release notes. */
1814
+ releaseNotes: ChangesetReleaseNotesMetadataSchema.optional()
1729
1815
  }).refine((entry) => entry.kind !== "breaking" || (entry.breaking?.length ?? 0) > 0, {
1730
1816
  message: "breaking entries must include a non-empty `breaking` migration note",
1731
1817
  path: ["breaking"]
@@ -4248,6 +4334,39 @@ var init_operations_registry = __esm({
4248
4334
  }
4249
4335
  ]
4250
4336
  },
4337
+ {
4338
+ gateway: "mutate",
4339
+ domain: "tasks",
4340
+ operation: "relates.remove",
4341
+ 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.",
4342
+ tier: 1,
4343
+ idempotent: true,
4344
+ sessionRequired: false,
4345
+ requiredParams: ["taskId", "relatedId"],
4346
+ params: [
4347
+ {
4348
+ name: "taskId",
4349
+ type: "string",
4350
+ required: true,
4351
+ description: "Source task ID",
4352
+ cli: { positional: true }
4353
+ },
4354
+ {
4355
+ name: "relatedId",
4356
+ type: "string",
4357
+ required: true,
4358
+ description: "Target task ID to remove the relation to",
4359
+ cli: { positional: true }
4360
+ },
4361
+ {
4362
+ name: "type",
4363
+ type: "string",
4364
+ required: false,
4365
+ description: "Optional relation type (blocks|related|duplicates|absorbs|fixes|extends|supersedes). Omit to remove any type.",
4366
+ cli: { flag: "type" }
4367
+ }
4368
+ ]
4369
+ },
4251
4370
  // === saga sub-domain (ADR-073 — above-epic grouping tier) ===
4252
4371
  {
4253
4372
  gateway: "mutate",
@@ -8533,6 +8652,39 @@ var init_operations_registry = __esm({
8533
8652
  }
8534
8653
  ]
8535
8654
  },
8655
+ // ── docs.supersede (T10162) ──────────────────────────────────────────────
8656
+ {
8657
+ gateway: "mutate",
8658
+ domain: "docs",
8659
+ operation: "supersede",
8660
+ 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)",
8661
+ tier: 1,
8662
+ idempotent: true,
8663
+ sessionRequired: false,
8664
+ requiredParams: ["oldSlug", "newSlug"],
8665
+ params: [
8666
+ {
8667
+ name: "oldSlug",
8668
+ type: "string",
8669
+ required: true,
8670
+ description: "Slug of the doc being replaced",
8671
+ cli: { positional: true }
8672
+ },
8673
+ {
8674
+ name: "newSlug",
8675
+ type: "string",
8676
+ required: true,
8677
+ description: "Slug of the doc that replaces oldSlug",
8678
+ cli: { positional: true }
8679
+ },
8680
+ {
8681
+ name: "reason",
8682
+ type: "string",
8683
+ required: false,
8684
+ description: "Optional human-readable reason carried back on the response"
8685
+ }
8686
+ ]
8687
+ },
8536
8688
  // ── docs.generate (T798) ─────────────────────────────────────────────────
8537
8689
  {
8538
8690
  gateway: "query",
@@ -8558,6 +8710,55 @@ var init_operations_registry = __esm({
8558
8710
  }
8559
8711
  ]
8560
8712
  },
8713
+ // ── docs.update (T10161 — Epic T10157 / Saga T9855) ──────────────────────
8714
+ {
8715
+ gateway: "mutate",
8716
+ domain: "docs",
8717
+ operation: "update",
8718
+ 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).",
8719
+ tier: 1,
8720
+ idempotent: false,
8721
+ sessionRequired: false,
8722
+ requiredParams: ["slug"],
8723
+ params: [
8724
+ {
8725
+ name: "slug",
8726
+ type: "string",
8727
+ required: true,
8728
+ description: "Slug of the existing attachment to update"
8729
+ },
8730
+ {
8731
+ name: "file",
8732
+ type: "string",
8733
+ required: false,
8734
+ description: "Path to a local file containing the new content"
8735
+ },
8736
+ {
8737
+ name: "content",
8738
+ type: "string",
8739
+ required: false,
8740
+ description: "Inline UTF-8 content (mutually exclusive with file)"
8741
+ },
8742
+ {
8743
+ name: "message",
8744
+ type: "string",
8745
+ required: false,
8746
+ description: "One-line summary describing the change (recorded in the audit log)"
8747
+ },
8748
+ {
8749
+ name: "status",
8750
+ type: "string",
8751
+ required: false,
8752
+ description: 'Override the new lifecycle status. Defaults to "draft" on every update. Valid: draft|proposed|accepted|superseded|archived|deprecated.'
8753
+ },
8754
+ {
8755
+ name: "attachedBy",
8756
+ type: "string",
8757
+ required: false,
8758
+ description: 'Agent identity that performed the update (defaults to "human")'
8759
+ }
8760
+ ]
8761
+ },
8561
8762
  // ── playbook.* HITL CLI surface (T935) ───────────────────────────────────
8562
8763
  {
8563
8764
  gateway: "mutate",
@@ -9218,6 +9419,35 @@ var init_operations_registry = __esm({
9218
9419
  }
9219
9420
  ]
9220
9421
  },
9422
+ // release query: validate-changelog (T9937 / Saga T9862 — canonical CHANGELOG
9423
+ // header validator that replaces the brittle inline grep step in
9424
+ // .github/workflows/release.yml). Read-only — exposed only under the query
9425
+ // gateway because no DB or filesystem mutation occurs.
9426
+ {
9427
+ gateway: "query",
9428
+ domain: "release",
9429
+ operation: "validate-changelog",
9430
+ description: "release.validate-changelog (query) \u2014 validate that CHANGELOG.md contains the canonical `## [VERSION]` header per ADR-028 \xA72.5. Replaces the brittle inline grep in .github/workflows/release.yml (T9937 / Saga T9862).",
9431
+ tier: 1,
9432
+ idempotent: true,
9433
+ sessionRequired: false,
9434
+ requiredParams: ["version"],
9435
+ params: [
9436
+ {
9437
+ name: "version",
9438
+ type: "string",
9439
+ required: true,
9440
+ description: "Release version (accepts v2026.5.94 or 2026.5.94)",
9441
+ cli: { positional: true }
9442
+ },
9443
+ {
9444
+ name: "changelogPath",
9445
+ type: "string",
9446
+ required: false,
9447
+ description: "Override the CHANGELOG file path (default: <projectRoot>/CHANGELOG.md)"
9448
+ }
9449
+ ]
9450
+ },
9221
9451
  // ---------------------------------------------------------------------------
9222
9452
  // Provenance domain — `cleo provenance` CLI surface (T9528 · Phase 2 of T9493)
9223
9453
  // ---------------------------------------------------------------------------
@@ -10397,7 +10627,7 @@ var init_errors = __esm({
10397
10627
 
10398
10628
  // packages/contracts/src/evidence-atom-schema.ts
10399
10629
  import { z as z6 } from "zod";
10400
- var commitAtomSchema, filesAtomSchema, testRunAtomSchema, toolAtomSchema, urlAtomSchema, noteAtomSchema, decisionAtomSchema, prAtomSchema, locDropAtomSchema, callsiteCoverageAtomSchema, EvidenceAtomSchema, GATE_EVIDENCE_REQUIREMENTS;
10630
+ var commitAtomSchema, filesAtomSchema, testRunAtomSchema, toolAtomSchema, urlAtomSchema, noteAtomSchema, decisionAtomSchema, prAtomSchema, locDropAtomSchema, callsiteCoverageAtomSchema, EvidenceAtomSchema, GATE_EVIDENCE_REQUIREMENTS, ATOM_EXAMPLES;
10401
10631
  var init_evidence_atom_schema = __esm({
10402
10632
  "packages/contracts/src/evidence-atom-schema.ts"() {
10403
10633
  "use strict";
@@ -10472,6 +10702,18 @@ var init_evidence_atom_schema = __esm({
10472
10702
  cleanupDone: { oneOf: [["note"]] },
10473
10703
  nexusImpact: { oneOf: [["tool"], ["note"]] }
10474
10704
  });
10705
+ ATOM_EXAMPLES = Object.freeze({
10706
+ commit: "commit:<sha>",
10707
+ files: "files:path/a.ts,path/b.ts",
10708
+ "test-run": "test-run:/tmp/vitest-out.json",
10709
+ tool: "tool:test",
10710
+ url: "url:https://example.com/docs",
10711
+ note: "note:<short description>",
10712
+ decision: "decision:D-arch-001",
10713
+ pr: "pr:357",
10714
+ "loc-drop": "loc-drop:<fromLines>:<toLines>",
10715
+ "callsite-coverage": "callsite-coverage:<symbolName>:<relativeSourcePath>"
10716
+ });
10475
10717
  }
10476
10718
  });
10477
10719
 
@@ -12520,6 +12762,174 @@ var init_normalizer = __esm({
12520
12762
  }
12521
12763
  });
12522
12764
 
12765
+ // packages/cleo/src/cli/renderers/output-mode.ts
12766
+ function extractIds(data) {
12767
+ if (data === null || typeof data !== "object") return [];
12768
+ const rec = data;
12769
+ const task = rec["task"];
12770
+ if (task && typeof task === "object") {
12771
+ const id2 = task["id"];
12772
+ if (typeof id2 === "string") return [id2];
12773
+ }
12774
+ const tasks = rec["tasks"];
12775
+ if (Array.isArray(tasks)) {
12776
+ return tasks.map((t) => t && typeof t === "object" ? t["id"] : void 0).filter((id2) => typeof id2 === "string");
12777
+ }
12778
+ const items = rec["items"];
12779
+ if (Array.isArray(items)) {
12780
+ return items.map((t) => t && typeof t === "object" ? t["id"] : void 0).filter((id2) => typeof id2 === "string");
12781
+ }
12782
+ const id = rec["id"];
12783
+ if (typeof id === "string") return [id];
12784
+ return [];
12785
+ }
12786
+ function extractCount(data) {
12787
+ if (data === null || typeof data !== "object") return 0;
12788
+ const rec = data;
12789
+ const total = rec["total"];
12790
+ if (typeof total === "number" && Number.isFinite(total)) return total;
12791
+ const tasks = rec["tasks"];
12792
+ if (Array.isArray(tasks)) return tasks.length;
12793
+ const items = rec["items"];
12794
+ if (Array.isArray(items)) return items.length;
12795
+ if (rec["task"] && typeof rec["task"] === "object") return 1;
12796
+ if (typeof rec["id"] === "string") return 1;
12797
+ return 0;
12798
+ }
12799
+ function truncate(value, max) {
12800
+ if (value.length <= max) return value;
12801
+ return value.slice(0, Math.max(0, max - 1)) + "\u2026";
12802
+ }
12803
+ function renderTableList(tasks) {
12804
+ if (tasks.length === 0) return "No rows.";
12805
+ const COL_TITLE_MAX = 60;
12806
+ const rows = tasks.map((t) => ({
12807
+ id: typeof t["id"] === "string" ? t["id"] : "",
12808
+ status: typeof t["status"] === "string" ? t["status"] : "",
12809
+ priority: typeof t["priority"] === "string" ? t["priority"] : "",
12810
+ title: truncate(typeof t["title"] === "string" ? t["title"] : "", COL_TITLE_MAX)
12811
+ }));
12812
+ const widths = {
12813
+ id: Math.max(2, ...rows.map((r) => r.id.length)),
12814
+ status: Math.max(6, ...rows.map((r) => r.status.length)),
12815
+ priority: Math.max(8, ...rows.map((r) => r.priority.length)),
12816
+ title: Math.max(5, ...rows.map((r) => r.title.length))
12817
+ };
12818
+ const pad = (s, w) => s + " ".repeat(Math.max(0, w - s.length));
12819
+ const header = `${pad("id", widths.id)} ${pad("status", widths.status)} ${pad(
12820
+ "priority",
12821
+ widths.priority
12822
+ )} ${pad("title", widths.title)}`;
12823
+ const sep2 = `${"-".repeat(widths.id)} ${"-".repeat(widths.status)} ${"-".repeat(
12824
+ widths.priority
12825
+ )} ${"-".repeat(widths.title)}`;
12826
+ const body = rows.map(
12827
+ (r) => `${pad(r.id, widths.id)} ${pad(r.status, widths.status)} ${pad(
12828
+ r.priority,
12829
+ widths.priority
12830
+ )} ${pad(r.title, widths.title)}`
12831
+ ).join("\n");
12832
+ return `${header}
12833
+ ${sep2}
12834
+ ${body}`;
12835
+ }
12836
+ function renderTableGeneric(data) {
12837
+ const entries = Object.entries(data);
12838
+ if (entries.length === 0) return "(empty)";
12839
+ const rows = entries.map(([k, v]) => ({
12840
+ field: k,
12841
+ value: v === null || v === void 0 ? "" : typeof v === "object" ? JSON.stringify(v) : String(v)
12842
+ }));
12843
+ const VAL_MAX = 80;
12844
+ for (const r of rows) r.value = truncate(r.value, VAL_MAX);
12845
+ const widths = {
12846
+ field: Math.max(5, ...rows.map((r) => r.field.length)),
12847
+ value: Math.max(5, ...rows.map((r) => r.value.length))
12848
+ };
12849
+ const pad = (s, w) => s + " ".repeat(Math.max(0, w - s.length));
12850
+ const header = `${pad("field", widths.field)} ${pad("value", widths.value)}`;
12851
+ const sep2 = `${"-".repeat(widths.field)} ${"-".repeat(widths.value)}`;
12852
+ const body = rows.map((r) => `${pad(r.field, widths.field)} ${pad(r.value, widths.value)}`).join("\n");
12853
+ return `${header}
12854
+ ${sep2}
12855
+ ${body}`;
12856
+ }
12857
+ function renderSummary2(data) {
12858
+ if (data === null || typeof data !== "object") {
12859
+ return { text: "" };
12860
+ }
12861
+ const rec = data;
12862
+ const tasks = rec["tasks"];
12863
+ if (Array.isArray(tasks)) {
12864
+ return { text: renderSummaryList(tasks) };
12865
+ }
12866
+ const items = rec["items"];
12867
+ if (Array.isArray(items)) {
12868
+ return { text: renderSummaryList(items) };
12869
+ }
12870
+ const task = rec["task"];
12871
+ if (task && typeof task === "object") {
12872
+ return { text: renderSummaryRow(task) };
12873
+ }
12874
+ if (typeof rec["id"] === "string") {
12875
+ return { text: renderSummaryRow(rec) };
12876
+ }
12877
+ return { text: "" };
12878
+ }
12879
+ function renderSummaryRow(record) {
12880
+ const id = typeof record["id"] === "string" ? record["id"] : "";
12881
+ const status = typeof record["status"] === "string" ? record["status"] : "";
12882
+ const title = truncate(typeof record["title"] === "string" ? record["title"] : "", 60);
12883
+ return `${id} [${status}] ${title}`;
12884
+ }
12885
+ function renderSummaryList(rows) {
12886
+ if (rows.length === 0) return "No rows.";
12887
+ const lines = [];
12888
+ for (const row of rows) {
12889
+ if (!row || typeof row !== "object") continue;
12890
+ const rec = row;
12891
+ if (typeof rec["id"] !== "string") continue;
12892
+ lines.push(renderSummaryRow(rec));
12893
+ }
12894
+ return lines.length === 0 ? "No rows." : lines.join("\n");
12895
+ }
12896
+ function renderOutputMode(mode, data) {
12897
+ switch (mode) {
12898
+ case "id": {
12899
+ const ids = extractIds(data);
12900
+ return { text: ids.length === 0 ? "" : ids.join("\n") };
12901
+ }
12902
+ case "count": {
12903
+ return { text: String(extractCount(data)) };
12904
+ }
12905
+ case "table": {
12906
+ if (data && typeof data === "object") {
12907
+ const rec = data;
12908
+ const tasks = rec["tasks"];
12909
+ if (Array.isArray(tasks)) {
12910
+ return { text: renderTableList(tasks) };
12911
+ }
12912
+ const items = rec["items"];
12913
+ if (Array.isArray(items)) {
12914
+ return { text: renderTableList(items) };
12915
+ }
12916
+ return { text: renderTableGeneric(rec) };
12917
+ }
12918
+ return { text: data === null || data === void 0 ? "(empty)" : String(data) };
12919
+ }
12920
+ case "silent": {
12921
+ return { text: null };
12922
+ }
12923
+ case "envelope":
12924
+ throw new Error("renderOutputMode: envelope mode must be handled by caller");
12925
+ }
12926
+ }
12927
+ var init_output_mode = __esm({
12928
+ "packages/cleo/src/cli/renderers/output-mode.ts"() {
12929
+ "use strict";
12930
+ }
12931
+ });
12932
+
12523
12933
  // packages/cleo/src/cli/renderers/index.ts
12524
12934
  var renderers_exports = {};
12525
12935
  __export(renderers_exports, {
@@ -12535,7 +12945,9 @@ __export(renderers_exports, {
12535
12945
  import { randomUUID } from "node:crypto";
12536
12946
  import {
12537
12947
  drainWarnings,
12948
+ extractByJsonPointer,
12538
12949
  formatSuccess,
12950
+ isJsonPointer,
12539
12951
  metaFooter,
12540
12952
  pagerFooter,
12541
12953
  renderAuditReconstruct,
@@ -12593,7 +13005,8 @@ import {
12593
13005
  renderStop,
12594
13006
  renderTree as renderTree2,
12595
13007
  renderVersion,
12596
- renderWaves
13008
+ renderWaves,
13009
+ serializePointerValue
12597
13010
  } from "@cleocode/core";
12598
13011
  import { applyFieldFilter, extractFieldFromResult } from "@cleocode/lafs";
12599
13012
  import {
@@ -12615,11 +13028,60 @@ function pickDecoratorMetaExtensionsLocal(responseMeta) {
12615
13028
  const out = {};
12616
13029
  if (responseMeta["_nexus"] !== void 0) out["_nexus"] = responseMeta["_nexus"];
12617
13030
  if (responseMeta["deprecated"] !== void 0) out["deprecated"] = responseMeta["deprecated"];
13031
+ if (responseMeta["suggestedNext"] !== void 0) {
13032
+ out["suggestedNext"] = responseMeta["suggestedNext"];
13033
+ }
13034
+ if (responseMeta["projection"] !== void 0) {
13035
+ out["projection"] = responseMeta["projection"];
13036
+ }
12618
13037
  return out;
12619
13038
  }
13039
+ function buildEnvelopeForPointer(data, opts) {
13040
+ const decoratorExt = pickDecoratorMetaExtensionsLocal(opts.responseMeta);
13041
+ const meta = {
13042
+ ...decoratorExt,
13043
+ ...opts.extensions ?? {},
13044
+ operation: opts.operation ?? "cli.output"
13045
+ };
13046
+ if (opts.message) meta["message"] = opts.message;
13047
+ const envelope = {
13048
+ success: true,
13049
+ data,
13050
+ meta
13051
+ };
13052
+ if (opts.page) envelope["page"] = opts.page;
13053
+ return envelope;
13054
+ }
12620
13055
  function cliOutput(data, opts) {
12621
13056
  const ctx = getFormatContext();
12622
13057
  const fieldCtx = getFieldContext();
13058
+ const outputMode = getOutputMode();
13059
+ const summary = getSummaryMode();
13060
+ if (outputMode !== "envelope" && !fieldCtx.field) {
13061
+ const out = renderOutputMode(outputMode, data);
13062
+ if (out.text !== null && out.text.length > 0) {
13063
+ process.stdout.write(out.text + "\n");
13064
+ }
13065
+ return;
13066
+ }
13067
+ if (summary && !fieldCtx.field) {
13068
+ const out = renderSummary2(data);
13069
+ if (out.text !== null && out.text.length > 0) {
13070
+ process.stdout.write(out.text + "\n");
13071
+ }
13072
+ return;
13073
+ }
13074
+ if (fieldCtx.field && isJsonPointer(fieldCtx.field)) {
13075
+ const envelope = buildEnvelopeForPointer(data, opts);
13076
+ const value = extractByJsonPointer(envelope, fieldCtx.field);
13077
+ if (value === void 0) {
13078
+ cliError(`Pointer "${fieldCtx.field}" did not resolve`, 4, { name: "E_FIELD_NOT_FOUND" });
13079
+ process.exit(4);
13080
+ }
13081
+ process.stdout.write(`${serializePointerValue(value)}
13082
+ `);
13083
+ return;
13084
+ }
12623
13085
  if (ctx.format === "human") {
12624
13086
  let dataToRender = data;
12625
13087
  let fieldExtracted = false;
@@ -12769,6 +13231,12 @@ function isHumanOutput() {
12769
13231
  }
12770
13232
  function cliError(message, code, details, meta) {
12771
13233
  const ctx = getFormatContext();
13234
+ const outputMode = getOutputMode();
13235
+ if (outputMode === "silent") {
13236
+ process.stderr.write(`Error: ${message}${code ? ` (${code})` : ""}
13237
+ `);
13238
+ return;
13239
+ }
12772
13240
  if (ctx.format === "human") {
12773
13241
  process.stderr.write(`Error: ${message}${code ? ` (${code})` : ""}
12774
13242
  `);
@@ -12811,8 +13279,11 @@ var init_renderers = __esm({
12811
13279
  "use strict";
12812
13280
  init_field_context();
12813
13281
  init_format_context();
13282
+ init_output_context();
13283
+ init_summary_context();
12814
13284
  init_lafs_validator();
12815
13285
  init_normalizer();
13286
+ init_output_mode();
12816
13287
  renderers = {
12817
13288
  // Task CRUD
12818
13289
  show: renderShow,
@@ -13429,6 +13900,7 @@ __export(engine_exports, {
13429
13900
  taskWorkHistory: () => taskWorkHistory,
13430
13901
  tasksAddBatchOp: () => tasksAddBatchOp,
13431
13902
  validateBatchValidate: () => coreBatchValidate,
13903
+ validateChangelog: () => validateChangelog,
13432
13904
  validateCoherenceCheck: () => coreCoherenceCheck,
13433
13905
  validateComplianceRecord: () => coreComplianceRecord,
13434
13906
  validateComplianceSummary: () => coreComplianceSummary,
@@ -13654,6 +14126,7 @@ import {
13654
14126
  taskUnclaim,
13655
14127
  taskUpdate,
13656
14128
  taskWorkHistory,
14129
+ validateChangelog,
13657
14130
  validateGateVerify,
13658
14131
  validateProtocolArchitectureDecision,
13659
14132
  validateProtocolArtifactPublish,
@@ -17005,18 +17478,25 @@ import { resolve as resolve2 } from "node:path";
17005
17478
  import { pushWarning } from "@cleocode/core";
17006
17479
  import {
17007
17480
  AUTO_TOKEN,
17481
+ allocateAdrSlug,
17008
17482
  allocateAutoSlugForDispatch,
17483
+ consumeReservedSlug,
17009
17484
  createAttachmentStore,
17010
17485
  createAttachmentStoreV2,
17011
17486
  generateDocsLlmsTxt,
17012
17487
  getCleoDirAbsolute,
17013
17488
  getProjectRoot as getProjectRoot5,
17489
+ isLifecycleStatus,
17014
17490
  memoryObserve as memoryObserve2,
17015
17491
  parseChangesetFrontmatter,
17016
17492
  releaseReservedSlug,
17017
17493
  reserveSlugForDispatch,
17018
17494
  resolveAttachmentBackend,
17019
17495
  SlugCollisionError,
17496
+ SUPERSEDE_NOT_FOUND_CODE,
17497
+ SUPERSEDE_SAME_SLUG_CODE,
17498
+ supersedeDoc,
17499
+ updateDocBySlug,
17020
17500
  validateDocBody,
17021
17501
  writeChangesetEntry
17022
17502
  } from "@cleocode/core/internal";
@@ -17494,6 +17974,7 @@ var init_docs2 = __esm({
17494
17974
  labels: rawLabels,
17495
17975
  attachedBy: rawAttachedBy,
17496
17976
  slug: rawSlug,
17977
+ title: rawTitle,
17497
17978
  type: rawType,
17498
17979
  strict: strictMode
17499
17980
  } = params;
@@ -17601,6 +18082,19 @@ var init_docs2 = __esm({
17601
18082
  if (err.code === "E_FILE_WRITE_FAILED") {
17602
18083
  return lafsError("E_FILE_ERROR", err.message, "add");
17603
18084
  }
18085
+ if (err.code === "E_SLUG_RESERVED") {
18086
+ return {
18087
+ success: false,
18088
+ error: {
18089
+ code: "E_SLUG_RESERVED",
18090
+ message: err.message,
18091
+ details: {
18092
+ suggestions: err.suggestions,
18093
+ aliases: err.aliases
18094
+ }
18095
+ }
18096
+ };
18097
+ }
17604
18098
  return lafsError("E_SSOT_WRITE_FAILED", err.message, "add");
17605
18099
  }
17606
18100
  const changesetPayload = {
@@ -17633,14 +18127,31 @@ var init_docs2 = __esm({
17633
18127
  "add"
17634
18128
  );
17635
18129
  }
18130
+ let adrNumber;
18131
+ if (type2 === "adr" && slug === void 0) {
18132
+ if (typeof rawTitle !== "string" || rawTitle.trim().length === 0) {
18133
+ return lafsError(
18134
+ "E_VALIDATION",
18135
+ "title is required when type=adr and slug is omitted \u2014 the allocator needs a title to assemble adr-NNN-<kebab-title>",
18136
+ "add"
18137
+ );
18138
+ }
18139
+ const allocation = await allocateAdrSlug(getProjectRoot5(), { title: rawTitle });
18140
+ if (!allocation.ok) {
18141
+ return lafsError(allocation.code, allocation.message, "add");
18142
+ }
18143
+ slug = allocation.slug;
18144
+ adrNumber = allocation.number;
18145
+ }
17636
18146
  if (type2 !== void 0 && slug !== void 0) {
17637
18147
  const patternCheck = getDocKindRegistry().validateSlug(type2, slug);
17638
18148
  if (!patternCheck.ok) {
18149
+ if (adrNumber !== void 0) releaseReservedSlug(slug);
17639
18150
  const exampleHint = patternCheck.example ? ` (example: ${patternCheck.example})` : "";
17640
18151
  return lafsError("E_SLUG_PATTERN_MISMATCH", `${patternCheck.error}${exampleHint}`, "add");
17641
18152
  }
17642
18153
  }
17643
- if (slug !== void 0) {
18154
+ if (slug !== void 0 && adrNumber === void 0) {
17644
18155
  const reservation = await reserveSlugForDispatch(getProjectRoot5(), {
17645
18156
  kind: type2 ?? "",
17646
18157
  slug
@@ -17741,6 +18252,7 @@ var init_docs2 = __esm({
17741
18252
  }
17742
18253
  throw err;
17743
18254
  }
18255
+ if (adrNumber !== void 0 && slug !== void 0) consumeReservedSlug(slug);
17744
18256
  let backend = "legacy";
17745
18257
  try {
17746
18258
  const v2 = createAttachmentStoreV2(getProjectRoot5());
@@ -17782,7 +18294,8 @@ var init_docs2 = __esm({
17782
18294
  // Cast: core returns 'llmtxt'|'legacy'; contracts uses 'legacy'|'llmstxt-v2' (T1529)
17783
18295
  attachmentBackend: backend,
17784
18296
  ...slug !== void 0 ? { slug } : {},
17785
- ...type2 !== void 0 ? { type: type2 } : {}
18297
+ ...type2 !== void 0 ? { type: type2 } : {},
18298
+ ...adrNumber !== void 0 ? { adrNumber } : {}
17786
18299
  },
17787
18300
  "add"
17788
18301
  );
@@ -17823,6 +18336,7 @@ var init_docs2 = __esm({
17823
18336
  }
17824
18337
  throw err;
17825
18338
  }
18339
+ if (adrNumber !== void 0 && slug !== void 0) consumeReservedSlug(slug);
17826
18340
  import("@cleocode/core/internal").then(
17827
18341
  ({ ensureLlmtxtNode }) => ensureLlmtxtNode(getProjectRoot5(), meta.sha256, `${ownerType}:${ownerId}`, url)
17828
18342
  ).catch(() => {
@@ -17849,7 +18363,8 @@ var init_docs2 = __esm({
17849
18363
  // Cast: core returns 'llmtxt'|'legacy'; contracts uses 'legacy'|'llmstxt-v2' (T1529)
17850
18364
  attachmentBackend: backend,
17851
18365
  ...slug !== void 0 ? { slug } : {},
17852
- ...type2 !== void 0 ? { type: type2 } : {}
18366
+ ...type2 !== void 0 ? { type: type2 } : {},
18367
+ ...adrNumber !== void 0 ? { adrNumber } : {}
17853
18368
  },
17854
18369
  "add"
17855
18370
  );
@@ -17907,10 +18422,90 @@ var init_docs2 = __esm({
17907
18422
  },
17908
18423
  "remove"
17909
18424
  );
18425
+ },
18426
+ // ── docs.update (T10161 — E12.C4 / Saga T9855) ─────────────────────────────
18427
+ update: async (params) => {
18428
+ const { slug: rawSlug, file: filePath, content: inlineContent, status: rawStatus } = params;
18429
+ if (typeof rawSlug !== "string" || rawSlug.length === 0) {
18430
+ return lafsError("E_INVALID_INPUT", "slug is required", "update");
18431
+ }
18432
+ const hasFile = typeof filePath === "string" && filePath.length > 0;
18433
+ const hasContent = typeof inlineContent === "string";
18434
+ if (hasFile === hasContent) {
18435
+ return lafsError(
18436
+ "E_INVALID_INPUT",
18437
+ "Provide exactly one of --file <path> or --content <text>",
18438
+ "update",
18439
+ 'Use `cleo docs update <slug> --file ./new.md` OR `cleo docs update <slug> --content "..."`.'
18440
+ );
18441
+ }
18442
+ if (rawStatus !== void 0 && !isLifecycleStatus(rawStatus)) {
18443
+ return lafsError(
18444
+ "E_INVALID_INPUT",
18445
+ `status must be one of: draft|proposed|accepted|superseded|archived|deprecated \u2014 got '${String(rawStatus)}'`,
18446
+ "update"
18447
+ );
18448
+ }
18449
+ const projectRoot = getProjectRoot5();
18450
+ const resolvedParams = hasFile ? { ...params, file: resolve2(filePath) } : params;
18451
+ const outcome = await updateDocBySlug(projectRoot, resolvedParams);
18452
+ if (!outcome.ok) {
18453
+ return lafsError(outcome.error.code, outcome.error.message, "update");
18454
+ }
18455
+ return lafsSuccess(
18456
+ {
18457
+ slug: outcome.result.slug,
18458
+ ...outcome.result.type !== null ? { type: outcome.result.type } : {},
18459
+ attachmentId: outcome.result.attachmentId,
18460
+ previousAttachmentId: outcome.result.previousAttachmentId,
18461
+ sha256: outcome.result.sha256,
18462
+ previousSha256: outcome.result.previousSha256,
18463
+ changed: outcome.result.changed,
18464
+ lifecycleStatus: outcome.result.lifecycleStatus,
18465
+ updatedAt: outcome.result.updatedAt,
18466
+ version: outcome.result.version,
18467
+ squashed: outcome.result.squashed
18468
+ },
18469
+ "update"
18470
+ );
18471
+ },
18472
+ // ── docs.supersede ─────────────────────────────────────────────────────────
18473
+ supersede: async (params) => {
18474
+ const { oldSlug, newSlug, reason } = params;
18475
+ if (typeof oldSlug !== "string" || oldSlug.length === 0) {
18476
+ return lafsError("E_INVALID_INPUT", "<oldSlug> is required", "supersede");
18477
+ }
18478
+ if (typeof newSlug !== "string" || newSlug.length === 0) {
18479
+ return lafsError("E_INVALID_INPUT", "<newSlug> is required", "supersede");
18480
+ }
18481
+ try {
18482
+ const result = await supersedeDoc(getProjectRoot5(), {
18483
+ oldSlug,
18484
+ newSlug,
18485
+ ...typeof reason === "string" && reason.length > 0 ? { reason } : {}
18486
+ });
18487
+ const payload = {
18488
+ oldSlug: result.oldSlug,
18489
+ newSlug: result.newSlug,
18490
+ oldAttachmentId: result.oldAttachmentId,
18491
+ newAttachmentId: result.newAttachmentId,
18492
+ supersededAt: result.supersededAt,
18493
+ edgeId: result.edgeId,
18494
+ ...result.reason !== void 0 ? { reason: result.reason } : {}
18495
+ };
18496
+ return lafsSuccess(payload, "supersede");
18497
+ } catch (err) {
18498
+ const code = err && typeof err === "object" && "code" in err && typeof err.code === "number" ? (
18499
+ // Map ExitCode (number) → stable LAFS string code expected by callers.
18500
+ err.code === 4 ? SUPERSEDE_NOT_FOUND_CODE : err.code === 6 ? SUPERSEDE_SAME_SLUG_CODE : "E_INTERNAL"
18501
+ ) : "E_INTERNAL";
18502
+ const message = err instanceof Error ? err.message : "supersede failed";
18503
+ return lafsError(code, message, "supersede");
18504
+ }
17910
18505
  }
17911
18506
  });
17912
18507
  QUERY_OPS3 = /* @__PURE__ */ new Set(["list", "fetch", "generate"]);
17913
- MUTATE_OPS3 = /* @__PURE__ */ new Set(["add", "remove"]);
18508
+ MUTATE_OPS3 = /* @__PURE__ */ new Set(["add", "remove", "update", "supersede"]);
17914
18509
  DocsHandler = class {
17915
18510
  // -----------------------------------------------------------------------
17916
18511
  // Query
@@ -17969,7 +18564,7 @@ var init_docs2 = __esm({
17969
18564
  getSupportedOperations() {
17970
18565
  return {
17971
18566
  query: ["list", "fetch", "generate"],
17972
- mutate: ["add", "remove"]
18567
+ mutate: ["add", "remove", "update", "supersede"]
17973
18568
  };
17974
18569
  }
17975
18570
  };
@@ -20430,6 +21025,9 @@ function pickDecoratorMetaExtensions(responseMeta) {
20430
21025
  const out = {};
20431
21026
  if (responseMeta["_nexus"] !== void 0) out["_nexus"] = responseMeta["_nexus"];
20432
21027
  if (responseMeta["deprecated"] !== void 0) out["deprecated"] = responseMeta["deprecated"];
21028
+ if (responseMeta["suggestedNext"] !== void 0) {
21029
+ out["suggestedNext"] = responseMeta["suggestedNext"];
21030
+ }
20433
21031
  return out;
20434
21032
  }
20435
21033
  function buildNexusMetaExtensions(operation, params = {}) {
@@ -26817,7 +27415,8 @@ async function orchestrateSpawnOp(params) {
26817
27415
  getProjectRoot11(),
26818
27416
  params.tier,
26819
27417
  params.noWorktree,
26820
- params.spawnScope
27418
+ params.spawnScope,
27419
+ params.atomicityScope
26821
27420
  );
26822
27421
  }
26823
27422
  async function orchestrateHandoffOp(params) {
@@ -26897,16 +27496,16 @@ async function orchestrateRejectOp(params) {
26897
27496
  async function orchestrateClassify(request, context, projectRoot) {
26898
27497
  try {
26899
27498
  const { getCleoCantWorkflowsDir } = await import("@cleocode/core/internal");
26900
- const { readFileSync: readFileSync21, readdirSync: readdirSync3, existsSync: existsSync19 } = await import("node:fs");
26901
- const { join: join37 } = await import("node:path");
27499
+ const { readFileSync: readFileSync21, readdirSync: readdirSync3, existsSync: existsSync20 } = await import("node:fs");
27500
+ const { join: join38 } = await import("node:path");
26902
27501
  const workflowsDir = getCleoCantWorkflowsDir();
26903
27502
  const combined = `${request} ${context ?? ""}`.toLowerCase();
26904
27503
  const matches = [];
26905
- if (existsSync19(workflowsDir)) {
27504
+ if (existsSync20(workflowsDir)) {
26906
27505
  const files = readdirSync3(workflowsDir).filter((f) => f.endsWith(".cant"));
26907
27506
  for (const file of files) {
26908
27507
  try {
26909
- const src = readFileSync21(join37(workflowsDir, file), "utf-8");
27508
+ const src = readFileSync21(join38(workflowsDir, file), "utf-8");
26910
27509
  const teamMatch = /^team\s+(\S+):/m.exec(src);
26911
27510
  if (!teamMatch) continue;
26912
27511
  const teamName = teamMatch[1];
@@ -26921,12 +27520,12 @@ async function orchestrateClassify(request, context, projectRoot) {
26921
27520
  }
26922
27521
  }
26923
27522
  }
26924
- const localCantDir = join37(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
26925
- if (existsSync19(localCantDir)) {
27523
+ const localCantDir = join38(projectRoot, CLEO_DIR_NAME, WORKFLOWS_SUBDIR);
27524
+ if (existsSync20(localCantDir)) {
26926
27525
  const files = readdirSync3(localCantDir).filter((f) => f.endsWith(".cant"));
26927
27526
  for (const file of files) {
26928
27527
  try {
26929
- const src = readFileSync21(join37(localCantDir, file), "utf-8");
27528
+ const src = readFileSync21(join38(localCantDir, file), "utf-8");
26930
27529
  const teamMatch = /^team\s+(\S+):/m.exec(src);
26931
27530
  if (!teamMatch) continue;
26932
27531
  const teamName = teamMatch[1];
@@ -27118,11 +27717,11 @@ async function orchestrateAnalyzeParallelSafety(taskIds, projectRoot) {
27118
27717
  };
27119
27718
  }
27120
27719
  }
27121
- async function handleWorktreeComplete(taskId, projectRoot, resolve8) {
27720
+ async function handleWorktreeComplete(taskId, projectRoot, resolve9) {
27122
27721
  try {
27123
27722
  const { completeWorktreeForTask } = await import("@cleocode/core/internal");
27124
27723
  const result = completeWorktreeForTask(taskId, projectRoot, {
27125
- resolve: resolve8 ?? "auto"
27724
+ resolve: resolve9 ?? "auto"
27126
27725
  });
27127
27726
  if (result.outcome === "conflict") {
27128
27727
  return {
@@ -27654,12 +28253,15 @@ var init_orchestrate2 = __esm({
27654
28253
  );
27655
28254
  const tierRaw = params.tier;
27656
28255
  const tier = tierRaw === 0 || tierRaw === 1 || tierRaw === 2 ? tierRaw : void 0;
28256
+ const atomicityScopeRaw = params.atomicityScope;
28257
+ const atomicityScope = atomicityScopeRaw === "orchestrator-defer" ? "orchestrator-defer" : void 0;
27657
28258
  const p = {
27658
28259
  taskId: params.taskId,
27659
28260
  protocolType: params.protocolType,
27660
28261
  tier,
27661
28262
  noWorktree: params.noWorktree,
27662
- spawnScope: params.spawnScope
28263
+ spawnScope: params.spawnScope,
28264
+ ...atomicityScope ? { atomicityScope } : {}
27663
28265
  };
27664
28266
  return wrapResult(await coreOps2.spawn(p), "mutate", "orchestrate", operation, startTime);
27665
28267
  }
@@ -27799,10 +28401,10 @@ var init_orchestrate2 = __esm({
27799
28401
  startTime
27800
28402
  );
27801
28403
  const rawResolve = params.resolve;
27802
- const resolve8 = rawResolve === "manual" ? "manual" : rawResolve === "auto" ? "auto" : void 0;
28404
+ const resolve9 = rawResolve === "manual" ? "manual" : rawResolve === "auto" ? "auto" : void 0;
27803
28405
  const p = {
27804
28406
  taskId: params.taskId,
27805
- ...resolve8 !== void 0 ? { resolve: resolve8 } : {}
28407
+ ...resolve9 !== void 0 ? { resolve: resolve9 } : {}
27806
28408
  };
27807
28409
  return wrapResult(
27808
28410
  await coreOps2["worktree.complete"](p),
@@ -28943,6 +29545,65 @@ var init_release2 = __esm({
28943
29545
  startTime
28944
29546
  );
28945
29547
  }
29548
+ // release.validate-changelog — canonical CHANGELOG.md header validator
29549
+ // (T9937 / Saga T9862). Replaces the brittle `grep -qF "## [VERSION]"`
29550
+ // step in .github/workflows/release.yml. Read-only.
29551
+ //
29552
+ // The core verb returns a plain `ValidateChangelogResult` envelope
29553
+ // (NOT an EngineResult discriminated union) so direct SDK consumers
29554
+ // can branch on `result.valid`. At the dispatch boundary we translate
29555
+ // `valid=false` into `E_CHANGELOG_MISSING_SECTION` so the CLI emits a
29556
+ // non-zero exit code — exactly the behaviour CI workflows depend on
29557
+ // (the legacy `grep -qF "## [VERSION]" || exit 1` had the same
29558
+ // contract).
29559
+ case "validate-changelog": {
29560
+ const version = typeof params?.version === "string" ? params.version : void 0;
29561
+ if (!version)
29562
+ return errorResult(
29563
+ "query",
29564
+ "release",
29565
+ operation,
29566
+ "E_INVALID_INPUT",
29567
+ "version is required",
29568
+ startTime
29569
+ );
29570
+ const typed = {
29571
+ version,
29572
+ projectRoot: getProjectRoot14(),
29573
+ ...typeof params?.changelogPath === "string" ? { changelogPath: params.changelogPath } : {}
29574
+ };
29575
+ const validation = await validateChangelog(typed);
29576
+ if (validation.valid) {
29577
+ return wrapResult(
29578
+ { success: true, data: validation },
29579
+ "query",
29580
+ "release",
29581
+ operation,
29582
+ startTime
29583
+ );
29584
+ }
29585
+ return wrapResult(
29586
+ {
29587
+ success: false,
29588
+ error: {
29589
+ code: "E_CHANGELOG_MISSING_SECTION",
29590
+ message: validation.reason ?? `CHANGELOG.md missing canonical header for v${validation.normalizedVersion}`,
29591
+ details: {
29592
+ version: validation.version,
29593
+ normalizedVersion: validation.normalizedVersion,
29594
+ changelogPath: validation.changelogPath,
29595
+ headerFound: validation.headerFound
29596
+ },
29597
+ fix: `Run \`cleo release plan v${validation.normalizedVersion}\` locally to write the section, then re-push.`,
29598
+ exitCode: 1
29599
+ }
29600
+ },
29601
+ "query",
29602
+ "release",
29603
+ operation,
29604
+ startTime
29605
+ );
29606
+ }
28946
29607
  default:
28947
29608
  return unsupportedOp("query", "release", operation, startTime);
28948
29609
  }
@@ -29110,7 +29771,7 @@ var init_release2 = __esm({
29110
29771
  /** Return declared operations for introspection and registry validation. */
29111
29772
  getSupportedOperations() {
29112
29773
  return {
29113
- query: ["gate", "ivtr-suggest"],
29774
+ query: ["gate", "ivtr-suggest", "validate-changelog"],
29114
29775
  mutate: ["gate", "ivtr-suggest", "reconcile", "plan", "open"]
29115
29776
  };
29116
29777
  }
@@ -30092,7 +30753,7 @@ var init_sticky2 = __esm({
30092
30753
  });
30093
30754
 
30094
30755
  // packages/cleo/src/dispatch/domains/tasks.ts
30095
- import { getLogger as getLogger15, getProjectRoot as getProjectRoot18 } from "@cleocode/core";
30756
+ import { getLogger as getLogger15, getProjectRoot as getProjectRoot18, TASKS_SUGGESTED_NEXT_BUILDERS } from "@cleocode/core";
30096
30757
  import { createAttachmentStore as createAttachmentStore4 } from "@cleocode/core/internal";
30097
30758
  import {
30098
30759
  sagaAdd as coreSagaAdd,
@@ -30170,6 +30831,25 @@ async function sagaReconcile(params) {
30170
30831
  "saga.reconcile"
30171
30832
  );
30172
30833
  }
30834
+ function stampSuggestedNext(response, operation, params) {
30835
+ if (!response.success) return response;
30836
+ const builder = TASKS_SUGGESTED_NEXT_BUILDERS[operation];
30837
+ if (!builder) return response;
30838
+ let suggestions;
30839
+ try {
30840
+ suggestions = builder(params, response.data);
30841
+ } catch {
30842
+ return response;
30843
+ }
30844
+ if (suggestions.length === 0) return response;
30845
+ return {
30846
+ ...response,
30847
+ meta: {
30848
+ ...response.meta,
30849
+ suggestedNext: suggestions
30850
+ }
30851
+ };
30852
+ }
30173
30853
  var _tasksTypedHandler, QUERY_OPS11, MUTATE_OPS10, TasksHandler;
30174
30854
  var init_tasks2 = __esm({
30175
30855
  "packages/cleo/src/dispatch/domains/tasks.ts"() {
@@ -30241,7 +30921,15 @@ var init_tasks2 = __esm({
30241
30921
  fields: params.fields,
30242
30922
  verbose: params.verbose,
30243
30923
  // T944/T9072: kind filter
30244
- kind: params.kind
30924
+ kind: params.kind,
30925
+ // T9905: unified urgency surface
30926
+ urgent: params.urgent,
30927
+ // T9904: label filter — `cleo find --label <name>` (closes GH#393).
30928
+ label: params.label,
30929
+ // T10108: parent filter — `cleo find --parent <id>`. Saga-aware via
30930
+ // resolveSagaMemberIds (ADR-073 §1) so saga members surface through
30931
+ // the same routing as `cleo list --parent`.
30932
+ parent: params.parent
30245
30933
  }),
30246
30934
  "find"
30247
30935
  );
@@ -30684,7 +31372,14 @@ var init_tasks2 = __esm({
30684
31372
  operation,
30685
31373
  params ?? {}
30686
31374
  );
30687
- return wrapResult(envelopeToEngineResult(envelope), "query", "tasks", operation, startTime);
31375
+ const response = wrapResult(
31376
+ envelopeToEngineResult(envelope),
31377
+ "query",
31378
+ "tasks",
31379
+ operation,
31380
+ startTime
31381
+ );
31382
+ return stampSuggestedNext(response, operation, params ?? {});
30688
31383
  } catch (error) {
30689
31384
  getLogger15("domain:tasks").error(
30690
31385
  { gateway: "query", domain: "tasks", operation, err: error },
@@ -30771,7 +31466,14 @@ var init_tasks2 = __esm({
30771
31466
  operation,
30772
31467
  params ?? {}
30773
31468
  );
30774
- return wrapResult(envelopeToEngineResult(envelope), "mutate", "tasks", operation, startTime);
31469
+ const response = wrapResult(
31470
+ envelopeToEngineResult(envelope),
31471
+ "mutate",
31472
+ "tasks",
31473
+ operation,
31474
+ startTime
31475
+ );
31476
+ return stampSuggestedNext(response, operation, params ?? {});
30775
31477
  } catch (error) {
30776
31478
  getLogger15("domain:tasks").error(
30777
31479
  { gateway: "mutate", domain: "tasks", operation, err: error },
@@ -32296,6 +32998,88 @@ var init_field_filter = __esm({
32296
32998
  }
32297
32999
  });
32298
33000
 
33001
+ // packages/cleo/src/cli/projection-context.ts
33002
+ function setProjectionOptOut(optOut) {
33003
+ currentOptOut = optOut;
33004
+ }
33005
+ function getProjectionOptOut() {
33006
+ return currentOptOut;
33007
+ }
33008
+ var currentOptOut;
33009
+ var init_projection_context = __esm({
33010
+ "packages/cleo/src/cli/projection-context.ts"() {
33011
+ "use strict";
33012
+ currentOptOut = false;
33013
+ }
33014
+ });
33015
+
33016
+ // packages/cleo/src/dispatch/middleware/mutate-minimal-envelope.ts
33017
+ import {
33018
+ applyMutateProjection,
33019
+ MUTATE_PROJECTION_PLANS,
33020
+ resolveProjectionMode
33021
+ } from "@cleocode/core";
33022
+ function resolveModeFor(req) {
33023
+ const override = req.params?.["_projection"];
33024
+ if (override === "full" || override === "mvi") return override;
33025
+ return resolveProjectionMode(getProjectionOptOut() || void 0);
33026
+ }
33027
+ function createMutateMinimalEnvelope() {
33028
+ return async (req, next) => {
33029
+ const mode = resolveModeFor(req);
33030
+ const opKey = `${req.domain}.${req.operation}`;
33031
+ const hasPlan = MUTATE_PROJECTION_PLANS[opKey] !== void 0;
33032
+ const response = await next();
33033
+ if (!hasPlan) return response;
33034
+ if (response.success && response.data !== void 0) {
33035
+ response.data = applyMutateProjection(response.data, opKey, mode);
33036
+ }
33037
+ response.meta.mutateProjection = mode;
33038
+ return response;
33039
+ };
33040
+ }
33041
+ var init_mutate_minimal_envelope = __esm({
33042
+ "packages/cleo/src/dispatch/middleware/mutate-minimal-envelope.ts"() {
33043
+ "use strict";
33044
+ init_projection_context();
33045
+ }
33046
+ });
33047
+
33048
+ // packages/cleo/src/dispatch/middleware/mvi-record-projection.ts
33049
+ import {
33050
+ applyProjectionPlan,
33051
+ PROJECTION_PLANS,
33052
+ resolveProjectionMode as resolveProjectionMode2
33053
+ } from "@cleocode/core";
33054
+ function resolveModeFor2(req) {
33055
+ const override = req.params?.["_projection"];
33056
+ if (override === "full" || override === "mvi") return override;
33057
+ return resolveProjectionMode2(getProjectionOptOut() || void 0);
33058
+ }
33059
+ function createMviRecordProjection() {
33060
+ return async (req, next) => {
33061
+ const mode = resolveModeFor2(req);
33062
+ if (req.params && "_projection" in req.params) {
33063
+ delete req.params["_projection"];
33064
+ }
33065
+ const opKey = `${req.domain}.${req.operation}`;
33066
+ const hasPlan = PROJECTION_PLANS[opKey] !== void 0;
33067
+ const response = await next();
33068
+ if (!hasPlan) return response;
33069
+ if (response.success && response.data !== void 0) {
33070
+ response.data = applyProjectionPlan(response.data, opKey, mode);
33071
+ }
33072
+ response.meta.projection = mode;
33073
+ return response;
33074
+ };
33075
+ }
33076
+ var init_mvi_record_projection = __esm({
33077
+ "packages/cleo/src/dispatch/middleware/mvi-record-projection.ts"() {
33078
+ "use strict";
33079
+ init_projection_context();
33080
+ }
33081
+ });
33082
+
32299
33083
  // packages/cleo/src/dispatch/lib/security.ts
32300
33084
  import {
32301
33085
  ALL_VALID_STATUSES,
@@ -32503,6 +33287,15 @@ function createCliDispatcher() {
32503
33287
  // T4959: session identity first
32504
33288
  createSanitizer(() => getProjectRoot22()),
32505
33289
  createFieldFilter(),
33290
+ // T9922 (Saga T9855 / E8.3): MVI record projection default for read ops.
33291
+ // Runs AFTER the domain handler returns so it can trim the data payload
33292
+ // before audit + telemetry record byte sizes. Sits before audit so the
33293
+ // audit trail captures the projected (final) bytes.
33294
+ createMviRecordProjection(),
33295
+ // T9931 (Saga T9855 / E9.4): minimal envelopes for mutate ops. Mirror
33296
+ // policy to the read-side projection — sits in the same pre-audit slot
33297
+ // so audit/telemetry record the trimmed bytes.
33298
+ createMutateMinimalEnvelope(),
32506
33299
  createAudit(),
32507
33300
  // T4959: CLI now gets audit trail
32508
33301
  createTelemetry()
@@ -32669,6 +33462,8 @@ var init_cli = __esm({
32669
33462
  init_domains();
32670
33463
  init_audit();
32671
33464
  init_field_filter();
33465
+ init_mutate_minimal_envelope();
33466
+ init_mvi_record_projection();
32672
33467
  init_sanitizer();
32673
33468
  init_session_resolver();
32674
33469
  init_telemetry();
@@ -32864,26 +33659,26 @@ function wrapParseError(rawInput, parseErr, sourceLabel) {
32864
33659
  const snippet2 = rawInput.length > PARSE_ERROR_SNIPPET_MAX_LENGTH ? `${rawInput.slice(0, PARSE_ERROR_SNIPPET_MAX_LENGTH)}\u2026` : rawInput;
32865
33660
  return new Error(`Invalid JSON in ${sourceLabel}: ${parseErr.message} (got: ${snippet2})`);
32866
33661
  }
32867
- function readStdinJson(stdin) {
32868
- return new Promise((resolve8, reject) => {
33662
+ function readStdinJson(stdin2) {
33663
+ return new Promise((resolve9, reject) => {
32869
33664
  const chunks = [];
32870
- stdin.on("data", (chunk) => {
33665
+ stdin2.on("data", (chunk) => {
32871
33666
  chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
32872
33667
  });
32873
- stdin.on("error", (err) => {
33668
+ stdin2.on("error", (err) => {
32874
33669
  reject(err);
32875
33670
  });
32876
- stdin.on("end", () => {
33671
+ stdin2.on("end", () => {
32877
33672
  const raw = Buffer.concat(chunks).toString("utf8");
32878
33673
  try {
32879
- resolve8(JSON.parse(raw));
33674
+ resolve9(JSON.parse(raw));
32880
33675
  } catch (err) {
32881
33676
  reject(wrapParseError(raw, err, "stdin"));
32882
33677
  }
32883
33678
  });
32884
33679
  });
32885
33680
  }
32886
- async function collectMutateInput(args, stdin) {
33681
+ async function collectMutateInput(args, stdin2) {
32887
33682
  if (typeof args.params === "string" && args.params.length > 0) {
32888
33683
  try {
32889
33684
  return JSON.parse(args.params);
@@ -32899,8 +33694,8 @@ async function collectMutateInput(args, stdin) {
32899
33694
  throw wrapParseError(raw, err, `--file ${args.file}`);
32900
33695
  }
32901
33696
  }
32902
- if (stdin.isTTY !== true) {
32903
- return readStdinJson(stdin);
33697
+ if (stdin2.isTTY !== true) {
33698
+ return readStdinJson(stdin2);
32904
33699
  }
32905
33700
  if (args.positional !== void 0 && args.positional.length > 0) {
32906
33701
  return args.positional;
@@ -34105,12 +34900,12 @@ var init_agent = __esm({
34105
34900
  transportConfig: {},
34106
34901
  isActive: true
34107
34902
  });
34108
- const { existsSync: existsSync19, mkdirSync: mkdirSync7, writeFileSync: writeFileSync7 } = await import("node:fs");
34109
- const { join: join37 } = await import("node:path");
34110
- const cantDir = join37(CLEO_DIR_NAME, AGENTS_SUBDIR);
34111
- const cantPath = join37(cantDir, `${agentId}.cant`);
34903
+ const { existsSync: existsSync20, mkdirSync: mkdirSync7, writeFileSync: writeFileSync7 } = await import("node:fs");
34904
+ const { join: join38 } = await import("node:path");
34905
+ const cantDir = join38(CLEO_DIR_NAME, AGENTS_SUBDIR);
34906
+ const cantPath = join38(cantDir, `${agentId}.cant`);
34112
34907
  let cantScaffolded = false;
34113
- if (!existsSync19(cantPath)) {
34908
+ if (!existsSync20(cantPath)) {
34114
34909
  mkdirSync7(cantDir, { recursive: true });
34115
34910
  const role = classification ?? "specialist";
34116
34911
  const cantContent = `---
@@ -34170,7 +34965,7 @@ agent ${agentId}:
34170
34965
  data: {
34171
34966
  agentId: credential.agentId,
34172
34967
  displayName: credential.displayName,
34173
- cantFile: cantScaffolded ? cantPath : existsSync19(cantPath) ? cantPath : null,
34968
+ cantFile: cantScaffolded ? cantPath : existsSync20(cantPath) ? cantPath : null,
34174
34969
  cantScaffolded
34175
34970
  }
34176
34971
  },
@@ -34289,8 +35084,8 @@ agent ${agentId}:
34289
35084
  try {
34290
35085
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
34291
35086
  const { createRuntime } = await import("@cleocode/runtime");
34292
- const { existsSync: existsSync19, readFileSync: readFileSync21 } = await import("node:fs");
34293
- const { join: join37 } = await import("node:path");
35087
+ const { existsSync: existsSync20, readFileSync: readFileSync21 } = await import("node:fs");
35088
+ const { join: join38 } = await import("node:path");
34294
35089
  await openCleoDb("tasks");
34295
35090
  const registry = new AgentRegistryAccessor(getProjectRoot24());
34296
35091
  const credential = await registry.get(args.agentId);
@@ -34310,8 +35105,8 @@ agent ${agentId}:
34310
35105
  }
34311
35106
  let profile = null;
34312
35107
  let cantValidation = null;
34313
- const cantPath = args.cant ?? join37(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
34314
- if (existsSync19(cantPath)) {
35108
+ const cantPath = args.cant ?? join38(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
35109
+ if (existsSync20(cantPath)) {
34315
35110
  profile = readFileSync21(cantPath, "utf-8");
34316
35111
  try {
34317
35112
  const cantModule = await import("@cleocode/cant");
@@ -34835,8 +35630,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34835
35630
  try {
34836
35631
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
34837
35632
  const { createRuntime } = await import("@cleocode/runtime");
34838
- const { existsSync: existsSync19 } = await import("node:fs");
34839
- const { join: join37 } = await import("node:path");
35633
+ const { existsSync: existsSync20 } = await import("node:fs");
35634
+ const { join: join38 } = await import("node:path");
34840
35635
  await openCleoDb("tasks");
34841
35636
  const registry = new AgentRegistryAccessor(getProjectRoot24());
34842
35637
  const credential = await registry.get(args.agentId);
@@ -34853,8 +35648,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
34853
35648
  }
34854
35649
  await registry.update(args.agentId, { isActive: true });
34855
35650
  await registry.markUsed(args.agentId);
34856
- const cantPath = join37(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
34857
- const hasProfile = existsSync19(cantPath);
35651
+ const cantPath = join38(CLEO_DIR_NAME, AGENTS_SUBDIR, `${args.agentId}.cant`);
35652
+ const hasProfile = existsSync20(cantPath);
34858
35653
  const runtime = await createRuntime(registry, {
34859
35654
  agentId: args.agentId,
34860
35655
  pollIntervalMs: 5e3,
@@ -35650,10 +36445,10 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35650
36445
  async run({ args }) {
35651
36446
  let tempDir = null;
35652
36447
  try {
35653
- const { existsSync: existsSync19 } = await import("node:fs");
35654
- const { basename, resolve: resolve8 } = await import("node:path");
35655
- const resolvedPath = resolve8(args.path);
35656
- if (!existsSync19(resolvedPath)) {
36448
+ const { existsSync: existsSync20 } = await import("node:fs");
36449
+ const { basename, resolve: resolve9 } = await import("node:path");
36450
+ const resolvedPath = resolve9(args.path);
36451
+ if (!existsSync20(resolvedPath)) {
35657
36452
  cliOutput(
35658
36453
  {
35659
36454
  success: false,
@@ -35778,11 +36573,11 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35778
36573
  },
35779
36574
  async run({ args }) {
35780
36575
  try {
35781
- const { existsSync: existsSync19, statSync } = await import("node:fs");
35782
- const { resolve: resolve8, basename, dirname: dirname12 } = await import("node:path");
35783
- const { execFileSync: execFileSync4 } = await import("node:child_process");
35784
- const resolvedDir = resolve8(args.dir);
35785
- if (!existsSync19(resolvedDir) || !statSync(resolvedDir).isDirectory()) {
36576
+ const { existsSync: existsSync20, statSync } = await import("node:fs");
36577
+ const { resolve: resolve9, basename, dirname: dirname12 } = await import("node:path");
36578
+ const { execFileSync: execFileSync5 } = await import("node:child_process");
36579
+ const resolvedDir = resolve9(args.dir);
36580
+ if (!existsSync20(resolvedDir) || !statSync(resolvedDir).isDirectory()) {
35786
36581
  cliOutput(
35787
36582
  {
35788
36583
  success: false,
@@ -35796,9 +36591,9 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35796
36591
  process.exitCode = 4;
35797
36592
  return;
35798
36593
  }
35799
- const { join: join37 } = await import("node:path");
35800
- const personaPath = join37(resolvedDir, "persona.cant");
35801
- if (!existsSync19(personaPath)) {
36594
+ const { join: join38 } = await import("node:path");
36595
+ const personaPath = join38(resolvedDir, "persona.cant");
36596
+ if (!existsSync20(personaPath)) {
35802
36597
  cliOutput(
35803
36598
  {
35804
36599
  success: false,
@@ -35814,10 +36609,10 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35814
36609
  }
35815
36610
  const agentName = basename(resolvedDir);
35816
36611
  const archiveName = `${agentName}.cantz`;
35817
- const archivePath = resolve8(archiveName);
36612
+ const archivePath = resolve9(archiveName);
35818
36613
  const parentDir = dirname12(resolvedDir);
35819
36614
  try {
35820
- execFileSync4("zip", ["-r", archivePath, agentName], {
36615
+ execFileSync5("zip", ["-r", archivePath, agentName], {
35821
36616
  cwd: parentDir,
35822
36617
  encoding: "utf-8",
35823
36618
  timeout: 3e4
@@ -35845,7 +36640,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
35845
36640
  if (entry.isFile()) {
35846
36641
  fileCount++;
35847
36642
  } else if (entry.isDirectory()) {
35848
- countFiles(join37(dirPath, entry.name));
36643
+ countFiles(join38(dirPath, entry.name));
35849
36644
  }
35850
36645
  }
35851
36646
  };
@@ -36093,17 +36888,17 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
36093
36888
  },
36094
36889
  async run({ args }) {
36095
36890
  try {
36096
- const { existsSync: existsSync19, readFileSync: readFileSync21, mkdirSync: mkdirSync7 } = await import("node:fs");
36097
- const { resolve: resolve8, join: join37 } = await import("node:path");
36098
- const specPath = resolve8(args.spec);
36099
- if (!existsSync19(specPath)) {
36891
+ const { existsSync: existsSync20, readFileSync: readFileSync21, mkdirSync: mkdirSync7 } = await import("node:fs");
36892
+ const { resolve: resolve9, join: join38 } = await import("node:path");
36893
+ const specPath = resolve9(args.spec);
36894
+ if (!existsSync20(specPath)) {
36100
36895
  cliError(`spec file not found: ${specPath}`, 4, { name: "E_NOT_FOUND" });
36101
36896
  process.exitCode = 4;
36102
36897
  return;
36103
36898
  }
36104
36899
  const specContent = readFileSync21(specPath, "utf-8");
36105
36900
  const projectRoot = getProjectRoot24();
36106
- const outputDir = args["output-dir"] ? resolve8(args["output-dir"]) : join37(projectRoot, ".cleo", "cant", "agents");
36901
+ const outputDir = args["output-dir"] ? resolve9(args["output-dir"]) : join38(projectRoot, ".cleo", "cant", "agents");
36107
36902
  mkdirSync7(outputDir, { recursive: true });
36108
36903
  if (args["dry-run"]) {
36109
36904
  cliOutput(
@@ -36854,8 +37649,8 @@ function detectAuthType(provider, token) {
36854
37649
  async function promptYesNo(question) {
36855
37650
  const rl = createInterface({ input: process.stdin, output: process.stderr });
36856
37651
  try {
36857
- const answer = await new Promise((resolve8) => {
36858
- rl.question(question, (a) => resolve8(a));
37652
+ const answer = await new Promise((resolve9) => {
37653
+ rl.question(question, (a) => resolve9(a));
36859
37654
  });
36860
37655
  const clean = answer.trim().toLowerCase();
36861
37656
  return clean === "y" || clean === "yes";
@@ -37791,12 +38586,12 @@ async function promptPassphrase() {
37791
38586
  "Cannot prompt for passphrase: stdin is not a TTY. Set the CLEO_BACKUP_PASSPHRASE environment variable for non-interactive use."
37792
38587
  );
37793
38588
  }
37794
- return new Promise((resolve8) => {
38589
+ return new Promise((resolve9) => {
37795
38590
  process.stdout.write("Passphrase: ");
37796
38591
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
37797
38592
  rl.question("", (answer) => {
37798
38593
  rl.close();
37799
- resolve8(answer.trim());
38594
+ resolve9(answer.trim());
37800
38595
  });
37801
38596
  });
37802
38597
  }
@@ -38906,11 +39701,11 @@ var init_caamp = __esm({
38906
39701
  }
38907
39702
  if (args["dry-run"]) {
38908
39703
  const { parseCaampBlocks } = await import("@cleocode/caamp");
38909
- const { existsSync: existsSync19 } = await import("node:fs");
39704
+ const { existsSync: existsSync20 } = await import("node:fs");
38910
39705
  const { readFile: readFile8 } = await import("node:fs/promises");
38911
39706
  const dryResults = [];
38912
39707
  for (const filePath of filePaths) {
38913
- if (!existsSync19(filePath)) {
39708
+ if (!existsSync20(filePath)) {
38914
39709
  dryResults.push({ filePath, exists: false, blockCount: 0, wouldRemove: 0 });
38915
39710
  continue;
38916
39711
  }
@@ -39480,7 +40275,7 @@ var init_changeset = __esm({
39480
40275
  });
39481
40276
  if (!outcome.ok) {
39482
40277
  const err = outcome.error;
39483
- const hint = err.code === "E_SLUG_PATTERN_MISMATCH" && err.example ? `example slug: ${err.example}` : void 0;
40278
+ 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;
39484
40279
  cliError(err.message, 6 /* VALIDATION_ERROR */, {
39485
40280
  name: err.code,
39486
40281
  ...hint ? { fix: hint } : {}
@@ -39965,11 +40760,11 @@ var init_check2 = __esm({
39965
40760
  },
39966
40761
  async run({ args }) {
39967
40762
  const { spawnSync } = await import("node:child_process");
39968
- const { existsSync: existsSync19 } = await import("node:fs");
39969
- const { join: join37, resolve: resolve8 } = await import("node:path");
40763
+ const { existsSync: existsSync20 } = await import("node:fs");
40764
+ const { join: join38, resolve: resolve9 } = await import("node:path");
39970
40765
  const strict = Boolean(args.strict);
39971
40766
  const jsonOnly = Boolean(args.json);
39972
- const repoRoot = resolve8(process.cwd());
40767
+ const repoRoot = resolve9(process.cwd());
39973
40768
  const gates = [
39974
40769
  {
39975
40770
  id: "gate-1",
@@ -40006,8 +40801,8 @@ var init_check2 = __esm({
40006
40801
  const results = [];
40007
40802
  let anyFailed = false;
40008
40803
  for (const gate of gates) {
40009
- const scriptPath = join37(repoRoot, gate.script);
40010
- if (!existsSync19(scriptPath)) {
40804
+ const scriptPath = join38(repoRoot, gate.script);
40805
+ if (!existsSync20(scriptPath)) {
40011
40806
  results.push({
40012
40807
  id: gate.id,
40013
40808
  task: gate.task,
@@ -40322,9 +41117,9 @@ var init_code = __esm({
40322
41117
  async run({ args }) {
40323
41118
  await requireTreeSitter();
40324
41119
  const { smartOutline } = await import("@cleocode/core/internal");
40325
- const { join: join37 } = await import("node:path");
41120
+ const { join: join38 } = await import("node:path");
40326
41121
  const root = process.cwd();
40327
- const absPath = args.file.startsWith("/") ? args.file : join37(root, args.file);
41122
+ const absPath = args.file.startsWith("/") ? args.file : join38(root, args.file);
40328
41123
  const result = smartOutline(absPath, root);
40329
41124
  if (result.errors.length > 0 && result.symbols.length === 0) {
40330
41125
  cliError(result.errors.join(", "), 1, { name: "E_OUTLINE_FAILED" });
@@ -40415,9 +41210,9 @@ var init_code = __esm({
40415
41210
  async run({ args }) {
40416
41211
  await requireTreeSitter();
40417
41212
  const { smartUnfold } = await import("@cleocode/core/internal");
40418
- const { join: join37 } = await import("node:path");
41213
+ const { join: join38 } = await import("node:path");
40419
41214
  const root = process.cwd();
40420
- const absPath = args.file.startsWith("/") ? args.file : join37(root, args.file);
41215
+ const absPath = args.file.startsWith("/") ? args.file : join38(root, args.file);
40421
41216
  const result = smartUnfold(absPath, args.symbol, root);
40422
41217
  if (!result.found) {
40423
41218
  const errs = result.errors.length > 0 ? `: ${result.errors.join(", ")}` : "";
@@ -43786,6 +44581,94 @@ var init_strict_args = __esm({
43786
44581
  }
43787
44582
  });
43788
44583
 
44584
+ // packages/cleo/src/cli/commands/docs/graph.ts
44585
+ import {
44586
+ buildDocProvenanceGraph,
44587
+ DocProvenanceRootNotFoundError,
44588
+ renderProvenanceGraphAsDot
44589
+ } from "@cleocode/core/internal";
44590
+ function parseDepth(raw) {
44591
+ if (raw === void 0 || raw === null || raw === "") return 2;
44592
+ const parsed = Number.parseInt(String(raw), 10);
44593
+ if (!Number.isInteger(parsed) || parsed < 0) {
44594
+ cliError(
44595
+ `--depth must be a non-negative integer (got '${String(raw)}')`,
44596
+ 6 /* VALIDATION_ERROR */,
44597
+ { name: "E_VALIDATION" }
44598
+ );
44599
+ process.exit(6 /* VALIDATION_ERROR */);
44600
+ }
44601
+ return parsed;
44602
+ }
44603
+ function parseFormat(raw) {
44604
+ if (raw === void 0 || raw === null || raw === "") return "json";
44605
+ const candidate = String(raw);
44606
+ if (candidate !== "json" && candidate !== "dot") {
44607
+ cliError(`--format must be one of: json|dot \u2014 got '${candidate}'`, 6 /* VALIDATION_ERROR */, {
44608
+ name: "E_VALIDATION"
44609
+ });
44610
+ process.exit(6 /* VALIDATION_ERROR */);
44611
+ }
44612
+ return candidate;
44613
+ }
44614
+ var graphCommand;
44615
+ var init_graph2 = __esm({
44616
+ "packages/cleo/src/cli/commands/docs/graph.ts"() {
44617
+ "use strict";
44618
+ init_src2();
44619
+ init_define_cli_command();
44620
+ init_renderers();
44621
+ graphCommand = defineCommand({
44622
+ meta: {
44623
+ name: "graph",
44624
+ 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)."
44625
+ },
44626
+ args: {
44627
+ root: {
44628
+ type: "string",
44629
+ description: "Root identifier \u2014 a canonical doc slug (e.g. adr-078-docs-provenance) or a CLEO task ID (T####). Required.",
44630
+ required: true
44631
+ },
44632
+ depth: {
44633
+ type: "string",
44634
+ description: "Maximum BFS hops from the root (default: 2; minimum: 0)."
44635
+ },
44636
+ format: {
44637
+ type: "string",
44638
+ description: "Output format: json (default) | dot."
44639
+ }
44640
+ },
44641
+ async run({ args }) {
44642
+ const root = String(args.root);
44643
+ const depth = parseDepth(args.depth);
44644
+ const format = parseFormat(args.format);
44645
+ try {
44646
+ const graph = await buildDocProvenanceGraph({ root, depth });
44647
+ const payload = { ...graph };
44648
+ if (format === "dot") {
44649
+ payload["dot"] = renderProvenanceGraphAsDot(graph);
44650
+ }
44651
+ cliOutput(payload, { command: "docs graph", operation: "docs.graph" });
44652
+ } catch (err) {
44653
+ if (err instanceof DocProvenanceRootNotFoundError) {
44654
+ cliError(err.message, 4 /* NOT_FOUND */, {
44655
+ name: "E_DOC_PROVENANCE_ROOT_NOT_FOUND",
44656
+ 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.",
44657
+ details: { root }
44658
+ });
44659
+ process.exit(4 /* NOT_FOUND */);
44660
+ }
44661
+ const message = err instanceof Error ? err.message : String(err);
44662
+ cliError(`docs graph failed: ${message}`, 1 /* GENERAL_ERROR */, {
44663
+ name: "E_DOCS_GRAPH_FAILED"
44664
+ });
44665
+ process.exit(1 /* GENERAL_ERROR */);
44666
+ }
44667
+ }
44668
+ });
44669
+ }
44670
+ });
44671
+
43789
44672
  // packages/cleo/src/viewer/pidfile.ts
43790
44673
  import { mkdir, readFile as readFile3, unlink, writeFile } from "node:fs/promises";
43791
44674
  import { dirname as dirname6, join as join18 } from "node:path";
@@ -44614,7 +45497,6 @@ __export(docs_exports, {
44614
45497
  import { appendFile, mkdir as mkdir2, readdir, readFile as readFile4, writeFile as writeFile2 } from "node:fs/promises";
44615
45498
  import { dirname as dirname8, isAbsolute as isAbsolute2, join as join21, resolve as resolve5 } from "node:path";
44616
45499
  import {
44617
- buildDocsGraph,
44618
45500
  CleoError as CleoError3,
44619
45501
  CounterMismatchError,
44620
45502
  checkSlugSimilarity,
@@ -44623,6 +45505,7 @@ import {
44623
45505
  DEFAULT_SIMILARITY_THRESHOLD,
44624
45506
  detectStrayCleoDb as detectStrayCleoDb2,
44625
45507
  exportDocument,
45508
+ findSimilarDocs,
44626
45509
  getAgentOutputsAbsolute,
44627
45510
  getProjectRoot as getProjectRoot38,
44628
45511
  listDocVersions,
@@ -44728,7 +45611,7 @@ function loadCliRegistry(projectRoot) {
44728
45611
  throw err;
44729
45612
  }
44730
45613
  }
44731
- var addCommand5, listCommand8, fetchCommand, removeCommand2, generateCommand, exportCommand4, searchCommand, mergeCommand, graphCommand, rankCommand, versionsCommand, publishCommand2, publishPrCommand, syncCommand3, statusCommand7, gapCheckCommand, importCommand2, schemaCommand, listTypesCommand, docsCommand;
45614
+ var addCommand5, listCommand8, fetchCommand, removeCommand2, supersedeCommandArgs, supersedeCommand, generateCommand, exportCommand4, searchCommand, findCommand3, mergeCommand, rankCommand, updateCommand, versionsCommand, publishCommand2, publishPrCommand, syncCommand3, statusCommand7, gapCheckCommand, importCommand2, schemaCommand, listTypesCommand, docsCommand;
44732
45615
  var init_docs3 = __esm({
44733
45616
  "packages/cleo/src/cli/commands/docs.ts"() {
44734
45617
  "use strict";
@@ -44738,11 +45621,12 @@ var init_docs3 = __esm({
44738
45621
  init_canon_docs();
44739
45622
  init_strict_args();
44740
45623
  init_renderers();
45624
+ init_graph2();
44741
45625
  init_docs_viewer();
44742
45626
  addCommand5 = defineCommand({
44743
45627
  meta: {
44744
45628
  name: "add",
44745
- 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 --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 TODO(T10360): --type adr will auto-allocate adr-NNN-<title> from a --title flag.'
45629
+ 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.'
44746
45630
  },
44747
45631
  args: {
44748
45632
  "owner-id": {
@@ -44775,6 +45659,10 @@ var init_docs3 = __esm({
44775
45659
  type: "string",
44776
45660
  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)."
44777
45661
  },
45662
+ title: {
45663
+ type: "string",
45664
+ 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)."
45665
+ },
44778
45666
  type: {
44779
45667
  type: "string",
44780
45668
  description: "Taxonomy classification \u2014 run `cleo docs list-types` to enumerate registered kinds (T9637 / T9788)"
@@ -44814,6 +45702,17 @@ var init_docs3 = __esm({
44814
45702
  });
44815
45703
  process.exit(6);
44816
45704
  }
45705
+ if (args.type === "adr" && !args.slug && !args.title) {
45706
+ cliError(
45707
+ "--title <text> is required when --type adr is used without --slug \u2014 the allocator needs a title to assemble adr-NNN-<kebab-title>",
45708
+ 6,
45709
+ {
45710
+ name: "E_VALIDATION",
45711
+ fix: 'Re-run with --title "Adopt Drizzle v1 beta" (or pass --slug adr-042-explicit-name to bypass auto-allocation).'
45712
+ }
45713
+ );
45714
+ process.exit(6);
45715
+ }
44817
45716
  let resolvedFile;
44818
45717
  if (fileArg) {
44819
45718
  const routing = resolveWorktreeRouting2();
@@ -44926,6 +45825,7 @@ var init_docs3 = __esm({
44926
45825
  ...args.labels ? { labels: args.labels } : {},
44927
45826
  ...args["attached-by"] ? { attachedBy: args["attached-by"] } : {},
44928
45827
  ...args.slug ? { slug: args.slug } : {},
45828
+ ...args.title ? { title: args.title } : {},
44929
45829
  ...args.type ? { type: args.type } : {},
44930
45830
  ...args.strict === true ? { strict: true } : {}
44931
45831
  },
@@ -44966,6 +45866,15 @@ var init_docs3 = __esm({
44966
45866
  orderBy: {
44967
45867
  type: "string",
44968
45868
  description: "Sort key: newest (default \u2014 most recent first), sha (ascending hex), slug (alphabetical, slug-less rows last) (T9792)."
45869
+ },
45870
+ // T9922 — MVI record projection opt-out flags (surfaced for --help).
45871
+ verbose: {
45872
+ type: "boolean",
45873
+ description: "Return full attachment records instead of the MVI projection (id + slug + type + kind + sha + size + createdAt). T9922."
45874
+ },
45875
+ full: {
45876
+ type: "boolean",
45877
+ description: "Alias for --verbose. T9922."
44969
45878
  }
44970
45879
  },
44971
45880
  async run({ args }) {
@@ -45032,6 +45941,15 @@ var init_docs3 = __esm({
45032
45941
  type: "positional",
45033
45942
  description: "Attachment ID (att_*) or SHA-256 hex",
45034
45943
  required: true
45944
+ },
45945
+ // T9922 — MVI record projection opt-out flags (surfaced for --help).
45946
+ verbose: {
45947
+ type: "boolean",
45948
+ description: "Return the full attachment metadata block instead of the MVI projection. The byte payload is always returned. T9922."
45949
+ },
45950
+ full: {
45951
+ type: "boolean",
45952
+ description: "Alias for --verbose. T9922."
45035
45953
  }
45036
45954
  },
45037
45955
  async run({ args }) {
@@ -45075,6 +45993,54 @@ var init_docs3 = __esm({
45075
45993
  );
45076
45994
  }
45077
45995
  });
45996
+ supersedeCommandArgs = {
45997
+ oldSlug: {
45998
+ type: "positional",
45999
+ description: "Slug of the doc being replaced",
46000
+ required: true
46001
+ },
46002
+ newSlug: {
46003
+ type: "positional",
46004
+ description: "Slug of the doc that replaces oldSlug",
46005
+ required: true
46006
+ },
46007
+ reason: {
46008
+ type: "string",
46009
+ description: "Optional human-readable reason carried back on the response envelope"
46010
+ }
46011
+ };
46012
+ supersedeCommand = defineCommand({
46013
+ meta: {
46014
+ name: "supersede",
46015
+ 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."
46016
+ },
46017
+ args: supersedeCommandArgs,
46018
+ async run({ args, rawArgs }) {
46019
+ try {
46020
+ assertKnownFlags(rawArgs, supersedeCommandArgs, "docs supersede");
46021
+ } catch (err) {
46022
+ if (err instanceof UnknownFlagError) {
46023
+ cliError(err.message, 6 /* VALIDATION_ERROR */, { name: "E_VALIDATION" });
46024
+ process.exit(6 /* VALIDATION_ERROR */);
46025
+ }
46026
+ throw err;
46027
+ }
46028
+ const oldSlug = args.oldSlug;
46029
+ const newSlug = args.newSlug;
46030
+ const reason = typeof args.reason === "string" && args.reason.length > 0 ? args.reason : void 0;
46031
+ await dispatchFromCli(
46032
+ "mutate",
46033
+ "docs",
46034
+ "supersede",
46035
+ {
46036
+ oldSlug,
46037
+ newSlug,
46038
+ ...reason !== void 0 ? { reason } : {}
46039
+ },
46040
+ { command: "docs supersede" }
46041
+ );
46042
+ }
46043
+ });
45078
46044
  generateCommand = defineCommand({
45079
46045
  meta: {
45080
46046
  name: "generate",
@@ -45226,6 +46192,102 @@ var init_docs3 = __esm({
45226
46192
  }
45227
46193
  }
45228
46194
  });
46195
+ findCommand3 = defineCommand({
46196
+ meta: {
46197
+ name: "find",
46198
+ 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)"
46199
+ },
46200
+ args: {
46201
+ similar: {
46202
+ type: "string",
46203
+ description: "Slug of the seed doc to anchor similarity against"
46204
+ },
46205
+ limit: {
46206
+ type: "string",
46207
+ description: "Maximum number of hits to return (default: 10)"
46208
+ },
46209
+ threshold: {
46210
+ type: "string",
46211
+ description: "Minimum cosine similarity score in [0, 1] (default: 0.5)"
46212
+ },
46213
+ "all-kinds": {
46214
+ type: "boolean",
46215
+ description: "Disable the same-kind filter and rank across every DocKind"
46216
+ },
46217
+ json: {
46218
+ type: "boolean",
46219
+ description: "Emit LAFS JSON envelope instead of human-readable output"
46220
+ }
46221
+ },
46222
+ async run({ args, rawArgs }) {
46223
+ try {
46224
+ assertKnownFlags(rawArgs, findCommand3.args, "docs find");
46225
+ } catch (err) {
46226
+ if (err instanceof UnknownFlagError) {
46227
+ cliError(err.message, 6 /* VALIDATION_ERROR */, {
46228
+ name: err.code,
46229
+ fix: err.fix,
46230
+ alternatives: err.suggestions.map((s) => ({ action: s, command: s })),
46231
+ details: { flag: err.flag, knownFlags: err.knownFlags }
46232
+ });
46233
+ process.exit(6 /* VALIDATION_ERROR */);
46234
+ }
46235
+ throw err;
46236
+ }
46237
+ const similarSlug = typeof args.similar === "string" ? args.similar.trim() : "";
46238
+ if (similarSlug.length === 0) {
46239
+ cliError("--similar <slug> is required", 6 /* VALIDATION_ERROR */, {
46240
+ name: "E_VALIDATION",
46241
+ fix: "Example: `cleo docs find --similar adr-073-above-epic-naming --limit 5`."
46242
+ });
46243
+ process.exit(6 /* VALIDATION_ERROR */);
46244
+ }
46245
+ let limit;
46246
+ if (typeof args.limit === "string") {
46247
+ const parsed = Number.parseInt(args.limit, 10);
46248
+ if (!Number.isFinite(parsed) || parsed <= 0) {
46249
+ cliError(
46250
+ `--limit must be a positive integer (got "${args.limit}")`,
46251
+ 6 /* VALIDATION_ERROR */,
46252
+ {
46253
+ name: "E_VALIDATION"
46254
+ }
46255
+ );
46256
+ process.exit(6 /* VALIDATION_ERROR */);
46257
+ }
46258
+ limit = parsed;
46259
+ }
46260
+ let threshold;
46261
+ if (typeof args.threshold === "string") {
46262
+ const parsed = Number.parseFloat(args.threshold);
46263
+ if (!Number.isFinite(parsed) || parsed < 0 || parsed > 1) {
46264
+ cliError(
46265
+ `--threshold must be a number in [0, 1] (got "${args.threshold}")`,
46266
+ 6 /* VALIDATION_ERROR */,
46267
+ { name: "E_VALIDATION" }
46268
+ );
46269
+ process.exit(6 /* VALIDATION_ERROR */);
46270
+ }
46271
+ threshold = parsed;
46272
+ }
46273
+ const allKinds = args["all-kinds"] === true;
46274
+ const projectRoot = getProjectRoot38();
46275
+ try {
46276
+ const result = await findSimilarDocs(similarSlug, {
46277
+ ...limit !== void 0 ? { limit } : {},
46278
+ ...threshold !== void 0 ? { threshold } : {},
46279
+ allKinds,
46280
+ projectRoot
46281
+ });
46282
+ cliOutput(result, { command: "docs find", operation: "docs.find" });
46283
+ } catch (err) {
46284
+ const code = err instanceof Error && typeof err.code === "string" ? err.code : "E_DOCS_FIND_FAILED";
46285
+ const message = err instanceof Error ? err.message : String(err);
46286
+ cliError(`docs find failed: ${message}`, 1 /* GENERAL_ERROR */, { name: code });
46287
+ process.exit(1 /* GENERAL_ERROR */);
46288
+ }
46289
+ }
46290
+ });
45229
46291
  mergeCommand = defineCommand({
45230
46292
  meta: {
45231
46293
  name: "merge",
@@ -45284,10 +46346,10 @@ var init_docs3 = __esm({
45284
46346
  }
45285
46347
  }
45286
46348
  });
45287
- graphCommand = defineCommand({
46349
+ rankCommand = defineCommand({
45288
46350
  meta: {
45289
- name: "graph",
45290
- description: "Build a document relationship graph for an entity using llmtxt/graph.buildGraph. Output formats: mermaid (default), dot, json."
46351
+ name: "rank",
46352
+ 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."
45291
46353
  },
45292
46354
  args: {
45293
46355
  for: {
@@ -45295,13 +46357,9 @@ var init_docs3 = __esm({
45295
46357
  description: "Owner entity ID (T###, ses_*, O-*)",
45296
46358
  required: true
45297
46359
  },
45298
- format: {
45299
- type: "string",
45300
- description: "Output format: mermaid | dot | json (default: mermaid)"
45301
- },
45302
- out: {
46360
+ query: {
45303
46361
  type: "string",
45304
- description: "Write graph to this file path"
46362
+ description: "Optional free-text query to rank against (default: owner ID)"
45305
46363
  },
45306
46364
  json: {
45307
46365
  type: "boolean",
@@ -45310,89 +46368,105 @@ var init_docs3 = __esm({
45310
46368
  },
45311
46369
  async run({ args }) {
45312
46370
  const projectRoot = getProjectRoot38();
45313
- const fmt = args.format ?? "mermaid";
45314
46371
  try {
45315
- const result = await buildDocsGraph({ ownerId: String(args.for), projectRoot });
45316
- let output2;
45317
- if (fmt === "dot") {
45318
- const dotLines = ["digraph docs {"];
45319
- for (const node of result.nodes) {
45320
- dotLines.push(` "${node.id}" [label="${node.label}"];`);
45321
- }
45322
- for (const edge of result.edges) {
45323
- dotLines.push(` "${edge.source}" -> "${edge.target}" [label="${edge.relation}"];`);
45324
- }
45325
- dotLines.push("}");
45326
- output2 = dotLines.join("\n");
45327
- } else if (fmt === "json") {
45328
- output2 = JSON.stringify(result, null, 2);
45329
- } else {
45330
- const lines = ["graph LR"];
45331
- for (const edge of result.edges) {
45332
- lines.push(` ${edge.source} -->|${edge.relation}| ${edge.target}`);
45333
- }
45334
- if (result.edges.length === 0) {
45335
- for (const node of result.nodes) {
45336
- lines.push(` ${node.id}["${node.label}"]`);
45337
- }
45338
- }
45339
- output2 = lines.join("\n");
45340
- }
45341
- if (typeof args.out === "string" && args.out.length > 0) {
45342
- const outPath = isAbsolute2(args.out) ? args.out : resolve5(projectRoot, args.out);
45343
- await mkdir2(dirname8(outPath), { recursive: true });
45344
- await writeFile2(outPath, output2, "utf8");
45345
- humanInfo(`Wrote graph to ${outPath}`);
45346
- }
45347
- cliOutput(
45348
- { format: fmt, nodeCount: result.nodes.length, edgeCount: result.edges.length, output: output2 },
45349
- { command: "docs graph", operation: "docs.graph" }
45350
- );
46372
+ const result = await rankDocs({
46373
+ ownerId: String(args.for),
46374
+ query: args.query ?? void 0,
46375
+ projectRoot
46376
+ });
46377
+ cliOutput(result, { command: "docs rank", operation: "docs.rank" });
45351
46378
  } catch (err) {
45352
46379
  const message = err instanceof Error ? err.message : String(err);
45353
- cliError(`docs graph failed: ${message}`, 1 /* GENERAL_ERROR */, {
45354
- name: "E_DOCS_GRAPH_FAILED"
46380
+ cliError(`docs rank failed: ${message}`, 1 /* GENERAL_ERROR */, {
46381
+ name: "E_DOCS_RANK_FAILED"
45355
46382
  });
45356
46383
  process.exit(1 /* GENERAL_ERROR */);
45357
46384
  }
45358
46385
  }
45359
46386
  });
45360
- rankCommand = defineCommand({
46387
+ updateCommand = defineCommand({
45361
46388
  meta: {
45362
- name: "rank",
45363
- 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."
46389
+ name: "update",
46390
+ 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")'
45364
46391
  },
45365
46392
  args: {
45366
- for: {
45367
- type: "string",
45368
- description: "Owner entity ID (T###, ses_*, O-*)",
46393
+ slug: {
46394
+ type: "positional",
46395
+ description: "Slug of the attachment to update",
45369
46396
  required: true
45370
46397
  },
45371
- query: {
46398
+ file: {
45372
46399
  type: "string",
45373
- description: "Optional free-text query to rank against (default: owner ID)"
46400
+ description: "Local file containing the new content"
45374
46401
  },
45375
- json: {
45376
- type: "boolean",
45377
- description: "Emit LAFS JSON envelope"
46402
+ content: {
46403
+ type: "string",
46404
+ description: "Inline UTF-8 content (mutually exclusive with --file)"
46405
+ },
46406
+ message: {
46407
+ type: "string",
46408
+ description: "One-line summary of the change (recorded in the audit log)"
46409
+ },
46410
+ status: {
46411
+ type: "string",
46412
+ description: "Lifecycle status to set on the new row. Valid: draft|proposed|accepted|superseded|archived|deprecated. Default: draft."
46413
+ },
46414
+ "attached-by": {
46415
+ type: "string",
46416
+ description: 'Agent identity that performed the update (default: "human")'
45378
46417
  }
45379
46418
  },
45380
- async run({ args }) {
45381
- const projectRoot = getProjectRoot38();
46419
+ async run({ args, rawArgs }) {
45382
46420
  try {
45383
- const result = await rankDocs({
45384
- ownerId: String(args.for),
45385
- query: args.query ?? void 0,
45386
- projectRoot
45387
- });
45388
- cliOutput(result, { command: "docs rank", operation: "docs.rank" });
46421
+ assertKnownFlags(rawArgs, updateCommand.args, "docs update");
45389
46422
  } catch (err) {
45390
- const message = err instanceof Error ? err.message : String(err);
45391
- cliError(`docs rank failed: ${message}`, 1 /* GENERAL_ERROR */, {
45392
- name: "E_DOCS_RANK_FAILED"
46423
+ if (err instanceof UnknownFlagError) {
46424
+ cliError(err.message, 6 /* VALIDATION_ERROR */, {
46425
+ name: err.code,
46426
+ fix: err.fix,
46427
+ alternatives: err.suggestions.map((s) => ({ action: s, command: s })),
46428
+ details: { flag: err.flag, knownFlags: err.knownFlags }
46429
+ });
46430
+ process.exit(6 /* VALIDATION_ERROR */);
46431
+ }
46432
+ throw err;
46433
+ }
46434
+ const slug = String(args.slug);
46435
+ const filePath = typeof args.file === "string" ? args.file : void 0;
46436
+ const inlineContent = typeof args.content === "string" ? args.content : void 0;
46437
+ if (filePath !== void 0 && inlineContent !== void 0) {
46438
+ cliError("--file and --content are mutually exclusive", 6 /* VALIDATION_ERROR */, {
46439
+ name: "E_VALIDATION",
46440
+ fix: "Use `cleo docs update <slug> --file <path>` OR `--content <text>` (not both)."
45393
46441
  });
45394
- process.exit(1 /* GENERAL_ERROR */);
46442
+ process.exit(6 /* VALIDATION_ERROR */);
46443
+ }
46444
+ if (filePath === void 0 && inlineContent === void 0) {
46445
+ cliError("provide --file <path> OR --content <text>", 6 /* VALIDATION_ERROR */, {
46446
+ name: "E_VALIDATION",
46447
+ fix: 'Example: `cleo docs update my-doc --file ./new.md` OR `cleo docs update my-doc --content "..."`.'
46448
+ });
46449
+ process.exit(6 /* VALIDATION_ERROR */);
45395
46450
  }
46451
+ let resolvedFile;
46452
+ if (filePath !== void 0) {
46453
+ const routing = resolveWorktreeRouting2();
46454
+ resolvedFile = resolveWorktreeFilePath(filePath, routing);
46455
+ }
46456
+ await dispatchFromCli(
46457
+ "mutate",
46458
+ "docs",
46459
+ "update",
46460
+ {
46461
+ slug,
46462
+ ...resolvedFile !== void 0 ? { file: resolvedFile } : {},
46463
+ ...inlineContent !== void 0 ? { content: inlineContent } : {},
46464
+ ...typeof args.message === "string" ? { message: args.message } : {},
46465
+ ...typeof args.status === "string" ? { status: args.status } : {},
46466
+ ...typeof args["attached-by"] === "string" ? { attachedBy: args["attached-by"] } : {}
46467
+ },
46468
+ { command: "docs update" }
46469
+ );
45396
46470
  }
45397
46471
  });
45398
46472
  versionsCommand = defineCommand({
@@ -45901,13 +46975,17 @@ var init_docs3 = __esm({
45901
46975
  },
45902
46976
  subCommands: {
45903
46977
  add: addCommand5,
46978
+ update: updateCommand,
45904
46979
  list: listCommand8,
45905
46980
  fetch: fetchCommand,
45906
46981
  remove: removeCommand2,
46982
+ supersede: supersedeCommand,
45907
46983
  generate: generateCommand,
45908
46984
  export: exportCommand4,
46985
+ find: findCommand3,
45909
46986
  search: searchCommand,
45910
46987
  merge: mergeCommand,
46988
+ // T10164 — DocProvenanceResponse-typed graph (`--root <slug>|<taskId>`).
45911
46989
  graph: graphCommand,
45912
46990
  rank: rankCommand,
45913
46991
  versions: versionsCommand,
@@ -46349,6 +47427,7 @@ var ProgressTracker;
46349
47427
  var init_progress = __esm({
46350
47428
  "packages/cleo/src/cli/progress.ts"() {
46351
47429
  "use strict";
47430
+ init_format_context();
46352
47431
  ProgressTracker = class {
46353
47432
  enabled;
46354
47433
  prefix;
@@ -46365,7 +47444,7 @@ var init_progress = __esm({
46365
47444
  * Start the progress tracker.
46366
47445
  */
46367
47446
  start() {
46368
- if (!this.enabled) return;
47447
+ if (!this.enabled || isQuiet()) return;
46369
47448
  this.currentStep = 0;
46370
47449
  stderr.write(`
46371
47450
  ${this.prefix}: Starting...
@@ -46375,7 +47454,7 @@ ${this.prefix}: Starting...
46375
47454
  * Update to a specific step.
46376
47455
  */
46377
47456
  step(index, message) {
46378
- if (!this.enabled) return;
47457
+ if (!this.enabled || isQuiet()) return;
46379
47458
  this.currentStep = index;
46380
47459
  const stepName = this.steps[index] ?? message ?? "Working...";
46381
47460
  const progress = `[${index + 1}/${this.totalSteps}]`;
@@ -46397,7 +47476,7 @@ ${this.prefix}: Starting...
46397
47476
  * one JSON object per CLI invocation (ADR-039 / T927).
46398
47477
  */
46399
47478
  complete(summary) {
46400
- if (!this.enabled) return;
47479
+ if (!this.enabled || isQuiet()) return;
46401
47480
  if (summary) {
46402
47481
  stderr.write(`
46403
47482
  ${this.prefix}: \u2713 ${summary}
@@ -46414,7 +47493,7 @@ ${this.prefix}: \u2713 Complete
46414
47493
  * Report an error.
46415
47494
  */
46416
47495
  error(message) {
46417
- if (!this.enabled) return;
47496
+ if (!this.enabled || isQuiet()) return;
46418
47497
  stderr.write(`
46419
47498
  ${this.prefix}: \u2717 ${message}
46420
47499
 
@@ -46424,6 +47503,254 @@ ${this.prefix}: \u2717 ${message}
46424
47503
  }
46425
47504
  });
46426
47505
 
47506
+ // packages/cleo/src/cli/commands/doctor-release-readiness.ts
47507
+ import { existsSync as existsSync13 } from "node:fs";
47508
+ import { join as join22, resolve as resolve6 } from "node:path";
47509
+ async function runCheck(name, cmd, args, cwd) {
47510
+ const { spawnSync } = await import("node:child_process");
47511
+ const start = Date.now();
47512
+ const result = spawnSync(cmd, args, {
47513
+ encoding: "utf8",
47514
+ stdio: ["ignore", "pipe", "pipe"],
47515
+ cwd
47516
+ });
47517
+ const durationMs = Date.now() - start;
47518
+ const passed = result.status === 0;
47519
+ return {
47520
+ name,
47521
+ status: passed ? "pass" : "fail",
47522
+ exitCode: result.status,
47523
+ durationMs,
47524
+ stdout: (result.stdout ?? "").trim(),
47525
+ stderr: (result.stderr ?? "").trim()
47526
+ };
47527
+ }
47528
+ var doctorReleaseReadinessCommand;
47529
+ var init_doctor_release_readiness = __esm({
47530
+ "packages/cleo/src/cli/commands/doctor-release-readiness.ts"() {
47531
+ "use strict";
47532
+ init_define_cli_command();
47533
+ init_renderers();
47534
+ doctorReleaseReadinessCommand = defineCommand({
47535
+ meta: {
47536
+ name: "release-readiness",
47537
+ description: "Pre-flight release readiness check \u2014 lint matrix + changelog + changeset + npm OIDC + tag-trigger sanity (T10458)"
47538
+ },
47539
+ args: {
47540
+ json: { type: "boolean", description: "Output as JSON" },
47541
+ human: { type: "boolean", description: "Force human-readable output" },
47542
+ quiet: { type: "boolean", description: "Suppress non-essential output" }
47543
+ },
47544
+ async run({ args }) {
47545
+ const isHuman = args.human === true || !!process.stdout.isTTY && args.json !== true;
47546
+ const repoRoot = resolve6(process.cwd());
47547
+ const startTotal = Date.now();
47548
+ const checks = [];
47549
+ const biomePath = join22(repoRoot, "node_modules", ".bin", "biome");
47550
+ const biomeAvailable = existsSync13(biomePath);
47551
+ if (biomeAvailable) {
47552
+ checks.push(await runCheck("biome-lint", biomePath, ["ci", "."], repoRoot));
47553
+ } else {
47554
+ checks.push({
47555
+ name: "biome-lint",
47556
+ status: "skip",
47557
+ exitCode: null,
47558
+ durationMs: 0,
47559
+ stdout: "",
47560
+ stderr: "biome not found in node_modules/.bin \u2014 skipping"
47561
+ });
47562
+ }
47563
+ const changesetLintScript = join22(repoRoot, "scripts", "lint-changesets.mjs");
47564
+ if (existsSync13(changesetLintScript)) {
47565
+ checks.push(await runCheck("changeset-lint", "node", [changesetLintScript], repoRoot));
47566
+ } else {
47567
+ checks.push({
47568
+ name: "changeset-lint",
47569
+ status: "skip",
47570
+ exitCode: null,
47571
+ durationMs: 0,
47572
+ stdout: "",
47573
+ stderr: "scripts/lint-changesets.mjs not found \u2014 skipping"
47574
+ });
47575
+ }
47576
+ const changelogPath = join22(repoRoot, "CHANGELOG.md");
47577
+ const changelogExists = existsSync13(changelogPath);
47578
+ const changelogCheck = {
47579
+ name: "changelog-exists",
47580
+ status: changelogExists ? "pass" : "fail",
47581
+ exitCode: changelogExists ? 0 : 1,
47582
+ durationMs: 0,
47583
+ stdout: changelogExists ? `Found ${changelogPath}` : "",
47584
+ stderr: changelogExists ? "" : `CHANGELOG.md not found at ${changelogPath}`
47585
+ };
47586
+ checks.push(changelogCheck);
47587
+ const packageJsonPath = join22(repoRoot, "package.json");
47588
+ let oidcCheck;
47589
+ if (existsSync13(packageJsonPath)) {
47590
+ try {
47591
+ const pkg = JSON.parse(
47592
+ await import("node:fs").then((m) => m.readFileSync(packageJsonPath, "utf8"))
47593
+ );
47594
+ const hasPublishConfig = typeof pkg.publishConfig === "object" && pkg.publishConfig !== null;
47595
+ const accessPublic = hasPublishConfig && pkg.publishConfig.access === "public";
47596
+ oidcCheck = {
47597
+ name: "npm-oidc-sanity",
47598
+ status: accessPublic ? "pass" : "fail",
47599
+ exitCode: accessPublic ? 0 : 1,
47600
+ durationMs: 0,
47601
+ stdout: accessPublic ? "package.json has publishConfig.access=public" : "",
47602
+ stderr: accessPublic ? "" : "package.json missing publishConfig.access=public \u2014 required for npm OIDC Trusted Publishing"
47603
+ };
47604
+ } catch {
47605
+ oidcCheck = {
47606
+ name: "npm-oidc-sanity",
47607
+ status: "fail",
47608
+ exitCode: 1,
47609
+ durationMs: 0,
47610
+ stdout: "",
47611
+ stderr: "Failed to parse package.json"
47612
+ };
47613
+ }
47614
+ } else {
47615
+ oidcCheck = {
47616
+ name: "npm-oidc-sanity",
47617
+ status: "fail",
47618
+ exitCode: 1,
47619
+ durationMs: 0,
47620
+ stdout: "",
47621
+ stderr: "package.json not found"
47622
+ };
47623
+ }
47624
+ checks.push(oidcCheck);
47625
+ const tagWorkflowPath = join22(repoRoot, ".github", "workflows", "auto-tag-on-release-merge.yml");
47626
+ const tagWorkflowExists = existsSync13(tagWorkflowPath);
47627
+ let tagTriggerCheck;
47628
+ if (tagWorkflowExists) {
47629
+ try {
47630
+ const content = await import("node:fs").then(
47631
+ (m) => m.readFileSync(tagWorkflowPath, "utf8")
47632
+ );
47633
+ const hasName = content.includes("name:");
47634
+ const hasOnTrigger = content.includes("on:") || content.includes("pull_request:");
47635
+ const valid = hasName && hasOnTrigger;
47636
+ tagTriggerCheck = {
47637
+ name: "tag-trigger-sanity",
47638
+ status: valid ? "pass" : "fail",
47639
+ exitCode: valid ? 0 : 1,
47640
+ durationMs: 0,
47641
+ stdout: valid ? `Valid workflow at ${tagWorkflowPath}` : "",
47642
+ stderr: valid ? "" : "auto-tag-on-release-merge.yml appears malformed"
47643
+ };
47644
+ } catch {
47645
+ tagTriggerCheck = {
47646
+ name: "tag-trigger-sanity",
47647
+ status: "fail",
47648
+ exitCode: 1,
47649
+ durationMs: 0,
47650
+ stdout: "",
47651
+ stderr: "Failed to read auto-tag-on-release-merge.yml"
47652
+ };
47653
+ }
47654
+ } else {
47655
+ tagTriggerCheck = {
47656
+ name: "tag-trigger-sanity",
47657
+ status: "fail",
47658
+ exitCode: 1,
47659
+ durationMs: 0,
47660
+ stdout: "",
47661
+ stderr: `.github/workflows/auto-tag-on-release-merge.yml not found`
47662
+ };
47663
+ }
47664
+ checks.push(tagTriggerCheck);
47665
+ const tsconfigPath = join22(repoRoot, "tsconfig.json");
47666
+ if (existsSync13(tsconfigPath)) {
47667
+ const tscPath = join22(repoRoot, "node_modules", ".bin", "tsc");
47668
+ if (existsSync13(tscPath)) {
47669
+ checks.push(await runCheck("typecheck", tscPath, ["--noEmit"], repoRoot));
47670
+ } else {
47671
+ checks.push({
47672
+ name: "typecheck",
47673
+ status: "skip",
47674
+ exitCode: null,
47675
+ durationMs: 0,
47676
+ stdout: "",
47677
+ stderr: "tsc not found in node_modules/.bin \u2014 skipping"
47678
+ });
47679
+ }
47680
+ } else {
47681
+ checks.push({
47682
+ name: "typecheck",
47683
+ status: "skip",
47684
+ exitCode: null,
47685
+ durationMs: 0,
47686
+ stdout: "",
47687
+ stderr: "tsconfig.json not found \u2014 skipping"
47688
+ });
47689
+ }
47690
+ const fastLintScripts = [
47691
+ { name: "contracts-dep-lint", script: "scripts/lint-contracts-dep.mjs" },
47692
+ { name: "format-error-lint", script: "scripts/lint-format-error-misuse.mjs" },
47693
+ { name: "json-stream-lint", script: "scripts/lint-json-stream-hygiene.mjs" }
47694
+ ];
47695
+ for (const lint of fastLintScripts) {
47696
+ const scriptPath = join22(repoRoot, lint.script);
47697
+ if (existsSync13(scriptPath)) {
47698
+ checks.push(await runCheck(lint.name, "node", [scriptPath], repoRoot));
47699
+ } else {
47700
+ checks.push({
47701
+ name: lint.name,
47702
+ status: "skip",
47703
+ exitCode: null,
47704
+ durationMs: 0,
47705
+ stdout: "",
47706
+ stderr: `${lint.script} not found \u2014 skipping`
47707
+ });
47708
+ }
47709
+ }
47710
+ const passCount = checks.filter((c) => c.status === "pass").length;
47711
+ const failCount = checks.filter((c) => c.status === "fail").length;
47712
+ const skipCount = checks.filter((c) => c.status === "skip").length;
47713
+ const totalDurationMs = Date.now() - startTotal;
47714
+ const ready = failCount === 0;
47715
+ const result = {
47716
+ ready,
47717
+ checks,
47718
+ summary: {
47719
+ pass: passCount,
47720
+ fail: failCount,
47721
+ skip: skipCount,
47722
+ total: checks.length,
47723
+ durationMs: totalDurationMs
47724
+ }
47725
+ };
47726
+ if (isHuman && args.json !== true) {
47727
+ humanLine("\nRelease Readiness Check (T10458)\n");
47728
+ humanLine(`${"\u2500".repeat(60)}`);
47729
+ for (const c of checks) {
47730
+ const icon = c.status === "pass" ? "PASS" : c.status === "fail" ? "FAIL" : "SKIP";
47731
+ humanLine(` [${icon}] ${c.name} (${c.durationMs}ms)`);
47732
+ if (c.status === "fail" && c.stderr) {
47733
+ const lines = c.stderr.split("\n").slice(0, 3);
47734
+ for (const line of lines) {
47735
+ humanLine(` ${line}`);
47736
+ }
47737
+ }
47738
+ }
47739
+ humanLine(`${"\u2500".repeat(60)}`);
47740
+ humanLine(` Result: ${passCount} passed, ${failCount} failed, ${skipCount} skipped`);
47741
+ humanLine(` Total time: ${totalDurationMs}ms`);
47742
+ humanLine(` Ready: ${ready ? "YES" : "NO"}
47743
+ `);
47744
+ }
47745
+ cliOutput(result, { command: "doctor", operation: "doctor.release-readiness" });
47746
+ if (!ready) {
47747
+ process.exitCode = 1;
47748
+ }
47749
+ }
47750
+ });
47751
+ }
47752
+ });
47753
+
46427
47754
  // packages/cleo/src/cli/commands/migrate-agents-v2.ts
46428
47755
  var migrate_agents_v2_exports = {};
46429
47756
  __export(migrate_agents_v2_exports, {
@@ -46434,8 +47761,8 @@ __export(migrate_agents_v2_exports, {
46434
47761
  walkAgentsDir: () => walkAgentsDir
46435
47762
  });
46436
47763
  import { createHash as createHash2 } from "node:crypto";
46437
- import { appendFileSync as appendFileSync2, existsSync as existsSync13, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync13 } from "node:fs";
46438
- import { join as join22 } from "node:path";
47764
+ import { appendFileSync as appendFileSync2, existsSync as existsSync14, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync13 } from "node:fs";
47765
+ import { join as join23 } from "node:path";
46439
47766
  import { getProjectRoot as getProjectRoot41, installAgentFromCant } from "@cleocode/core/internal";
46440
47767
  import { openCleoDb as openCleoDb2 } from "@cleocode/core/store/open-cleo-db";
46441
47768
  function sha256Hex(bytes) {
@@ -46455,15 +47782,15 @@ function extractAgentName(source) {
46455
47782
  return headerMatch[1] ?? null;
46456
47783
  }
46457
47784
  function appendAuditLog(projectRoot, entry) {
46458
- const auditPath = join22(projectRoot, AUDIT_LOG_RELATIVE);
46459
- const auditDir = join22(auditPath, "..");
46460
- if (!existsSync13(auditDir)) {
47785
+ const auditPath = join23(projectRoot, AUDIT_LOG_RELATIVE);
47786
+ const auditDir = join23(auditPath, "..");
47787
+ if (!existsSync14(auditDir)) {
46461
47788
  mkdirSync3(auditDir, { recursive: true });
46462
47789
  }
46463
47790
  appendFileSync2(auditPath, JSON.stringify(entry) + "\n", "utf8");
46464
47791
  }
46465
47792
  function walkAgentsDir(db, scanDir, projectRoot, summary, verbose) {
46466
- if (!existsSync13(scanDir)) return;
47793
+ if (!existsSync14(scanDir)) return;
46467
47794
  let files;
46468
47795
  try {
46469
47796
  files = readdirSync2(scanDir).filter((f) => f.endsWith(".cant"));
@@ -46474,7 +47801,7 @@ function walkAgentsDir(db, scanDir, projectRoot, summary, verbose) {
46474
47801
  return;
46475
47802
  }
46476
47803
  for (const filename of files) {
46477
- const cantPath = join22(scanDir, filename);
47804
+ const cantPath = join23(scanDir, filename);
46478
47805
  const relPath = cantPath.replace(`${projectRoot}/`, "");
46479
47806
  let sourceBytes;
46480
47807
  let sourceText;
@@ -46571,9 +47898,9 @@ async function runMigrateAgentsV2(projectRoot, verbose = true) {
46571
47898
  const { db: _sdDb } = await openCleoDb2("signaldock");
46572
47899
  const db = _sdDb;
46573
47900
  try {
46574
- const canonicalDir = join22(projectRoot, ".cleo", "cant", "agents");
47901
+ const canonicalDir = join23(projectRoot, ".cleo", "cant", "agents");
46575
47902
  walkAgentsDir(db, canonicalDir, projectRoot, summary, verbose);
46576
- const legacyDir = join22(projectRoot, ".cleo", "agents");
47903
+ const legacyDir = join23(projectRoot, ".cleo", "agents");
46577
47904
  walkAgentsDir(db, legacyDir, projectRoot, summary, verbose);
46578
47905
  } finally {
46579
47906
  db.close();
@@ -46581,8 +47908,8 @@ async function runMigrateAgentsV2(projectRoot, verbose = true) {
46581
47908
  return summary;
46582
47909
  }
46583
47910
  function readMigrationConflicts(projectRoot) {
46584
- const auditPath = join22(projectRoot, AUDIT_LOG_RELATIVE);
46585
- if (!existsSync13(auditPath)) return [];
47911
+ const auditPath = join23(projectRoot, AUDIT_LOG_RELATIVE);
47912
+ if (!existsSync14(auditPath)) return [];
46586
47913
  let raw;
46587
47914
  try {
46588
47915
  raw = readFileSync13(auditPath, "utf8");
@@ -46666,7 +47993,7 @@ __export(doctor_exports, {
46666
47993
  doctorCommand: () => doctorCommand2
46667
47994
  });
46668
47995
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
46669
- import { join as join23 } from "node:path";
47996
+ import { join as join24 } from "node:path";
46670
47997
  import { getProjectRoot as getProjectRoot42, pushWarning as pushWarning4 } from "@cleocode/core";
46671
47998
  import { renderInvariantAuditLines } from "@cleocode/core/doctor/invariant-audit-render.js";
46672
47999
  import {
@@ -46706,8 +48033,8 @@ async function scanTestFixturesInProd(projectRoot) {
46706
48033
  }
46707
48034
  async function quarantineTestFixtures(projectRoot, matches) {
46708
48035
  if (matches.length === 0) return 0;
46709
- const cleoDir = join23(projectRoot, ".cleo");
46710
- const quarantineDir = join23(
48036
+ const cleoDir = join24(projectRoot, ".cleo");
48037
+ const quarantineDir = join24(
46711
48038
  cleoDir,
46712
48039
  "quarantine",
46713
48040
  `fixture-scan-${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}`
@@ -46715,7 +48042,7 @@ async function quarantineTestFixtures(projectRoot, matches) {
46715
48042
  mkdirSync4(quarantineDir, { recursive: true });
46716
48043
  const manifest = matches.map((m) => ({ ...m, quarantinedAt: (/* @__PURE__ */ new Date()).toISOString() }));
46717
48044
  writeFileSync4(
46718
- join23(quarantineDir, "manifest.jsonl"),
48045
+ join24(quarantineDir, "manifest.jsonl"),
46719
48046
  manifest.map((m) => JSON.stringify(m)).join("\n") + "\n"
46720
48047
  );
46721
48048
  const { getNativeDb } = await import("@cleocode/core/store/sqlite.js");
@@ -46786,6 +48113,7 @@ var init_doctor = __esm({
46786
48113
  init_doctor_db_substrate();
46787
48114
  init_doctor_legacy_backups();
46788
48115
  init_doctor_projects();
48116
+ init_doctor_release_readiness();
46789
48117
  init_migrate_agents_v2();
46790
48118
  FIXTURE_ID_PATTERNS = [/^E\d+$/, /^T\d+EP$/];
46791
48119
  FIXTURE_TITLE_KEYWORDS = [
@@ -46800,7 +48128,9 @@ var init_doctor = __esm({
46800
48128
  // T10307 / Saga T10281 / Epic T10282 — DB-substrate walker
46801
48129
  "db-substrate": doctorDbSubstrateCommand,
46802
48130
  // T10309 / Saga T10281 / Epic T10282 — Legacy-backup walker
46803
- "legacy-backups": doctorLegacyBackupsCommand
48131
+ "legacy-backups": doctorLegacyBackupsCommand,
48132
+ // T10458 / Saga T10431 / Epic T10436 — Release-readiness preflight
48133
+ "release-readiness": doctorReleaseReadinessCommand
46804
48134
  },
46805
48135
  args: {
46806
48136
  detailed: {
@@ -47289,8 +48619,8 @@ var init_doctor = __esm({
47289
48619
  );
47290
48620
  return;
47291
48621
  }
47292
- const archiveDir = join23(projectRoot, ".cleo", "backups");
47293
- const auditLogPath = join23(projectRoot, ".cleo", "audit", "worktree-prune.jsonl");
48622
+ const archiveDir = join24(projectRoot, ".cleo", "backups");
48623
+ const auditLogPath = join24(projectRoot, ".cleo", "audit", "worktree-prune.jsonl");
47294
48624
  const result = await pruneWorktreeOrphans(orphans, {
47295
48625
  archiveDir,
47296
48626
  auditLogPath,
@@ -47454,7 +48784,7 @@ __export(event_exports, {
47454
48784
  orchestratorCommand: () => orchestratorCommand
47455
48785
  });
47456
48786
  import { readdir as readdir2 } from "node:fs/promises";
47457
- import { join as join24 } from "node:path";
48787
+ import { join as join25 } from "node:path";
47458
48788
  import { cwd as processCwd } from "node:process";
47459
48789
  import { appendEvent } from "@cleocode/core/events/event-bus.js";
47460
48790
  function resolveProjectRoot3(arg) {
@@ -47577,7 +48907,7 @@ var init_event = __esm({
47577
48907
  const agentIdFilter = args.agent;
47578
48908
  const showAll = args.all === true;
47579
48909
  const lines = parseInt(args.lines ?? "20", 10);
47580
- const eventsDir = join24(projectRoot, ".cleo", "agent-events");
48910
+ const eventsDir = join25(projectRoot, ".cleo", "agent-events");
47581
48911
  try {
47582
48912
  let files = [];
47583
48913
  try {
@@ -47615,7 +48945,7 @@ var init_event = __esm({
47615
48945
  for (const file of filesToTail) {
47616
48946
  const agentId = file.replace(".jsonl", "");
47617
48947
  const { readFileSync: readFileSync21 } = await import("node:fs");
47618
- const content = readFileSync21(join24(eventsDir, file), "utf-8");
48948
+ const content = readFileSync21(join25(eventsDir, file), "utf-8");
47619
48949
  const eventLines = content.trim().split("\n").filter(Boolean);
47620
48950
  const tail = eventLines.slice(-lines);
47621
48951
  if (jsonMode) {
@@ -47685,7 +49015,7 @@ var init_event = __esm({
47685
49015
  const epicFilter = args.epic;
47686
49016
  const follow = args.follow === true;
47687
49017
  const lines = parseInt(args.lines ?? "50", 10);
47688
- const eventsDir = join24(projectRoot, ".cleo", "agent-events");
49018
+ const eventsDir = join25(projectRoot, ".cleo", "agent-events");
47689
49019
  let files = [];
47690
49020
  try {
47691
49021
  const entries = await readdir2(eventsDir);
@@ -47711,7 +49041,7 @@ var init_event = __esm({
47711
49041
  const agentId = file.replace(".jsonl", "");
47712
49042
  try {
47713
49043
  const { readFileSync: readFileSync21 } = await import("node:fs");
47714
- const content = readFileSync21(join24(eventsDir, file), "utf-8");
49044
+ const content = readFileSync21(join25(eventsDir, file), "utf-8");
47715
49045
  const eventLines = content.trim().split("\n").filter(Boolean);
47716
49046
  const tail = eventLines.slice(-lines);
47717
49047
  if (jsonMode) {
@@ -48129,10 +49459,10 @@ var init_federation = __esm({
48129
49459
  // packages/cleo/src/cli/commands/find.ts
48130
49460
  var find_exports = {};
48131
49461
  __export(find_exports, {
48132
- findCommand: () => findCommand3
49462
+ findCommand: () => findCommand4
48133
49463
  });
48134
49464
  import { createPage } from "@cleocode/core";
48135
- var findCommand3;
49465
+ var findCommand4;
48136
49466
  var init_find = __esm({
48137
49467
  "packages/cleo/src/cli/commands/find.ts"() {
48138
49468
  "use strict";
@@ -48140,7 +49470,7 @@ var init_find = __esm({
48140
49470
  init_dist();
48141
49471
  init_cli();
48142
49472
  init_renderers();
48143
- findCommand3 = defineCommand({
49473
+ findCommand4 = defineCommand({
48144
49474
  meta: { name: "find", description: "Fuzzy search tasks by title/description" },
48145
49475
  args: {
48146
49476
  query: {
@@ -48159,7 +49489,16 @@ var init_find = __esm({
48159
49489
  limit: { type: "string", description: "Max results (default: 20)" },
48160
49490
  offset: { type: "string", description: "Skip first N results" },
48161
49491
  fields: { type: "string", description: "Comma-separated additional fields to include" },
48162
- verbose: { type: "boolean", description: "Include all task fields", alias: "v" },
49492
+ verbose: {
49493
+ type: "boolean",
49494
+ description: "Return full task records instead of the MVI projection (id + title + status + key metadata). T9922.",
49495
+ alias: "v"
49496
+ },
49497
+ // T9922 — MVI record projection opt-out alias (surfaced for --help).
49498
+ full: {
49499
+ type: "boolean",
49500
+ description: "Alias for --verbose. T9922."
49501
+ },
48163
49502
  /**
48164
49503
  * Filter by task kind axis (T944/T9072).
48165
49504
  * Values: work | research | experiment | bug | spike | release
@@ -48167,6 +49506,47 @@ var init_find = __esm({
48167
49506
  kind: {
48168
49507
  type: "string",
48169
49508
  description: "Filter by kind axis (work|research|experiment|bug|spike|release) \u2014 T944"
49509
+ },
49510
+ /**
49511
+ * Unified urgency surface (T9905).
49512
+ *
49513
+ * Selects tasks where
49514
+ * priority IN ('critical','high') OR severity IN ('P0','P1')
49515
+ *
49516
+ * Combines the two orthogonal urgency axes (priority + severity) into a
49517
+ * single filter so agents don't have to query each axis separately.
49518
+ */
49519
+ urgent: {
49520
+ type: "boolean",
49521
+ description: "Surface urgent work across both axes: priority IN (critical,high) OR severity IN (P0,P1) (T9905)",
49522
+ alias: "u"
49523
+ },
49524
+ /**
49525
+ * Filter by label — `cleo find --label <name>` returns every task
49526
+ * whose `labels[]` includes the given value. Closes GH#393 and gives
49527
+ * `find` parity with the positional `cleo labels <name>` surface.
49528
+ * @task T9904
49529
+ */
49530
+ label: {
49531
+ type: "string",
49532
+ description: "Filter by label \u2014 return tasks whose labels[] includes this value (T9904)"
49533
+ },
49534
+ /**
49535
+ * Filter by parent task ID — `cleo find --parent <id>` returns only
49536
+ * tasks whose `parentId` matches. Mirrors the `--parent` axis on
49537
+ * `cleo list`. When the parent target is a Saga (Epic with
49538
+ * `label='saga'`), routing goes through `task_relations.type='groups'`
49539
+ * member IDs (ADR-073 §1) — same path as `cleo list --parent`.
49540
+ *
49541
+ * Closes T10108 — pre-fix the flag was missing entirely AND empty-string
49542
+ * queries bypassed every filter via `fuzzyScore('', '<title>')===80`.
49543
+ *
49544
+ * @task T10108
49545
+ * @saga T9862
49546
+ */
49547
+ parent: {
49548
+ type: "string",
49549
+ description: "Filter by parent task ID \u2014 Saga-aware via task_relations groups (ADR-073 \xA71) (T10108)"
48170
49550
  }
48171
49551
  },
48172
49552
  async run({ args }) {
@@ -48184,6 +49564,9 @@ var init_find = __esm({
48184
49564
  if (args.fields !== void 0) params["fields"] = args.fields;
48185
49565
  if (args.verbose !== void 0) params["verbose"] = args.verbose;
48186
49566
  if (args.kind !== void 0) params["kind"] = args.kind;
49567
+ if (args.urgent !== void 0) params["urgent"] = args.urgent;
49568
+ if (args.label !== void 0) params["label"] = args.label;
49569
+ if (args.parent !== void 0) params["parent"] = args.parent;
48187
49570
  const response = await dispatchRaw("query", "tasks", "find", params);
48188
49571
  if (!response.success) {
48189
49572
  handleRawError(response, { command: "find", operation: "tasks.find" });
@@ -48250,7 +49633,7 @@ __export(gc_exports, {
48250
49633
  gcCommand: () => gcCommand
48251
49634
  });
48252
49635
  import { homedir as homedir4, tmpdir } from "node:os";
48253
- import { join as join25 } from "node:path";
49636
+ import { join as join26 } from "node:path";
48254
49637
  import { pruneOrphanTempDirs, pruneOrphanWorktrees } from "@cleocode/core/gc/cleanup.js";
48255
49638
  import { runGC } from "@cleocode/core/gc/runner.js";
48256
49639
  import { readGCState } from "@cleocode/core/gc/state.js";
@@ -48333,7 +49716,7 @@ var init_gc = __esm({
48333
49716
  },
48334
49717
  async run({ args }) {
48335
49718
  const cleoDir = resolveLegacyCleoDir3(args["cleo-dir"]);
48336
- const statePath = join25(cleoDir, "gc-state.json");
49719
+ const statePath = join26(cleoDir, "gc-state.json");
48337
49720
  try {
48338
49721
  const state = await readGCState(statePath);
48339
49722
  const diskStr = state.lastDiskUsedPct !== null ? `${state.lastDiskUsedPct.toFixed(1)}%` : "unknown";
@@ -48386,8 +49769,8 @@ var init_gc = __esm({
48386
49769
  }
48387
49770
  },
48388
49771
  async run({ args }) {
48389
- const xdgData = process.env["XDG_DATA_HOME"] ?? join25(homedir4(), ".local", "share");
48390
- const worktreesRoot = args["worktrees-root"] ?? join25(xdgData, "cleo", "worktrees");
49772
+ const xdgData = process.env["XDG_DATA_HOME"] ?? join26(homedir4(), ".local", "share");
49773
+ const worktreesRoot = args["worktrees-root"] ?? join26(xdgData, "cleo", "worktrees");
48391
49774
  const projectHash = args["project-hash"];
48392
49775
  const dryRun = args["dry-run"];
48393
49776
  const preserveRaw = args["preserve-tasks"];
@@ -48540,7 +49923,7 @@ function applyJsonFlag(jsonFlag) {
48540
49923
  }
48541
49924
  }
48542
49925
  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;
48543
- var init_graph2 = __esm({
49926
+ var init_graph3 = __esm({
48544
49927
  "packages/cleo/src/cli/commands/graph.ts"() {
48545
49928
  "use strict";
48546
49929
  init_dist();
@@ -49599,24 +50982,25 @@ __export(init_exports, {
49599
50982
  getWorkflowTemplatesDir: () => getWorkflowTemplatesDir2,
49600
50983
  initCommand: () => initCommand2
49601
50984
  });
49602
- import { existsSync as existsSync14, readFileSync as readFileSync14 } from "node:fs";
49603
- import { join as join26 } from "node:path";
50985
+ import { existsSync as existsSync15, readFileSync as readFileSync14 } from "node:fs";
50986
+ import { join as join27 } from "node:path";
49604
50987
  import { fileURLToPath as fileURLToPath6 } from "node:url";
49605
50988
  import {
49606
50989
  CleoError as CleoError4,
49607
- formatError as formatError4,
49608
50990
  getWorkflowTemplatesDir as getCoreWorkflowTemplatesDir,
49609
50991
  initProject as initProject2,
50992
+ pushWarning as pushWarning5,
49610
50993
  scaffoldWorkflows
49611
50994
  } from "@cleocode/core";
50995
+ import { getTemplatesByKind } from "@cleocode/core/templates/registry";
49612
50996
  function getGitignoreTemplate() {
49613
50997
  try {
49614
50998
  const thisFile = fileURLToPath6(import.meta.url);
49615
- const packageRoot = join26(thisFile, "..", "..", "..", "..");
49616
- const localTemplatePath = join26(packageRoot, "templates", "cleo-gitignore");
49617
- const monorepoTemplatePath = join26(packageRoot, "..", "..", "templates", "cleo-gitignore");
49618
- const templatePath = existsSync14(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
49619
- if (existsSync14(templatePath)) {
50999
+ const packageRoot = join27(thisFile, "..", "..", "..", "..");
51000
+ const localTemplatePath = join27(packageRoot, "templates", "cleo-gitignore");
51001
+ const monorepoTemplatePath = join27(packageRoot, "..", "..", "templates", "cleo-gitignore");
51002
+ const templatePath = existsSync15(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
51003
+ if (existsSync15(templatePath)) {
49620
51004
  return readFileSync14(templatePath, "utf-8");
49621
51005
  }
49622
51006
  } catch {
@@ -49626,6 +51010,9 @@ function getGitignoreTemplate() {
49626
51010
  function getWorkflowTemplatesDir2() {
49627
51011
  return getCoreWorkflowTemplatesDir();
49628
51012
  }
51013
+ function isWorkflowName(id) {
51014
+ return id === "release-prepare" || id === "release-publish" || id === "release-fanout" || id === "release-rollback";
51015
+ }
49629
51016
  var initCommand2;
49630
51017
  var init_init = __esm({
49631
51018
  "packages/cleo/src/cli/commands/init.ts"() {
@@ -49666,7 +51053,11 @@ var init_init = __esm({
49666
51053
  },
49667
51054
  workflows: {
49668
51055
  type: "boolean",
49669
- description: "Scaffold the release-prepare.yml workflow into .github/workflows/ (T9531).",
51056
+ /**
51057
+ * @deprecated Use `cleo templates install --kind workflow` instead
51058
+ * (T9886 / Saga T9855). Removal target: v2026.7.0. T9888.
51059
+ */
51060
+ description: "[DEPRECATED \u2014 use `cleo templates install --kind workflow`] Scaffold release workflows into .github/workflows/. Will be removed in v2026.7.0.",
49670
51061
  default: false
49671
51062
  },
49672
51063
  "dry-run": {
@@ -49678,11 +51069,23 @@ var init_init = __esm({
49678
51069
  async run({ args }) {
49679
51070
  try {
49680
51071
  if (args.workflows) {
51072
+ pushWarning5({
51073
+ code: "W_INIT_WORKFLOWS_DEPRECATED",
51074
+ message: "[deprecated] cleo init --workflows: use `cleo templates install --kind workflow` instead. This alias will be removed in v2026.7.0.",
51075
+ severity: "warn",
51076
+ deprecated: "cleo init --workflows",
51077
+ replacement: "cleo templates install --kind workflow",
51078
+ removeBy: "v2026.7.0",
51079
+ context: { task: "T9888", saga: "T9855" }
51080
+ });
49681
51081
  const projectRoot = process.cwd();
49682
51082
  const templatesDir = getWorkflowTemplatesDir2();
51083
+ const workflowEntries = getTemplatesByKind("workflow");
51084
+ const templates2 = workflowEntries.map((entry) => entry.id).filter((id) => isWorkflowName(id));
49683
51085
  const result2 = await scaffoldWorkflows({
49684
51086
  projectRoot,
49685
51087
  templatesDir,
51088
+ ...templates2.length > 0 ? { templates: templates2 } : {},
49686
51089
  dryRun: !!args["dry-run"],
49687
51090
  force: !!args.force
49688
51091
  });
@@ -49724,7 +51127,7 @@ var init_init = __esm({
49724
51127
  );
49725
51128
  } catch (err) {
49726
51129
  if (err instanceof CleoError4) {
49727
- cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
51130
+ cliError(`init failed: ${err.message}`, err.code, { name: "E_INTERNAL" });
49728
51131
  process.exit(err.code);
49729
51132
  }
49730
51133
  throw err;
@@ -50209,7 +51612,17 @@ var init_labels = __esm({
50209
51612
  labelsCommand = defineCommand({
50210
51613
  meta: {
50211
51614
  name: "labels",
50212
- description: "List all labels with counts or show tasks with specific label"
51615
+ description: "List all labels (no args), or show tasks for a label (cleo labels <name>)"
51616
+ },
51617
+ args: {
51618
+ // Optional positional — when present, dispatches to tasks.list with the
51619
+ // label filter; when absent, falls through to the legacy label.list path.
51620
+ // Required:false keeps the bare `cleo labels` invocation working.
51621
+ name: {
51622
+ type: "positional",
51623
+ description: "Label name to filter tasks by (omit to list all labels)",
51624
+ required: false
51625
+ }
50213
51626
  },
50214
51627
  subCommands: {
50215
51628
  list: listCommand10,
@@ -50217,9 +51630,16 @@ var init_labels = __esm({
50217
51630
  stats: statsCommand2
50218
51631
  },
50219
51632
  async run(ctx) {
50220
- if (!ctx.rawArgs.some((a) => ["list", "show", "stats"].includes(a))) {
50221
- await dispatchFromCli("query", "tasks", "label.list", {}, { command: "labels" });
51633
+ const rawArgs = ctx.rawArgs ?? [];
51634
+ if (rawArgs.some((a) => ["list", "show", "stats"].includes(a))) {
51635
+ return;
50222
51636
  }
51637
+ const name = ctx.args.name;
51638
+ if (typeof name === "string" && name.length > 0) {
51639
+ await dispatchFromCli("query", "tasks", "list", { label: name }, { command: "labels" });
51640
+ return;
51641
+ }
51642
+ await dispatchFromCli("query", "tasks", "label.list", {}, { command: "labels" });
50223
51643
  }
50224
51644
  });
50225
51645
  }
@@ -50495,6 +51915,20 @@ var init_list3 = __esm({
50495
51915
  "parent-id": {
50496
51916
  type: "string",
50497
51917
  description: "Alias for --parent (legacy parentId compatibility)"
51918
+ },
51919
+ // T9922 — MVI record projection opt-out flags (surfaced for --help).
51920
+ verbose: {
51921
+ type: "boolean",
51922
+ description: "Return full task records instead of the MVI projection (id + title + status + key metadata). T9922."
51923
+ },
51924
+ full: {
51925
+ type: "boolean",
51926
+ description: "Alias for --verbose. T9922."
51927
+ },
51928
+ // T9932 — 1-line-per-record summary render. Global flag; parsed by cli/index.ts.
51929
+ summary: {
51930
+ type: "boolean",
51931
+ description: 'Render each task as a single line "<id> [<status>] <title-truncated-60>". Composes with --output: --output {id|table|count|silent} wins. T9932.'
50498
51932
  }
50499
51933
  };
50500
51934
  listCommand11 = defineCommand({
@@ -50727,7 +52161,7 @@ async function resolveDefaultModel(provider) {
50727
52161
  return profile?.defaultModel ?? IMPLICIT_FALLBACK_MODEL;
50728
52162
  }
50729
52163
  async function runLlmStream(opts) {
50730
- const stdout = opts.stdout ?? process.stdout;
52164
+ const stdout2 = opts.stdout ?? process.stdout;
50731
52165
  const stderr2 = opts.stderr ?? process.stderr;
50732
52166
  const session = opts._sessionOverride ?? await buildSession(opts.provider, opts.model ?? await resolveDefaultModel(opts.provider));
50733
52167
  const sendOpts = {
@@ -50738,7 +52172,7 @@ async function runLlmStream(opts) {
50738
52172
  const stream = session.stream(messages, sendOpts);
50739
52173
  for await (const delta of stream) {
50740
52174
  if (delta.text) {
50741
- stdout.write(delta.text);
52175
+ stdout2.write(delta.text);
50742
52176
  }
50743
52177
  if (delta.reasoning && opts.showThink) {
50744
52178
  stderr2.write(delta.reasoning);
@@ -50983,7 +52417,7 @@ async function _headlessPkceFlow(provider, authUrl) {
50983
52417
  ` After approving, paste the full redirect URL (http://localhost?code=\u2026&state=\u2026):
50984
52418
  `
50985
52419
  );
50986
- return new Promise((resolve8, reject) => {
52420
+ return new Promise((resolve9, reject) => {
50987
52421
  let buf = "";
50988
52422
  process.stdin.setEncoding("utf8");
50989
52423
  process.stdin.once("data", (chunk) => {
@@ -50995,7 +52429,7 @@ async function _headlessPkceFlow(provider, authUrl) {
50995
52429
  reject(new Error('Redirect URL is missing the "code" parameter'));
50996
52430
  return;
50997
52431
  }
50998
- resolve8(code);
52432
+ resolve9(code);
50999
52433
  } catch {
51000
52434
  reject(new Error(`Invalid redirect URL: ${buf}`));
51001
52435
  }
@@ -51003,7 +52437,7 @@ async function _headlessPkceFlow(provider, authUrl) {
51003
52437
  });
51004
52438
  }
51005
52439
  async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
51006
- return new Promise((resolve8) => {
52440
+ return new Promise((resolve9) => {
51007
52441
  const server = createServer2((req, res) => {
51008
52442
  const url = new URL(req.url ?? "/", `http://localhost:${port}`);
51009
52443
  const code = url.searchParams.get("code");
@@ -51013,7 +52447,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
51013
52447
  if (error) {
51014
52448
  res.end(`<h1>Authorization failed</h1><p>${error}</p><p>You may close this tab.</p>`);
51015
52449
  server.close();
51016
- resolve8({
52450
+ resolve9({
51017
52451
  error: {
51018
52452
  code: "E_PKCE_AUTH_DENIED",
51019
52453
  codeName: "E_PKCE_AUTH_DENIED",
@@ -51025,7 +52459,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
51025
52459
  if (!code || state !== expectedState) {
51026
52460
  res.end("<h1>Invalid callback</h1><p>You may close this tab.</p>");
51027
52461
  server.close();
51028
- resolve8({
52462
+ resolve9({
51029
52463
  error: {
51030
52464
  code: "E_PKCE_INVALID_CALLBACK",
51031
52465
  codeName: "E_PKCE_INVALID_CALLBACK",
@@ -51036,7 +52470,7 @@ async function _localCallbackPkceFlow(provider, authUrl, expectedState, port) {
51036
52470
  }
51037
52471
  res.end("<h1>Authorized</h1><p>You may close this tab and return to your terminal.</p>");
51038
52472
  server.close();
51039
- resolve8({ code });
52473
+ resolve9({ code });
51040
52474
  });
51041
52475
  server.listen(port, "localhost", () => {
51042
52476
  process.stderr.write("\n");
@@ -51169,7 +52603,7 @@ function _generateState() {
51169
52603
  return Array.from(bytes, (b) => b.toString(16).padStart(2, "0")).join("");
51170
52604
  }
51171
52605
  function _findFreePort() {
51172
- return new Promise((resolve8, reject) => {
52606
+ return new Promise((resolve9, reject) => {
51173
52607
  const srv = createServer2();
51174
52608
  srv.listen(0, "localhost", () => {
51175
52609
  const addr = srv.address();
@@ -51179,7 +52613,7 @@ function _findFreePort() {
51179
52613
  return;
51180
52614
  }
51181
52615
  const port = addr.port;
51182
- srv.close(() => resolve8(port));
52616
+ srv.close(() => resolve9(port));
51183
52617
  });
51184
52618
  srv.on("error", reject);
51185
52619
  });
@@ -51253,7 +52687,7 @@ var llm_exports = {};
51253
52687
  __export(llm_exports, {
51254
52688
  llmCommand: () => llmCommand
51255
52689
  });
51256
- import { pushWarning as pushWarning5 } from "@cleocode/core";
52690
+ import { pushWarning as pushWarning6 } from "@cleocode/core";
51257
52691
  async function getListProviders() {
51258
52692
  const { listProviders } = await import(
51259
52693
  /* webpackIgnore: true */
@@ -51384,7 +52818,7 @@ var init_llm3 = __esm({
51384
52818
  apiKey = envValue;
51385
52819
  source = "env";
51386
52820
  } else if (typeof a["api-key"] === "string" && a["api-key"]) {
51387
- pushWarning5({
52821
+ pushWarning6({
51388
52822
  code: "W_DEPRECATED_FLAG",
51389
52823
  message: API_KEY_FLAG_DEPRECATION,
51390
52824
  deprecated: "--api-key=<value>",
@@ -51801,19 +53235,19 @@ async function readStdin() {
51801
53235
  if (process.stdin.isTTY) {
51802
53236
  return "";
51803
53237
  }
51804
- return new Promise((resolve8, reject) => {
53238
+ return new Promise((resolve9, reject) => {
51805
53239
  let data = "";
51806
53240
  process.stdin.setEncoding("utf-8");
51807
53241
  process.stdin.on("data", (chunk) => {
51808
53242
  data += chunk;
51809
53243
  });
51810
53244
  process.stdin.on("end", () => {
51811
- resolve8(data.trim());
53245
+ resolve9(data.trim());
51812
53246
  });
51813
53247
  process.stdin.on("error", reject);
51814
53248
  });
51815
53249
  }
51816
- var showCommand7, listCommand13, findCommand4, statsCommand3, appendCommand, archiveCommand2, manifestCommand;
53250
+ var showCommand7, listCommand13, findCommand5, statsCommand3, appendCommand, archiveCommand2, manifestCommand;
51817
53251
  var init_manifest3 = __esm({
51818
53252
  "packages/cleo/src/cli/commands/manifest.ts"() {
51819
53253
  "use strict";
@@ -51899,7 +53333,7 @@ var init_manifest3 = __esm({
51899
53333
  );
51900
53334
  }
51901
53335
  });
51902
- findCommand4 = defineCommand({
53336
+ findCommand5 = defineCommand({
51903
53337
  meta: {
51904
53338
  name: "find",
51905
53339
  description: "Full-text search manifest entries"
@@ -52108,7 +53542,7 @@ var init_manifest3 = __esm({
52108
53542
  subCommands: {
52109
53543
  show: showCommand7,
52110
53544
  list: listCommand13,
52111
- find: findCommand4,
53545
+ find: findCommand5,
52112
53546
  stats: statsCommand3,
52113
53547
  append: appendCommand,
52114
53548
  archive: archiveCommand2
@@ -52188,7 +53622,7 @@ function makeMemorySubcommand(opts) {
52188
53622
  }
52189
53623
  });
52190
53624
  }
52191
- 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;
53625
+ 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;
52192
53626
  var init_memory3 = __esm({
52193
53627
  "packages/cleo/src/cli/commands/memory.ts"() {
52194
53628
  "use strict";
@@ -52280,7 +53714,7 @@ var init_memory3 = __esm({
52280
53714
  }
52281
53715
  }
52282
53716
  });
52283
- findCommand5 = defineCommand({
53717
+ findCommand6 = defineCommand({
52284
53718
  meta: {
52285
53719
  name: "find",
52286
53720
  description: "Search BRAIN memory (all tables, or filter by --type pattern|learning)"
@@ -53893,7 +55327,7 @@ data: ${JSON.stringify({ ts: item.ts })}
53893
55327
  meta: { name: "memory", description: "BRAIN memory operations (patterns, learnings)" },
53894
55328
  subCommands: {
53895
55329
  store: storeCommand,
53896
- find: findCommand5,
55330
+ find: findCommand6,
53897
55331
  stats: statsCommand4,
53898
55332
  observe: observeCommand,
53899
55333
  timeline: timelineCommand,
@@ -55375,15 +56809,15 @@ var init_nexus3 = __esm({
55375
56809
  return;
55376
56810
  }
55377
56811
  if (!skipPrompt) {
55378
- const { createInterface: createInterface4 } = await import("node:readline");
55379
- const rl = createInterface4({ input: process.stdin, output: process.stdout });
55380
- const confirmed = await new Promise((resolve8) => {
56812
+ const { createInterface: createInterface5 } = await import("node:readline");
56813
+ const rl = createInterface5({ input: process.stdin, output: process.stdout });
56814
+ const confirmed = await new Promise((resolve9) => {
55381
56815
  rl.question(
55382
56816
  `
55383
56817
  [nexus] Delete ${matchCount} project(s) from the registry? [y/N] `,
55384
56818
  (answer) => {
55385
56819
  rl.close();
55386
- resolve8(answer.trim().toLowerCase() === "y");
56820
+ resolve9(answer.trim().toLowerCase() === "y");
55387
56821
  }
55388
56822
  );
55389
56823
  });
@@ -56682,7 +58116,9 @@ __export(orchestrate_exports, {
56682
58116
  formatRollupTable: () => formatRollupTable,
56683
58117
  orchestrateCommand: () => orchestrateCommand
56684
58118
  });
58119
+ import { execFileSync as execFileSync3 } from "node:child_process";
56685
58120
  import { orchestration } from "@cleocode/core";
58121
+ import { BUILD_CONFIG as BUILD_CONFIG2 } from "@cleocode/core/internal";
56686
58122
  function formatRollupTable(rollup) {
56687
58123
  const waves = "waves" in rollup ? rollup.waves : [rollup];
56688
58124
  const lines = [];
@@ -56775,9 +58211,34 @@ var init_orchestrate3 = __esm({
56775
58211
  epic: {
56776
58212
  type: "string",
56777
58213
  description: "Epic ID to scope status to"
58214
+ },
58215
+ "merge-queue": {
58216
+ type: "boolean",
58217
+ description: "Show GitHub merge queue depth instead of epic status (T10445)"
56778
58218
  }
56779
58219
  },
56780
58220
  async run({ args }) {
58221
+ if (args["merge-queue"]) {
58222
+ const repo = BUILD_CONFIG2.repository.fullName;
58223
+ let queueDepth = 0;
58224
+ let estimatedWaitMinutes = 0;
58225
+ let blocked = false;
58226
+ let note = "merge queue not enabled";
58227
+ try {
58228
+ const raw = execFileSync3(
58229
+ "gh",
58230
+ ["api", `repos/${repo}/merge-queue`, "--jq", ".entries | length"],
58231
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 15e3 }
58232
+ );
58233
+ queueDepth = Number(raw.trim()) || 0;
58234
+ estimatedWaitMinutes = queueDepth * 5;
58235
+ blocked = queueDepth > 10;
58236
+ note = queueDepth > 0 ? "active" : "empty";
58237
+ } catch {
58238
+ }
58239
+ cliOutput({ queueDepth, estimatedWaitMinutes, blocked, note }, { command: "orchestrate" });
58240
+ return;
58241
+ }
56781
58242
  await dispatchFromCli(
56782
58243
  "query",
56783
58244
  "orchestrate",
@@ -56947,6 +58408,10 @@ var init_orchestrate3 = __esm({
56947
58408
  scope: {
56948
58409
  type: "string",
56949
58410
  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."
58411
+ },
58412
+ "orchestrator-defer": {
58413
+ type: "boolean",
58414
+ 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."
56950
58415
  }
56951
58416
  },
56952
58417
  async run({ args }) {
@@ -56957,6 +58422,7 @@ var init_orchestrate3 = __esm({
56957
58422
  tier = parsed;
56958
58423
  }
56959
58424
  }
58425
+ const atomicityScope = args["orchestrator-defer"] ? "orchestrator-defer" : void 0;
56960
58426
  await dispatchFromCli(
56961
58427
  "mutate",
56962
58428
  "orchestrate",
@@ -56966,7 +58432,8 @@ var init_orchestrate3 = __esm({
56966
58432
  protocolType: args.protocol,
56967
58433
  tier,
56968
58434
  noWorktree: args["no-worktree"] === true,
56969
- ...args.scope ? { spawnScope: args.scope } : {}
58435
+ ...args.scope ? { spawnScope: args.scope } : {},
58436
+ ...atomicityScope ? { atomicityScope } : {}
56970
58437
  },
56971
58438
  { command: "orchestrate" }
56972
58439
  );
@@ -57585,7 +59052,7 @@ __export(otel_exports, {
57585
59052
  import {
57586
59053
  CleoError as CleoError5,
57587
59054
  clearOtelData,
57588
- formatError as formatError5,
59055
+ formatError as formatError4,
57589
59056
  getOtelSessions,
57590
59057
  getOtelSpawns,
57591
59058
  getOtelStatus,
@@ -57606,7 +59073,7 @@ var init_otel = __esm({
57606
59073
  cliOutput(result, { command: "otel" });
57607
59074
  } catch (err) {
57608
59075
  if (err instanceof CleoError5) {
57609
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
59076
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57610
59077
  process.exit(err.code);
57611
59078
  }
57612
59079
  throw err;
@@ -57621,7 +59088,7 @@ var init_otel = __esm({
57621
59088
  cliOutput(result, { command: "otel" });
57622
59089
  } catch (err) {
57623
59090
  if (err instanceof CleoError5) {
57624
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
59091
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57625
59092
  process.exit(err.code);
57626
59093
  }
57627
59094
  throw err;
@@ -57649,7 +59116,7 @@ var init_otel = __esm({
57649
59116
  cliOutput(result, { command: "otel" });
57650
59117
  } catch (err) {
57651
59118
  if (err instanceof CleoError5) {
57652
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
59119
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57653
59120
  process.exit(err.code);
57654
59121
  }
57655
59122
  throw err;
@@ -57677,7 +59144,7 @@ var init_otel = __esm({
57677
59144
  cliOutput(result, { command: "otel" });
57678
59145
  } catch (err) {
57679
59146
  if (err instanceof CleoError5) {
57680
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
59147
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57681
59148
  process.exit(err.code);
57682
59149
  }
57683
59150
  throw err;
@@ -57705,7 +59172,7 @@ var init_otel = __esm({
57705
59172
  cliOutput(result, { command: "otel" });
57706
59173
  } catch (err) {
57707
59174
  if (err instanceof CleoError5) {
57708
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
59175
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57709
59176
  process.exit(err.code);
57710
59177
  }
57711
59178
  throw err;
@@ -57720,7 +59187,7 @@ var init_otel = __esm({
57720
59187
  cliOutput(result, { command: "otel" });
57721
59188
  } catch (err) {
57722
59189
  if (err instanceof CleoError5) {
57723
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
59190
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
57724
59191
  process.exit(err.code);
57725
59192
  }
57726
59193
  throw err;
@@ -59022,7 +60489,7 @@ __export(release_exports, {
59022
60489
  releaseCommand: () => releaseCommand
59023
60490
  });
59024
60491
  import { release as release3 } from "@cleocode/core";
59025
- var listCommand19, showCommand10, cancelCommand2, rollbackCommand, rollbackFullCommand, prStatusCommand, channelCommand, planCommand3, openCommand2, reconcileCommand4, releaseCommand;
60492
+ var listCommand19, showCommand10, cancelCommand2, rollbackCommand, rollbackFullCommand, prStatusCommand, channelCommand, validateChangelogCommand, planCommand3, openCommand2, reconcileCommand4, releaseCommand;
59026
60493
  var init_release3 = __esm({
59027
60494
  "packages/cleo/src/cli/commands/release.ts"() {
59028
60495
  "use strict";
@@ -59171,6 +60638,36 @@ var init_release3 = __esm({
59171
60638
  await dispatchFromCli("query", "pipeline", "release.channel.show", {}, { command: "release" });
59172
60639
  }
59173
60640
  });
60641
+ validateChangelogCommand = defineCommand({
60642
+ meta: {
60643
+ name: "validate-changelog",
60644
+ description: "Validate that CHANGELOG.md contains the canonical `## [VERSION]` header (T9937)"
60645
+ },
60646
+ args: {
60647
+ version: {
60648
+ type: "positional",
60649
+ description: "Release version (accepts v2026.5.94 or 2026.5.94)",
60650
+ required: true
60651
+ },
60652
+ path: {
60653
+ type: "string",
60654
+ description: "Override the CHANGELOG file path (default: <projectRoot>/CHANGELOG.md)",
60655
+ required: false
60656
+ }
60657
+ },
60658
+ async run({ args }) {
60659
+ await dispatchFromCli(
60660
+ "query",
60661
+ "release",
60662
+ "validate-changelog",
60663
+ {
60664
+ version: args.version,
60665
+ ...typeof args.path === "string" && args.path.length > 0 ? { changelogPath: args.path } : {}
60666
+ },
60667
+ { command: "release" }
60668
+ );
60669
+ }
60670
+ });
59174
60671
  planCommand3 = defineCommand({
59175
60672
  meta: {
59176
60673
  name: "plan",
@@ -59211,9 +60708,17 @@ var init_release3 = __esm({
59211
60708
  "no-changelog": {
59212
60709
  type: "boolean",
59213
60710
  description: "Skip CHANGELOG.md auto-write (default: write/replace the ## [<version>] section). (T9838)"
60711
+ },
60712
+ "skip-readiness": {
60713
+ type: "boolean",
60714
+ description: "Skip the release-readiness preflight check (default: run check). Use only in emergency. (T10459)"
59214
60715
  }
59215
60716
  },
59216
60717
  async run({ args }) {
60718
+ if (args["skip-readiness"] !== true) {
60719
+ const { runSpawnReadinessHygieneCli } = await import("@cleocode/core/hygiene/validate-spawn-readiness.js");
60720
+ await runSpawnReadinessHygieneCli();
60721
+ }
59217
60722
  await dispatchFromCli(
59218
60723
  "mutate",
59219
60724
  "release",
@@ -59334,7 +60839,9 @@ var init_release3 = __esm({
59334
60839
  cancel: cancelCommand2,
59335
60840
  "pr-status": prStatusCommand,
59336
60841
  channel: channelCommand,
59337
- "rollback-full": rollbackFullCommand
60842
+ "rollback-full": rollbackFullCommand,
60843
+ // T9937 — canonical CHANGELOG.md header validator (Saga T9862).
60844
+ "validate-changelog": validateChangelogCommand
59338
60845
  },
59339
60846
  async run({ cmd, rawArgs }) {
59340
60847
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
@@ -59829,7 +61336,7 @@ __export(research_exports, {
59829
61336
  function generateResearchId() {
59830
61337
  return `res_${Date.now()}`;
59831
61338
  }
59832
- var addCommand10, showCommand11, listCommand21, pendingCommand2, linkCommand2, updateCommand, statsCommand5, linksCommand, archiveCommand3, manifestCommand2, researchCommand;
61339
+ var addCommand10, showCommand11, listCommand21, pendingCommand2, linkCommand2, updateCommand2, statsCommand5, linksCommand, archiveCommand3, manifestCommand2, researchCommand;
59833
61340
  var init_research2 = __esm({
59834
61341
  "packages/cleo/src/cli/commands/research.ts"() {
59835
61342
  "use strict";
@@ -59996,7 +61503,7 @@ var init_research2 = __esm({
59996
61503
  );
59997
61504
  }
59998
61505
  });
59999
- updateCommand = defineCommand({
61506
+ updateCommand2 = defineCommand({
60000
61507
  meta: { name: "update", description: "Update research findings" },
60001
61508
  args: {
60002
61509
  id: {
@@ -60150,7 +61657,7 @@ var init_research2 = __esm({
60150
61657
  list: listCommand21,
60151
61658
  pending: pendingCommand2,
60152
61659
  link: linkCommand2,
60153
- update: updateCommand,
61660
+ update: updateCommand2,
60154
61661
  stats: statsCommand5,
60155
61662
  links: linksCommand,
60156
61663
  archive: archiveCommand3,
@@ -60562,7 +62069,7 @@ __export(revert_exports, {
60562
62069
  revertCommand: () => revertCommand
60563
62070
  });
60564
62071
  import { readFile as readFile5 } from "node:fs/promises";
60565
- import { join as join27 } from "node:path";
62072
+ import { join as join28 } from "node:path";
60566
62073
  import { cwd as processCwd2 } from "node:process";
60567
62074
  import { E_RECEIPT_NOT_FOUND } from "@cleocode/core/sentient/chain-walker.js";
60568
62075
  import { SENTIENT_STATE_FILE } from "@cleocode/core/sentient/daemon.js";
@@ -60615,7 +62122,7 @@ async function loadOwnerAttestation(attestationFilePath) {
60615
62122
  return obj;
60616
62123
  }
60617
62124
  async function loadOwnerPubkeys(projectRoot) {
60618
- const path6 = join27(projectRoot, OWNER_PUBKEYS_FILE);
62125
+ const path6 = join28(projectRoot, OWNER_PUBKEYS_FILE);
60619
62126
  try {
60620
62127
  const raw = await readFile5(path6, "utf-8");
60621
62128
  const parsed = JSON.parse(raw);
@@ -60699,7 +62206,7 @@ var init_revert = __esm({
60699
62206
  if (attestation && allowedPubkeys.size > 0 && !allowedPubkeys.has(attestation.ownerPubkey)) {
60700
62207
  emitFailure2(
60701
62208
  E_OWNER_ATTESTATION_REQUIRED,
60702
- `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join27(projectRoot, OWNER_PUBKEYS_FILE)}`,
62209
+ `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join28(projectRoot, OWNER_PUBKEYS_FILE)}`,
60703
62210
  jsonMode
60704
62211
  );
60705
62212
  }
@@ -60752,7 +62259,7 @@ ${lines}`
60752
62259
  identity,
60753
62260
  includeHuman
60754
62261
  });
60755
- const statePath = join27(projectRoot, SENTIENT_STATE_FILE);
62262
+ const statePath = join28(projectRoot, SENTIENT_STATE_FILE);
60756
62263
  const state = await readSentientState(statePath);
60757
62264
  emitSuccess(
60758
62265
  {
@@ -61286,11 +62793,11 @@ __export(self_update_exports, {
61286
62793
  });
61287
62794
  import { execFile } from "node:child_process";
61288
62795
  import { readFile as readFile6 } from "node:fs/promises";
61289
- import { join as join28 } from "node:path";
62796
+ import { join as join29 } from "node:path";
61290
62797
  import * as readline2 from "node:readline";
61291
62798
  import { promisify } from "node:util";
61292
62799
  import {
61293
- BUILD_CONFIG as BUILD_CONFIG2,
62800
+ BUILD_CONFIG as BUILD_CONFIG3,
61294
62801
  CleoError as CleoError8,
61295
62802
  checkAllRegisteredProjects as checkAllRegisteredProjects2,
61296
62803
  checkStorageMigration,
@@ -61301,7 +62808,7 @@ import {
61301
62808
  async function getCurrentVersion() {
61302
62809
  const cleoHome = getCleoHome4();
61303
62810
  try {
61304
- const content = await readFile6(join28(cleoHome, "VERSION"), "utf-8");
62811
+ const content = await readFile6(join29(cleoHome, "VERSION"), "utf-8");
61305
62812
  return (content.split("\n")[0] ?? "unknown").trim();
61306
62813
  } catch {
61307
62814
  return "unknown";
@@ -61309,14 +62816,14 @@ async function getCurrentVersion() {
61309
62816
  }
61310
62817
  async function getNpmInstalledVersion() {
61311
62818
  try {
61312
- const { stdout } = await execAsync("npm", [
62819
+ const { stdout: stdout2 } = await execAsync("npm", [
61313
62820
  "ls",
61314
62821
  "-g",
61315
62822
  "@cleocode/cleo",
61316
62823
  "--depth=0",
61317
62824
  "--json"
61318
62825
  ]);
61319
- const data = JSON.parse(stdout);
62826
+ const data = JSON.parse(stdout2);
61320
62827
  return data.dependencies?.["@cleocode/cleo"]?.version ?? null;
61321
62828
  } catch {
61322
62829
  return null;
@@ -61324,19 +62831,19 @@ async function getNpmInstalledVersion() {
61324
62831
  }
61325
62832
  async function getDistTagVersion(tag) {
61326
62833
  try {
61327
- const { stdout } = await execAsync("npm", ["view", `@cleocode/cleo@${tag}`, "version"]);
61328
- const v = stdout.trim();
62834
+ const { stdout: stdout2 } = await execAsync("npm", ["view", `@cleocode/cleo@${tag}`, "version"]);
62835
+ const v = stdout2.trim();
61329
62836
  return v || null;
61330
62837
  } catch {
61331
62838
  if (tag === "latest") {
61332
62839
  try {
61333
- const { stdout } = await execAsync("curl", [
62840
+ const { stdout: stdout2 } = await execAsync("curl", [
61334
62841
  "-sL",
61335
62842
  "--max-time",
61336
62843
  "10",
61337
62844
  `https://api.github.com/repos/${GITHUB_REPO}/releases/latest`
61338
62845
  ]);
61339
- const data = JSON.parse(stdout);
62846
+ const data = JSON.parse(stdout2);
61340
62847
  return data.tag_name?.replace(/^v/, "") ?? null;
61341
62848
  } catch {
61342
62849
  return null;
@@ -61355,7 +62862,7 @@ async function writeRuntimeVersionMetadata(mode, source, version) {
61355
62862
  ];
61356
62863
  await import("node:fs/promises").then(
61357
62864
  ({ writeFile: writeFile4, mkdir: mkdir5 }) => mkdir5(cleoHome, { recursive: true }).then(
61358
- () => writeFile4(join28(cleoHome, "VERSION"), `${lines.join("\n")}
62865
+ () => writeFile4(join29(cleoHome, "VERSION"), `${lines.join("\n")}
61359
62866
  `, "utf-8")
61360
62867
  )
61361
62868
  );
@@ -61393,11 +62900,11 @@ async function runPostUpdateDiagnostics(opts) {
61393
62900
  input: process.stdin,
61394
62901
  output: process.stdout
61395
62902
  });
61396
- shouldMigrate = await new Promise((resolve8) => {
62903
+ shouldMigrate = await new Promise((resolve9) => {
61397
62904
  rl.question(" Do you want to run the upgrade now? [Y/n] ", (answer) => {
61398
62905
  rl.close();
61399
62906
  const clean = answer.trim().toLowerCase();
61400
- resolve8(clean === "" || clean === "y" || clean === "yes");
62907
+ resolve9(clean === "" || clean === "y" || clean === "yes");
61401
62908
  });
61402
62909
  });
61403
62910
  }
@@ -61537,7 +63044,7 @@ var init_self_update = __esm({
61537
63044
  init_progress();
61538
63045
  init_renderers();
61539
63046
  execAsync = promisify(execFile);
61540
- GITHUB_REPO = BUILD_CONFIG2.repository.fullName;
63047
+ GITHUB_REPO = BUILD_CONFIG3.repository.fullName;
61541
63048
  selfUpdateCommand = defineCommand({
61542
63049
  meta: {
61543
63050
  name: "self-update",
@@ -61764,10 +63271,13 @@ var init_self_update = __esm({
61764
63271
  // packages/cleo/src/cli/commands/sentient.ts
61765
63272
  var sentient_exports = {};
61766
63273
  __export(sentient_exports, {
63274
+ __setPromptAcceptExecutionForTest: () => __setPromptAcceptExecutionForTest,
63275
+ promptAcceptExecution: () => promptAcceptExecution,
61767
63276
  sentientCommand: () => sentientCommand
61768
63277
  });
61769
- import { join as join29 } from "node:path";
61770
- import { cwd as processCwd3 } from "node:process";
63278
+ import { join as join30 } from "node:path";
63279
+ import { cwd as processCwd3, stdin, stdout } from "node:process";
63280
+ import { createInterface as createInterface3 } from "node:readline/promises";
61771
63281
  import {
61772
63282
  getSentientDaemonStatus as getSentientDaemonStatus2,
61773
63283
  monitorWorkers,
@@ -61778,6 +63288,12 @@ import {
61778
63288
  stopSentientDaemon,
61779
63289
  WORKER_BUDGET_MS
61780
63290
  } from "@cleocode/core/sentient/daemon.js";
63291
+ import {
63292
+ appendSentientExecuteAudit,
63293
+ executeFixAction,
63294
+ extractFixActionFromNotesJson,
63295
+ parseFixAction
63296
+ } from "@cleocode/core/sentient/execute-action.js";
61781
63297
  import { safeRunProposeTick } from "@cleocode/core/sentient/propose-tick.js";
61782
63298
  import { patchSentientState, readSentientState as readSentientState2 } from "@cleocode/core/sentient/state.js";
61783
63299
  import { safeRunTick } from "@cleocode/core/sentient/tick.js";
@@ -61797,7 +63313,14 @@ function emitFailure3(code, message, _jsonMode, operation) {
61797
63313
  cliError(message, code, { name: code }, operation ? { operation } : void 0);
61798
63314
  process.exit(1);
61799
63315
  }
61800
- 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;
63316
+ function __setPromptAcceptExecutionForTest(next) {
63317
+ const prev = promptAcceptExecution;
63318
+ promptAcceptExecution = next;
63319
+ return () => {
63320
+ promptAcceptExecution = prev;
63321
+ };
63322
+ }
63323
+ 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;
61801
63324
  var init_sentient3 = __esm({
61802
63325
  "packages/cleo/src/cli/commands/sentient.ts"() {
61803
63326
  "use strict";
@@ -61841,7 +63364,7 @@ var init_sentient3 = __esm({
61841
63364
  return;
61842
63365
  }
61843
63366
  if (dryRun) {
61844
- const statePath2 = join29(projectRoot, SENTIENT_STATE_FILE2);
63367
+ const statePath2 = join30(projectRoot, SENTIENT_STATE_FILE2);
61845
63368
  const outcome = await safeRunTick({ projectRoot, statePath: statePath2, dryRun: true });
61846
63369
  emitSuccess2(
61847
63370
  { dryRun: true, outcome },
@@ -61957,7 +63480,7 @@ Logs: ${logPath}`
61957
63480
  const jsonMode = args.json === true;
61958
63481
  const dryRun = args["dry-run"] === true;
61959
63482
  try {
61960
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63483
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
61961
63484
  const outcome = await safeRunTick({ projectRoot, statePath, dryRun });
61962
63485
  emitSuccess2(
61963
63486
  { outcome, dryRun },
@@ -61995,19 +63518,42 @@ Logs: ${logPath}`
61995
63518
  }
61996
63519
  }
61997
63520
  });
63521
+ promptAcceptExecution = async (fixAction) => {
63522
+ const rl = createInterface3({ input: stdin, output: stdout });
63523
+ try {
63524
+ stdout.write(`[sentient] Proposal accepted. fixAction:
63525
+ $ ${fixAction}
63526
+ `);
63527
+ const answer = await rl.question("Execute now? [y/N] ");
63528
+ const normalised = answer.trim().toLowerCase();
63529
+ return normalised === "y" || normalised === "yes";
63530
+ } finally {
63531
+ rl.close();
63532
+ }
63533
+ };
61998
63534
  proposeAcceptSub = defineCommand({
61999
63535
  meta: {
62000
63536
  name: "accept",
62001
- description: "Accept a proposal \u2014 transition proposed \u2192 pending"
63537
+ description: "Accept a proposal \u2014 transition proposed \u2192 pending, optionally execute its fixAction"
62002
63538
  },
62003
63539
  args: {
62004
63540
  ...projectArgs2,
62005
- id: { type: "positional", description: "Proposal task ID", required: true }
63541
+ id: { type: "positional", description: "Proposal task ID", required: true },
63542
+ execute: {
63543
+ type: "boolean",
63544
+ description: "Execute proposal.fixAction without prompting"
63545
+ },
63546
+ "no-execute": {
63547
+ type: "boolean",
63548
+ description: "Skip fixAction execution even if the proposal carries one"
63549
+ }
62006
63550
  },
62007
63551
  async run({ args }) {
62008
63552
  const projectRoot = resolveProjectRoot6(args.project);
62009
63553
  const jsonMode = args.json === true;
62010
63554
  const id = args.id;
63555
+ const forceExecute = args.execute === true;
63556
+ const skipExecute = args["no-execute"] === true;
62011
63557
  try {
62012
63558
  const { getDb: getDb3 } = await import("@cleocode/core/store/sqlite.js");
62013
63559
  const { tasks } = await import("@cleocode/core/store/tasks-schema");
@@ -62026,7 +63572,7 @@ Logs: ${logPath}`
62026
63572
  return;
62027
63573
  }
62028
63574
  await db.update(tasks).set({ status: "pending", updatedAt: now }).where(eq2(tasks.id, id)).run();
62029
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63575
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
62030
63576
  const state = await readSentientState2(statePath);
62031
63577
  await patchSentientState(statePath, {
62032
63578
  tier2Stats: {
@@ -62034,10 +63580,54 @@ Logs: ${logPath}`
62034
63580
  proposalsAccepted: state.tier2Stats.proposalsAccepted + 1
62035
63581
  }
62036
63582
  });
63583
+ const fixAction = extractFixActionFromNotesJson(existing.notesJson ?? null);
63584
+ let shouldExecute = false;
63585
+ if (fixAction && !skipExecute) {
63586
+ if (forceExecute) {
63587
+ shouldExecute = true;
63588
+ } else {
63589
+ shouldExecute = await promptAcceptExecution(fixAction);
63590
+ }
63591
+ }
63592
+ if (!shouldExecute) {
63593
+ emitSuccess2(
63594
+ {
63595
+ id,
63596
+ status: "pending",
63597
+ acceptedAt: now,
63598
+ executed: false,
63599
+ fixAction: fixAction ?? null
63600
+ },
63601
+ jsonMode,
63602
+ `Proposal ${id} accepted \u2192 pending`
63603
+ );
63604
+ return;
63605
+ }
63606
+ const parsed = parseFixAction(fixAction);
63607
+ if (!parsed.ok) {
63608
+ emitFailure3(parsed.code, parsed.reason, jsonMode);
63609
+ return;
63610
+ }
63611
+ const result = await executeFixAction(parsed, { cwd: projectRoot });
63612
+ await appendSentientExecuteAudit(projectRoot, {
63613
+ proposalId: id,
63614
+ fixAction,
63615
+ exitCode: result.exitCode,
63616
+ durationMs: result.durationMs,
63617
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
63618
+ });
62037
63619
  emitSuccess2(
62038
- { id, status: "pending", acceptedAt: now },
63620
+ {
63621
+ id,
63622
+ status: "pending",
63623
+ acceptedAt: now,
63624
+ executed: true,
63625
+ exitCode: result.exitCode,
63626
+ stderrSnippet: result.stderrSnippet,
63627
+ fixAction
63628
+ },
62039
63629
  jsonMode,
62040
- `Proposal ${id} accepted \u2192 pending`
63630
+ `Proposal ${id} accepted \u2192 pending (fixAction exit=${result.exitCode})`
62041
63631
  );
62042
63632
  } catch (err) {
62043
63633
  const message = err instanceof Error ? err.message : String(err);
@@ -62078,7 +63668,7 @@ Logs: ${logPath}`
62078
63668
  return;
62079
63669
  }
62080
63670
  await db.update(tasks).set({ status: "cancelled", cancellationReason: reason, cancelledAt: now, updatedAt: now }).where(eq2(tasks.id, id)).run();
62081
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63671
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
62082
63672
  const state = await readSentientState2(statePath);
62083
63673
  await patchSentientState(statePath, {
62084
63674
  tier2Stats: {
@@ -62123,7 +63713,7 @@ Logs: ${logPath}`
62123
63713
  const projectRoot = resolveProjectRoot6(args.project);
62124
63714
  const jsonMode = args.json === true;
62125
63715
  try {
62126
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63716
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
62127
63717
  const outcome = await safeRunProposeTick({ projectRoot, statePath });
62128
63718
  emitSuccess2(
62129
63719
  { outcome },
@@ -62143,7 +63733,7 @@ Logs: ${logPath}`
62143
63733
  const projectRoot = resolveProjectRoot6(args.project);
62144
63734
  const jsonMode = args.json === true;
62145
63735
  try {
62146
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63736
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
62147
63737
  const updated = await patchSentientState(statePath, { tier2Enabled: true });
62148
63738
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals enabled");
62149
63739
  } catch (err) {
@@ -62162,7 +63752,7 @@ Logs: ${logPath}`
62162
63752
  const projectRoot = resolveProjectRoot6(args.project);
62163
63753
  const jsonMode = args.json === true;
62164
63754
  try {
62165
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63755
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
62166
63756
  const updated = await patchSentientState(statePath, { tier2Enabled: false });
62167
63757
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals disabled");
62168
63758
  } catch (err) {
@@ -62193,7 +63783,7 @@ Logs: ${logPath}`
62193
63783
  const projectRoot = resolveProjectRoot6(args.project);
62194
63784
  const jsonMode = args.json === true;
62195
63785
  try {
62196
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE2);
63786
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE2);
62197
63787
  const state = await readSentientState2(statePath);
62198
63788
  emitSuccess2(
62199
63789
  {
@@ -62833,15 +64423,15 @@ async function promptOwnerAuthPassword(sessionName) {
62833
64423
  );
62834
64424
  return null;
62835
64425
  }
62836
- const { createInterface: createInterface4 } = await import("node:readline");
64426
+ const { createInterface: createInterface5 } = await import("node:readline");
62837
64427
  const { deriveOwnerAuthToken } = await import("@cleocode/core/internal");
62838
- const rl = createInterface4({
64428
+ const rl = createInterface5({
62839
64429
  input: process.stdin,
62840
64430
  output: process.stderr,
62841
64431
  terminal: true
62842
64432
  });
62843
64433
  process.stderr.write(`[cleo] Enter owner-auth password for session "${sessionName}": `);
62844
- const password = await new Promise((resolve8) => {
64434
+ const password = await new Promise((resolve9) => {
62845
64435
  if (process.stdin.setRawMode) {
62846
64436
  process.stdin.setRawMode(
62847
64437
  true
@@ -62859,10 +64449,10 @@ async function promptOwnerAuthPassword(sessionName) {
62859
64449
  );
62860
64450
  }
62861
64451
  process.stderr.write("\n");
62862
- resolve8(pw);
64452
+ resolve9(pw);
62863
64453
  } else if (ch === "") {
62864
64454
  process.stderr.write("\n[cleo] Cancelled.\n");
62865
- resolve8("");
64455
+ resolve9("");
62866
64456
  } else if (ch === "\x7F" || ch === "\b") {
62867
64457
  pw = pw.slice(0, -1);
62868
64458
  } else {
@@ -62876,7 +64466,7 @@ async function promptOwnerAuthPassword(sessionName) {
62876
64466
  const token = deriveOwnerAuthToken(sessionName, password);
62877
64467
  return token;
62878
64468
  }
62879
- var startCommand7, endCommand, handoffCommand2, statusCommand14, resumeCommand2, findCommand6, listCommand23, gcCommand2, showCommand13, driftCommand, contextDriftCommand, suspendCommand, recordAssumptionCommand, recordDecisionCommand, decisionLogCommand, adoptCommand, lintCommand, sessionCommand;
64469
+ var startCommand7, endCommand, handoffCommand2, statusCommand14, resumeCommand2, findCommand7, listCommand23, gcCommand2, showCommand13, driftCommand, contextDriftCommand, suspendCommand, recordAssumptionCommand, recordDecisionCommand, decisionLogCommand, adoptCommand, lintCommand, sessionCommand;
62880
64470
  var init_session4 = __esm({
62881
64471
  "packages/cleo/src/cli/commands/session.ts"() {
62882
64472
  "use strict";
@@ -63106,7 +64696,7 @@ var init_session4 = __esm({
63106
64696
  );
63107
64697
  }
63108
64698
  });
63109
- findCommand6 = defineCommand({
64699
+ findCommand7 = defineCommand({
63110
64700
  meta: {
63111
64701
  name: "find",
63112
64702
  description: "Find sessions (lightweight discovery \u2014 minimal fields, low context cost)"
@@ -63469,7 +65059,7 @@ var init_session4 = __esm({
63469
65059
  handoff: handoffCommand2,
63470
65060
  status: statusCommand14,
63471
65061
  resume: resumeCommand2,
63472
- find: findCommand6,
65062
+ find: findCommand7,
63473
65063
  list: listCommand23,
63474
65064
  gc: gcCommand2,
63475
65065
  show: showCommand13,
@@ -63954,9 +65544,27 @@ var init_show2 = __esm({
63954
65544
  showCommand14 = defineCommand({
63955
65545
  meta: {
63956
65546
  name: "show",
63957
- description: "Show full task details by ID (returns complete task record with metadata, verification, lifecycle)"
65547
+ 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)"
65548
+ },
65549
+ args: {
65550
+ ...paramsToCittyArgs(getOperationParams("query", "tasks", "show")),
65551
+ // T9922 — MVI record projection opt-out flags. The global parser in
65552
+ // cli/index.ts reads these too; the declarations here surface them in
65553
+ // `cleo show --help` and document the contract for agents.
65554
+ verbose: {
65555
+ type: "boolean",
65556
+ description: "Return the full task record (description, acceptance, verification, evidence) instead of the MVI projection. T9922."
65557
+ },
65558
+ full: {
65559
+ type: "boolean",
65560
+ description: "Alias for --verbose. T9922."
65561
+ },
65562
+ // T9932 — 1-line summary render. Global flag; parsed by cli/index.ts.
65563
+ summary: {
65564
+ type: "boolean",
65565
+ description: 'Render the task as a single line "<id> [<status>] <title-truncated-60>". Composes with --output: --output {id|table|count|silent} wins. T9932.'
65566
+ }
63958
65567
  },
63959
- args: paramsToCittyArgs(getOperationParams("query", "tasks", "show")),
63960
65568
  async run({ args }) {
63961
65569
  await dispatchFromCli(
63962
65570
  "query",
@@ -64078,7 +65686,7 @@ function buildSkillsDoctorAdoptAdapters() {
64078
65686
  }
64079
65687
  };
64080
65688
  }
64081
- 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;
65689
+ 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;
64082
65690
  var init_skills2 = __esm({
64083
65691
  "packages/cleo/src/cli/commands/skills.ts"() {
64084
65692
  "use strict";
@@ -64136,7 +65744,7 @@ var init_skills2 = __esm({
64136
65744
  );
64137
65745
  }
64138
65746
  });
64139
- findCommand7 = defineCommand({
65747
+ findCommand8 = defineCommand({
64140
65748
  meta: {
64141
65749
  name: "find",
64142
65750
  description: "Federated skill search across local, canonical, and federation peers"
@@ -64821,7 +66429,7 @@ var init_skills2 = __esm({
64821
66429
  subCommands: {
64822
66430
  list: listCommand24,
64823
66431
  search: searchCommand4,
64824
- find: findCommand7,
66432
+ find: findCommand8,
64825
66433
  validate: validateCommand8,
64826
66434
  info: infoCommand,
64827
66435
  install: installCommand3,
@@ -65879,12 +67487,12 @@ var init_telemetry2 = __esm({
65879
67487
 
65880
67488
  // packages/cleo/src/cli/commands/templates/lib.ts
65881
67489
  import { readFileSync as readFileSync15 } from "node:fs";
65882
- import { isAbsolute as isAbsolute3, resolve as resolve6 } from "node:path";
67490
+ import { isAbsolute as isAbsolute3, resolve as resolve7 } from "node:path";
65883
67491
  import { getProjectRoot as getProjectRoot50 } from "@cleocode/core";
65884
67492
  import { resolveSourcePathAbsolute } from "@cleocode/core/templates/registry";
65885
67493
  function resolveProjectRoot7(raw) {
65886
67494
  if (typeof raw === "string" && raw.length > 0) {
65887
- return isAbsolute3(raw) ? raw : resolve6(process.cwd(), raw);
67495
+ return isAbsolute3(raw) ? raw : resolve7(process.cwd(), raw);
65888
67496
  }
65889
67497
  return getProjectRoot50();
65890
67498
  }
@@ -65905,8 +67513,8 @@ var init_lib = __esm({
65905
67513
  });
65906
67514
 
65907
67515
  // packages/cleo/src/cli/commands/templates/diff.ts
65908
- import { existsSync as existsSync15, readFileSync as readFileSync16 } from "node:fs";
65909
- import { join as join30 } from "node:path";
67516
+ import { existsSync as existsSync16, readFileSync as readFileSync16 } from "node:fs";
67517
+ import { join as join31 } from "node:path";
65910
67518
  import { getTemplateById } from "@cleocode/core/templates/registry";
65911
67519
  function unifiedDiff(a, b) {
65912
67520
  const aLines = a.length === 0 ? [] : a.split("\n");
@@ -65976,7 +67584,7 @@ var init_diff = __esm({
65976
67584
  let rendered;
65977
67585
  try {
65978
67586
  projectRoot = resolveProjectRoot7(args["project"]);
65979
- installPath = join30(projectRoot, entry.installPath);
67587
+ installPath = join31(projectRoot, entry.installPath);
65980
67588
  const source = readTemplateSource(entry);
65981
67589
  rendered = applySubstitution(entry, source).rendered;
65982
67590
  } catch (err) {
@@ -65987,7 +67595,7 @@ var init_diff = __esm({
65987
67595
  process.exit(1 /* GENERAL_ERROR */);
65988
67596
  return;
65989
67597
  }
65990
- if (!existsSync15(installPath)) {
67598
+ if (!existsSync16(installPath)) {
65991
67599
  const missingResult = {
65992
67600
  id,
65993
67601
  installPath,
@@ -66026,8 +67634,8 @@ ${unifiedDiff("", rendered)}`
66026
67634
  });
66027
67635
 
66028
67636
  // packages/cleo/src/cli/commands/templates/install.ts
66029
- import { existsSync as existsSync16, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync5 } from "node:fs";
66030
- import { dirname as dirname9, join as join31 } from "node:path";
67637
+ import { existsSync as existsSync17, mkdirSync as mkdirSync5, readFileSync as readFileSync17, writeFileSync as writeFileSync5 } from "node:fs";
67638
+ import { dirname as dirname9, join as join32 } from "node:path";
66031
67639
  import { getTemplateById as getTemplateById2 } from "@cleocode/core/templates/registry";
66032
67640
  var templatesInstallCommand;
66033
67641
  var init_install = __esm({
@@ -66081,7 +67689,7 @@ var init_install = __esm({
66081
67689
  let substituted;
66082
67690
  try {
66083
67691
  projectRoot = resolveProjectRoot7(args["project"]);
66084
- installPath = join31(projectRoot, entry.installPath);
67692
+ installPath = join32(projectRoot, entry.installPath);
66085
67693
  const source = readTemplateSource(entry);
66086
67694
  const sub = applySubstitution(entry, source);
66087
67695
  rendered = sub.rendered;
@@ -66094,7 +67702,7 @@ var init_install = __esm({
66094
67702
  process.exit(1 /* GENERAL_ERROR */);
66095
67703
  return;
66096
67704
  }
66097
- if (existsSync16(installPath)) {
67705
+ if (existsSync17(installPath)) {
66098
67706
  const current = readFileSync17(installPath, "utf8");
66099
67707
  if (current === rendered) {
66100
67708
  const noopResult = {
@@ -66139,7 +67747,7 @@ var init_install = __esm({
66139
67747
  });
66140
67748
 
66141
67749
  // packages/cleo/src/cli/commands/templates/list.ts
66142
- import { getTemplateManifest, getTemplatesByKind } from "@cleocode/core/templates/registry";
67750
+ import { getTemplateManifest, getTemplatesByKind as getTemplatesByKind2 } from "@cleocode/core/templates/registry";
66143
67751
  function parseTemplateKind(raw) {
66144
67752
  if (raw === void 0 || raw === "") return null;
66145
67753
  return TEMPLATE_KINDS.includes(raw) ? raw : null;
@@ -66178,7 +67786,7 @@ var init_list4 = __esm({
66178
67786
  process.exit(2 /* INVALID_INPUT */);
66179
67787
  return;
66180
67788
  }
66181
- const entries = kind === null ? getTemplateManifest() : getTemplatesByKind(kind);
67789
+ const entries = kind === null ? getTemplateManifest() : getTemplatesByKind2(kind);
66182
67790
  const result = { kind, entries };
66183
67791
  cliOutput(result, {
66184
67792
  command: "templates-list",
@@ -66243,8 +67851,8 @@ var init_show3 = __esm({
66243
67851
  });
66244
67852
 
66245
67853
  // packages/cleo/src/cli/commands/templates/upgrade.ts
66246
- import { existsSync as existsSync17, mkdirSync as mkdirSync6, readFileSync as readFileSync18, writeFileSync as writeFileSync6 } from "node:fs";
66247
- import { dirname as dirname10, join as join32 } from "node:path";
67854
+ import { existsSync as existsSync18, mkdirSync as mkdirSync6, readFileSync as readFileSync18, writeFileSync as writeFileSync6 } from "node:fs";
67855
+ import { dirname as dirname10, join as join33 } from "node:path";
66248
67856
  import { getTemplateById as getTemplateById4 } from "@cleocode/core/templates/registry";
66249
67857
  var templatesUpgradeCommand;
66250
67858
  var init_upgrade2 = __esm({
@@ -66306,7 +67914,7 @@ var init_upgrade2 = __esm({
66306
67914
  let rendered;
66307
67915
  try {
66308
67916
  projectRoot = resolveProjectRoot7(args["project"]);
66309
- installPath = join32(projectRoot, entry.installPath);
67917
+ installPath = join33(projectRoot, entry.installPath);
66310
67918
  const source = readTemplateSource(entry);
66311
67919
  rendered = applySubstitution(entry, source).rendered;
66312
67920
  } catch (err) {
@@ -66319,7 +67927,7 @@ var init_upgrade2 = __esm({
66319
67927
  }
66320
67928
  const previewOnly = args["diff"] === true;
66321
67929
  const accept = args["accept"] === true;
66322
- const current = existsSync17(installPath) ? readFileSync18(installPath, "utf8") : null;
67930
+ const current = existsSync18(installPath) ? readFileSync18(installPath, "utf8") : null;
66323
67931
  const diffBody = current === null ? "" : current === rendered ? "" : unifiedDiff(current, rendered);
66324
67932
  let outcome;
66325
67933
  let reason;
@@ -66869,7 +68477,7 @@ __export(transcript_exports, {
66869
68477
  transcriptCommand: () => transcriptCommand
66870
68478
  });
66871
68479
  import { homedir as homedir6 } from "node:os";
66872
- import { join as join33 } from "node:path";
68480
+ import { join as join34 } from "node:path";
66873
68481
  import { getProjectRoot as getProjectRoot52 } from "@cleocode/core";
66874
68482
  import {
66875
68483
  parseDurationMs,
@@ -66923,7 +68531,7 @@ var init_transcript = __esm({
66923
68531
  }
66924
68532
  return;
66925
68533
  }
66926
- const projectsDir = args["projects-dir"] ?? join33(homedir6(), ".claude", "projects");
68534
+ const projectsDir = args["projects-dir"] ?? join34(homedir6(), ".claude", "projects");
66927
68535
  try {
66928
68536
  const result = await scanTranscripts(projectsDir);
66929
68537
  cliOutput(
@@ -67229,7 +68837,7 @@ var init_transcript = __esm({
67229
68837
  process.exit(2);
67230
68838
  return;
67231
68839
  }
67232
- const projectsDir = args["projects-dir"] ?? join33(homedir6(), ".claude", "projects");
68840
+ const projectsDir = args["projects-dir"] ?? join34(homedir6(), ".claude", "projects");
67233
68841
  try {
67234
68842
  const pruneResult = await pruneTranscripts({
67235
68843
  olderThanMs,
@@ -67286,7 +68894,7 @@ var init_transcript = __esm({
67286
68894
  // packages/cleo/src/cli/commands/update.ts
67287
68895
  var update_exports = {};
67288
68896
  __export(update_exports, {
67289
- updateCommand: () => updateCommand2
68897
+ updateCommand: () => updateCommand3
67290
68898
  });
67291
68899
  import {
67292
68900
  appendSignedSeverityAttestation as appendSignedSeverityAttestation2,
@@ -67297,7 +68905,7 @@ import {
67297
68905
  TASK_PIPELINE_STAGES,
67298
68906
  validateOperationInput as validateOperationInput3
67299
68907
  } from "@cleocode/core";
67300
- var updateCommand2;
68908
+ var updateCommand3;
67301
68909
  var init_update = __esm({
67302
68910
  "packages/cleo/src/cli/commands/update.ts"() {
67303
68911
  "use strict";
@@ -67306,7 +68914,7 @@ var init_update = __esm({
67306
68914
  init_cli();
67307
68915
  init_collect_input();
67308
68916
  init_renderers();
67309
- updateCommand2 = defineCommand({
68917
+ updateCommand3 = defineCommand({
67310
68918
  meta: {
67311
68919
  name: "update",
67312
68920
  description: "Update a task. Safe under concurrent invocation \u2014 retries on SQLITE_BUSY up to 4 attempts (gh#391)."
@@ -67350,7 +68958,7 @@ var init_update = __esm({
67350
68958
  },
67351
68959
  priority: {
67352
68960
  type: "string",
67353
- description: "New priority (critical|high|medium|low)",
68961
+ description: "New priority (critical|high|medium|low). Orthogonal to --severity \u2014 see `cleo find --urgent` for the unified surface (T9905).",
67354
68962
  alias: "p"
67355
68963
  },
67356
68964
  type: {
@@ -67474,7 +69082,7 @@ var init_update = __esm({
67474
69082
  */
67475
69083
  severity: {
67476
69084
  type: "string",
67477
- description: "Severity level (P0|P1|P2|P3) \u2014 valid for any --role (T9073). Orthogonal to priority. Appends signed attestation."
69085
+ 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."
67478
69086
  },
67479
69087
  /**
67480
69088
  * Operator-supplied justification required to override the
@@ -67761,7 +69369,7 @@ var upgrade_exports = {};
67761
69369
  __export(upgrade_exports, {
67762
69370
  upgradeCommand: () => upgradeCommand
67763
69371
  });
67764
- import { resolve as resolve7 } from "node:path";
69372
+ import { resolve as resolve8 } from "node:path";
67765
69373
  import { CleoError as CleoError10, diagnoseUpgrade, runUpgrade as runUpgrade2, upgradeWorkflows as upgradeWorkflows2 } from "@cleocode/core/internal";
67766
69374
  var workflowsSubcommand, upgradeCommand;
67767
69375
  var init_upgrade3 = __esm({
@@ -67801,7 +69409,7 @@ var init_upgrade3 = __esm({
67801
69409
  const dryRun = args["dry-run"] === true || args.check === true;
67802
69410
  const force = args.force === true && !dryRun;
67803
69411
  const result = await upgradeWorkflows2({
67804
- projectRoot: resolve7(process.cwd()),
69412
+ projectRoot: resolve8(process.cwd()),
67805
69413
  templatesDir: getWorkflowTemplatesDir2(),
67806
69414
  dryRun,
67807
69415
  force
@@ -68060,17 +69668,17 @@ var web_exports = {};
68060
69668
  __export(web_exports, {
68061
69669
  webCommand: () => webCommand
68062
69670
  });
68063
- import { execFileSync as execFileSync3, spawn as spawn3 } from "node:child_process";
69671
+ import { execFileSync as execFileSync4, spawn as spawn3 } from "node:child_process";
68064
69672
  import { mkdir as mkdir4, open, readFile as readFile7, rm, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
68065
- import { join as join34 } from "node:path";
68066
- import { CleoError as CleoError11, formatError as formatError6, getCleoHome as getCleoHome5 } from "@cleocode/core";
69673
+ import { join as join35 } from "node:path";
69674
+ import { CleoError as CleoError11, formatError as formatError5, getCleoHome as getCleoHome5 } from "@cleocode/core";
68067
69675
  function getWebPaths() {
68068
69676
  const cleoHome = getCleoHome5();
68069
69677
  return {
68070
- pidFile: join34(cleoHome, "web-server.pid"),
68071
- configFile: join34(cleoHome, "web-server.json"),
68072
- logDir: join34(cleoHome, "logs"),
68073
- logFile: join34(cleoHome, "logs", "web-server.log")
69678
+ pidFile: join35(cleoHome, "web-server.pid"),
69679
+ configFile: join35(cleoHome, "web-server.json"),
69680
+ logDir: join35(cleoHome, "logs"),
69681
+ logFile: join35(cleoHome, "logs", "web-server.log")
68074
69682
  };
68075
69683
  }
68076
69684
  function isProcessRunning(pid) {
@@ -68109,7 +69717,7 @@ async function startWebServer(port, host) {
68109
69717
  throw new CleoError11(1 /* GENERAL_ERROR */, `Server already running (PID: ${status.pid})`);
68110
69718
  }
68111
69719
  const projectRoot = process.env["CLEO_ROOT"] ?? process.cwd();
68112
- const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join34(projectRoot, "packages", "studio", "build");
69720
+ const studioDir = process.env["CLEO_STUDIO_DIR"] ?? join35(projectRoot, "packages", "studio", "build");
68113
69721
  await mkdir4(logDir, { recursive: true });
68114
69722
  await writeFile3(
68115
69723
  configFile,
@@ -68119,12 +69727,12 @@ async function startWebServer(port, host) {
68119
69727
  startedAt: (/* @__PURE__ */ new Date()).toISOString()
68120
69728
  })
68121
69729
  );
68122
- const webIndexPath = join34(studioDir, "index.js");
69730
+ const webIndexPath = join35(studioDir, "index.js");
68123
69731
  try {
68124
69732
  await stat2(webIndexPath);
68125
69733
  } catch {
68126
69734
  try {
68127
- execFileSync3("pnpm", ["--filter", "@cleocode/studio", "run", "build"], {
69735
+ execFileSync4("pnpm", ["--filter", "@cleocode/studio", "run", "build"], {
68128
69736
  cwd: projectRoot,
68129
69737
  stdio: "ignore"
68130
69738
  });
@@ -68167,7 +69775,7 @@ Logs: ${logFile}`
68167
69775
  }
68168
69776
  } catch {
68169
69777
  }
68170
- await new Promise((resolve8) => setTimeout(resolve8, 500));
69778
+ await new Promise((resolve9) => setTimeout(resolve9, 500));
68171
69779
  }
68172
69780
  if (!started) {
68173
69781
  try {
@@ -68216,7 +69824,7 @@ var init_web = __esm({
68216
69824
  await startWebServer(Number.parseInt(args.port, 10), args.host);
68217
69825
  } catch (err) {
68218
69826
  if (err instanceof CleoError11) {
68219
- console.error(formatError6(err));
69827
+ console.error(formatError5(err));
68220
69828
  process.exit(err.code);
68221
69829
  }
68222
69830
  throw err;
@@ -68244,7 +69852,7 @@ var init_web = __esm({
68244
69852
  }
68245
69853
  for (let i = 0; i < 60; i++) {
68246
69854
  if (!isProcessRunning(status.pid)) break;
68247
- await new Promise((resolve8) => setTimeout(resolve8, 500));
69855
+ await new Promise((resolve9) => setTimeout(resolve9, 500));
68248
69856
  }
68249
69857
  if (isProcessRunning(status.pid)) {
68250
69858
  try {
@@ -68260,7 +69868,7 @@ var init_web = __esm({
68260
69868
  cliOutput({ stopped: true }, { command: "web", message: "CLEO Web UI stopped" });
68261
69869
  } catch (err) {
68262
69870
  if (err instanceof CleoError11) {
68263
- console.error(formatError6(err));
69871
+ console.error(formatError5(err));
68264
69872
  process.exit(err.code);
68265
69873
  }
68266
69874
  throw err;
@@ -68296,7 +69904,7 @@ var init_web = __esm({
68296
69904
  }
68297
69905
  for (let i = 0; i < 60; i++) {
68298
69906
  if (!isProcessRunning(status.pid)) break;
68299
- await new Promise((resolve8) => setTimeout(resolve8, 500));
69907
+ await new Promise((resolve9) => setTimeout(resolve9, 500));
68300
69908
  }
68301
69909
  if (isProcessRunning(status.pid)) {
68302
69910
  try {
@@ -68313,7 +69921,7 @@ var init_web = __esm({
68313
69921
  await startWebServer(Number.parseInt(args.port, 10), args.host);
68314
69922
  } catch (err) {
68315
69923
  if (err instanceof CleoError11) {
68316
- console.error(formatError6(err));
69924
+ console.error(formatError5(err));
68317
69925
  process.exit(err.code);
68318
69926
  }
68319
69927
  throw err;
@@ -68328,7 +69936,7 @@ var init_web = __esm({
68328
69936
  cliOutput(status, { command: "web" });
68329
69937
  } catch (err) {
68330
69938
  if (err instanceof CleoError11) {
68331
- console.error(formatError6(err));
69939
+ console.error(formatError5(err));
68332
69940
  process.exit(err.code);
68333
69941
  }
68334
69942
  throw err;
@@ -68361,7 +69969,7 @@ var init_web = __esm({
68361
69969
  cliOutput({ url }, { command: "web", message: `Open browser to: ${url}` });
68362
69970
  } catch (err) {
68363
69971
  if (err instanceof CleoError11) {
68364
- console.error(formatError6(err));
69972
+ console.error(formatError5(err));
68365
69973
  process.exit(err.code);
68366
69974
  }
68367
69975
  throw err;
@@ -68394,12 +70002,12 @@ __export(worktree_exports, {
68394
70002
  import readline4 from "node:readline";
68395
70003
  import { getProjectRoot as getProjectRoot53, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
68396
70004
  async function promptYesNo2(question) {
68397
- return new Promise((resolve8) => {
70005
+ return new Promise((resolve9) => {
68398
70006
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
68399
70007
  rl.question(`${question} [y/N]: `, (answer) => {
68400
70008
  rl.close();
68401
70009
  const trimmed = answer.trim().toLowerCase();
68402
- resolve8(trimmed === "y" || trimmed === "yes");
70010
+ resolve9(trimmed === "y" || trimmed === "yes");
68403
70011
  });
68404
70012
  });
68405
70013
  }
@@ -68733,7 +70341,7 @@ init_dist();
68733
70341
  init_field_context();
68734
70342
  init_format_context();
68735
70343
  import { readFileSync as readFileSync20 } from "node:fs";
68736
- import { dirname as dirname11, join as join36 } from "node:path";
70344
+ import { dirname as dirname11, join as join37 } from "node:path";
68737
70345
  import { fileURLToPath as fileURLToPath7 } from "node:url";
68738
70346
 
68739
70347
  // packages/cleo/src/cli/generated/command-manifest.ts
@@ -69126,7 +70734,7 @@ var COMMAND_MANIFEST = [
69126
70734
  exportName: "graphCommand",
69127
70735
  name: "graph",
69128
70736
  description: "Project-scoped code intelligence: symbol graph, impact analysis, clusters, flows",
69129
- load: async () => (await Promise.resolve().then(() => (init_graph2(), graph_exports))).graphCommand
70737
+ load: async () => (await Promise.resolve().then(() => (init_graph3(), graph_exports))).graphCommand
69130
70738
  },
69131
70739
  {
69132
70740
  exportName: "historyCommand",
@@ -69179,7 +70787,7 @@ var COMMAND_MANIFEST = [
69179
70787
  {
69180
70788
  exportName: "labelsCommand",
69181
70789
  name: "labels",
69182
- description: "List all labels with counts or show tasks with specific label",
70790
+ description: "List all labels (no args), or show tasks for a label (cleo labels <name>)",
69183
70791
  load: async () => (await Promise.resolve().then(() => (init_labels(), labels_exports))).labelsCommand
69184
70792
  },
69185
70793
  {
@@ -69461,7 +71069,7 @@ var COMMAND_MANIFEST = [
69461
71069
  {
69462
71070
  exportName: "showCommand",
69463
71071
  name: "show",
69464
- description: "Show full task details by ID (returns complete task record with metadata, verification, lifecycle)",
71072
+ 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)",
69465
71073
  load: async () => (await Promise.resolve().then(() => (init_show2(), show_exports))).showCommand
69466
71074
  },
69467
71075
  {
@@ -69747,14 +71355,14 @@ function lazyCommand(meta, loader2) {
69747
71355
  init_did_you_mean();
69748
71356
 
69749
71357
  // packages/cleo/src/cli/lib/first-run-detection.ts
69750
- import { existsSync as existsSync18 } from "node:fs";
69751
- import { join as join35 } from "node:path";
71358
+ import { existsSync as existsSync19 } from "node:fs";
71359
+ import { join as join36 } from "node:path";
69752
71360
  async function detectFirstRun() {
69753
71361
  const envKey = process.env["ANTHROPIC_API_KEY"];
69754
71362
  if (typeof envKey === "string" && envKey.length > 0) return false;
69755
71363
  const { getCleoPlatformPaths } = await import("@cleocode/paths");
69756
- const configPath = join35(getCleoPlatformPaths().config, "config.json");
69757
- if (existsSync18(configPath)) return false;
71364
+ const configPath = join36(getCleoPlatformPaths().config, "config.json");
71365
+ if (existsSync19(configPath)) return false;
69758
71366
  try {
69759
71367
  const { getCredentialPool } = await import("@cleocode/core/llm/credential-pool.js");
69760
71368
  const pool = getCredentialPool();
@@ -69765,7 +71373,7 @@ async function detectFirstRun() {
69765
71373
  return true;
69766
71374
  }
69767
71375
  function waitForEnterOrTimeout(timeoutMs) {
69768
- return new Promise((resolve8) => {
71376
+ return new Promise((resolve9) => {
69769
71377
  let resolved = false;
69770
71378
  const finish = () => {
69771
71379
  if (resolved) return;
@@ -69777,7 +71385,7 @@ function waitForEnterOrTimeout(timeoutMs) {
69777
71385
  process.stdin.pause();
69778
71386
  } catch {
69779
71387
  }
69780
- resolve8();
71388
+ resolve9();
69781
71389
  };
69782
71390
  const onData = (chunk) => {
69783
71391
  const s = typeof chunk === "string" ? chunk : chunk.toString("utf8");
@@ -69819,6 +71427,10 @@ function resolveFormat(opts, defaults) {
69819
71427
  return resolveOutputFormat(input2);
69820
71428
  }
69821
71429
 
71430
+ // packages/cleo/src/cli/index.ts
71431
+ init_output_context();
71432
+ init_projection_context();
71433
+
69822
71434
  // packages/cleo/src/cli/resolve-subcommand.ts
69823
71435
  async function resolveLazyValue(input2) {
69824
71436
  if (typeof input2 === "function") {
@@ -69846,6 +71458,7 @@ async function resolveSubCommandForHelp(cmd, rawArgs) {
69846
71458
  }
69847
71459
 
69848
71460
  // packages/cleo/src/cli/index.ts
71461
+ init_summary_context();
69849
71462
  {
69850
71463
  const [major] = process.versions.node.split(".").map(Number);
69851
71464
  if (typeof major !== "number" || major < 24) {
@@ -69868,7 +71481,7 @@ Or via NodeSource: https://github.com/nodesource/distributions
69868
71481
  }
69869
71482
  }
69870
71483
  function getPackageVersion() {
69871
- const pkgPath = join36(dirname11(fileURLToPath7(import.meta.url)), "../../package.json");
71484
+ const pkgPath = join37(dirname11(fileURLToPath7(import.meta.url)), "../../package.json");
69872
71485
  const pkg = JSON.parse(readFileSync20(pkgPath, "utf-8"));
69873
71486
  return pkg.version;
69874
71487
  }
@@ -69904,6 +71517,9 @@ alias("pipeline", "phaseCommand");
69904
71517
  async function startCli() {
69905
71518
  const argv = process.argv.slice(2);
69906
71519
  const rawOpts = {};
71520
+ let verboseFlag = false;
71521
+ let outputModeRaw;
71522
+ let summaryFlag = false;
69907
71523
  for (let i = 0; i < argv.length; i++) {
69908
71524
  const arg = argv[i];
69909
71525
  if (arg === "--json") rawOpts["json"] = true;
@@ -69912,6 +71528,9 @@ async function startCli() {
69912
71528
  else if (arg === "--field" && i + 1 < argv.length) rawOpts["field"] = argv[++i];
69913
71529
  else if (arg === "--fields" && i + 1 < argv.length) rawOpts["fields"] = argv[++i];
69914
71530
  else if (arg === "--mvi" && i + 1 < argv.length) rawOpts["mvi"] = argv[++i];
71531
+ else if (arg === "--verbose" || arg === "--full") verboseFlag = true;
71532
+ else if (arg === "--output" && i + 1 < argv.length) outputModeRaw = argv[++i];
71533
+ else if (arg === "--summary") summaryFlag = true;
69915
71534
  }
69916
71535
  const formatResolution = resolveFormat(rawOpts);
69917
71536
  setFormatContext(formatResolution);
@@ -69920,6 +71539,19 @@ async function startCli() {
69920
71539
  fieldResolution.mvi = "minimal";
69921
71540
  }
69922
71541
  setFieldContext(fieldResolution);
71542
+ setProjectionOptOut(verboseFlag || formatResolution.format === "human");
71543
+ if (outputModeRaw !== void 0) {
71544
+ if (!isOutputMode(outputModeRaw)) {
71545
+ process.stderr.write(
71546
+ `Error: invalid --output mode "${outputModeRaw}"
71547
+ Valid modes: envelope, id, table, count, silent
71548
+ `
71549
+ );
71550
+ process.exit(2);
71551
+ }
71552
+ setOutputMode(outputModeRaw);
71553
+ }
71554
+ setSummaryMode(summaryFlag);
69923
71555
  const isHelpOrVersion = argv.length === 0 || argv[0] === "--help" || argv[0] === "-h" || argv[0] === "--version" || argv[0] === "-V" || argv[0] === "help";
69924
71556
  if (argv[0] === "--version" || argv[0] === "-V") {
69925
71557
  const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
@@ -69927,6 +71559,10 @@ async function startCli() {
69927
71559
  return;
69928
71560
  }
69929
71561
  if (!isHelpOrVersion) {
71562
+ if (rawOpts["quiet"] === true) {
71563
+ const { setLoggerQuiet } = await import("@cleocode/core/internal");
71564
+ setLoggerQuiet(true);
71565
+ }
69930
71566
  await runStartupMaintenance();
69931
71567
  }
69932
71568
  if (!isHelpOrVersion) {