@cleocode/cleo 2026.5.111 → 2026.5.113

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli/index.js CHANGED
@@ -1079,6 +1079,33 @@ var init_braille = __esm({
1079
1079
  }
1080
1080
  });
1081
1081
 
1082
+ // packages/animations/src/render/legend.ts
1083
+ function renderLegend(input2) {
1084
+ if (!input2.ctx.enabled) return "";
1085
+ if (input2.items.length === 0) return "";
1086
+ const threshold = input2.multiLineThreshold ?? DEFAULT_MULTILINE_THRESHOLD;
1087
+ const formatted = input2.items.map((item) => `${item.icon} ${item.label}`);
1088
+ if (input2.items.length <= threshold) {
1089
+ return formatted.join(" ");
1090
+ }
1091
+ return formatted.join("\n");
1092
+ }
1093
+ function renderSummary(input2) {
1094
+ if (!input2.ctx.enabled) return "";
1095
+ if (input2.counts.length === 0) return "";
1096
+ const separator = input2.ctx.inputs.noColor ? SUMMARY_SEPARATOR_ASCII : SUMMARY_SEPARATOR;
1097
+ return input2.counts.map((c) => `${c.n} ${c.label}`).join(separator);
1098
+ }
1099
+ var DEFAULT_MULTILINE_THRESHOLD, SUMMARY_SEPARATOR, SUMMARY_SEPARATOR_ASCII;
1100
+ var init_legend = __esm({
1101
+ "packages/animations/src/render/legend.ts"() {
1102
+ "use strict";
1103
+ DEFAULT_MULTILINE_THRESHOLD = 8;
1104
+ SUMMARY_SEPARATOR = " \xB7 ";
1105
+ SUMMARY_SEPARATOR_ASCII = " | ";
1106
+ }
1107
+ });
1108
+
1082
1109
  // packages/animations/src/render/tree.ts
1083
1110
  import { ascii, KindIcon, StatusIcon } from "@cleocode/contracts/render/icon.js";
1084
1111
  function renderTree(resp, opts) {
@@ -1192,6 +1219,7 @@ var init_tree = __esm({
1192
1219
  // packages/animations/src/render/index.ts
1193
1220
  var init_render = __esm({
1194
1221
  "packages/animations/src/render/index.ts"() {
1222
+ init_legend();
1195
1223
  init_tree();
1196
1224
  }
1197
1225
  });
@@ -1712,6 +1740,63 @@ var init_cli_category = __esm({
1712
1740
  }
1713
1741
  });
1714
1742
 
1743
+ // packages/contracts/src/config/manifest.ts
1744
+ import { z as z4 } from "zod";
1745
+ var PROJECT_INFO_MANIFEST, PROJECT_CONTEXT_MANIFEST, CLEO_CONFIG_MANIFEST, GLOBAL_CLEO_CONFIG_MANIFEST, CONFIG_MANIFEST_ENTRIES, configManifestEntrySchema;
1746
+ var init_manifest = __esm({
1747
+ "packages/contracts/src/config/manifest.ts"() {
1748
+ "use strict";
1749
+ PROJECT_INFO_MANIFEST = {
1750
+ id: "project-info",
1751
+ scope: "metadata",
1752
+ path: ".cleo/project-info.json",
1753
+ mergePrecedence: 0,
1754
+ driftDetection: "schema-validate"
1755
+ };
1756
+ PROJECT_CONTEXT_MANIFEST = {
1757
+ id: "project-context",
1758
+ scope: "metadata",
1759
+ path: ".cleo/project-context.json",
1760
+ mergePrecedence: 0,
1761
+ driftDetection: "staleness-gate"
1762
+ };
1763
+ CLEO_CONFIG_MANIFEST = {
1764
+ id: "cleo-config-project",
1765
+ scope: "project",
1766
+ path: ".cleo/config.json",
1767
+ mergePrecedence: 20,
1768
+ driftDetection: "schema-validate"
1769
+ };
1770
+ GLOBAL_CLEO_CONFIG_MANIFEST = {
1771
+ id: "cleo-config-global",
1772
+ scope: "global",
1773
+ path: "~/.cleo/config.json",
1774
+ mergePrecedence: 10,
1775
+ driftDetection: "schema-validate"
1776
+ };
1777
+ CONFIG_MANIFEST_ENTRIES = Object.freeze([
1778
+ PROJECT_INFO_MANIFEST,
1779
+ PROJECT_CONTEXT_MANIFEST,
1780
+ GLOBAL_CLEO_CONFIG_MANIFEST,
1781
+ CLEO_CONFIG_MANIFEST
1782
+ ]);
1783
+ configManifestEntrySchema = z4.object({
1784
+ id: z4.string().min(1),
1785
+ scope: z4.union([z4.literal("global"), z4.literal("project"), z4.literal("metadata")]),
1786
+ path: z4.string().min(1),
1787
+ schema: z4.unknown().optional(),
1788
+ mergePrecedence: z4.number().int().nonnegative(),
1789
+ driftDetection: z4.union([
1790
+ z4.literal("schema-validate"),
1791
+ z4.literal("staleness-gate"),
1792
+ z4.literal("value-diff"),
1793
+ z4.literal("none")
1794
+ ]),
1795
+ defaults: z4.record(z4.string(), z4.unknown()).optional()
1796
+ });
1797
+ }
1798
+ });
1799
+
1715
1800
  // packages/contracts/src/credentials.ts
1716
1801
  var init_credentials = __esm({
1717
1802
  "packages/contracts/src/credentials.ts"() {
@@ -9660,6 +9745,100 @@ var init_operations_registry = __esm({
9660
9745
  }
9661
9746
  });
9662
9747
 
9748
+ // packages/contracts/src/docs/provenance.ts
9749
+ import { z as z5 } from "zod";
9750
+ var PROVENANCE_NODE_KINDS, PROVENANCE_EDGE_RELATIONS, DOC_LIFECYCLE_STATUSES, provenanceNodeKindSchema, provenanceEdgeRelationSchema, docLifecycleStatusSchema, provenanceNodeBaseFields, provenanceDocNodeSchema, provenanceTaskNodeSchema, provenanceDecisionNodeSchema, provenanceSessionNodeSchema, provenanceMemoryNodeSchema, provenanceNodeSchema, provenanceEdgeSchema, docProvenanceResponseSchema;
9751
+ var init_provenance = __esm({
9752
+ "packages/contracts/src/docs/provenance.ts"() {
9753
+ "use strict";
9754
+ PROVENANCE_NODE_KINDS = [
9755
+ "doc",
9756
+ "task",
9757
+ "decision",
9758
+ "session",
9759
+ "memory"
9760
+ ];
9761
+ PROVENANCE_EDGE_RELATIONS = [
9762
+ "attached-to",
9763
+ "supersedes",
9764
+ "superseded-by",
9765
+ "related-task",
9766
+ "linked-decision",
9767
+ "derived-from"
9768
+ ];
9769
+ DOC_LIFECYCLE_STATUSES = [
9770
+ "active",
9771
+ "superseded",
9772
+ "archived",
9773
+ "draft"
9774
+ ];
9775
+ provenanceNodeKindSchema = z5.enum(PROVENANCE_NODE_KINDS);
9776
+ provenanceEdgeRelationSchema = z5.enum(PROVENANCE_EDGE_RELATIONS);
9777
+ docLifecycleStatusSchema = z5.enum(DOC_LIFECYCLE_STATUSES);
9778
+ provenanceNodeBaseFields = {
9779
+ id: z5.string().min(1),
9780
+ title: z5.string().min(1),
9781
+ metadata: z5.record(z5.string(), z5.unknown()).optional()
9782
+ };
9783
+ provenanceDocNodeSchema = z5.object({
9784
+ ...provenanceNodeBaseFields,
9785
+ kind: z5.literal("doc"),
9786
+ slug: z5.string().min(1),
9787
+ docKind: z5.string().min(1),
9788
+ lifecycleStatus: docLifecycleStatusSchema,
9789
+ publishedAt: z5.string().min(1),
9790
+ supersededAt: z5.string().min(1).optional(),
9791
+ summary: z5.string().optional()
9792
+ });
9793
+ provenanceTaskNodeSchema = z5.object({
9794
+ ...provenanceNodeBaseFields,
9795
+ kind: z5.literal("task"),
9796
+ taskType: z5.enum(["saga", "epic", "task", "subtask"]),
9797
+ status: z5.enum(["pending", "in_progress", "done", "blocked", "cancelled", "archived"])
9798
+ });
9799
+ provenanceDecisionNodeSchema = z5.object({
9800
+ ...provenanceNodeBaseFields,
9801
+ kind: z5.literal("decision"),
9802
+ outcome: z5.enum(["proposed", "accepted", "rejected", "superseded"]),
9803
+ decidedAt: z5.string().min(1)
9804
+ });
9805
+ provenanceSessionNodeSchema = z5.object({
9806
+ ...provenanceNodeBaseFields,
9807
+ kind: z5.literal("session"),
9808
+ startedAt: z5.string().min(1),
9809
+ endedAt: z5.string().min(1).optional()
9810
+ });
9811
+ provenanceMemoryNodeSchema = z5.object({
9812
+ ...provenanceNodeBaseFields,
9813
+ kind: z5.literal("memory"),
9814
+ memoryType: z5.enum(["observation", "pattern", "decision", "diary"]),
9815
+ recordedAt: z5.string().min(1)
9816
+ });
9817
+ provenanceNodeSchema = z5.discriminatedUnion("kind", [
9818
+ provenanceDocNodeSchema,
9819
+ provenanceTaskNodeSchema,
9820
+ provenanceDecisionNodeSchema,
9821
+ provenanceSessionNodeSchema,
9822
+ provenanceMemoryNodeSchema
9823
+ ]);
9824
+ provenanceEdgeSchema = z5.object({
9825
+ relation: provenanceEdgeRelationSchema,
9826
+ from: z5.string().min(1),
9827
+ fromKind: provenanceNodeKindSchema,
9828
+ to: z5.string().min(1),
9829
+ toKind: provenanceNodeKindSchema,
9830
+ addedAt: z5.string().min(1),
9831
+ summary: z5.string().optional()
9832
+ });
9833
+ docProvenanceResponseSchema = z5.object({
9834
+ nodes: z5.array(provenanceNodeSchema).readonly(),
9835
+ edges: z5.array(provenanceEdgeSchema).readonly(),
9836
+ totalNodes: z5.number().int().nonnegative(),
9837
+ totalEdges: z5.number().int().nonnegative()
9838
+ });
9839
+ }
9840
+ });
9841
+
9663
9842
  // packages/contracts/src/docs-taxonomy.ts
9664
9843
  import { readFileSync } from "node:fs";
9665
9844
  import { join } from "node:path";
@@ -9734,6 +9913,24 @@ function validateExtensionEntry(raw, source, index) {
9734
9913
  source
9735
9914
  );
9736
9915
  }
9916
+ let requiredSections;
9917
+ if (obj.requiredSections !== void 0) {
9918
+ if (!Array.isArray(obj.requiredSections)) {
9919
+ throw new DocKindConfigError(`${where}: 'requiredSections' must be an array`, source);
9920
+ }
9921
+ const sections = [];
9922
+ for (let i = 0; i < obj.requiredSections.length; i++) {
9923
+ const item = obj.requiredSections[i];
9924
+ if (typeof item !== "string" || item.length === 0) {
9925
+ throw new DocKindConfigError(
9926
+ `${where}: 'requiredSections[${i}]' must be a non-empty string`,
9927
+ source
9928
+ );
9929
+ }
9930
+ sections.push(item);
9931
+ }
9932
+ requiredSections = sections;
9933
+ }
9737
9934
  return {
9738
9935
  kind,
9739
9936
  label,
@@ -9741,7 +9938,8 @@ function validateExtensionEntry(raw, source, index) {
9741
9938
  defaultOwnerKind,
9742
9939
  publishDir,
9743
9940
  requiresEntityId,
9744
- ...entityIdPattern !== void 0 ? { entityIdPattern } : {}
9941
+ ...entityIdPattern !== void 0 ? { entityIdPattern } : {},
9942
+ ...requiredSections !== void 0 ? { requiredSections } : {}
9745
9943
  };
9746
9944
  }
9747
9945
  function compileExtension(ext, source) {
@@ -9764,6 +9962,7 @@ function compileExtension(ext, source) {
9764
9962
  publishDir: ext.publishDir,
9765
9963
  requiresEntityId: ext.requiresEntityId,
9766
9964
  ...entityIdPattern !== void 0 ? { entityIdPattern } : {},
9965
+ ...ext.requiredSections !== void 0 ? { requiredSections: ext.requiredSections } : {},
9767
9966
  isExtension: true
9768
9967
  };
9769
9968
  }
@@ -9800,7 +9999,8 @@ var init_docs_taxonomy = __esm({
9800
9999
  defaultOwnerKind: "task",
9801
10000
  publishDir: "docs/adr",
9802
10001
  requiresEntityId: true,
9803
- entityIdPattern: /^adr-\d{3,4}-[a-z0-9-]+$/
10002
+ entityIdPattern: /^adr-\d{3,4}-[a-z0-9-]+$/,
10003
+ requiredSections: ["Status", "Date", "Context", "Decision", "Consequences"]
9804
10004
  },
9805
10005
  {
9806
10006
  kind: "spec",
@@ -9808,7 +10008,8 @@ var init_docs_taxonomy = __esm({
9808
10008
  description: "Technical specification",
9809
10009
  defaultOwnerKind: "task",
9810
10010
  publishDir: "docs/spec",
9811
- requiresEntityId: false
10011
+ requiresEntityId: false,
10012
+ requiredSections: ["Goal", "Non-Goals", "Requirements", "Out-of-Scope"]
9812
10013
  },
9813
10014
  {
9814
10015
  kind: "research",
@@ -9816,7 +10017,8 @@ var init_docs_taxonomy = __esm({
9816
10017
  description: "Investigation / research note",
9817
10018
  defaultOwnerKind: "task",
9818
10019
  publishDir: "docs/research",
9819
- requiresEntityId: false
10020
+ requiresEntityId: false,
10021
+ requiredSections: ["Question", "Findings", "Sources"]
9820
10022
  },
9821
10023
  {
9822
10024
  kind: "handoff",
@@ -9824,7 +10026,8 @@ var init_docs_taxonomy = __esm({
9824
10026
  description: "Session / agent handoff",
9825
10027
  defaultOwnerKind: "session",
9826
10028
  publishDir: "docs/handoff",
9827
- requiresEntityId: false
10029
+ requiresEntityId: false,
10030
+ requiredSections: ["Context", "State", "Next-Steps"]
9828
10031
  },
9829
10032
  {
9830
10033
  kind: "note",
@@ -9832,7 +10035,8 @@ var init_docs_taxonomy = __esm({
9832
10035
  description: "Agent observation / informal note",
9833
10036
  defaultOwnerKind: "observation",
9834
10037
  publishDir: "docs/note",
9835
- requiresEntityId: false
10038
+ requiresEntityId: false,
10039
+ requiredSections: []
9836
10040
  },
9837
10041
  {
9838
10042
  kind: "llm-readme",
@@ -9840,7 +10044,8 @@ var init_docs_taxonomy = __esm({
9840
10044
  description: "Machine-readable README (llms.txt)",
9841
10045
  defaultOwnerKind: "project",
9842
10046
  publishDir: ".",
9843
- requiresEntityId: false
10047
+ requiresEntityId: false,
10048
+ requiredSections: []
9844
10049
  },
9845
10050
  {
9846
10051
  kind: "changeset",
@@ -9849,7 +10054,8 @@ var init_docs_taxonomy = __esm({
9849
10054
  defaultOwnerKind: "task",
9850
10055
  publishDir: ".changeset",
9851
10056
  requiresEntityId: true,
9852
- entityIdPattern: /^t\d+-[a-z0-9-]+$/
10057
+ entityIdPattern: /^t\d+-[a-z0-9-]+$/,
10058
+ requiredSections: []
9853
10059
  },
9854
10060
  {
9855
10061
  kind: "release-note",
@@ -9858,7 +10064,8 @@ var init_docs_taxonomy = __esm({
9858
10064
  defaultOwnerKind: "project",
9859
10065
  publishDir: "docs/release",
9860
10066
  requiresEntityId: true,
9861
- entityIdPattern: /^v\d{4}\.\d+\.\d+(-[a-z0-9-]+)?$/
10067
+ entityIdPattern: /^v\d{4}\.\d+\.\d+(-[a-z0-9-]+)?$/,
10068
+ requiredSections: ["Changes", "Migration"]
9862
10069
  },
9863
10070
  {
9864
10071
  kind: "plan",
@@ -9866,7 +10073,8 @@ var init_docs_taxonomy = __esm({
9866
10073
  description: "Epic / saga decomposition plan",
9867
10074
  defaultOwnerKind: "task",
9868
10075
  publishDir: "docs/plan",
9869
- requiresEntityId: false
10076
+ requiresEntityId: false,
10077
+ requiredSections: ["Goal", "Steps", "Owners"]
9870
10078
  },
9871
10079
  {
9872
10080
  kind: "rcasd",
@@ -9875,7 +10083,8 @@ var init_docs_taxonomy = __esm({
9875
10083
  defaultOwnerKind: "task",
9876
10084
  publishDir: ".cleo/rcasd",
9877
10085
  requiresEntityId: true,
9878
- entityIdPattern: /^t\d+(-.+)?$/
10086
+ entityIdPattern: /^t\d+(-.+)?$/,
10087
+ requiredSections: ["Root-Cause", "Action", "Schedule", "Detection"]
9879
10088
  }
9880
10089
  ];
9881
10090
  BUILTIN_DOC_KIND_VALUES = Object.freeze(
@@ -10052,9 +10261,11 @@ var init_engine_result = __esm({
10052
10261
  });
10053
10262
 
10054
10263
  // packages/contracts/src/enums.ts
10264
+ var TASK_SEVERITIES;
10055
10265
  var init_enums = __esm({
10056
10266
  "packages/contracts/src/enums.ts"() {
10057
10267
  "use strict";
10268
+ TASK_SEVERITIES = ["P0", "P1", "P2", "P3"];
10058
10269
  }
10059
10270
  });
10060
10271
 
@@ -10184,59 +10395,139 @@ var init_errors = __esm({
10184
10395
  }
10185
10396
  });
10186
10397
 
10398
+ // packages/contracts/src/evidence-atom-schema.ts
10399
+ import { z as z6 } from "zod";
10400
+ var commitAtomSchema, filesAtomSchema, testRunAtomSchema, toolAtomSchema, urlAtomSchema, noteAtomSchema, decisionAtomSchema, prAtomSchema, locDropAtomSchema, callsiteCoverageAtomSchema, EvidenceAtomSchema, GATE_EVIDENCE_REQUIREMENTS;
10401
+ var init_evidence_atom_schema = __esm({
10402
+ "packages/contracts/src/evidence-atom-schema.ts"() {
10403
+ "use strict";
10404
+ commitAtomSchema = z6.object({
10405
+ kind: z6.literal("commit"),
10406
+ sha: z6.string().regex(/^[0-9a-f]{7,40}$/i, "commit sha must be 7-40 hex characters")
10407
+ });
10408
+ filesAtomSchema = z6.object({
10409
+ kind: z6.literal("files"),
10410
+ paths: z6.array(z6.string().min(1)).min(1, "files atom requires at least one path")
10411
+ });
10412
+ testRunAtomSchema = z6.object({
10413
+ kind: z6.literal("test-run"),
10414
+ path: z6.string().min(1, "test-run atom requires a non-empty path")
10415
+ });
10416
+ toolAtomSchema = z6.object({
10417
+ kind: z6.literal("tool"),
10418
+ tool: z6.string().min(1, "tool atom requires a non-empty tool name")
10419
+ });
10420
+ urlAtomSchema = z6.object({
10421
+ kind: z6.literal("url"),
10422
+ url: z6.string().min(1).regex(/^https?:\/\//, "url atom must start with http:// or https://")
10423
+ });
10424
+ noteAtomSchema = z6.object({
10425
+ kind: z6.literal("note"),
10426
+ note: z6.string().min(1, "note atom must be non-empty").max(512, "note atom is too long (max 512 chars)")
10427
+ });
10428
+ decisionAtomSchema = z6.object({
10429
+ kind: z6.literal("decision"),
10430
+ decisionId: z6.string().min(1, "decision atom requires a non-empty decision ID")
10431
+ });
10432
+ prAtomSchema = z6.object({
10433
+ kind: z6.literal("pr"),
10434
+ prNumber: z6.number().int().positive("pr atom requires a positive integer PR number")
10435
+ });
10436
+ locDropAtomSchema = z6.object({
10437
+ kind: z6.literal("loc-drop"),
10438
+ fromLines: z6.number().int().nonnegative("loc-drop fromLines must be \u2265 0"),
10439
+ toLines: z6.number().int().nonnegative("loc-drop toLines must be \u2265 0")
10440
+ });
10441
+ callsiteCoverageAtomSchema = z6.object({
10442
+ kind: z6.literal("callsite-coverage"),
10443
+ symbolName: z6.string().min(1, "callsite-coverage atom requires a non-empty symbolName"),
10444
+ relativeSourcePath: z6.string().min(1, "callsite-coverage atom requires a non-empty relativeSourcePath")
10445
+ });
10446
+ EvidenceAtomSchema = z6.discriminatedUnion("kind", [
10447
+ commitAtomSchema,
10448
+ filesAtomSchema,
10449
+ testRunAtomSchema,
10450
+ toolAtomSchema,
10451
+ urlAtomSchema,
10452
+ noteAtomSchema,
10453
+ decisionAtomSchema,
10454
+ prAtomSchema,
10455
+ locDropAtomSchema,
10456
+ callsiteCoverageAtomSchema
10457
+ ]);
10458
+ GATE_EVIDENCE_REQUIREMENTS = Object.freeze({
10459
+ implemented: {
10460
+ oneOf: [
10461
+ ["commit", "files"],
10462
+ ["commit", "note"],
10463
+ ["decision", "files"],
10464
+ ["decision", "note"],
10465
+ ["pr"]
10466
+ ]
10467
+ },
10468
+ testsPassed: { oneOf: [["test-run"], ["tool"], ["pr"]] },
10469
+ qaPassed: { oneOf: [["tool"], ["pr"]] },
10470
+ documented: { oneOf: [["files"], ["url"]] },
10471
+ securityPassed: { oneOf: [["tool"], ["note"]] },
10472
+ cleanupDone: { oneOf: [["note"]] },
10473
+ nexusImpact: { oneOf: [["tool"], ["note"]] }
10474
+ });
10475
+ }
10476
+ });
10477
+
10187
10478
  // packages/contracts/src/evidence-record-schema.ts
10188
- import { z as z4 } from "zod";
10479
+ import { z as z7 } from "zod";
10189
10480
  var evidenceBaseSchema, implDiffRecordSchema, validateSpecCheckRecordSchema, testOutputRecordSchema, lintReportRecordSchema, commandOutputRecordSchema, evidenceRecordSchema;
10190
10481
  var init_evidence_record_schema = __esm({
10191
10482
  "packages/contracts/src/evidence-record-schema.ts"() {
10192
10483
  "use strict";
10193
- evidenceBaseSchema = z4.object({
10484
+ evidenceBaseSchema = z7.object({
10194
10485
  /** Identity string of the agent that produced this record. */
10195
- agentIdentity: z4.string().min(1),
10486
+ agentIdentity: z7.string().min(1),
10196
10487
  /** SHA-256 hex digest (64 chars) of the attached artifact. */
10197
- attachmentSha256: z4.string().length(64),
10488
+ attachmentSha256: z7.string().length(64),
10198
10489
  /** ISO 8601 timestamp at which the action ran. */
10199
- ranAt: z4.string().datetime(),
10490
+ ranAt: z7.string().datetime(),
10200
10491
  /** Wall-clock duration of the action in milliseconds. */
10201
- durationMs: z4.number().nonnegative()
10492
+ durationMs: z7.number().nonnegative()
10202
10493
  });
10203
10494
  implDiffRecordSchema = evidenceBaseSchema.extend({
10204
- kind: z4.literal("impl-diff"),
10205
- phase: z4.literal("implement"),
10206
- filesChanged: z4.array(z4.string().min(1)).min(1),
10207
- linesAdded: z4.number().int().nonnegative(),
10208
- linesRemoved: z4.number().int().nonnegative()
10495
+ kind: z7.literal("impl-diff"),
10496
+ phase: z7.literal("implement"),
10497
+ filesChanged: z7.array(z7.string().min(1)).min(1),
10498
+ linesAdded: z7.number().int().nonnegative(),
10499
+ linesRemoved: z7.number().int().nonnegative()
10209
10500
  });
10210
10501
  validateSpecCheckRecordSchema = evidenceBaseSchema.extend({
10211
- kind: z4.literal("validate-spec-check"),
10212
- phase: z4.literal("validate"),
10213
- reqIdsChecked: z4.array(z4.string().min(1)).min(1),
10214
- passed: z4.boolean(),
10215
- details: z4.string().min(1)
10502
+ kind: z7.literal("validate-spec-check"),
10503
+ phase: z7.literal("validate"),
10504
+ reqIdsChecked: z7.array(z7.string().min(1)).min(1),
10505
+ passed: z7.boolean(),
10506
+ details: z7.string().min(1)
10216
10507
  });
10217
10508
  testOutputRecordSchema = evidenceBaseSchema.extend({
10218
- kind: z4.literal("test-output"),
10219
- phase: z4.literal("test"),
10220
- command: z4.string().min(1),
10221
- exitCode: z4.number().int(),
10222
- testsPassed: z4.number().int().nonnegative(),
10223
- testsFailed: z4.number().int().nonnegative()
10509
+ kind: z7.literal("test-output"),
10510
+ phase: z7.literal("test"),
10511
+ command: z7.string().min(1),
10512
+ exitCode: z7.number().int(),
10513
+ testsPassed: z7.number().int().nonnegative(),
10514
+ testsFailed: z7.number().int().nonnegative()
10224
10515
  });
10225
10516
  lintReportRecordSchema = evidenceBaseSchema.extend({
10226
- kind: z4.literal("lint-report"),
10227
- phase: z4.enum(["implement", "test"]),
10228
- tool: z4.string().min(1),
10229
- passed: z4.boolean(),
10230
- warnings: z4.number().int().nonnegative(),
10231
- errors: z4.number().int().nonnegative()
10517
+ kind: z7.literal("lint-report"),
10518
+ phase: z7.enum(["implement", "test"]),
10519
+ tool: z7.string().min(1),
10520
+ passed: z7.boolean(),
10521
+ warnings: z7.number().int().nonnegative(),
10522
+ errors: z7.number().int().nonnegative()
10232
10523
  });
10233
10524
  commandOutputRecordSchema = evidenceBaseSchema.extend({
10234
- kind: z4.literal("command-output"),
10235
- phase: z4.enum(["implement", "validate", "test"]),
10236
- cmd: z4.string().min(1),
10237
- exitCode: z4.number().int()
10525
+ kind: z7.literal("command-output"),
10526
+ phase: z7.enum(["implement", "validate", "test"]),
10527
+ cmd: z7.string().min(1),
10528
+ exitCode: z7.number().int()
10238
10529
  });
10239
- evidenceRecordSchema = z4.discriminatedUnion("kind", [
10530
+ evidenceRecordSchema = z7.discriminatedUnion("kind", [
10240
10531
  implDiffRecordSchema,
10241
10532
  validateSpecCheckRecordSchema,
10242
10533
  testOutputRecordSchema,
@@ -10260,6 +10551,458 @@ var init_graph = __esm({
10260
10551
  }
10261
10552
  });
10262
10553
 
10554
+ // packages/contracts/src/invariants/adr-056-release.ts
10555
+ var ARCHIVE_REASON_MODULE, RELEASE_INVARIANTS_REGISTRY_MODULE, RELEASE_COMMIT_MSG_HOOK, ADR_056_INVARIANTS;
10556
+ var init_adr_056_release = __esm({
10557
+ "packages/contracts/src/invariants/adr-056-release.ts"() {
10558
+ "use strict";
10559
+ ARCHIVE_REASON_MODULE = "packages/contracts/src/tasks/archive.ts";
10560
+ RELEASE_INVARIANTS_REGISTRY_MODULE = "packages/core/src/release/invariants/registry.ts";
10561
+ RELEASE_COMMIT_MSG_HOOK = "scripts/hooks/commit-msg-release-lint.mjs";
10562
+ ADR_056_INVARIANTS = Object.freeze([
10563
+ {
10564
+ adr: "ADR-056",
10565
+ code: "D1",
10566
+ name: "Database topology: keep per-domain split",
10567
+ description: "CLEO retains the six per-domain SQLite databases (tasks, brain, conduit, nexus, signaldock, telemetry) documented in DATABASE-ERDS.md. Consolidation is rejected to preserve per-DB WAL throughput, per-DB rollback granularity, and avoid single-writer contention during multi-agent waves.",
10568
+ severity: "info",
10569
+ // D1 is a topology decision; the absence of consolidation is its only
10570
+ // enforcement surface. No runtime guard, no lint script.
10571
+ runtimeGate: null,
10572
+ lintRule: null,
10573
+ doctorAudit: null,
10574
+ tests: []
10575
+ },
10576
+ {
10577
+ adr: "ADR-056",
10578
+ code: "D2",
10579
+ name: "Store-layer naming convention",
10580
+ description: "New always-on store-layer domains MUST use the kebab-case pair `packages/core/src/store/<domain>-schema.ts` (Drizzle defs) + `packages/core/src/store/<domain>-sqlite.ts` (open/init/CRUD). Opt-in / isolated domains MAY use the folder variant `packages/core/src/<domain>/{schema,sqlite}.ts` (currently telemetry only).",
10581
+ severity: "info",
10582
+ // D2 is a naming-convention decision; enforced by code review and the
10583
+ // ADR-073/ADR-056 doctor audit. No runtime guard.
10584
+ runtimeGate: null,
10585
+ lintRule: null,
10586
+ doctorAudit: null,
10587
+ tests: []
10588
+ },
10589
+ {
10590
+ adr: "ADR-056",
10591
+ code: "D3",
10592
+ name: "Migration runner SSoT under migration-manager.ts",
10593
+ description: "All six SQLite databases MUST be initialized via `packages/core/src/migration/migration-manager.ts` (`migrateWithRetry()` + `reconcileJournal()`). Per-DB bespoke runners are prohibited for new domains. Rust Diesel migrations for cloud signaldock-storage MUST NOT touch the local SQLite signaldock.db at runtime.",
10594
+ severity: "info",
10595
+ // D3 is enforced by the absence of bespoke runners — every domain's
10596
+ // `<domain>-sqlite.ts` open path delegates to migration-manager. No
10597
+ // single runtime guard; per-DB chokepoints are the enforcement surface.
10598
+ runtimeGate: null,
10599
+ lintRule: null,
10600
+ doctorAudit: null,
10601
+ tests: []
10602
+ },
10603
+ {
10604
+ adr: "ADR-056",
10605
+ code: "D4",
10606
+ name: "archiveReason 6-value enum with tombstone semantics",
10607
+ description: "The tasks.archive_reason column is constrained to exactly six values (verified, reconciled, superseded, shadowed, cancelled, completed-unverified) via SQLite CHECK constraint AND Zod z.enum validation. Writing 'completed-unverified' from non-migration code MUST throw E_ARCHIVE_REASON_TOMBSTONE \u2014 the tombstone is reserved for the T1408 backfill migration only.",
10608
+ severity: "error",
10609
+ runtimeGate: {
10610
+ module: ARCHIVE_REASON_MODULE,
10611
+ functionName: "assertArchiveReason"
10612
+ },
10613
+ lintRule: null,
10614
+ doctorAudit: null,
10615
+ tests: ["packages/contracts/src/tasks/__tests__/archive.test.ts"]
10616
+ },
10617
+ {
10618
+ adr: "ADR-056",
10619
+ code: "D5",
10620
+ name: "Post-release reconciliation: registry-driven cleo verify --release",
10621
+ description: "Post-release reconciliation flows through the executable invariants registry at packages/core/src/release/invariants/registry.ts. Customers register via registerInvariant() and the CLI runs every entry on `cleo verify --release <tag>`. First customer: archive-reason-invariant.ts (stamps verified tasks done; creates follow-up tasks for unverified references).",
10622
+ severity: "warning",
10623
+ runtimeGate: {
10624
+ module: RELEASE_INVARIANTS_REGISTRY_MODULE,
10625
+ functionName: "runInvariants"
10626
+ },
10627
+ lintRule: null,
10628
+ doctorAudit: null,
10629
+ tests: ["packages/core/src/release/invariants/__tests__/archive-reason-invariant.test.ts"]
10630
+ },
10631
+ {
10632
+ adr: "ADR-056",
10633
+ code: "D6",
10634
+ name: "Commit-message lint for release commits",
10635
+ description: "Every commit whose subject matches `^(chore|feat)\\(release\\):` MUST contain at least one `T\\d+` task reference in the commit body. Enforced by scripts/hooks/commit-msg-release-lint.mjs (T1410). Bypass via CLEO_OWNER_OVERRIDE=1 with audited justification.",
10636
+ severity: "info",
10637
+ // D6 is a CI-hook concern. The hook itself is the enforcement surface
10638
+ // — represented here via lintRule for cross-reference rendering.
10639
+ runtimeGate: null,
10640
+ lintRule: {
10641
+ lintScript: RELEASE_COMMIT_MSG_HOOK
10642
+ },
10643
+ doctorAudit: null,
10644
+ tests: []
10645
+ }
10646
+ ]);
10647
+ }
10648
+ });
10649
+
10650
+ // packages/contracts/src/invariants/adr-070-orchestration.ts
10651
+ var THIN_AGENT_MODULE, SESSIONS_MODULE, WORKTREE_CREATE_MODULE, CT_ORCHESTRATOR_SKILL, VALIDATE_SPAWN_MODULE, SKILL_VALIDATOR_TESTS, ADR_070_INVARIANTS, ADR_070_INVARIANT_COUNT;
10652
+ var init_adr_070_orchestration = __esm({
10653
+ "packages/contracts/src/invariants/adr-070-orchestration.ts"() {
10654
+ "use strict";
10655
+ THIN_AGENT_MODULE = "packages/core/src/orchestration/thin-agent.ts";
10656
+ SESSIONS_MODULE = "packages/core/src/sessions/index.ts";
10657
+ WORKTREE_CREATE_MODULE = "packages/worktree/src/worktree-create.ts";
10658
+ CT_ORCHESTRATOR_SKILL = "packages/skills/skills/ct-orchestrator/SKILL.md";
10659
+ VALIDATE_SPAWN_MODULE = "packages/core/src/orchestration/validate-spawn.ts";
10660
+ SKILL_VALIDATOR_TESTS = "packages/core/src/skills/orchestrator/__tests__/validator.test.ts";
10661
+ ADR_070_INVARIANTS = Object.freeze([
10662
+ {
10663
+ adr: "ADR-070",
10664
+ code: "ORC-001",
10665
+ name: "Orchestrator is the HITL interface",
10666
+ description: "The Orchestrator (Cleo) is the single subagent that talks to the human operator. It plans, decomposes, and delegates \u2014 it never produces line-level implementation. Source-of-truth lives in ct-orchestrator/SKILL.md row ORC-001 and is injected into the Orchestrator prompt at spawn time. UNENFORCED at the dispatch layer: this is a prompt-time invariant with no runtime guard today.",
10667
+ severity: "warning",
10668
+ runtimeGate: null,
10669
+ lintRule: null,
10670
+ doctorAudit: null,
10671
+ tests: [CT_ORCHESTRATOR_SKILL]
10672
+ },
10673
+ {
10674
+ adr: "ADR-070",
10675
+ code: "ORC-002",
10676
+ name: "Orchestrator MUST NOT write or edit code",
10677
+ description: "Every line of code is written by a spawned subagent. The Orchestrator delegates implementation work via cleo orchestrate spawn / delegate_task. UNENFORCED at the dispatch layer: this is a prompt-time invariant \u2014 there is no runtime gate that blocks the Orchestrator from calling Edit/Write, so the contract is held by the ct-orchestrator skill text.",
10678
+ severity: "warning",
10679
+ runtimeGate: null,
10680
+ lintRule: null,
10681
+ doctorAudit: null,
10682
+ tests: [CT_ORCHESTRATOR_SKILL]
10683
+ },
10684
+ {
10685
+ adr: "ADR-070",
10686
+ code: "ORC-003",
10687
+ name: "Orchestrator MUST NOT read full source files",
10688
+ description: "Orchestrator reads only pipeline manifests, task envelopes, and rolled-up phase summaries returned by Phase Leads. Workers read code; the Orchestrator reads summaries. UNENFORCED at the dispatch layer \u2014 held by the ct-orchestrator skill text and reinforced by ORC-005 budget pressure.",
10689
+ severity: "warning",
10690
+ runtimeGate: null,
10691
+ lintRule: null,
10692
+ doctorAudit: null,
10693
+ tests: [CT_ORCHESTRATOR_SKILL]
10694
+ },
10695
+ {
10696
+ adr: "ADR-070",
10697
+ code: "ORC-004",
10698
+ name: "Dependency-ordered spawning",
10699
+ description: "Spawns within a wave are ordered by task.depends \u2014 a Worker MUST NOT be dispatched until its declared dependencies are status=done. Surfaced by validateSpawnReadiness via V_MISSING_DEP / V_UNMET_DEP codes; surfaced by the skill-orchestrator validator via the ORC-004_DEPENDENCY_ORDER warning emitted from packages/core/src/skills/orchestrator/validator.ts. Tier: warning because the validator surfaces ordering issues but does not throw \u2014 workers can still proceed if the operator overrides.",
10700
+ severity: "warning",
10701
+ runtimeGate: {
10702
+ module: VALIDATE_SPAWN_MODULE,
10703
+ functionName: "validateSpawnReadiness"
10704
+ },
10705
+ lintRule: null,
10706
+ doctorAudit: null,
10707
+ tests: [
10708
+ "packages/core/src/orchestration/__tests__/validate-spawn.test.ts",
10709
+ SKILL_VALIDATOR_TESTS
10710
+ ]
10711
+ },
10712
+ {
10713
+ adr: "ADR-070",
10714
+ code: "ORC-005",
10715
+ name: "Orchestrator context budget \u2248 10 K tokens",
10716
+ description: "The Orchestrator MUST keep its working context under ~10 K tokens; delegate at 80 %. Surfaced by cleo orchestrate context (estimateContext) and by the skill-orchestrator validator (ORC-005_NO_MANIFEST / ORC-005_EMPTY_MANIFEST). UNENFORCED as a hard gate \u2014 the budget is advisory, surfaced to the Orchestrator as a warning so the human operator can intervene.",
10717
+ severity: "warning",
10718
+ runtimeGate: {
10719
+ module: "packages/core/src/orchestration/context.ts",
10720
+ functionName: "estimateContext"
10721
+ },
10722
+ lintRule: null,
10723
+ doctorAudit: null,
10724
+ tests: ["packages/core/src/orchestration/__tests__/"]
10725
+ },
10726
+ {
10727
+ adr: "ADR-070",
10728
+ code: "ORC-006",
10729
+ name: "Worker scope \u2264 3 files per spawn",
10730
+ description: "Cross-file reasoning quality degrades beyond ~3 files for a single Worker. Enforced at spawn-time by validateSpawnReadiness \u2014 V_ATOMIC_SCOPE_MISSING when task.files is empty, V_ATOMIC_SCOPE_TOO_LARGE when files.length > MAX_WORKER_FILES (currently 3). Spawn-prompt builder injects a Worker Budget Constraints section so the Worker sees the budget inline. Tier: error because the gate refuses to spawn an over-scoped Worker.",
10731
+ severity: "error",
10732
+ runtimeGate: {
10733
+ module: VALIDATE_SPAWN_MODULE,
10734
+ functionName: "validateSpawnReadiness"
10735
+ },
10736
+ lintRule: null,
10737
+ doctorAudit: null,
10738
+ tests: [
10739
+ "packages/core/src/orchestration/__tests__/validate-spawn.test.ts",
10740
+ "packages/core/src/orchestration/__tests__/spawn-prompt.test.ts"
10741
+ ]
10742
+ },
10743
+ {
10744
+ adr: "ADR-070",
10745
+ code: "ORC-007",
10746
+ name: "All work traced to an Epic",
10747
+ description: "Every Task and Subtask MUST attach to a parent Epic (directly or transitively). No orphan work \u2014 orphans are filed against the ADR-066 acceptance-criteria gate and surface via cleo find. UNENFORCED at the dispatch layer; the parent-id requirement is materialised through cleo add validation rather than a single ORC-named guard. R6 doctor audit should walk the task graph to surface orphans.",
10748
+ severity: "warning",
10749
+ runtimeGate: null,
10750
+ lintRule: null,
10751
+ doctorAudit: null,
10752
+ tests: [CT_ORCHESTRATOR_SKILL]
10753
+ },
10754
+ {
10755
+ adr: "ADR-070",
10756
+ code: "ORC-008",
10757
+ name: "Zero architectural decisions during execution",
10758
+ description: "Architectural choices MUST be pre-decided via RCASD consensus or HITL \u2014 never inside a worker session. UNENFORCED at the dispatch layer: this is a behavioural invariant held by the ct-orchestrator skill text plus the ADR-066 acceptance criterion that every task must declare its architecture-relevant decisions before spawn.",
10759
+ severity: "warning",
10760
+ runtimeGate: null,
10761
+ lintRule: null,
10762
+ doctorAudit: null,
10763
+ tests: [CT_ORCHESTRATOR_SKILL]
10764
+ },
10765
+ {
10766
+ adr: "ADR-070",
10767
+ code: "ORC-009",
10768
+ name: "Manifest-mediated handoffs",
10769
+ description: "Orchestrator reads only the key_findings field of pipeline_manifest rows when reconciling worker output. Subagents read the full task description and supporting files. UNENFORCED at the dispatch layer: the contract is held by the ct-orchestrator skill text and reinforced by ORC-003 + ORC-005 budget pressure.",
10770
+ severity: "warning",
10771
+ runtimeGate: null,
10772
+ lintRule: null,
10773
+ doctorAudit: null,
10774
+ tests: [CT_ORCHESTRATOR_SKILL]
10775
+ },
10776
+ {
10777
+ adr: "ADR-070",
10778
+ code: "ORC-010",
10779
+ name: "Lead-interposition required for Epic-child Workers",
10780
+ description: "A Worker spawn against a Task whose parent is type=epic MUST be preceded by a Lead spawn for the same Task (ADR-083 \xA72.4 / \xA76). The intended runtime gate (composeSpawnPayload throwing E_LEAD_REQUIRED_FOR_EPIC_CHILD) is FILED but UNSHIPPED \u2014 tracked under T10278. Registered here as a warning + runtimeGate:null so the gap is visible in the R6 doctor audit.",
10781
+ severity: "warning",
10782
+ runtimeGate: null,
10783
+ lintRule: null,
10784
+ doctorAudit: null,
10785
+ tests: []
10786
+ },
10787
+ {
10788
+ adr: "ADR-070",
10789
+ code: "ORC-011",
10790
+ name: "Orchestrator-depth cap at 3",
10791
+ description: "Recursive Orchestrator spawns (Cleo \u2192 sub-Orchestrator \u2192 sub-Orchestrator \u2192 \u2026) MUST stop at depth 3 (ADR-083 \xA72.2 + \xA72.4). The intended runtime gate (composeSpawnPayload throwing E_ORCHESTRATOR_DEPTH_EXCEEDED) is FILED but UNSHIPPED \u2014 tracked under T10279. Registered here as a warning + runtimeGate:null so the gap is visible in the R6 doctor audit.",
10792
+ severity: "warning",
10793
+ runtimeGate: null,
10794
+ lintRule: null,
10795
+ doctorAudit: null,
10796
+ tests: []
10797
+ },
10798
+ {
10799
+ adr: "ADR-070",
10800
+ code: "ORC-012",
10801
+ name: "Thin-agent inversion-of-control",
10802
+ description: "Workers MUST NOT spawn other subagents. The spawn-capable tools (Agent / Task / TaskCreate) are stripped from the Worker tool list at .cant compile time, and any survivor at spawn time triggers ThinAgentViolationError \u2192 E_THIN_AGENT_VIOLATION (exit 68). The only ORC rule with a hard-enforced dispatch-time gate today.",
10803
+ severity: "error",
10804
+ runtimeGate: {
10805
+ module: THIN_AGENT_MODULE,
10806
+ functionName: "enforceThinAgent"
10807
+ },
10808
+ lintRule: null,
10809
+ doctorAudit: null,
10810
+ tests: [
10811
+ "packages/core/src/orchestration/__tests__/thin-agent.test.ts",
10812
+ "packages/cant/src/__tests__/hierarchy.test.ts"
10813
+ ]
10814
+ },
10815
+ {
10816
+ adr: "ADR-070",
10817
+ code: "ORC-013",
10818
+ name: "Worktree provisioning at canonical XDG location",
10819
+ description: "Every agent worktree MUST be created under <cleoHome>/worktrees/<projectHash>/<taskId>/ (ADR-055 + Council D009). createWorktree throws E_WT_LOCATION_FORBIDDEN before any git worktree add call when the computed path falls outside the canonical root. CI gate lint-worktree-location.mjs enforces the same invariant on every PR. The single-most-load-bearing orchestration guard after ORC-012.",
10820
+ severity: "error",
10821
+ runtimeGate: {
10822
+ module: WORKTREE_CREATE_MODULE,
10823
+ functionName: "assertCanonicalWorktreeLocation"
10824
+ },
10825
+ lintRule: {
10826
+ lintScript: "scripts/lint-worktree-location.mjs"
10827
+ },
10828
+ doctorAudit: null,
10829
+ tests: ["packages/worktree/src/__tests__/"]
10830
+ },
10831
+ {
10832
+ adr: "ADR-070",
10833
+ code: "ORC-014",
10834
+ name: "Lead-bypass detection at session end",
10835
+ description: "A Lead session (CLEO_AGENT_ROLE=lead) that ends with tasks_completed > 0 AND delegate_task_count = 0 is rejected with LeadBypassDetectedError \u2192 E_LEAD_BYPASS_DETECTED (exit 107). Leads MUST fan out work to Workers; a Lead that did the work itself defeats the three-tier topology. Override via CLEO_OWNER_OVERRIDE=1 (audited to force-bypass.jsonl).",
10836
+ severity: "error",
10837
+ runtimeGate: {
10838
+ module: SESSIONS_MODULE,
10839
+ functionName: "endSession"
10840
+ },
10841
+ lintRule: null,
10842
+ doctorAudit: null,
10843
+ tests: ["packages/core/src/sessions/__tests__/"]
10844
+ }
10845
+ ]);
10846
+ ADR_070_INVARIANT_COUNT = ADR_070_INVARIANTS.length;
10847
+ }
10848
+ });
10849
+
10850
+ // packages/contracts/src/invariants/adr-073-saga.ts
10851
+ var SAGA_ENFORCEMENT_MODULE, SAGA_ENFORCEMENT_TESTS, ADR_073_INVARIANTS;
10852
+ var init_adr_073_saga = __esm({
10853
+ "packages/contracts/src/invariants/adr-073-saga.ts"() {
10854
+ "use strict";
10855
+ SAGA_ENFORCEMENT_MODULE = "packages/core/src/sagas/enforcement.ts";
10856
+ SAGA_ENFORCEMENT_TESTS = "packages/core/src/sagas/__tests__/enforcement.test.ts";
10857
+ ADR_073_INVARIANTS = Object.freeze([
10858
+ {
10859
+ adr: "ADR-073",
10860
+ code: "I1",
10861
+ name: "Storage uniformity",
10862
+ description: 'All task IDs are stored as T#### and the type column is the canonical tier discriminator. There is no separate ID space for Sagas, Epics, Tasks, or Subtasks; label="saga" elevates a type="epic" row to Saga semantics.',
10863
+ severity: "info",
10864
+ // I1 is enforced by the DB CHECK constraints introduced in W1.B (T10329)
10865
+ // and by TASK_ID_PATTERN in packages/core/src/tasks/id-generator.ts —
10866
+ // not by a single runtime function.
10867
+ runtimeGate: null,
10868
+ lintRule: null,
10869
+ doctorAudit: null,
10870
+ tests: ["packages/core/src/tasks/__tests__/id-generator.test.ts"]
10871
+ },
10872
+ {
10873
+ adr: "ADR-073",
10874
+ code: "I2",
10875
+ name: "Conceptual prefixes are display + import only",
10876
+ description: "SG-, E-, T- (and Subtask's implicit absence) are documentation, CLI display, and import-mapping conventions only. They MUST NOT be used as DB primary keys \u2014 display-only with no runtime enforcement.",
10877
+ severity: "info",
10878
+ // I2 is a display convention; the SG- prefix preservation snapshot
10879
+ // (T10333) protects the display contract but there is no runtime guard.
10880
+ runtimeGate: null,
10881
+ lintRule: null,
10882
+ doctorAudit: null,
10883
+ tests: []
10884
+ },
10885
+ {
10886
+ adr: "ADR-073",
10887
+ code: "I3",
10888
+ name: "Tier promotion mandatory when scope outgrows the tier",
10889
+ description: "A Subtask whose change exceeds 2 files or crosses a module boundary MUST be split or promoted to a sibling Task. A Task that requires more than one PR or wave MUST be split. An Epic that spans more than one release MUST be regrouped under a Saga.",
10890
+ severity: "error",
10891
+ runtimeGate: {
10892
+ module: SAGA_ENFORCEMENT_MODULE,
10893
+ functionName: "assertSagaInvariantI3"
10894
+ },
10895
+ lintRule: null,
10896
+ doctorAudit: null,
10897
+ tests: [SAGA_ENFORCEMENT_TESTS]
10898
+ },
10899
+ {
10900
+ adr: "ADR-073",
10901
+ code: "I4",
10902
+ name: "Ownership non-overlapping",
10903
+ description: "A single tier maps to a single orchestration role (per ADR-070). Workers MUST NOT spawn other Workers. Phase Leads MUST NOT own multiple Epics simultaneously. The Orchestrator MUST NOT spawn Workers directly when fan-out exceeds the ADR-070 migration threshold.",
10904
+ severity: "warning",
10905
+ // I4 is partially covered by ADR-070 spawn guards but the unification
10906
+ // with the registry happens in R2 (T10336 — ORC codes). For now this
10907
+ // entry stays warning + runtimeGate:null to mark the gap explicitly.
10908
+ runtimeGate: null,
10909
+ lintRule: null,
10910
+ doctorAudit: null,
10911
+ tests: []
10912
+ },
10913
+ {
10914
+ adr: "ADR-073",
10915
+ code: "I5",
10916
+ name: "Sagas link via groups, not parent",
10917
+ description: `task_relations.type="groups" is the ONLY relation type that links a Saga to its member Epics. The Saga row's parent_id MUST be NULL. Enforced at runtime by assertSagaInvariantI5 AND by the DB CHECK constraint from W1.B (T10329) on label="saga" rows.`,
10918
+ severity: "error",
10919
+ runtimeGate: {
10920
+ module: SAGA_ENFORCEMENT_MODULE,
10921
+ functionName: "assertSagaInvariantI5"
10922
+ },
10923
+ lintRule: null,
10924
+ doctorAudit: null,
10925
+ tests: [SAGA_ENFORCEMENT_TESTS]
10926
+ },
10927
+ {
10928
+ adr: "ADR-073",
10929
+ code: "I6",
10930
+ name: "Acceptance criteria required at every tier",
10931
+ description: 'Per ADR-066 \xA7"Ownership Matrix" invariant #5, all tasks regardless of type or kind MUST have --acceptance set at creation time. No tier exemption exists. Delegated to the ADR-066 --acceptance requirement on cleo add/add-batch.',
10932
+ severity: "warning",
10933
+ // I6 is enforced by ADR-066's CLI requirement, not by a saga runtime
10934
+ // function. UNENFORCED in the saga module — left as a warning so R6
10935
+ // doctor audit reminds operators of the upstream guard's location.
10936
+ runtimeGate: null,
10937
+ lintRule: null,
10938
+ doctorAudit: null,
10939
+ tests: []
10940
+ },
10941
+ {
10942
+ adr: "ADR-073",
10943
+ code: "I7",
10944
+ name: "Maximum parent depth is 3",
10945
+ description: "The parent ladder Subtask \u2192 Task \u2192 Epic is fixed at depth 3 (hierarchy.maxDepth=3). Sagas do NOT consume depth \u2014 they attach via groups relations, not parent edges. Enforced at runtime by assertSagaInvariantI7.",
10946
+ severity: "error",
10947
+ runtimeGate: {
10948
+ module: SAGA_ENFORCEMENT_MODULE,
10949
+ functionName: "assertSagaInvariantI7"
10950
+ },
10951
+ lintRule: null,
10952
+ doctorAudit: null,
10953
+ tests: [SAGA_ENFORCEMENT_TESTS]
10954
+ },
10955
+ {
10956
+ adr: "ADR-073",
10957
+ code: "I8",
10958
+ name: "Subtask-to-PR aggregation rule",
10959
+ description: "A Task ships as exactly one PR. The PR's commit history is the union of the Task's Subtask commits. A Subtask never produces its own PR; if a unit of work warrants its own PR, it is a Task, not a Subtask. UNENFORCED at runtime today \u2014 load-bearing convention enforced via code review and the lifecycle decision table.",
10960
+ severity: "warning",
10961
+ // I8 is explicitly "UNENFORCED, load-bearing" — there is no automated
10962
+ // gate. R6 doctor audit surfaces this entry so it stays visible.
10963
+ runtimeGate: null,
10964
+ lintRule: null,
10965
+ doctorAudit: null,
10966
+ tests: []
10967
+ }
10968
+ ]);
10969
+ }
10970
+ });
10971
+
10972
+ // packages/contracts/src/invariants/index.ts
10973
+ function buildKey(invariant) {
10974
+ return `${invariant.adr}.${invariant.code}`;
10975
+ }
10976
+ function buildRegistry() {
10977
+ const entries = [
10978
+ ...ADR_073_INVARIANTS,
10979
+ ...ADR_056_INVARIANTS,
10980
+ ...ADR_070_INVARIANTS
10981
+ ];
10982
+ const record = {};
10983
+ for (const entry of entries) {
10984
+ const key = buildKey(entry);
10985
+ if (record[key] !== void 0) {
10986
+ throw new Error(`Duplicate invariant key registered: ${key}`);
10987
+ }
10988
+ record[key] = entry;
10989
+ }
10990
+ return Object.freeze(record);
10991
+ }
10992
+ var INVARIANTS_REGISTRY;
10993
+ var init_invariants = __esm({
10994
+ "packages/contracts/src/invariants/index.ts"() {
10995
+ "use strict";
10996
+ init_adr_056_release();
10997
+ init_adr_070_orchestration();
10998
+ init_adr_073_saga();
10999
+ init_adr_056_release();
11000
+ init_adr_070_orchestration();
11001
+ init_adr_073_saga();
11002
+ INVARIANTS_REGISTRY = buildRegistry();
11003
+ }
11004
+ });
11005
+
10263
11006
  // packages/contracts/src/lafs.ts
10264
11007
  var init_lafs = __esm({
10265
11008
  "packages/contracts/src/lafs.ts"() {
@@ -11066,31 +11809,31 @@ var init_peer = __esm({
11066
11809
  });
11067
11810
 
11068
11811
  // packages/contracts/src/release/evidence-atoms.ts
11069
- import { z as z5 } from "zod";
11812
+ import { z as z8 } from "zod";
11070
11813
  var parsedPrEvidenceAtomSchema, prEvidenceStateModifierSchema, ghPrViewSchema, PR_REQUIRED_WORKFLOWS;
11071
11814
  var init_evidence_atoms = __esm({
11072
11815
  "packages/contracts/src/release/evidence-atoms.ts"() {
11073
11816
  "use strict";
11074
- parsedPrEvidenceAtomSchema = z5.object({
11075
- kind: z5.literal("pr"),
11076
- prNumber: z5.number().int().positive()
11077
- });
11078
- prEvidenceStateModifierSchema = z5.object({
11079
- kind: z5.literal("state"),
11080
- value: z5.literal("MERGED")
11081
- });
11082
- ghPrViewSchema = z5.object({
11083
- state: z5.enum(["OPEN", "CLOSED", "MERGED"]),
11084
- mergedAt: z5.string().nullable(),
11085
- headRefOid: z5.string().optional(),
11086
- mergeable: z5.string().optional(),
11087
- statusCheckRollup: z5.array(
11088
- z5.object({
11089
- __typename: z5.string().optional(),
11090
- name: z5.string().optional(),
11091
- workflowName: z5.string().optional(),
11092
- conclusion: z5.string().nullable().optional(),
11093
- status: z5.string().optional()
11817
+ parsedPrEvidenceAtomSchema = z8.object({
11818
+ kind: z8.literal("pr"),
11819
+ prNumber: z8.number().int().positive()
11820
+ });
11821
+ prEvidenceStateModifierSchema = z8.object({
11822
+ kind: z8.literal("state"),
11823
+ value: z8.literal("MERGED")
11824
+ });
11825
+ ghPrViewSchema = z8.object({
11826
+ state: z8.enum(["OPEN", "CLOSED", "MERGED"]),
11827
+ mergedAt: z8.string().nullable(),
11828
+ headRefOid: z8.string().optional(),
11829
+ mergeable: z8.string().optional(),
11830
+ statusCheckRollup: z8.array(
11831
+ z8.object({
11832
+ __typename: z8.string().optional(),
11833
+ name: z8.string().optional(),
11834
+ workflowName: z8.string().optional(),
11835
+ conclusion: z8.string().nullable().optional(),
11836
+ status: z8.string().optional()
11094
11837
  }).passthrough()
11095
11838
  ).optional().default([])
11096
11839
  }).passthrough();
@@ -11103,7 +11846,7 @@ var init_evidence_atoms = __esm({
11103
11846
  });
11104
11847
 
11105
11848
  // packages/contracts/src/release/plan.ts
11106
- import { z as z6 } from "zod";
11849
+ import { z as z9 } from "zod";
11107
11850
  var RELEASE_CHANNEL, RELEASE_SCHEME, RELEASE_KIND, RELEASE_STATUS, GATE_STATUS, GATE_NAME, PLATFORM_TUPLE, PUBLISHER, TASK_KIND, IMPACT, RESOLVED_SOURCE, ReleaseChannelSchema, ReleaseSchemeSchema, ReleaseKindSchema, ReleaseStatusSchema, GateStatusSchema, GateNameSchema, PlatformTupleSchema, PublisherSchema, TaskKindSchema, ImpactSchema, ResolvedSourceSchema, Iso8601, NonEmptyString, ReleasePlanTaskSchema, ReleaseGateSchema, ReleasePlatformMatrixEntrySchema, ReleasePreflightSummarySchema, ReleasePlanChangelogSchema, ReleasePlanMetaSchema, ReleasePlanSchema;
11108
11851
  var init_plan = __esm({
11109
11852
  "packages/contracts/src/release/plan.ts"() {
@@ -11146,20 +11889,20 @@ var init_plan = __esm({
11146
11889
  ];
11147
11890
  IMPACT = ["major", "minor", "patch"];
11148
11891
  RESOLVED_SOURCE = ["project-context", "language-default", "legacy-alias"];
11149
- ReleaseChannelSchema = z6.enum(RELEASE_CHANNEL);
11150
- ReleaseSchemeSchema = z6.enum(RELEASE_SCHEME);
11151
- ReleaseKindSchema = z6.enum(RELEASE_KIND);
11152
- ReleaseStatusSchema = z6.enum(RELEASE_STATUS);
11153
- GateStatusSchema = z6.enum(GATE_STATUS);
11154
- GateNameSchema = z6.enum(GATE_NAME);
11155
- PlatformTupleSchema = z6.enum(PLATFORM_TUPLE);
11156
- PublisherSchema = z6.enum(PUBLISHER);
11157
- TaskKindSchema = z6.enum(TASK_KIND);
11158
- ImpactSchema = z6.enum(IMPACT);
11159
- ResolvedSourceSchema = z6.enum(RESOLVED_SOURCE);
11160
- Iso8601 = z6.iso.datetime({ offset: true });
11161
- NonEmptyString = z6.string().min(1);
11162
- ReleasePlanTaskSchema = z6.object({
11892
+ ReleaseChannelSchema = z9.enum(RELEASE_CHANNEL);
11893
+ ReleaseSchemeSchema = z9.enum(RELEASE_SCHEME);
11894
+ ReleaseKindSchema = z9.enum(RELEASE_KIND);
11895
+ ReleaseStatusSchema = z9.enum(RELEASE_STATUS);
11896
+ GateStatusSchema = z9.enum(GATE_STATUS);
11897
+ GateNameSchema = z9.enum(GATE_NAME);
11898
+ PlatformTupleSchema = z9.enum(PLATFORM_TUPLE);
11899
+ PublisherSchema = z9.enum(PUBLISHER);
11900
+ TaskKindSchema = z9.enum(TASK_KIND);
11901
+ ImpactSchema = z9.enum(IMPACT);
11902
+ ResolvedSourceSchema = z9.enum(RESOLVED_SOURCE);
11903
+ Iso8601 = z9.iso.datetime({ offset: true });
11904
+ NonEmptyString = z9.string().min(1);
11905
+ ReleasePlanTaskSchema = z9.object({
11163
11906
  /** Task ID (e.g. "T10001"). Format intentionally loose so historical IDs validate. */
11164
11907
  id: NonEmptyString,
11165
11908
  /** Conventional-commit-aligned task classification. */
@@ -11167,20 +11910,20 @@ var init_plan = __esm({
11167
11910
  /** SemVer impact classification. */
11168
11911
  impact: ImpactSchema,
11169
11912
  /** Human-readable changelog line for this task. */
11170
- userFacingSummary: z6.string(),
11913
+ userFacingSummary: z9.string(),
11171
11914
  /**
11172
11915
  * ADR-051 evidence atoms attesting the task's gate results. Format is
11173
11916
  * `kind:value` (e.g. `commit:abc123`, `test-run:vitest.json`). The contract
11174
11917
  * accepts empty arrays so legacy plans validate; `cleo release plan`
11175
11918
  * enforces non-empty via R-301.
11176
11919
  */
11177
- evidenceAtoms: z6.array(NonEmptyString),
11920
+ evidenceAtoms: z9.array(NonEmptyString),
11178
11921
  /** IVTR phase at plan time — informational only per R-316. */
11179
- ivtrPhaseAtPlan: z6.string().optional(),
11922
+ ivtrPhaseAtPlan: z9.string().optional(),
11180
11923
  /** Epic this task rolls up to, locked at plan time per R-303. */
11181
11924
  epicAncestor: NonEmptyString
11182
11925
  });
11183
- ReleaseGateSchema = z6.object({
11926
+ ReleaseGateSchema = z9.object({
11184
11927
  /** Canonical gate name. */
11185
11928
  name: GateNameSchema,
11186
11929
  /** ADR-051 atom string identifying the resolved tool (e.g. `tool:test`). */
@@ -11190,11 +11933,11 @@ var init_plan = __esm({
11190
11933
  /** ISO-8601 timestamp the gate was last verified. */
11191
11934
  lastVerifiedAt: Iso8601,
11192
11935
  /** Resolved shell command (e.g. `pnpm run test`). Optional for unresolved gates. */
11193
- resolvedCommand: z6.string().optional(),
11936
+ resolvedCommand: z9.string().optional(),
11194
11937
  /** Provenance of the resolved command. Optional for unresolved gates. */
11195
11938
  resolvedSource: ResolvedSourceSchema.optional()
11196
11939
  });
11197
- ReleasePlatformMatrixEntrySchema = z6.object({
11940
+ ReleasePlatformMatrixEntrySchema = z9.object({
11198
11941
  /** Target platform tuple. */
11199
11942
  platform: PlatformTupleSchema,
11200
11943
  /** Distribution backend. */
@@ -11202,47 +11945,47 @@ var init_plan = __esm({
11202
11945
  /** Package identifier on the target backend (e.g. `@cleocode/cleo`). */
11203
11946
  package: NonEmptyString,
11204
11947
  /** Whether to run the GHA smoke job for this matrix entry. */
11205
- smoke: z6.boolean().default(true).optional()
11948
+ smoke: z9.boolean().default(true).optional()
11206
11949
  });
11207
- ReleasePreflightSummarySchema = z6.object({
11950
+ ReleasePreflightSummarySchema = z9.object({
11208
11951
  /** True if esbuild externals are out of sync with package.json. */
11209
- esbuildExternalsDrift: z6.boolean(),
11952
+ esbuildExternalsDrift: z9.boolean(),
11210
11953
  /** True if `pnpm-lock.yaml` diverges from the workspace manifest. */
11211
- lockfileDrift: z6.boolean(),
11954
+ lockfileDrift: z9.boolean(),
11212
11955
  /** True if all epic children are in terminal lifecycle states. */
11213
- epicCompletenessClean: z6.boolean(),
11956
+ epicCompletenessClean: z9.boolean(),
11214
11957
  /** True if no task appears in multiple in-flight release plans. */
11215
- doubleListingClean: z6.boolean(),
11958
+ doubleListingClean: z9.boolean(),
11216
11959
  /** Non-fatal preflight warnings (e.g. unresolved tools per R-024). */
11217
- preflightWarnings: z6.array(z6.string()).default([]).optional()
11960
+ preflightWarnings: z9.array(z9.string()).default([]).optional()
11218
11961
  });
11219
- ReleasePlanChangelogSchema = z6.object({
11962
+ ReleasePlanChangelogSchema = z9.object({
11220
11963
  /** `kind=feat` tasks. */
11221
- features: z6.array(NonEmptyString).default([]),
11964
+ features: z9.array(NonEmptyString).default([]),
11222
11965
  /** `kind=fix` or `kind=hotfix` tasks. */
11223
- fixes: z6.array(NonEmptyString).default([]),
11966
+ fixes: z9.array(NonEmptyString).default([]),
11224
11967
  /** `kind=chore`, `docs`, `refactor`, `test`, `perf` tasks. */
11225
- chores: z6.array(NonEmptyString).default([]),
11968
+ chores: z9.array(NonEmptyString).default([]),
11226
11969
  /** `kind=breaking` or `kind=revert` tasks. */
11227
- breaking: z6.array(NonEmptyString).default([])
11970
+ breaking: z9.array(NonEmptyString).default([])
11228
11971
  });
11229
- ReleasePlanMetaSchema = z6.object({
11972
+ ReleasePlanMetaSchema = z9.object({
11230
11973
  /** True if this is the project's first ever release. */
11231
- firstEverRelease: z6.boolean().optional(),
11974
+ firstEverRelease: z9.boolean().optional(),
11232
11975
  /** Canonical tool names that could not be resolved at plan time. */
11233
- unresolvedTools: z6.array(z6.string()).optional(),
11976
+ unresolvedTools: z9.array(z9.string()).optional(),
11234
11977
  /** Project archetype detected at plan time. */
11235
- archetype: z6.string().optional()
11236
- }).catchall(z6.unknown());
11237
- ReleasePlanSchema = z6.object({
11978
+ archetype: z9.string().optional()
11979
+ }).catchall(z9.unknown());
11980
+ ReleasePlanSchema = z9.object({
11238
11981
  /** Schema URL for this plan version. */
11239
- $schema: z6.string().optional(),
11982
+ $schema: z9.string().optional(),
11240
11983
  /** Requested version string (e.g. "v2026.6.0"). Includes the leading `v`. */
11241
11984
  version: NonEmptyString,
11242
11985
  /** Resolved version string after suffix application (e.g. "v2026.6.0.2"). */
11243
11986
  resolvedVersion: NonEmptyString,
11244
11987
  /** True if a `calver-suffix` was applied to disambiguate a same-day hotfix. */
11245
- suffixApplied: z6.boolean(),
11988
+ suffixApplied: z9.boolean(),
11246
11989
  /** Versioning scheme governing `version` / `resolvedVersion`. */
11247
11990
  scheme: ReleaseSchemeSchema,
11248
11991
  /** npm dist-tag channel for this release. */
@@ -11259,27 +12002,27 @@ var init_plan = __esm({
11259
12002
  * Version of the previous release on the same channel. MUST be `null` only
11260
12003
  * for first-ever releases (R-300, enforced at the verb layer).
11261
12004
  */
11262
- previousVersion: z6.string().nullable(),
12005
+ previousVersion: z9.string().nullable(),
11263
12006
  /** Git tag of the previous release (typically `previousVersion` prefixed). */
11264
- previousTag: z6.string().nullable(),
12007
+ previousTag: z9.string().nullable(),
11265
12008
  /** ISO-8601 timestamp the previous release was published. */
11266
12009
  previousShippedAt: Iso8601.nullable(),
11267
12010
  /** Tasks rolled into this release. */
11268
- tasks: z6.array(ReleasePlanTaskSchema),
12011
+ tasks: z9.array(ReleasePlanTaskSchema),
11269
12012
  /** Bucketed changelog. */
11270
12013
  changelog: ReleasePlanChangelogSchema,
11271
12014
  /** Per-gate verification status. */
11272
- gates: z6.array(ReleaseGateSchema),
12015
+ gates: z9.array(ReleaseGateSchema),
11273
12016
  /** Platform / publisher matrix. */
11274
- platformMatrix: z6.array(ReleasePlatformMatrixEntrySchema),
12017
+ platformMatrix: z9.array(ReleasePlatformMatrixEntrySchema),
11275
12018
  /** Preflight summary from `cleo release plan`. */
11276
12019
  preflightSummary: ReleasePreflightSummarySchema,
11277
12020
  /** URL of the GHA workflow run (populated by `release-prepare.yml`). */
11278
- workflowRunUrl: z6.string().nullable(),
12021
+ workflowRunUrl: z9.string().nullable(),
11279
12022
  /** URL of the bump PR (populated by `cleo release open`). */
11280
- prUrl: z6.string().nullable(),
12023
+ prUrl: z9.string().nullable(),
11281
12024
  /** Merge commit SHA on `main` (populated by `release-publish.yml`). */
11282
- mergeCommitSha: z6.string().nullable(),
12025
+ mergeCommitSha: z9.string().nullable(),
11283
12026
  /** Current FSM state per R-302. */
11284
12027
  status: ReleaseStatusSchema,
11285
12028
  /** Informational / forward-compat metadata. */
@@ -11335,52 +12078,52 @@ var init_session2 = __esm({
11335
12078
  });
11336
12079
 
11337
12080
  // packages/contracts/src/session-journal.ts
11338
- import { z as z7 } from "zod";
12081
+ import { z as z10 } from "zod";
11339
12082
  var SESSION_JOURNAL_SCHEMA_VERSION, sessionJournalDoctorSummarySchema, sessionJournalDebriefSummarySchema, sessionJournalEntrySchema;
11340
12083
  var init_session_journal = __esm({
11341
12084
  "packages/contracts/src/session-journal.ts"() {
11342
12085
  "use strict";
11343
12086
  SESSION_JOURNAL_SCHEMA_VERSION = "1.0";
11344
- sessionJournalDoctorSummarySchema = z7.object({
12087
+ sessionJournalDoctorSummarySchema = z10.object({
11345
12088
  /** `true` when zero noise patterns were detected. */
11346
- isClean: z7.boolean(),
12089
+ isClean: z10.boolean(),
11347
12090
  /** Total number of noise findings across all patterns. */
11348
- findingsCount: z7.number().int().nonnegative(),
12091
+ findingsCount: z10.number().int().nonnegative(),
11349
12092
  /** Pattern names that were detected (empty when isClean). */
11350
- patterns: z7.array(z7.string()),
12093
+ patterns: z10.array(z10.string()),
11351
12094
  /** Total brain entries scanned. `0` = empty or unavailable. */
11352
- totalScanned: z7.number().int().nonnegative()
12095
+ totalScanned: z10.number().int().nonnegative()
11353
12096
  });
11354
- sessionJournalDebriefSummarySchema = z7.object({
12097
+ sessionJournalDebriefSummarySchema = z10.object({
11355
12098
  /** First 200 characters of the session end note (if provided). */
11356
- noteExcerpt: z7.string().max(200).optional(),
12099
+ noteExcerpt: z10.string().max(200).optional(),
11357
12100
  /** Number of tasks completed during the session. */
11358
- tasksCompletedCount: z7.number().int().nonnegative(),
12101
+ tasksCompletedCount: z10.number().int().nonnegative(),
11359
12102
  /** Up to 5 task IDs (not titles) that were the focus of the session. */
11360
- tasksFocused: z7.array(z7.string()).max(5).optional()
12103
+ tasksFocused: z10.array(z10.string()).max(5).optional()
11361
12104
  });
11362
- sessionJournalEntrySchema = z7.object({
12105
+ sessionJournalEntrySchema = z10.object({
11363
12106
  // Identity
11364
12107
  /** Schema version for forward-compatibility. Always `'1.0'` in this release. */
11365
- schemaVersion: z7.literal(SESSION_JOURNAL_SCHEMA_VERSION),
12108
+ schemaVersion: z10.literal(SESSION_JOURNAL_SCHEMA_VERSION),
11366
12109
  /** ISO 8601 timestamp when the entry was written. */
11367
- timestamp: z7.string(),
12110
+ timestamp: z10.string(),
11368
12111
  /** CLEO session ID (e.g. `ses_20260424055456_ede571`). */
11369
- sessionId: z7.string(),
12112
+ sessionId: z10.string(),
11370
12113
  /** Event type that triggered this journal entry. */
11371
- eventType: z7.enum(["session_start", "session_end", "observation", "decision", "error"]),
12114
+ eventType: z10.enum(["session_start", "session_end", "observation", "decision", "error"]),
11372
12115
  // Session metadata (set on session_start / session_end)
11373
12116
  /** Agent identifier (e.g. `cleo-prime`, `claude-code`). */
11374
- agentIdentifier: z7.string().optional(),
12117
+ agentIdentifier: z10.string().optional(),
11375
12118
  /** Provider adapter ID active for this session. */
11376
- providerId: z7.string().optional(),
12119
+ providerId: z10.string().optional(),
11377
12120
  /** Session scope string (e.g. `'global'` or `'epic:T1263'`). */
11378
- scope: z7.string().optional(),
12121
+ scope: z10.string().optional(),
11379
12122
  // Session-end fields
11380
12123
  /** Duration of the session in seconds (session_end only). */
11381
- duration: z7.number().int().nonnegative().optional(),
12124
+ duration: z10.number().int().nonnegative().optional(),
11382
12125
  /** Task IDs (not titles) completed during the session. */
11383
- tasksCompleted: z7.array(z7.string()).optional(),
12126
+ tasksCompleted: z10.array(z10.string()).optional(),
11384
12127
  // Doctor summary (T1262 absorbed)
11385
12128
  /** Compact result of `scanBrainNoise` run at session-end. */
11386
12129
  doctorSummary: sessionJournalDoctorSummarySchema.optional(),
@@ -11389,7 +12132,7 @@ var init_session_journal = __esm({
11389
12132
  debriefSummary: sessionJournalDebriefSummarySchema.optional(),
11390
12133
  // Optional hash chain
11391
12134
  /** SHA-256 hex of the previous entry's raw JSON string (for integrity chain). */
11392
- prevEntryHash: z7.string().optional()
12135
+ prevEntryHash: z10.string().optional()
11393
12136
  });
11394
12137
  }
11395
12138
  });
@@ -11409,52 +12152,52 @@ var init_task = __esm({
11409
12152
  });
11410
12153
 
11411
12154
  // packages/contracts/src/task-evidence.ts
11412
- import { z as z8 } from "zod";
12155
+ import { z as z11 } from "zod";
11413
12156
  var fileEvidenceSchema, logEvidenceSchema, screenshotEvidenceSchema, testOutputEvidenceSchema, commandOutputEvidenceSchema, taskEvidenceSchema;
11414
12157
  var init_task_evidence = __esm({
11415
12158
  "packages/contracts/src/task-evidence.ts"() {
11416
12159
  "use strict";
11417
- fileEvidenceSchema = z8.object({
11418
- kind: z8.literal("file"),
11419
- sha256: z8.string().length(64),
11420
- timestamp: z8.string().datetime(),
11421
- path: z8.string().min(1),
11422
- mime: z8.string().optional(),
11423
- description: z8.string().optional()
11424
- });
11425
- logEvidenceSchema = z8.object({
11426
- kind: z8.literal("log"),
11427
- sha256: z8.string().length(64),
11428
- timestamp: z8.string().datetime(),
11429
- source: z8.string().min(1),
11430
- description: z8.string().optional()
11431
- });
11432
- screenshotEvidenceSchema = z8.object({
11433
- kind: z8.literal("screenshot"),
11434
- sha256: z8.string().length(64),
11435
- timestamp: z8.string().datetime(),
11436
- mime: z8.enum(["image/png", "image/jpeg", "image/webp"]).optional(),
11437
- description: z8.string().optional()
11438
- });
11439
- testOutputEvidenceSchema = z8.object({
11440
- kind: z8.literal("test-output"),
11441
- sha256: z8.string().length(64),
11442
- timestamp: z8.string().datetime(),
11443
- passed: z8.number().int().nonnegative(),
11444
- failed: z8.number().int().nonnegative(),
11445
- skipped: z8.number().int().nonnegative(),
11446
- exitCode: z8.number().int(),
11447
- description: z8.string().optional()
11448
- });
11449
- commandOutputEvidenceSchema = z8.object({
11450
- kind: z8.literal("command-output"),
11451
- sha256: z8.string().length(64),
11452
- timestamp: z8.string().datetime(),
11453
- cmd: z8.string().min(1),
11454
- exitCode: z8.number().int(),
11455
- description: z8.string().optional()
11456
- });
11457
- taskEvidenceSchema = z8.discriminatedUnion("kind", [
12160
+ fileEvidenceSchema = z11.object({
12161
+ kind: z11.literal("file"),
12162
+ sha256: z11.string().length(64),
12163
+ timestamp: z11.string().datetime(),
12164
+ path: z11.string().min(1),
12165
+ mime: z11.string().optional(),
12166
+ description: z11.string().optional()
12167
+ });
12168
+ logEvidenceSchema = z11.object({
12169
+ kind: z11.literal("log"),
12170
+ sha256: z11.string().length(64),
12171
+ timestamp: z11.string().datetime(),
12172
+ source: z11.string().min(1),
12173
+ description: z11.string().optional()
12174
+ });
12175
+ screenshotEvidenceSchema = z11.object({
12176
+ kind: z11.literal("screenshot"),
12177
+ sha256: z11.string().length(64),
12178
+ timestamp: z11.string().datetime(),
12179
+ mime: z11.enum(["image/png", "image/jpeg", "image/webp"]).optional(),
12180
+ description: z11.string().optional()
12181
+ });
12182
+ testOutputEvidenceSchema = z11.object({
12183
+ kind: z11.literal("test-output"),
12184
+ sha256: z11.string().length(64),
12185
+ timestamp: z11.string().datetime(),
12186
+ passed: z11.number().int().nonnegative(),
12187
+ failed: z11.number().int().nonnegative(),
12188
+ skipped: z11.number().int().nonnegative(),
12189
+ exitCode: z11.number().int(),
12190
+ description: z11.string().optional()
12191
+ });
12192
+ commandOutputEvidenceSchema = z11.object({
12193
+ kind: z11.literal("command-output"),
12194
+ sha256: z11.string().length(64),
12195
+ timestamp: z11.string().datetime(),
12196
+ cmd: z11.string().min(1),
12197
+ exitCode: z11.number().int(),
12198
+ description: z11.string().optional()
12199
+ });
12200
+ taskEvidenceSchema = z11.discriminatedUnion("kind", [
11458
12201
  fileEvidenceSchema,
11459
12202
  logEvidenceSchema,
11460
12203
  screenshotEvidenceSchema,
@@ -11465,12 +12208,12 @@ var init_task_evidence = __esm({
11465
12208
  });
11466
12209
 
11467
12210
  // packages/contracts/src/tasks/archive.ts
11468
- import { z as z9 } from "zod";
12211
+ import { z as z12 } from "zod";
11469
12212
  var ArchiveReason, ARCHIVE_REASON_VALUES;
11470
12213
  var init_archive = __esm({
11471
12214
  "packages/contracts/src/tasks/archive.ts"() {
11472
12215
  "use strict";
11473
- ArchiveReason = z9.enum([
12216
+ ArchiveReason = z12.enum([
11474
12217
  "verified",
11475
12218
  "reconciled",
11476
12219
  "superseded",
@@ -11482,6 +12225,67 @@ var init_archive = __esm({
11482
12225
  }
11483
12226
  });
11484
12227
 
12228
+ // packages/contracts/src/templates/manifest.ts
12229
+ import { z as z13 } from "zod";
12230
+ var TEMPLATE_KINDS, TEMPLATE_SUBSTITUTIONS, TEMPLATE_UPDATE_STRATEGIES, PLACEHOLDER_SOURCES, PlaceholderSpecSchema, TemplateManifestEntrySchema;
12231
+ var init_manifest2 = __esm({
12232
+ "packages/contracts/src/templates/manifest.ts"() {
12233
+ "use strict";
12234
+ TEMPLATE_KINDS = ["workflow", "config", "agent", "skill", "provider", "doc"];
12235
+ TEMPLATE_SUBSTITUTIONS = ["regex-tmpl", "static", "json-merge"];
12236
+ TEMPLATE_UPDATE_STRATEGIES = [
12237
+ "overwrite-on-bump",
12238
+ "diff-prompt",
12239
+ "immutable",
12240
+ "manifest-merge"
12241
+ ];
12242
+ PLACEHOLDER_SOURCES = [
12243
+ "project-context",
12244
+ "project-info",
12245
+ ".cleo/config",
12246
+ "~/.cleo/config",
12247
+ "tool-resolver",
12248
+ "literal"
12249
+ ];
12250
+ PlaceholderSpecSchema = z13.object({
12251
+ /**
12252
+ * Placeholder identifier as it appears in the template body
12253
+ * (e.g. `NODE_VERSION` matches `{{NODE_VERSION}}`).
12254
+ */
12255
+ name: z13.string().min(1, "placeholder name must be non-empty"),
12256
+ /** Resolver source the installer consults for this placeholder. */
12257
+ source: z13.enum(PLACEHOLDER_SOURCES),
12258
+ /**
12259
+ * Path expression evaluated against `source` (e.g. `engines.node` against
12260
+ * `project-context`, `defaults.branchModel` against `.cleo/config`).
12261
+ * For `literal` source, this MAY be the literal value's identifier.
12262
+ */
12263
+ sourcePath: z13.string().min(1, "placeholder sourcePath must be non-empty"),
12264
+ /**
12265
+ * Fallback value used when `source[sourcePath]` resolves to `undefined`.
12266
+ * `null` is permitted to explicitly mark "no default — failure required".
12267
+ */
12268
+ defaultValue: z13.union([z13.string(), z13.number(), z13.boolean(), z13.null()]).optional()
12269
+ });
12270
+ TemplateManifestEntrySchema = z13.object({
12271
+ /** Stable identifier for this template entry. */
12272
+ id: z13.string().min(1, "id must be non-empty"),
12273
+ /** Category of file this template represents. */
12274
+ kind: z13.enum(TEMPLATE_KINDS),
12275
+ /** Repo-relative path of the template source file. */
12276
+ sourcePath: z13.string().min(1, "sourcePath must be non-empty"),
12277
+ /** Project-relative path where the rendered template installs. */
12278
+ installPath: z13.string().min(1, "installPath must be non-empty"),
12279
+ /** Substitution strategy the installer applies to `sourcePath`. */
12280
+ substitution: z13.enum(TEMPLATE_SUBSTITUTIONS),
12281
+ /** Declared placeholders this template requires. May be empty. */
12282
+ placeholders: z13.array(PlaceholderSpecSchema),
12283
+ /** Reconciliation policy on upgrade. */
12284
+ updateStrategy: z13.enum(TEMPLATE_UPDATE_STRATEGIES)
12285
+ });
12286
+ }
12287
+ });
12288
+
11485
12289
  // packages/contracts/src/index.ts
11486
12290
  var init_src2 = __esm({
11487
12291
  "packages/contracts/src/index.ts"() {
@@ -11491,18 +12295,22 @@ var init_src2 = __esm({
11491
12295
  init_branch_lock();
11492
12296
  init_changesets();
11493
12297
  init_cli_category();
12298
+ init_manifest();
11494
12299
  init_credentials();
11495
12300
  init_db_inventory2();
11496
12301
  init_identity();
11497
12302
  init_operations_registry();
12303
+ init_provenance();
11498
12304
  init_docs_taxonomy();
11499
12305
  init_engine_result();
11500
12306
  init_enums();
11501
12307
  init_errors();
12308
+ init_evidence_atom_schema();
11502
12309
  init_evidence_record_schema();
11503
12310
  init_exit_codes();
11504
12311
  init_facade();
11505
12312
  init_graph();
12313
+ init_invariants();
11506
12314
  init_lafs();
11507
12315
  init_plugin_llm();
11508
12316
  init_observe();
@@ -11519,6 +12327,7 @@ var init_src2 = __esm({
11519
12327
  init_task();
11520
12328
  init_task_evidence();
11521
12329
  init_archive();
12330
+ init_manifest2();
11522
12331
  }
11523
12332
  });
11524
12333
 
@@ -16192,7 +17001,10 @@ var init_diagnostics = __esm({
16192
17001
  // packages/cleo/src/dispatch/domains/docs.ts
16193
17002
  import { readFile } from "node:fs/promises";
16194
17003
  import { resolve as resolve2 } from "node:path";
17004
+ import { pushWarning } from "@cleocode/core";
16195
17005
  import {
17006
+ AUTO_TOKEN,
17007
+ allocateAutoSlugForDispatch,
16196
17008
  createAttachmentStore,
16197
17009
  createAttachmentStoreV2,
16198
17010
  generateDocsLlmsTxt,
@@ -16204,6 +17016,7 @@ import {
16204
17016
  reserveSlugForDispatch,
16205
17017
  resolveAttachmentBackend,
16206
17018
  SlugCollisionError,
17019
+ validateDocBody,
16207
17020
  writeChangesetEntry
16208
17021
  } from "@cleocode/core/internal";
16209
17022
  function getDocKindRegistry() {
@@ -16680,7 +17493,8 @@ var init_docs2 = __esm({
16680
17493
  labels: rawLabels,
16681
17494
  attachedBy: rawAttachedBy,
16682
17495
  slug: rawSlug,
16683
- type: rawType
17496
+ type: rawType,
17497
+ strict: strictMode
16684
17498
  } = params;
16685
17499
  if (!ownerId) {
16686
17500
  return lafsError("E_INVALID_INPUT", "ownerId is required", "add");
@@ -16694,11 +17508,19 @@ var init_docs2 = __esm({
16694
17508
  }
16695
17509
  let slug;
16696
17510
  if (rawSlug !== void 0) {
16697
- const check = validateSlug(rawSlug);
17511
+ let candidate = rawSlug;
17512
+ if (typeof candidate === "string" && candidate.includes(AUTO_TOKEN)) {
17513
+ const allocated = await allocateAutoSlugForDispatch(getProjectRoot5(), {
17514
+ kind: typeof rawType === "string" ? rawType : "",
17515
+ rawSlug: candidate
17516
+ });
17517
+ candidate = allocated.resolvedSlug;
17518
+ }
17519
+ const check = validateSlug(candidate);
16698
17520
  if (!check.valid) {
16699
17521
  return lafsError("E_INVALID_SLUG", check.reason, "add");
16700
17522
  }
16701
- slug = rawSlug;
17523
+ slug = candidate;
16702
17524
  }
16703
17525
  let type2;
16704
17526
  if (rawType !== void 0) {
@@ -16851,6 +17673,36 @@ var init_docs2 = __esm({
16851
17673
  } catch {
16852
17674
  return lafsError("E_FILE_ERROR", `Cannot read file: ${absPath}`, "add");
16853
17675
  }
17676
+ if (type2 !== void 0) {
17677
+ const bodyText = bytes.toString("utf-8");
17678
+ let registry;
17679
+ try {
17680
+ registry = DocKindRegistry.load(getProjectRoot5());
17681
+ } catch {
17682
+ registry = void 0;
17683
+ }
17684
+ const check = validateDocBody(type2, bodyText, registry);
17685
+ if (!check.ok) {
17686
+ const missingList = check.missing.join(", ");
17687
+ if (strictMode === true) {
17688
+ return lafsError(
17689
+ "E_DOC_SCHEMA_MISMATCH",
17690
+ `body for kind '${type2}' is missing required section(s): ${missingList}`,
17691
+ "add",
17692
+ `Add the missing H2 section(s) \u2014 '## ${check.missing[0] ?? ""}' \u2014 then retry. Pass --strict=false (default) to surface as an advisory warning instead of an error.`,
17693
+ {
17694
+ kind: type2,
17695
+ missing: check.missing,
17696
+ strict: true
17697
+ }
17698
+ );
17699
+ }
17700
+ pushWarning({
17701
+ code: "W_DOC_SCHEMA_MISMATCH",
17702
+ message: `body for kind '${type2}' is missing required section(s): ${missingList}. Add '--strict' to fail on schema violations.`
17703
+ });
17704
+ }
17705
+ }
16854
17706
  const mime = mimeFromPath(absPath);
16855
17707
  const attachment = {
16856
17708
  kind: "local-file",
@@ -25372,8 +26224,8 @@ async function loadPlaybookByName(name) {
25372
26224
  return null;
25373
26225
  }
25374
26226
  try {
25375
- const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
25376
- const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot48();
26227
+ const { getProjectRoot: getProjectRoot53 } = await import("@cleocode/core/internal");
26228
+ const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot53();
25377
26229
  const resolved = resolvePlaybook(name, {
25378
26230
  projectRoot,
25379
26231
  globalPlaybooksDir: __playbookRuntimeOverrides.globalPlaybooksDir,
@@ -25417,8 +26269,8 @@ async function acquireDb() {
25417
26269
  async function buildDefaultDispatcher() {
25418
26270
  if (__playbookRuntimeOverrides.dispatcher) return __playbookRuntimeOverrides.dispatcher;
25419
26271
  const { orchestrateSpawnExecute: orchestrateSpawnExecute2 } = await Promise.resolve().then(() => (init_engine(), engine_exports));
25420
- const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
25421
- const projectRoot = getProjectRoot48();
26272
+ const { getProjectRoot: getProjectRoot53 } = await import("@cleocode/core/internal");
26273
+ const projectRoot = getProjectRoot53();
25422
26274
  return {
25423
26275
  async dispatch(input2) {
25424
26276
  try {
@@ -25608,8 +26460,8 @@ var init_playbook2 = __esm({
25608
26460
  projectRoot = __playbookRuntimeOverrides.projectRoot;
25609
26461
  } else {
25610
26462
  try {
25611
- const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
25612
- projectRoot = getProjectRoot48();
26463
+ const { getProjectRoot: getProjectRoot53 } = await import("@cleocode/core/internal");
26464
+ projectRoot = getProjectRoot53();
25613
26465
  } catch {
25614
26466
  projectRoot = void 0;
25615
26467
  }
@@ -25673,14 +26525,14 @@ var init_playbook2 = __esm({
25673
26525
  const dispatcher = await buildDefaultDispatcher();
25674
26526
  let result;
25675
26527
  try {
25676
- const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core/internal");
26528
+ const { getProjectRoot: getProjectRoot53 } = await import("@cleocode/core/internal");
25677
26529
  const opts = {
25678
26530
  db,
25679
26531
  playbook: parsed.definition,
25680
26532
  playbookHash: parsed.sourceHash,
25681
26533
  initialContext,
25682
26534
  dispatcher,
25683
- projectRoot: getProjectRoot48()
26535
+ projectRoot: getProjectRoot53()
25684
26536
  };
25685
26537
  if (__playbookRuntimeOverrides.approvalSecret !== void 0) {
25686
26538
  opts.approvalSecret = __playbookRuntimeOverrides.approvalSecret;
@@ -27900,7 +28752,7 @@ import {
27900
28752
  verifyProvenance
27901
28753
  } from "@cleocode/core/internal";
27902
28754
  var log2, ProvenanceHandler;
27903
- var init_provenance = __esm({
28755
+ var init_provenance2 = __esm({
27904
28756
  "packages/cleo/src/dispatch/domains/provenance.ts"() {
27905
28757
  "use strict";
27906
28758
  init_base();
@@ -31023,7 +31875,7 @@ var init_domains = __esm({
31023
31875
  init_orchestrate2();
31024
31876
  init_pipeline3();
31025
31877
  init_playbook2();
31026
- init_provenance();
31878
+ init_provenance2();
31027
31879
  init_release2();
31028
31880
  init_sentient2();
31029
31881
  init_session3();
@@ -31468,11 +32320,11 @@ var init_security = __esm({
31468
32320
  });
31469
32321
 
31470
32322
  // packages/cleo/src/dispatch/middleware/sanitizer.ts
31471
- function createSanitizer(getProjectRoot48) {
32323
+ function createSanitizer(getProjectRoot53) {
31472
32324
  return async (req, next) => {
31473
32325
  if (req.params) {
31474
32326
  try {
31475
- const root = getProjectRoot48 ? getProjectRoot48() : void 0;
32327
+ const root = getProjectRoot53 ? getProjectRoot53() : void 0;
31476
32328
  req.params = sanitizeParams(req.params, root, {
31477
32329
  domain: req.domain,
31478
32330
  operation: req.operation
@@ -32131,6 +32983,7 @@ var addCommand;
32131
32983
  var init_add = __esm({
32132
32984
  "packages/cleo/src/cli/commands/add.ts"() {
32133
32985
  "use strict";
32986
+ init_src2();
32134
32987
  init_dist();
32135
32988
  init_cli();
32136
32989
  init_renderers();
@@ -32307,6 +33160,20 @@ For 2+ tasks at once: cleo add-batch --file tasks.json (single transaction, atom
32307
33160
  await showUsage(cmd);
32308
33161
  return;
32309
33162
  }
33163
+ if (args.severity !== void 0 && !TASK_SEVERITIES.includes(args.severity)) {
33164
+ const valid = TASK_SEVERITIES.join(", ");
33165
+ cliError(
33166
+ `severity must be one of: ${valid} \u2014 got '${args.severity}'`,
33167
+ 6,
33168
+ {
33169
+ name: "E_INVALID_SEVERITY_VALUE",
33170
+ fix: `Pass --severity with one of: ${valid}`
33171
+ },
33172
+ { operation: "tasks.add" }
33173
+ );
33174
+ process.exit(6);
33175
+ return;
33176
+ }
32310
33177
  const params = { title: args.title };
32311
33178
  if (args.status !== void 0) params["status"] = args.status;
32312
33179
  if (args.priority !== void 0) params["priority"] = args.priority;
@@ -35583,8 +36450,8 @@ var init_consent = __esm({
35583
36450
  /* webpackIgnore: true */
35584
36451
  "@cleocode/core/config.js"
35585
36452
  );
35586
- const getConfigValue2 = configMod.getConfigValue;
35587
- const setConfigValue2 = configMod.setConfigValue;
36453
+ const getConfigValue3 = configMod.getConfigValue;
36454
+ const setConfigValue3 = configMod.setConfigValue;
35588
36455
  const { addSuppression, removeSuppression, isSuppressed } = await import(
35589
36456
  /* webpackIgnore: true */
35590
36457
  "@cleocode/core/llm/credential-removal.js"
@@ -35593,7 +36460,7 @@ var init_consent = __esm({
35593
36460
  const SOURCE_ID = "claude-code";
35594
36461
  const PROVIDER = "anthropic";
35595
36462
  if (showStatus) {
35596
- const resolved = await getConfigValue2(CONSENT_KEY);
36463
+ const resolved = await getConfigValue3(CONSENT_KEY);
35597
36464
  const consentEnabled = resolved.value === true;
35598
36465
  const suppressed = isSuppressed(PROVIDER, SOURCE_ID);
35599
36466
  const result2 = {
@@ -35613,7 +36480,7 @@ var init_consent = __esm({
35613
36480
  return;
35614
36481
  }
35615
36482
  if (enableClaudeCode) {
35616
- await setConfigValue2(CONSENT_KEY, true, void 0, { global: true });
36483
+ await setConfigValue3(CONSENT_KEY, true, void 0, { global: true });
35617
36484
  const suppressionChanged2 = removeSuppression(PROVIDER, SOURCE_ID);
35618
36485
  const result2 = {
35619
36486
  action: "enabled",
@@ -35629,7 +36496,7 @@ var init_consent = __esm({
35629
36496
  });
35630
36497
  return;
35631
36498
  }
35632
- await setConfigValue2(CONSENT_KEY, false, void 0, { global: true });
36499
+ await setConfigValue3(CONSENT_KEY, false, void 0, { global: true });
35633
36500
  const wasAlreadySuppressed = isSuppressed(PROVIDER, SOURCE_ID);
35634
36501
  addSuppression(PROVIDER, SOURCE_ID);
35635
36502
  const suppressionChanged = !wasAlreadySuppressed;
@@ -36890,9 +37757,9 @@ var init_backup = __esm({
36890
37757
  async run({ args }) {
36891
37758
  const scope = args.scope;
36892
37759
  const { packBundle } = await import("@cleocode/core/store/backup-pack.js");
36893
- const { getProjectRoot: getProjectRoot48 } = await import("@cleocode/core");
37760
+ const { getProjectRoot: getProjectRoot53 } = await import("@cleocode/core");
36894
37761
  const includesProject = scope === "project" || scope === "all";
36895
- const projectRoot = includesProject ? getProjectRoot48() : void 0;
37762
+ const projectRoot = includesProject ? getProjectRoot53() : void 0;
36896
37763
  let passphrase;
36897
37764
  if (args.encrypt === true) {
36898
37765
  passphrase = process.env["CLEO_BACKUP_PASSPHRASE"];
@@ -36968,12 +37835,12 @@ var init_backup = __esm({
36968
37835
  },
36969
37836
  async run({ args }) {
36970
37837
  const bundlePath = args.bundle;
36971
- const { getProjectRoot: getProjectRoot48, getCleoHome: getCleoHome6, getCleoVersion } = await import("@cleocode/core");
37838
+ const { getProjectRoot: getProjectRoot53, getCleoHome: getCleoHome6, getCleoVersion } = await import("@cleocode/core");
36972
37839
  const { BundleError, cleanupStaging, unpackBundle } = await import("@cleocode/core/store/backup-unpack.js");
36973
37840
  const { regenerateConfigJson, regenerateProjectContextJson, regenerateProjectInfoJson } = await import("@cleocode/core/store/regenerators.js");
36974
37841
  const { regenerateAndCompare } = await import("@cleocode/core/store/restore-json-merge.js");
36975
37842
  const { buildConflictReport, writeConflictReport } = await import("@cleocode/core/store/restore-conflict-report.js");
36976
- const projectRoot = getProjectRoot48();
37843
+ const projectRoot = getProjectRoot53();
36977
37844
  if (args.force !== true) {
36978
37845
  const existing = checkForExistingData(projectRoot, getCleoHome6());
36979
37846
  if (existing.length > 0) {
@@ -37577,7 +38444,7 @@ __export(briefing_exports, {
37577
38444
  });
37578
38445
  import { existsSync as existsSync9, readFileSync as readFileSync10 } from "node:fs";
37579
38446
  import { join as join11 } from "node:path";
37580
- import { pushWarning } from "@cleocode/core";
38447
+ import { pushWarning as pushWarning2 } from "@cleocode/core";
37581
38448
  import { resolveLegacyCleoDir } from "@cleocode/paths";
37582
38449
  function resolveInjectionTemplatePath() {
37583
38450
  const xdgConfig = resolveLegacyCleoDir(process.env["XDG_CONFIG_HOME"]);
@@ -37609,7 +38476,7 @@ function renderForAdapter(sectionName, content, format) {
37609
38476
  async function runBriefingInject(sectionName, formatStr) {
37610
38477
  const templatePath = resolveInjectionTemplatePath();
37611
38478
  if (!existsSync9(templatePath)) {
37612
- pushWarning({
38479
+ pushWarning2({
37613
38480
  code: "W_TEMPLATE_INJECT_FAILED",
37614
38481
  message: `CLEO-INJECTION.md not found at ${templatePath}`
37615
38482
  });
@@ -37629,7 +38496,7 @@ async function runBriefingInject(sectionName, formatStr) {
37629
38496
  const section = extractSection(content, sectionName);
37630
38497
  if (section === null) {
37631
38498
  const available = INJECTION_SECTION_NAMES.join(", ");
37632
- pushWarning({
38499
+ pushWarning2({
37633
38500
  code: "W_TEMPLATE_INJECT_FAILED",
37634
38501
  message: `Section "${sectionName}" not found in CLEO-INJECTION.md.`
37635
38502
  });
@@ -37650,7 +38517,7 @@ async function runBriefingInject(sectionName, formatStr) {
37650
38517
  const adapterName = formatStr.slice("adapter:".length);
37651
38518
  if (!ADAPTER_FORMATS.includes(adapterName)) {
37652
38519
  const supported = ADAPTER_FORMATS.join(", ");
37653
- pushWarning({
38520
+ pushWarning2({
37654
38521
  code: "W_TEMPLATE_INJECT_FAILED",
37655
38522
  message: `Unknown adapter format "${adapterName}".`
37656
38523
  });
@@ -40052,71 +40919,479 @@ var init_conduit3 = __esm({
40052
40919
  }
40053
40920
  });
40054
40921
 
40055
- // packages/cleo/src/cli/commands/config.ts
40056
- var config_exports = {};
40057
- __export(config_exports, {
40058
- configCommand: () => configCommand
40922
+ // packages/cleo/src/cli/commands/config/drift-check.ts
40923
+ import { getProjectRoot as getProjectRoot31 } from "@cleocode/core";
40924
+ import { checkDrift } from "@cleocode/core/config/registry";
40925
+ function parseDriftScope(raw) {
40926
+ const value = raw ?? "project";
40927
+ if (value === "global" || value === "project" || value === "metadata") {
40928
+ return value;
40929
+ }
40930
+ return null;
40931
+ }
40932
+ var configDriftCheckCommand;
40933
+ var init_drift_check = __esm({
40934
+ "packages/cleo/src/cli/commands/config/drift-check.ts"() {
40935
+ "use strict";
40936
+ init_src2();
40937
+ init_define_cli_command();
40938
+ init_renderers();
40939
+ configDriftCheckCommand = defineCommand({
40940
+ meta: {
40941
+ name: "drift-check",
40942
+ description: "Check a scoped config file for drift (default scope: project; metadata covers project-info/project-context)"
40943
+ },
40944
+ args: {
40945
+ scope: {
40946
+ type: "string",
40947
+ description: "Scope to check: global | project | metadata (default project)",
40948
+ default: "project"
40949
+ },
40950
+ json: {
40951
+ type: "boolean",
40952
+ description: "Output as JSON"
40953
+ }
40954
+ },
40955
+ async run({ args }) {
40956
+ const scope = parseDriftScope(args["scope"]);
40957
+ if (scope === null) {
40958
+ cliError(
40959
+ `config drift-check failed: invalid --scope (must be global|project|metadata)`,
40960
+ 1 /* GENERAL_ERROR */,
40961
+ { name: "E_CONFIG_DRIFT_CHECK_FAILED" }
40962
+ );
40963
+ process.exit(1 /* GENERAL_ERROR */);
40964
+ return;
40965
+ }
40966
+ let driftResult;
40967
+ try {
40968
+ const projectRoot = getProjectRoot31();
40969
+ driftResult = await checkDrift(scope, projectRoot);
40970
+ } catch (err) {
40971
+ const message = err instanceof Error ? err.message : String(err);
40972
+ cliError(`config drift-check failed: ${message}`, 1 /* GENERAL_ERROR */, {
40973
+ name: "E_CONFIG_DRIFT_CHECK_FAILED"
40974
+ });
40975
+ process.exit(1 /* GENERAL_ERROR */);
40976
+ return;
40977
+ }
40978
+ const result = {
40979
+ scope,
40980
+ drift: driftResult.drift,
40981
+ ...driftResult.reason !== void 0 ? { reason: driftResult.reason } : {}
40982
+ };
40983
+ cliOutput(result, {
40984
+ command: "config-drift-check",
40985
+ operation: "config.drift-check"
40986
+ });
40987
+ if (driftResult.drift) {
40988
+ process.exit(6 /* VALIDATION_ERROR */);
40989
+ }
40990
+ }
40991
+ });
40992
+ }
40059
40993
  });
40060
- import { CleoError as CleoError2, formatError as formatError4, loadConfig as loadConfig2 } from "@cleocode/core";
40061
- var PRESET_DESCRIPTIONS, getCommand2, setCommand, setPresetCommand, presetsCommand, listCommand7, configCommand;
40062
- var init_config2 = __esm({
40063
- "packages/cleo/src/cli/commands/config.ts"() {
40994
+
40995
+ // packages/cleo/src/cli/commands/config/get.ts
40996
+ import { getProjectRoot as getProjectRoot32 } from "@cleocode/core";
40997
+ import { getConfigValue } from "@cleocode/core/config/registry";
40998
+ function parseResolveScope(raw) {
40999
+ const value = raw ?? "merged";
41000
+ if (value === "global" || value === "project" || value === "merged") {
41001
+ return value;
41002
+ }
41003
+ return null;
41004
+ }
41005
+ var configGetCommand;
41006
+ var init_get = __esm({
41007
+ "packages/cleo/src/cli/commands/config/get.ts"() {
40064
41008
  "use strict";
40065
- init_dist();
40066
- init_cli();
41009
+ init_src2();
41010
+ init_define_cli_command();
40067
41011
  init_renderers();
40068
- PRESET_DESCRIPTIONS = {
40069
- strict: "Block on missing AC, require session notes, enforce lifecycle pipeline.",
40070
- standard: "Warn on missing AC, optional session notes, advisory lifecycle pipeline.",
40071
- minimal: "No AC checking, no session requirement, lifecycle pipeline off."
40072
- };
40073
- getCommand2 = defineCommand({
40074
- meta: { name: "get", description: "Get a configuration value" },
41012
+ configGetCommand = defineCommand({
41013
+ meta: {
41014
+ name: "get",
41015
+ description: "Read a single config value by dot-separated key (default scope: merged)"
41016
+ },
40075
41017
  args: {
40076
41018
  key: {
40077
41019
  type: "positional",
40078
- description: "Configuration key to retrieve",
40079
- required: true
41020
+ required: true,
41021
+ description: "Dot-separated key path (e.g. release.branchModel)"
41022
+ },
41023
+ scope: {
41024
+ type: "string",
41025
+ description: "Cascade scope to read: global | project | merged (default merged)",
41026
+ default: "merged"
41027
+ },
41028
+ json: {
41029
+ type: "boolean",
41030
+ description: "Output as JSON"
40080
41031
  }
40081
41032
  },
40082
41033
  async run({ args }) {
40083
- await dispatchFromCli(
40084
- "query",
40085
- "admin",
40086
- "config.show",
40087
- { key: args.key },
40088
- { command: "config" }
40089
- );
41034
+ const key = String(args["key"] ?? "").trim();
41035
+ if (key.length === 0) {
41036
+ cliError(`config get failed: <key> is required`, 2 /* INVALID_INPUT */, {
41037
+ name: "E_CONFIG_GET_FAILED"
41038
+ });
41039
+ process.exit(2 /* INVALID_INPUT */);
41040
+ return;
41041
+ }
41042
+ const scope = parseResolveScope(args["scope"]);
41043
+ if (scope === null) {
41044
+ cliError(
41045
+ `config get failed: invalid --scope (must be global|project|merged)`,
41046
+ 1 /* GENERAL_ERROR */,
41047
+ { name: "E_CONFIG_GET_FAILED" }
41048
+ );
41049
+ process.exit(1 /* GENERAL_ERROR */);
41050
+ return;
41051
+ }
41052
+ let value;
41053
+ try {
41054
+ const projectRoot = getProjectRoot32();
41055
+ value = await getConfigValue(key, { scope, projectRoot });
41056
+ } catch (err) {
41057
+ const message = err instanceof Error ? err.message : String(err);
41058
+ cliError(`config get failed: ${message}`, 1 /* GENERAL_ERROR */, {
41059
+ name: "E_CONFIG_GET_FAILED"
41060
+ });
41061
+ process.exit(1 /* GENERAL_ERROR */);
41062
+ return;
41063
+ }
41064
+ if (value === void 0) {
41065
+ cliError(`config get failed: key "${key}" not found`, 4 /* NOT_FOUND */, {
41066
+ name: "E_NOT_FOUND",
41067
+ details: { key, scope }
41068
+ });
41069
+ process.exit(4 /* NOT_FOUND */);
41070
+ return;
41071
+ }
41072
+ const result = { scope, key, value };
41073
+ cliOutput(result, {
41074
+ command: "config-get",
41075
+ operation: "config.get"
41076
+ });
40090
41077
  }
40091
41078
  });
40092
- setCommand = defineCommand({
40093
- meta: { name: "set", description: "Set a configuration value" },
41079
+ }
41080
+ });
41081
+
41082
+ // packages/cleo/src/cli/commands/config/set.ts
41083
+ import { getProjectRoot as getProjectRoot33, parseConfigValue, setConfigValue } from "@cleocode/core";
41084
+ import { validateConfig as validateConfig2 } from "@cleocode/core/config/registry";
41085
+ function parseWriteScope(raw) {
41086
+ const value = raw ?? "project";
41087
+ if (value === "global" || value === "project") {
41088
+ return value;
41089
+ }
41090
+ return null;
41091
+ }
41092
+ function coerceValue(raw, typeFlag) {
41093
+ if (typeFlag === void 0) return parseConfigValue(raw);
41094
+ if (typeFlag === "string") return raw;
41095
+ if (typeFlag === "number") return coerceNumber(raw);
41096
+ if (typeFlag === "boolean") return coerceBoolean(raw);
41097
+ if (typeFlag === "json") return coerceJson(raw);
41098
+ throw new Error(`--type must be one of: string | number | boolean | json (got "${typeFlag}")`);
41099
+ }
41100
+ function coerceNumber(raw) {
41101
+ const n = Number(raw);
41102
+ if (Number.isNaN(n)) {
41103
+ throw new Error(`--type number cannot coerce "${raw}"`);
41104
+ }
41105
+ return n;
41106
+ }
41107
+ function coerceBoolean(raw) {
41108
+ const lower = raw.toLowerCase();
41109
+ if (lower === "true") return true;
41110
+ if (lower === "false") return false;
41111
+ throw new Error(`--type boolean accepts only "true"/"false" (got "${raw}")`);
41112
+ }
41113
+ function coerceJson(raw) {
41114
+ try {
41115
+ return JSON.parse(raw);
41116
+ } catch (err) {
41117
+ const msg = err instanceof Error ? err.message : String(err);
41118
+ throw new Error(`--type json failed to parse: ${msg}`);
41119
+ }
41120
+ }
41121
+ var configSetCommand;
41122
+ var init_set = __esm({
41123
+ "packages/cleo/src/cli/commands/config/set.ts"() {
41124
+ "use strict";
41125
+ init_src2();
41126
+ init_define_cli_command();
41127
+ init_renderers();
41128
+ configSetCommand = defineCommand({
41129
+ meta: {
41130
+ name: "set",
41131
+ description: "Write a value into project or global .cleo/config.json"
41132
+ },
40094
41133
  args: {
40095
41134
  key: {
40096
41135
  type: "positional",
40097
- description: "Configuration key to set",
40098
- required: true
41136
+ required: true,
41137
+ description: "Dot-separated key path"
40099
41138
  },
40100
41139
  value: {
40101
41140
  type: "positional",
40102
- description: "Value to assign",
40103
- required: true
41141
+ required: true,
41142
+ description: "Raw value (string). Use --type to coerce explicitly."
40104
41143
  },
40105
- global: {
41144
+ scope: {
41145
+ type: "string",
41146
+ description: "Where to write: project | global (default project)",
41147
+ default: "project"
41148
+ },
41149
+ type: {
41150
+ type: "string",
41151
+ description: "Explicit value type: string | number | boolean | json"
41152
+ },
41153
+ json: {
40106
41154
  type: "boolean",
40107
- description: "Set in global config instead of project config"
41155
+ description: "Output as JSON"
40108
41156
  }
40109
41157
  },
40110
41158
  async run({ args }) {
40111
- await dispatchFromCli(
40112
- "mutate",
40113
- "admin",
40114
- "config.set",
40115
- { key: args.key, value: args.value },
40116
- { command: "config" }
40117
- );
41159
+ const key = String(args["key"] ?? "").trim();
41160
+ if (key.length === 0) {
41161
+ cliError(`config set failed: <key> is required`, 2 /* INVALID_INPUT */, {
41162
+ name: "E_CONFIG_SET_FAILED"
41163
+ });
41164
+ process.exit(2 /* INVALID_INPUT */);
41165
+ return;
41166
+ }
41167
+ const rawValue = String(args["value"] ?? "");
41168
+ const scope = parseWriteScope(args["scope"]);
41169
+ if (scope === null) {
41170
+ cliError(
41171
+ `config set failed: invalid --scope (must be global|project)`,
41172
+ 1 /* GENERAL_ERROR */,
41173
+ { name: "E_CONFIG_SET_FAILED" }
41174
+ );
41175
+ process.exit(1 /* GENERAL_ERROR */);
41176
+ return;
41177
+ }
41178
+ const typeFlag = args["type"];
41179
+ let coerced;
41180
+ try {
41181
+ coerced = coerceValue(rawValue, typeFlag);
41182
+ } catch (err) {
41183
+ const message = err instanceof Error ? err.message : String(err);
41184
+ cliError(`config set failed: ${message}`, 2 /* INVALID_INPUT */, {
41185
+ name: "E_CONFIG_SET_FAILED"
41186
+ });
41187
+ process.exit(2 /* INVALID_INPUT */);
41188
+ return;
41189
+ }
41190
+ let written;
41191
+ let validate;
41192
+ try {
41193
+ const projectRoot = getProjectRoot33();
41194
+ written = await setConfigValue(key, coerced, projectRoot, {
41195
+ global: scope === "global"
41196
+ });
41197
+ validate = await validateConfig2(scope, projectRoot);
41198
+ } catch (err) {
41199
+ const message = err instanceof Error ? err.message : String(err);
41200
+ cliError(`config set failed: ${message}`, 1 /* GENERAL_ERROR */, {
41201
+ name: "E_CONFIG_SET_FAILED"
41202
+ });
41203
+ process.exit(1 /* GENERAL_ERROR */);
41204
+ return;
41205
+ }
41206
+ const result = {
41207
+ scope: written.scope,
41208
+ key: written.key,
41209
+ value: written.value,
41210
+ validate
41211
+ };
41212
+ cliOutput(result, {
41213
+ command: "config-set",
41214
+ operation: "config.set"
41215
+ });
41216
+ if (!validate.ok) {
41217
+ process.exit(6 /* VALIDATION_ERROR */);
41218
+ }
40118
41219
  }
40119
41220
  });
41221
+ }
41222
+ });
41223
+
41224
+ // packages/cleo/src/cli/commands/config/show.ts
41225
+ import { getProjectRoot as getProjectRoot34 } from "@cleocode/core";
41226
+ import {
41227
+ resolveCleoConfig
41228
+ } from "@cleocode/core/config/registry";
41229
+ function parseResolveScope2(raw) {
41230
+ const value = raw ?? "merged";
41231
+ if (value === "global" || value === "project" || value === "merged") {
41232
+ return value;
41233
+ }
41234
+ return null;
41235
+ }
41236
+ var configShowCommand;
41237
+ var init_show = __esm({
41238
+ "packages/cleo/src/cli/commands/config/show.ts"() {
41239
+ "use strict";
41240
+ init_src2();
41241
+ init_define_cli_command();
41242
+ init_renderers();
41243
+ configShowCommand = defineCommand({
41244
+ meta: {
41245
+ name: "show",
41246
+ description: "Print the resolved CleoConfig envelope (default scope: merged)"
41247
+ },
41248
+ args: {
41249
+ scope: {
41250
+ type: "string",
41251
+ description: "Cascade scope to read: global | project | merged (default merged)",
41252
+ default: "merged"
41253
+ },
41254
+ json: {
41255
+ type: "boolean",
41256
+ description: "Output as JSON"
41257
+ }
41258
+ },
41259
+ async run({ args }) {
41260
+ const scope = parseResolveScope2(args["scope"]);
41261
+ if (scope === null) {
41262
+ cliError(
41263
+ `config show failed: invalid --scope (must be global|project|merged)`,
41264
+ 1 /* GENERAL_ERROR */,
41265
+ { name: "E_CONFIG_SHOW_FAILED" }
41266
+ );
41267
+ process.exit(1 /* GENERAL_ERROR */);
41268
+ return;
41269
+ }
41270
+ try {
41271
+ const projectRoot = getProjectRoot34();
41272
+ const config = await resolveCleoConfig({ scope, projectRoot });
41273
+ const result = { scope, config };
41274
+ cliOutput(result, {
41275
+ command: "config-show",
41276
+ operation: "config.show"
41277
+ });
41278
+ } catch (err) {
41279
+ const message = err instanceof Error ? err.message : String(err);
41280
+ cliError(`config show failed: ${message}`, 1 /* GENERAL_ERROR */, {
41281
+ name: "E_CONFIG_SHOW_FAILED"
41282
+ });
41283
+ process.exit(1 /* GENERAL_ERROR */);
41284
+ }
41285
+ }
41286
+ });
41287
+ }
41288
+ });
41289
+
41290
+ // packages/cleo/src/cli/commands/config/validate.ts
41291
+ import { getProjectRoot as getProjectRoot35 } from "@cleocode/core";
41292
+ import { validateConfig as validateConfig3 } from "@cleocode/core/config/registry";
41293
+ function parseValidateScope(raw) {
41294
+ const value = raw ?? "project";
41295
+ if (value === "global" || value === "project") {
41296
+ return value;
41297
+ }
41298
+ return null;
41299
+ }
41300
+ var configValidateCommand;
41301
+ var init_validate2 = __esm({
41302
+ "packages/cleo/src/cli/commands/config/validate.ts"() {
41303
+ "use strict";
41304
+ init_src2();
41305
+ init_define_cli_command();
41306
+ init_renderers();
41307
+ configValidateCommand = defineCommand({
41308
+ meta: {
41309
+ name: "validate",
41310
+ description: "Validate a scoped config file against its schema (default scope: project)"
41311
+ },
41312
+ args: {
41313
+ scope: {
41314
+ type: "string",
41315
+ description: "Scope to validate: global | project (default project)",
41316
+ default: "project"
41317
+ },
41318
+ json: {
41319
+ type: "boolean",
41320
+ description: "Output as JSON"
41321
+ }
41322
+ },
41323
+ async run({ args }) {
41324
+ const scope = parseValidateScope(args["scope"]);
41325
+ if (scope === null) {
41326
+ cliError(
41327
+ `config validate failed: invalid --scope (must be global|project)`,
41328
+ 1 /* GENERAL_ERROR */,
41329
+ { name: "E_CONFIG_VALIDATE_FAILED" }
41330
+ );
41331
+ process.exit(1 /* GENERAL_ERROR */);
41332
+ return;
41333
+ }
41334
+ let validate;
41335
+ try {
41336
+ const projectRoot = getProjectRoot35();
41337
+ validate = await validateConfig3(scope, projectRoot);
41338
+ } catch (err) {
41339
+ const message = err instanceof Error ? err.message : String(err);
41340
+ cliError(`config validate failed: ${message}`, 1 /* GENERAL_ERROR */, {
41341
+ name: "E_CONFIG_VALIDATE_FAILED"
41342
+ });
41343
+ process.exit(1 /* GENERAL_ERROR */);
41344
+ return;
41345
+ }
41346
+ const result = {
41347
+ scope,
41348
+ ok: validate.ok,
41349
+ issues: validate.issues
41350
+ };
41351
+ cliOutput(result, {
41352
+ command: "config-validate",
41353
+ operation: "config.validate"
41354
+ });
41355
+ if (!validate.ok) {
41356
+ process.exit(6 /* VALIDATION_ERROR */);
41357
+ }
41358
+ }
41359
+ });
41360
+ }
41361
+ });
41362
+
41363
+ // packages/cleo/src/cli/commands/config/index.ts
41364
+ var init_config2 = __esm({
41365
+ "packages/cleo/src/cli/commands/config/index.ts"() {
41366
+ "use strict";
41367
+ init_drift_check();
41368
+ init_get();
41369
+ init_set();
41370
+ init_show();
41371
+ init_validate2();
41372
+ }
41373
+ });
41374
+
41375
+ // packages/cleo/src/cli/commands/config.ts
41376
+ var config_exports = {};
41377
+ __export(config_exports, {
41378
+ configCommand: () => configCommand
41379
+ });
41380
+ import { CleoError as CleoError2, loadConfig as loadConfig2 } from "@cleocode/core";
41381
+ var PRESET_DESCRIPTIONS, setPresetCommand, presetsCommand, listCommand7, configCommand;
41382
+ var init_config3 = __esm({
41383
+ "packages/cleo/src/cli/commands/config.ts"() {
41384
+ "use strict";
41385
+ init_dist();
41386
+ init_cli();
41387
+ init_define_cli_command();
41388
+ init_renderers();
41389
+ init_config2();
41390
+ PRESET_DESCRIPTIONS = {
41391
+ strict: "Block on missing AC, require session notes, enforce lifecycle pipeline.",
41392
+ standard: "Warn on missing AC, optional session notes, advisory lifecycle pipeline.",
41393
+ minimal: "No AC checking, no session requirement, lifecycle pipeline off."
41394
+ };
40120
41395
  setPresetCommand = defineCommand({
40121
41396
  meta: {
40122
41397
  name: "set-preset",
@@ -40158,7 +41433,7 @@ var init_config2 = __esm({
40158
41433
  cliOutput({ config: resolved }, { command: "config" });
40159
41434
  } catch (err) {
40160
41435
  if (err instanceof CleoError2) {
40161
- cliError(formatError4(err), err.code, { name: "E_CONFIG_LOAD" });
41436
+ cliError(`config list failed: ${err.message}`, err.code, { name: "E_CONFIG_LOAD" });
40162
41437
  process.exit(err.code);
40163
41438
  }
40164
41439
  throw err;
@@ -40166,10 +41441,16 @@ var init_config2 = __esm({
40166
41441
  }
40167
41442
  });
40168
41443
  configCommand = defineCommand({
40169
- meta: { name: "config", description: "Configuration management" },
41444
+ meta: {
41445
+ name: "config",
41446
+ description: "CleoConfig SSoT registry surface (show, get, set, validate, drift-check) + legacy presets/list"
41447
+ },
40170
41448
  subCommands: {
40171
- get: getCommand2,
40172
- set: setCommand,
41449
+ show: configShowCommand,
41450
+ get: configGetCommand,
41451
+ set: configSetCommand,
41452
+ validate: configValidateCommand,
41453
+ "drift-check": configDriftCheckCommand,
40173
41454
  "set-preset": setPresetCommand,
40174
41455
  presets: presetsCommand,
40175
41456
  list: listCommand7
@@ -41190,7 +42471,13 @@ var init_colors = __esm({
41190
42471
  });
41191
42472
 
41192
42473
  // packages/cleo/src/cli/renderers/generic-tree.ts
41193
- import { ascii as ascii2, KindIcon as KindIcon2, pickIcon, RelationIcon } from "@cleocode/contracts/render/icon.js";
42474
+ import {
42475
+ ascii as ascii2,
42476
+ KindIcon as KindIcon2,
42477
+ pickIcon,
42478
+ RelationIcon,
42479
+ StatusIcon as StatusIcon2
42480
+ } from "@cleocode/contracts/render/icon.js";
41194
42481
  function renderGenericTree(result, opts) {
41195
42482
  const explicitCtx = opts.ctx !== void 0;
41196
42483
  const ctx = opts.ctx ?? resolveAnimateContext();
@@ -41209,8 +42496,74 @@ function renderGenericTree(result, opts) {
41209
42496
  const annotations = renderAnnotations(result.tree, opts);
41210
42497
  if (annotations) lines.push(annotations);
41211
42498
  }
42499
+ const footer = renderFooterLegend(result, ctx, useAscii);
42500
+ if (footer) {
42501
+ lines.push("");
42502
+ lines.push(footer);
42503
+ }
41212
42504
  return lines.join("\n");
41213
42505
  }
42506
+ function renderFooterLegend(result, ctx, useAscii) {
42507
+ if (!ctx.enabled) return "";
42508
+ const kindsSeen = /* @__PURE__ */ new Set();
42509
+ const statusesSeen = /* @__PURE__ */ new Set();
42510
+ let hasGroupsEdge = false;
42511
+ for (const node of result.tree.tree) {
42512
+ kindsSeen.add(node.kind);
42513
+ statusesSeen.add(node.status);
42514
+ if (node.metadata.edgeType === "groups") hasGroupsEdge = true;
42515
+ }
42516
+ const items = [];
42517
+ const KIND_ORDER = [
42518
+ ["saga", "saga"],
42519
+ ["epic", "epic"],
42520
+ ["task", "task"],
42521
+ ["subtask", "subtask"]
42522
+ ];
42523
+ for (const [kind, label] of KIND_ORDER) {
42524
+ if (!kindsSeen.has(kind)) continue;
42525
+ items.push({ icon: pickIcon(kindIconOf(kind), { noColor: useAscii }), label });
42526
+ }
42527
+ if (hasGroupsEdge) {
42528
+ items.push({
42529
+ icon: useAscii ? ascii2(RelationIcon.GROUPS) : RelationIcon.GROUPS,
42530
+ label: "groups-edge"
42531
+ });
42532
+ }
42533
+ const STATUS_ORDER = [
42534
+ ["done", StatusIcon2.DONE],
42535
+ ["in_progress", StatusIcon2.ACTIVE],
42536
+ ["pending", StatusIcon2.PENDING],
42537
+ ["blocked", StatusIcon2.BLOCKED],
42538
+ ["archived", StatusIcon2.ARCHIVED],
42539
+ ["cancelled", StatusIcon2.CANCELLED]
42540
+ ];
42541
+ const STATUS_LABEL = {
42542
+ done: "done",
42543
+ in_progress: "active",
42544
+ pending: "pending",
42545
+ blocked: "blocked",
42546
+ archived: "archived",
42547
+ cancelled: "cancelled"
42548
+ };
42549
+ for (const [status, icon] of STATUS_ORDER) {
42550
+ if (!statusesSeen.has(status)) continue;
42551
+ items.push({
42552
+ icon: pickIcon(icon, { noColor: useAscii }),
42553
+ label: STATUS_LABEL[status] ?? status
42554
+ });
42555
+ }
42556
+ const legend = renderLegend({ items, ctx });
42557
+ const sagaMembers2 = result.tree.tree.filter((n) => n.metadata.edgeType === "groups").length;
42558
+ const counts2 = [
42559
+ { label: "nodes", n: result.tree.totalNodes },
42560
+ { label: "depth", n: result.tree.maxDepth }
42561
+ ];
42562
+ if (sagaMembers2 > 0) counts2.push({ label: "saga members", n: sagaMembers2 });
42563
+ const summary = renderSummary({ counts: counts2, ctx });
42564
+ const divider = `${DIM}\u2500\u2500\u2500 Legend \u2500\u2500\u2500${NC}`;
42565
+ return [divider, legend, summary].filter(Boolean).join("\n");
42566
+ }
41214
42567
  function decorateGroupsEdges(tree, useAscii) {
41215
42568
  const glyph = useAscii ? ascii2(RelationIcon.GROUPS) : RelationIcon.GROUPS;
41216
42569
  const prefix = `${glyph} `;
@@ -42367,7 +43720,7 @@ import { dirname as dirname7, join as join19, normalize, resolve as resolve4 } f
42367
43720
  import { fileURLToPath as fileURLToPath4 } from "node:url";
42368
43721
  import {
42369
43722
  createAttachmentStore as createAttachmentStore5,
42370
- getProjectRoot as getProjectRoot31,
43723
+ getProjectRoot as getProjectRoot36,
42371
43724
  searchAllProjectDocs
42372
43725
  } from "@cleocode/core/internal";
42373
43726
  function getViewerAssetsDir() {
@@ -42427,7 +43780,7 @@ async function serveStatic(res, assetsDir, relPath) {
42427
43780
  }
42428
43781
  }
42429
43782
  function buildViewerHandler(opts = {}) {
42430
- const projectRoot = opts.projectRoot ?? getProjectRoot31();
43783
+ const projectRoot = opts.projectRoot ?? getProjectRoot36();
42431
43784
  const assetsDir = getViewerAssetsDir();
42432
43785
  const store = createAttachmentStore5();
42433
43786
  return async (req, res) => {
@@ -42605,7 +43958,7 @@ import { spawn } from "node:child_process";
42605
43958
  import { open as fsOpen } from "node:fs/promises";
42606
43959
  import { join as join20 } from "node:path";
42607
43960
  import { fileURLToPath as fileURLToPath5 } from "node:url";
42608
- import { getCleoHome as getCleoHome3, getProjectRoot as getProjectRoot32 } from "@cleocode/core";
43961
+ import { getCleoHome as getCleoHome3, getProjectRoot as getProjectRoot37 } from "@cleocode/core";
42609
43962
  function getCleoBinPath() {
42610
43963
  const thisFile = fileURLToPath5(import.meta.url);
42611
43964
  return join20(thisFile, "..", "..", "index.js");
@@ -42656,7 +44009,7 @@ async function spawnDetachedServer(opts) {
42656
44009
  detached: true,
42657
44010
  stdio,
42658
44011
  env: { ...process.env, [DETACHED_CHILD_ENV]: "1" },
42659
- cwd: getProjectRoot32()
44012
+ cwd: getProjectRoot37()
42660
44013
  });
42661
44014
  child.unref();
42662
44015
  if (handle) await handle.close();
@@ -42808,7 +44161,7 @@ var init_docs_viewer = __esm({
42808
44161
  pid: process.pid,
42809
44162
  port: handle.port,
42810
44163
  host: handle.host,
42811
- projectRoot: getProjectRoot32(),
44164
+ projectRoot: getProjectRoot37(),
42812
44165
  startedAt: Date.now()
42813
44166
  };
42814
44167
  await writeViewerPidFile(record);
@@ -43096,7 +44449,7 @@ import {
43096
44449
  detectStrayCleoDb as detectStrayCleoDb2,
43097
44450
  exportDocument,
43098
44451
  getAgentOutputsAbsolute,
43099
- getProjectRoot as getProjectRoot33,
44452
+ getProjectRoot as getProjectRoot38,
43100
44453
  listDocVersions,
43101
44454
  makeClassifierForScanRoot,
43102
44455
  mergeDocs,
@@ -43254,6 +44607,10 @@ var init_docs3 = __esm({
43254
44607
  "allow-similar": {
43255
44608
  type: "boolean",
43256
44609
  description: "Bypass the T10361 slug-similarity check. Use when you really do mean to add a new doc with a near-duplicate slug (e.g. intentional fork). Every bypass is logged to .cleo/audit/similar-bypass.jsonl."
44610
+ },
44611
+ strict: {
44612
+ type: "boolean",
44613
+ description: "Enforce body-schema validation against the kind's requiredSections (T10160). When set, a missing H2 section fails the write with E_DOC_SCHEMA_MISMATCH. Default (advisory) surfaces missing sections as a W_DOC_SCHEMA_MISMATCH warning."
43257
44614
  }
43258
44615
  },
43259
44616
  async run({ args, rawArgs }) {
@@ -43305,7 +44662,7 @@ var init_docs3 = __esm({
43305
44662
  resolvedFile = resolveWorktreeFilePath(String(fileArg), routing);
43306
44663
  }
43307
44664
  if (args.slug && args.type) {
43308
- const projectRoot = await getProjectRoot33();
44665
+ const projectRoot = await getProjectRoot38();
43309
44666
  let warnThreshold = DEFAULT_SIMILARITY_THRESHOLD;
43310
44667
  let mode = DEFAULT_SIMILARITY_MODE;
43311
44668
  try {
@@ -43394,7 +44751,8 @@ var init_docs3 = __esm({
43394
44751
  ...args.labels ? { labels: args.labels } : {},
43395
44752
  ...args["attached-by"] ? { attachedBy: args["attached-by"] } : {},
43396
44753
  ...args.slug ? { slug: args.slug } : {},
43397
- ...args.type ? { type: args.type } : {}
44754
+ ...args.type ? { type: args.type } : {},
44755
+ ...args.strict === true ? { strict: true } : {}
43398
44756
  },
43399
44757
  { command: "docs add" }
43400
44758
  );
@@ -43605,7 +44963,7 @@ var init_docs3 = __esm({
43605
44963
  const taskId = String(args.task);
43606
44964
  const includeAttachments = args["include-attachments"] !== false;
43607
44965
  const includeMemoryRefs = args["include-memory-refs"] === true;
43608
- const projectRoot = getProjectRoot33();
44966
+ const projectRoot = getProjectRoot38();
43609
44967
  try {
43610
44968
  const result = await exportDocument({
43611
44969
  taskId,
@@ -43671,7 +45029,7 @@ var init_docs3 = __esm({
43671
45029
  }
43672
45030
  },
43673
45031
  async run({ args }) {
43674
- const projectRoot = getProjectRoot33();
45032
+ const projectRoot = getProjectRoot38();
43675
45033
  const limit = args.limit ? Number.parseInt(String(args.limit), 10) : 10;
43676
45034
  try {
43677
45035
  const result = args.owner ? await searchDocs2(String(args.query), {
@@ -43727,7 +45085,7 @@ var init_docs3 = __esm({
43727
45085
  }
43728
45086
  },
43729
45087
  async run({ args }) {
43730
- const projectRoot = getProjectRoot33();
45088
+ const projectRoot = getProjectRoot38();
43731
45089
  const rawStrategy = args.strategy ?? "three-way";
43732
45090
  const strategy = rawStrategy === "cherry-pick" || rawStrategy === "multi-diff" ? rawStrategy : "three-way";
43733
45091
  try {
@@ -43776,7 +45134,7 @@ var init_docs3 = __esm({
43776
45134
  }
43777
45135
  },
43778
45136
  async run({ args }) {
43779
- const projectRoot = getProjectRoot33();
45137
+ const projectRoot = getProjectRoot38();
43780
45138
  const fmt = args.format ?? "mermaid";
43781
45139
  try {
43782
45140
  const result = await buildDocsGraph({ ownerId: String(args.for), projectRoot });
@@ -43845,7 +45203,7 @@ var init_docs3 = __esm({
43845
45203
  }
43846
45204
  },
43847
45205
  async run({ args }) {
43848
- const projectRoot = getProjectRoot33();
45206
+ const projectRoot = getProjectRoot38();
43849
45207
  try {
43850
45208
  const result = await rankDocs({
43851
45209
  ownerId: String(args.for),
@@ -43883,7 +45241,7 @@ var init_docs3 = __esm({
43883
45241
  }
43884
45242
  },
43885
45243
  async run({ args }) {
43886
- const projectRoot = getProjectRoot33();
45244
+ const projectRoot = getProjectRoot38();
43887
45245
  try {
43888
45246
  const result = await listDocVersions({
43889
45247
  ownerId: String(args.for),
@@ -43926,7 +45284,7 @@ var init_docs3 = __esm({
43926
45284
  }
43927
45285
  },
43928
45286
  async run({ args }) {
43929
- const projectRoot = getProjectRoot33();
45287
+ const projectRoot = getProjectRoot38();
43930
45288
  try {
43931
45289
  const result = await publishDocs({
43932
45290
  ownerId: String(args.for),
@@ -44050,7 +45408,7 @@ var init_docs3 = __esm({
44050
45408
  },
44051
45409
  async run({ args }) {
44052
45410
  if (args.from) {
44053
- const projectRoot = getProjectRoot33();
45411
+ const projectRoot = getProjectRoot38();
44054
45412
  const ownerId = args.for ?? void 0;
44055
45413
  if (!ownerId) {
44056
45414
  cliError(
@@ -44117,7 +45475,7 @@ var init_docs3 = __esm({
44117
45475
  }
44118
45476
  },
44119
45477
  async run() {
44120
- const projectRoot = getProjectRoot33();
45478
+ const projectRoot = getProjectRoot38();
44121
45479
  try {
44122
45480
  const result = await statusDocs({ projectRoot });
44123
45481
  cliOutput(result, { command: "docs status", operation: "docs.status" });
@@ -44202,7 +45560,7 @@ var init_docs3 = __esm({
44202
45560
  }
44203
45561
  },
44204
45562
  async run({ args }) {
44205
- const projectRoot = getProjectRoot33();
45563
+ const projectRoot = getProjectRoot38();
44206
45564
  const dirArg = String(args.dir);
44207
45565
  const scanRoot = isAbsolute2(dirArg) ? dirArg : resolve5(projectRoot, dirArg);
44208
45566
  const dryRun = args["dry-run"] === true;
@@ -44276,7 +45634,7 @@ var init_docs3 = __esm({
44276
45634
  }
44277
45635
  },
44278
45636
  async run({ args }) {
44279
- const projectRoot = getProjectRoot33();
45637
+ const projectRoot = getProjectRoot38();
44280
45638
  const { registry, configError } = loadCliRegistry(projectRoot);
44281
45639
  const kinds = registry.list().map(toWireKind);
44282
45640
  const extensionsCount = kinds.filter((k) => k.isExtension).length;
@@ -44320,7 +45678,7 @@ var init_docs3 = __esm({
44320
45678
  }
44321
45679
  },
44322
45680
  async run({ args }) {
44323
- const projectRoot = getProjectRoot33();
45681
+ const projectRoot = getProjectRoot38();
44324
45682
  const { registry, configError } = loadCliRegistry(projectRoot);
44325
45683
  const kinds = registry.list().map(toWireKind);
44326
45684
  let counts2;
@@ -44403,7 +45761,7 @@ var doctor_db_substrate_exports = {};
44403
45761
  __export(doctor_db_substrate_exports, {
44404
45762
  doctorDbSubstrateCommand: () => doctorDbSubstrateCommand
44405
45763
  });
44406
- import { getProjectRoot as getProjectRoot34, pushWarning as pushWarning2 } from "@cleocode/core";
45764
+ import { getProjectRoot as getProjectRoot39, pushWarning as pushWarning3 } from "@cleocode/core";
44407
45765
  import { surveyDbSubstrate, surveyFleetDbSubstrate } from "@cleocode/core/doctor/db-substrate.js";
44408
45766
  function pushSubstrateWarnings(result) {
44409
45767
  for (const warning of result.warnings) {
@@ -44415,7 +45773,7 @@ function pushSubstrateWarnings(result) {
44415
45773
  if (warning.kind === "orphan-project-root") {
44416
45774
  context["parentWorkspace"] = warning.parentWorkspace ?? null;
44417
45775
  }
44418
- pushWarning2({
45776
+ pushWarning3({
44419
45777
  code: warning.kind === "orphan-project-root" ? "W_DB_SUBSTRATE_ORPHAN_PROJECT_ROOT" : "W_DB_SUBSTRATE_NESTED_NEXUS_DUPLICATE",
44420
45778
  message: warning.kind === "orphan-project-root" ? `Orphan project-root .cleo/ at ${warning.path} (T9550 regression class \u2014 review then remove)` + (warning.parentWorkspace ? ` \u2014 attributed to workspace: ${warning.parentWorkspace}` : "") : `Nested-nexus duplicate at ${warning.path} (structural duplicate of the canonical flat layout)`,
44421
45779
  severity: "warn",
@@ -44426,7 +45784,7 @@ function pushSubstrateWarnings(result) {
44426
45784
  for (const [role, entry] of Object.entries(projectSurvey.dbs)) {
44427
45785
  if (entry.pragmaDrift === null || entry.pragmaDrift.length === 0) continue;
44428
45786
  for (const drift of entry.pragmaDrift) {
44429
- pushWarning2({
45787
+ pushWarning3({
44430
45788
  code: "W_DB_SUBSTRATE_PRAGMA_DRIFT",
44431
45789
  message: `Pragma drift on ${role} (${entry.filePath}): expected ${drift.pragma}=${drift.expected}, actual=${drift.actual ?? "<unmeasurable>"}`,
44432
45790
  severity: "warn",
@@ -44443,7 +45801,7 @@ function pushSubstrateWarnings(result) {
44443
45801
  }
44444
45802
  for (const report of result.crossDbOrphans) {
44445
45803
  if (report.skipped || report.orphanCount === 0) continue;
44446
- pushWarning2({
45804
+ pushWarning3({
44447
45805
  code: `W_DB_SUBSTRATE_CROSS_DB_${report.invariant}`,
44448
45806
  message: `${report.invariant}: ${report.orphanCount} orphan row${report.orphanCount === 1 ? "" : "s"} \u2014 ${report.description}. ${report.suggestedFix}`,
44449
45807
  severity: "warn",
@@ -44460,7 +45818,7 @@ function pushPerDbWarnings(result) {
44460
45818
  for (const projectSurvey of result.projects) {
44461
45819
  for (const [role, dbEntry] of Object.entries(projectSurvey.dbs)) {
44462
45820
  if (dbEntry.quarantinedTo !== null) {
44463
- pushWarning2({
45821
+ pushWarning3({
44464
45822
  code: "W_DB_SUBSTRATE_AUTO_QUARANTINED",
44465
45823
  message: `Auto-quarantined corrupt ${role} DB at ${dbEntry.filePath} \u2192 ${dbEntry.quarantinedTo}. Recover via: cleo backup recover ${role}`,
44466
45824
  severity: "warn",
@@ -44473,7 +45831,7 @@ function pushPerDbWarnings(result) {
44473
45831
  });
44474
45832
  }
44475
45833
  if (dbEntry.timedOut) {
44476
- pushWarning2({
45834
+ pushWarning3({
44477
45835
  code: "W_DB_SUBSTRATE_INTEGRITY_TIMEOUT",
44478
45836
  message: `integrity_check on ${role} DB at ${dbEntry.filePath} took ${dbEntry.integrityCheckMs}ms \u2014 slow substrate flagged for operator attention`,
44479
45837
  severity: "warn",
@@ -44536,7 +45894,7 @@ var init_doctor_db_substrate = __esm({
44536
45894
  const result = isFleet ? surveyFleetDbSubstrate(
44537
45895
  typeof args["fleet-root"] === "string" && args["fleet-root"].length > 0 ? args["fleet-root"] : DEFAULT_FLEET_ROOT,
44538
45896
  options
44539
- ) : surveyDbSubstrate(getProjectRoot34(), options);
45897
+ ) : surveyDbSubstrate(getProjectRoot39(), options);
44540
45898
  pushSubstrateWarnings(result);
44541
45899
  pushPerDbWarnings(result);
44542
45900
  cliOutput(result, {
@@ -44556,7 +45914,7 @@ var doctor_legacy_backups_exports = {};
44556
45914
  __export(doctor_legacy_backups_exports, {
44557
45915
  doctorLegacyBackupsCommand: () => doctorLegacyBackupsCommand
44558
45916
  });
44559
- import { getProjectRoot as getProjectRoot35 } from "@cleocode/core";
45917
+ import { getProjectRoot as getProjectRoot40 } from "@cleocode/core";
44560
45918
  import { pruneLegacyBackups, scanLegacyBackups } from "@cleocode/core/doctor/legacy-backups.js";
44561
45919
  function parsePositiveInt(raw, fallback) {
44562
45920
  if (raw === void 0 || raw === null) return fallback;
@@ -44600,7 +45958,7 @@ var init_doctor_legacy_backups = __esm({
44600
45958
  async run({ args }) {
44601
45959
  const softRetentionDays = parsePositiveInt(args["soft-retention-days"], 30);
44602
45960
  const hardRetentionDays = parsePositiveInt(args["hard-retention-days"], 90);
44603
- const projectRoot = getProjectRoot35();
45961
+ const projectRoot = getProjectRoot40();
44604
45962
  let result;
44605
45963
  if (args.prune === true) {
44606
45964
  const dryRun = args["dry-run"] !== false;
@@ -44903,7 +46261,7 @@ __export(migrate_agents_v2_exports, {
44903
46261
  import { createHash as createHash2 } from "node:crypto";
44904
46262
  import { appendFileSync as appendFileSync2, existsSync as existsSync14, mkdirSync as mkdirSync3, readdirSync as readdirSync2, readFileSync as readFileSync14 } from "node:fs";
44905
46263
  import { join as join22 } from "node:path";
44906
- import { getProjectRoot as getProjectRoot36, installAgentFromCant } from "@cleocode/core/internal";
46264
+ import { getProjectRoot as getProjectRoot41, installAgentFromCant } from "@cleocode/core/internal";
44907
46265
  import { openCleoDb as openCleoDb2 } from "@cleocode/core/store/open-cleo-db";
44908
46266
  function sha256Hex(bytes) {
44909
46267
  return createHash2("sha256").update(bytes).digest("hex");
@@ -45090,7 +46448,7 @@ var init_migrate_agents_v2 = __esm({
45090
46448
  }
45091
46449
  },
45092
46450
  async run({ args }) {
45093
- const projectRoot = getProjectRoot36();
46451
+ const projectRoot = getProjectRoot41();
45094
46452
  const verbose = args.quiet !== true;
45095
46453
  if (verbose) {
45096
46454
  humanInfo("Scanning .cleo/cant/agents/ and .cleo/agents/ for unregistered agents...");
@@ -45134,7 +46492,8 @@ __export(doctor_exports, {
45134
46492
  });
45135
46493
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync4 } from "node:fs";
45136
46494
  import { join as join23 } from "node:path";
45137
- import { getProjectRoot as getProjectRoot37, pushWarning as pushWarning3 } from "@cleocode/core";
46495
+ import { getProjectRoot as getProjectRoot42, pushWarning as pushWarning4 } from "@cleocode/core";
46496
+ import { renderInvariantAuditLines } from "@cleocode/core/doctor/invariant-audit-render.js";
45138
46497
  import {
45139
46498
  quarantineRogueCleoDir,
45140
46499
  scanRogueCleoDirs
@@ -45235,6 +46594,11 @@ Provider Hook Matrix (CAAMP ${caampVersion} canonical taxonomy)
45235
46594
  humanLine(`Coverage: ${coverageParts.join(", ")}
45236
46595
  `);
45237
46596
  }
46597
+ function renderInvariantAuditHuman(result) {
46598
+ for (const line of renderInvariantAuditLines(result)) {
46599
+ humanLine(line);
46600
+ }
46601
+ }
45238
46602
  var FIXTURE_ID_PATTERNS, FIXTURE_TITLE_KEYWORDS, doctorCommand2;
45239
46603
  var init_doctor = __esm({
45240
46604
  "packages/cleo/src/cli/commands/doctor.ts"() {
@@ -45356,13 +46720,36 @@ var init_doctor = __esm({
45356
46720
  * auto-close drift. Read-only; non-zero exit when any I-invariant
45357
46721
  * fails so the check is CI-gateable.
45358
46722
  *
46723
+ * As of T10340 (R6), `--audit-sagas` is a focused alias on top of
46724
+ * `--audit-invariants` — it filters the registry walk to ADR-073
46725
+ * only. The implementation re-uses the central walker so the two
46726
+ * surfaces stay in lock-step.
46727
+ *
45359
46728
  * @task T10119
46729
+ * @task T10340
45360
46730
  * @saga T10113
45361
46731
  * @epic T10209
45362
46732
  */
45363
46733
  "audit-sagas": {
45364
46734
  type: "boolean",
45365
- description: "Audit every Saga for ADR-073 \xA71.2 invariant violations (I5/I7/depth) + auto-close drift (T10119)"
46735
+ description: "Audit every Saga for ADR-073 \xA71.2 invariant violations (I5/I7/depth) + auto-close drift \u2014 focused alias on top of --audit-invariants (T10119, T10340)"
46736
+ },
46737
+ /**
46738
+ * T10340: walk the central `INVARIANTS_REGISTRY` and audit every
46739
+ * registered invariant against the project's current state.
46740
+ *
46741
+ * Output groups violations by ADR + severity and includes an
46742
+ * actionable repair command per violation. Supports `--json` for
46743
+ * machine consumption. Exit code is non-zero when any
46744
+ * `severity:'error'` violation is observed.
46745
+ *
46746
+ * @task T10340 — R6
46747
+ * @epic T10327 — E-INVARIANT-REGISTRY-SSOT
46748
+ * @saga T10326 — SG-SUBSTRATE-RECONCILIATION
46749
+ */
46750
+ "audit-invariants": {
46751
+ type: "boolean",
46752
+ description: "Walk the central INVARIANTS_REGISTRY and audit every registered invariant \u2014 groups by ADR + severity with repair commands (T10340 / Saga T10326 R6)"
45366
46753
  },
45367
46754
  /**
45368
46755
  * T9983: migrate the worktree-include file location from
@@ -45429,7 +46816,7 @@ var init_doctor = __esm({
45429
46816
  try {
45430
46817
  if (args.brain) {
45431
46818
  const { computeBrainHealthDashboard } = await import("@cleocode/core/memory/brain-health-dashboard.js");
45432
- const projectRoot = getProjectRoot37();
46819
+ const projectRoot = getProjectRoot42();
45433
46820
  const dashboard = await computeBrainHealthDashboard(projectRoot);
45434
46821
  cliOutput(dashboard, { command: "doctor", operation: "doctor.brain" });
45435
46822
  if (dashboard.hasP0Failure) {
@@ -45438,7 +46825,7 @@ var init_doctor = __esm({
45438
46825
  return;
45439
46826
  }
45440
46827
  if (args["scan-test-fixtures-in-prod"]) {
45441
- const projectRoot = getProjectRoot37();
46828
+ const projectRoot = getProjectRoot42();
45442
46829
  const matches = await scanTestFixturesInProd(projectRoot);
45443
46830
  const dryRun = args["dry-run"] !== false && args.quarantine !== true;
45444
46831
  const quarantined = !dryRun && matches.length > 0 ? await quarantineTestFixtures(projectRoot, matches) : void 0;
@@ -45526,7 +46913,7 @@ var init_doctor = __esm({
45526
46913
  progress.complete("Comprehensive diagnostics complete");
45527
46914
  } else if (args["scan-rogue-cleo-dirs"]) {
45528
46915
  progress.step(0, "Scanning for rogue .cleo/ directories");
45529
- const projectRoot = getProjectRoot37();
46916
+ const projectRoot = getProjectRoot42();
45530
46917
  const reports = scanRogueCleoDirs(projectRoot);
45531
46918
  progress.complete(
45532
46919
  `Found ${reports.length} rogue .cleo/ director${reports.length === 1 ? "y" : "ies"}`
@@ -45535,7 +46922,7 @@ var init_doctor = __esm({
45535
46922
  } else if (args["quarantine-rogue-cleo-dirs"]) {
45536
46923
  const isDryRun = args["dry-run"] === true;
45537
46924
  progress.step(0, `${isDryRun ? "[DRY RUN] " : ""}Scanning for rogue .cleo/ directories`);
45538
- const projectRoot = getProjectRoot37();
46925
+ const projectRoot = getProjectRoot42();
45539
46926
  const reports = scanRogueCleoDirs(projectRoot);
45540
46927
  if (reports.length === 0) {
45541
46928
  progress.complete("No rogue .cleo/ directories found \u2014 nothing to quarantine");
@@ -45589,7 +46976,7 @@ var init_doctor = __esm({
45589
46976
  const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/store/cleanup-legacy.js");
45590
46977
  const { getCleoHome: getCleoHome6 } = await import("@cleocode/core");
45591
46978
  const cleoHome = getCleoHome6();
45592
- const projectRoot = getProjectRoot37();
46979
+ const projectRoot = getProjectRoot42();
45593
46980
  const legacyResult = detectAndRemoveLegacyGlobalFiles(cleoHome);
45594
46981
  const strayResult = detectAndRemoveStrayProjectNexus(projectRoot);
45595
46982
  const isDryRun = args["dry-run"] === true;
@@ -45622,7 +47009,7 @@ var init_doctor = __esm({
45622
47009
  } else if (args["audit-worktree-orphans"]) {
45623
47010
  progress.step(0, "Comprehensive worktree anomaly audit (T9808 / council D009)");
45624
47011
  const { auditWorktreeOrphansComprehensive, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
45625
- const projectRoot = getProjectRoot37();
47012
+ const projectRoot = getProjectRoot42();
45626
47013
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
45627
47014
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
45628
47015
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -45636,7 +47023,7 @@ var init_doctor = __esm({
45636
47023
  const legacyOrphans = legacyScanResult.orphans;
45637
47024
  const totalAnomalies = comprehensive.count;
45638
47025
  if (legacyScanResult.softWarnMessage) {
45639
- pushWarning3({
47026
+ pushWarning4({
45640
47027
  code: "W_DOCTOR_SCAN_SOFT_WARN",
45641
47028
  message: legacyScanResult.softWarnMessage,
45642
47029
  severity: "warn"
@@ -45644,7 +47031,7 @@ var init_doctor = __esm({
45644
47031
  }
45645
47032
  if (legacyScanResult.isPartial) {
45646
47033
  const reason = legacyScanResult.partialReason === "timeout" ? `timed out after ${timeoutSecs}s (use --timeout <seconds> to adjust)` : `per-level entry cap of ${maxEntriesPerLevel} exceeded (use --max-entries-per-level <n> to adjust)`;
45647
- pushWarning3({
47034
+ pushWarning4({
45648
47035
  code: "W_DOCTOR_SCAN_PARTIAL",
45649
47036
  message: `legacy orphan scan is PARTIAL \u2014 ${reason}. Results may be incomplete.`,
45650
47037
  severity: "warn",
@@ -45679,7 +47066,7 @@ var init_doctor = __esm({
45679
47066
  `${isDryRun ? "[DRY RUN] " : ""}Scanning + pruning worktree-orphan .cleo/ directories`
45680
47067
  );
45681
47068
  const { pruneWorktreeOrphans, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
45682
- const projectRoot = getProjectRoot37();
47069
+ const projectRoot = getProjectRoot42();
45683
47070
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
45684
47071
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
45685
47072
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -45688,7 +47075,7 @@ var init_doctor = __esm({
45688
47075
  maxEntriesPerLevel: Number.isFinite(maxEntriesPerLevel) ? maxEntriesPerLevel : 500
45689
47076
  });
45690
47077
  if (scanResult.softWarnMessage) {
45691
- pushWarning3({
47078
+ pushWarning4({
45692
47079
  code: "W_DOCTOR_SCAN_SOFT_WARN",
45693
47080
  message: scanResult.softWarnMessage,
45694
47081
  severity: "warn"
@@ -45696,7 +47083,7 @@ var init_doctor = __esm({
45696
47083
  }
45697
47084
  if (scanResult.isPartial) {
45698
47085
  const reason = scanResult.partialReason === "timeout" ? `timed out after ${timeoutSecs}s (use --timeout <seconds> to adjust)` : `per-level entry cap of ${maxEntriesPerLevel} exceeded (use --max-entries-per-level <n> to adjust)`;
45699
- pushWarning3({
47086
+ pushWarning4({
45700
47087
  code: "W_DOCTOR_SCAN_PARTIAL",
45701
47088
  message: `orphan scan is PARTIAL \u2014 ${reason}. Only orphans found before abort will be pruned.`,
45702
47089
  severity: "warn",
@@ -45758,7 +47145,7 @@ var init_doctor = __esm({
45758
47145
  `${isDryRun ? "[DRY RUN] " : ""}Migrating .cleo/worktree-include \u2192 .worktreeinclude`
45759
47146
  );
45760
47147
  const { migrateWorktreeIncludeFile } = await import("@cleocode/core");
45761
- const projectRoot = getProjectRoot37();
47148
+ const projectRoot = getProjectRoot42();
45762
47149
  const result = await migrateWorktreeIncludeFile(projectRoot, { dryRun: isDryRun });
45763
47150
  progress.complete(`Migration ${result.action}`);
45764
47151
  cliOutput(result, { command: "doctor", operation: "doctor.migrate-worktree-include" });
@@ -45771,15 +47158,22 @@ var init_doctor = __esm({
45771
47158
  if (checkResult.details?.["orphans"] && checkResult.details["orphans"].length > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
45772
47159
  process.exitCode = 2;
45773
47160
  }
45774
- } else if (args["audit-sagas"]) {
45775
- progress.step(0, "Auditing Saga hierarchy for ADR-073 invariants");
45776
- const { auditSagaHierarchy } = await import("@cleocode/core/doctor/saga-audit.js");
45777
- const projectRoot = getProjectRoot37();
45778
- const result = await auditSagaHierarchy(projectRoot);
45779
- const summary = `Saga audit complete \u2014 ${result.sagas.length} saga(s) inspected, ${result.count} invariant violation(s), ${result.driftCount} drift warning(s)`;
47161
+ } else if (args["audit-invariants"] || args["audit-sagas"]) {
47162
+ const isFocusedAlias = args["audit-sagas"] === true && args["audit-invariants"] !== true;
47163
+ const adrFilter = isFocusedAlias ? "ADR-073" : void 0;
47164
+ const stepLabel = isFocusedAlias ? "Auditing Saga hierarchy for ADR-073 invariants" : "Walking central INVARIANTS_REGISTRY";
47165
+ progress.step(0, stepLabel);
47166
+ const { auditInvariantRegistry } = await import("@cleocode/core/doctor/invariant-audit.js");
47167
+ const projectRoot = getProjectRoot42();
47168
+ const result = await auditInvariantRegistry(projectRoot, { adrFilter });
47169
+ const operation = isFocusedAlias ? "doctor.audit-sagas" : "doctor.audit-invariants";
47170
+ const summary = `Invariant audit complete \u2014 ${result.totalCount} entries walked, ${result.errorCount} error / ${result.warningCount} warning / ${result.infoCount} info violation(s), ${result.notApplicableCount} not-applicable, ${result.documentedCount} documented`;
45780
47171
  progress.complete(summary);
45781
- cliOutput(result, { command: "doctor", operation: "doctor.audit-sagas" });
45782
- if (result.count > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
47172
+ if (isHuman && args.json !== true) {
47173
+ renderInvariantAuditHuman(result);
47174
+ }
47175
+ cliOutput(result, { command: "doctor", operation });
47176
+ if (result.errorCount > 0 && (process.exitCode === void 0 || process.exitCode === 0)) {
45783
47177
  process.exitCode = 2;
45784
47178
  }
45785
47179
  } else {
@@ -45792,7 +47186,7 @@ var init_doctor = __esm({
45792
47186
  { command: "doctor", operation: "admin.health" }
45793
47187
  );
45794
47188
  try {
45795
- const projectRoot = getProjectRoot37();
47189
+ const projectRoot = getProjectRoot42();
45796
47190
  const conflicts = readMigrationConflicts(projectRoot);
45797
47191
  if (conflicts.length > 0) {
45798
47192
  progress.complete(
@@ -45823,7 +47217,7 @@ var init_doctor = __esm({
45823
47217
  progress.complete("Health check complete");
45824
47218
  }
45825
47219
  try {
45826
- const projectRoot = getProjectRoot37();
47220
+ const projectRoot = getProjectRoot42();
45827
47221
  const { auditSagaHierarchy } = await import("@cleocode/core/doctor/saga-audit.js");
45828
47222
  const sagaAudit = await auditSagaHierarchy(projectRoot);
45829
47223
  if (sagaAudit.sagas.length === 0) {
@@ -48035,7 +49429,7 @@ import { join as join26 } from "node:path";
48035
49429
  import { fileURLToPath as fileURLToPath6 } from "node:url";
48036
49430
  import {
48037
49431
  CleoError as CleoError4,
48038
- formatError as formatError5,
49432
+ formatError as formatError4,
48039
49433
  getWorkflowTemplatesDir as getCoreWorkflowTemplatesDir,
48040
49434
  initProject as initProject2,
48041
49435
  scaffoldWorkflows
@@ -48155,7 +49549,7 @@ var init_init = __esm({
48155
49549
  );
48156
49550
  } catch (err) {
48157
49551
  if (err instanceof CleoError4) {
48158
- cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
49552
+ cliError(formatError4(err), err.code, { name: "E_INTERNAL" });
48159
49553
  process.exit(err.code);
48160
49554
  }
48161
49555
  throw err;
@@ -48970,7 +50364,7 @@ var llm_cost_exports = {};
48970
50364
  __export(llm_cost_exports, {
48971
50365
  costCommand: () => costCommand
48972
50366
  });
48973
- import { getProjectRoot as getProjectRoot38 } from "@cleocode/core/internal";
50367
+ import { getProjectRoot as getProjectRoot43 } from "@cleocode/core/internal";
48974
50368
  import { computeCost } from "@cleocode/core/llm/usage-pricing";
48975
50369
  function resolveSessionId(raw) {
48976
50370
  if (raw === "current") {
@@ -49043,7 +50437,7 @@ var init_llm_cost = __esm({
49043
50437
  process.exit(6);
49044
50438
  }
49045
50439
  const sessionId = resolveSessionId(rawSessionId);
49046
- const projectRoot = getProjectRoot38(process.cwd());
50440
+ const projectRoot = getProjectRoot43(process.cwd());
49047
50441
  let breakdown;
49048
50442
  try {
49049
50443
  breakdown = await loadSessionCostBreakdown(projectRoot, sessionId);
@@ -49684,7 +51078,7 @@ var llm_exports = {};
49684
51078
  __export(llm_exports, {
49685
51079
  llmCommand: () => llmCommand
49686
51080
  });
49687
- import { pushWarning as pushWarning4 } from "@cleocode/core";
51081
+ import { pushWarning as pushWarning5 } from "@cleocode/core";
49688
51082
  async function getListProviders() {
49689
51083
  const { listProviders } = await import(
49690
51084
  /* webpackIgnore: true */
@@ -49815,7 +51209,7 @@ var init_llm3 = __esm({
49815
51209
  apiKey = envValue;
49816
51210
  source = "env";
49817
51211
  } else if (typeof a["api-key"] === "string" && a["api-key"]) {
49818
- pushWarning4({
51212
+ pushWarning5({
49819
51213
  code: "W_DEPRECATED_FLAG",
49820
51214
  message: API_KEY_FLAG_DEPRECATION,
49821
51215
  deprecated: "--api-key=<value>",
@@ -50245,7 +51639,7 @@ async function readStdin() {
50245
51639
  });
50246
51640
  }
50247
51641
  var showCommand7, listCommand13, findCommand4, statsCommand3, appendCommand, archiveCommand2, manifestCommand;
50248
- var init_manifest = __esm({
51642
+ var init_manifest3 = __esm({
50249
51643
  "packages/cleo/src/cli/commands/manifest.ts"() {
50250
51644
  "use strict";
50251
51645
  init_dist();
@@ -50590,7 +51984,7 @@ var memory_exports = {};
50590
51984
  __export(memory_exports, {
50591
51985
  memoryCommand: () => memoryCommand
50592
51986
  });
50593
- import { getProjectRoot as getProjectRoot39 } from "@cleocode/core";
51987
+ import { getProjectRoot as getProjectRoot44 } from "@cleocode/core";
50594
51988
  import {
50595
51989
  getBrainDb as getBrainDb2,
50596
51990
  getDreamStatus,
@@ -51514,7 +52908,7 @@ var init_memory3 = __esm({
51514
52908
  },
51515
52909
  args: {},
51516
52910
  async run() {
51517
- const root = getProjectRoot39();
52911
+ const root = getProjectRoot44();
51518
52912
  try {
51519
52913
  const result = await runConsolidation(root);
51520
52914
  cliOutput(result, { command: "memory-consolidate", operation: "memory.consolidate" });
@@ -51538,7 +52932,7 @@ var init_memory3 = __esm({
51538
52932
  }
51539
52933
  },
51540
52934
  async run({ args }) {
51541
- const root = getProjectRoot39();
52935
+ const root = getProjectRoot44();
51542
52936
  if (args.status) {
51543
52937
  try {
51544
52938
  const status = await getDreamStatus(root);
@@ -51575,7 +52969,7 @@ var init_memory3 = __esm({
51575
52969
  }
51576
52970
  },
51577
52971
  async run({ args }) {
51578
- const root = getProjectRoot39();
52972
+ const root = getProjectRoot44();
51579
52973
  try {
51580
52974
  const { runObserver, runReflector } = await import("@cleocode/core/memory");
51581
52975
  const observerResult = await runObserver(root, args.session, {
@@ -51615,7 +53009,7 @@ var init_memory3 = __esm({
51615
53009
  }
51616
53010
  },
51617
53011
  async run({ args }) {
51618
- const root = getProjectRoot39();
53012
+ const root = getProjectRoot44();
51619
53013
  try {
51620
53014
  await getBrainDb2(root);
51621
53015
  const { totalDuplicateRows, groups } = await scanDuplicateEntries();
@@ -51661,7 +53055,7 @@ var init_memory3 = __esm({
51661
53055
  async run({ args }) {
51662
53056
  const sourceDir = args.from;
51663
53057
  const isDryRun = !!args["dry-run"];
51664
- const projectRoot = getProjectRoot39();
53058
+ const projectRoot = getProjectRoot44();
51665
53059
  try {
51666
53060
  const result = await importMemoryFiles({
51667
53061
  sourceDir,
@@ -51812,7 +53206,7 @@ var init_memory3 = __esm({
51812
53206
  },
51813
53207
  args: {},
51814
53208
  async run() {
51815
- const root = getProjectRoot39();
53209
+ const root = getProjectRoot44();
51816
53210
  try {
51817
53211
  await getBrainDb2(root);
51818
53212
  const result = await getTierStats(root);
@@ -51855,7 +53249,7 @@ var init_memory3 = __esm({
51855
53249
  }
51856
53250
  },
51857
53251
  async run({ args }) {
51858
- const root = getProjectRoot39();
53252
+ const root = getProjectRoot44();
51859
53253
  const targetTier = args.to;
51860
53254
  const reason = args.reason;
51861
53255
  const validTiers = ["medium", "long"];
@@ -51921,7 +53315,7 @@ var init_memory3 = __esm({
51921
53315
  }
51922
53316
  },
51923
53317
  async run({ args }) {
51924
- const root = getProjectRoot39();
53318
+ const root = getProjectRoot44();
51925
53319
  const targetTier = args.to;
51926
53320
  const reason = args.reason;
51927
53321
  const validTiers = ["short", "medium"];
@@ -52381,7 +53775,7 @@ var migrate_claude_mem_exports = {};
52381
53775
  __export(migrate_claude_mem_exports, {
52382
53776
  migrateClaudeMemCommand: () => migrateClaudeMemCommand
52383
53777
  });
52384
- import { getProjectRoot as getProjectRoot40, migrateClaudeMem } from "@cleocode/core/internal";
53778
+ import { getProjectRoot as getProjectRoot45, migrateClaudeMem } from "@cleocode/core/internal";
52385
53779
  import { ingestLooseAgentOutputs, ingestRcasdDirectories } from "@cleocode/core/memory";
52386
53780
  import { getDb as getDb2 } from "@cleocode/core/store/sqlite";
52387
53781
  var storageCommand, claudeMemCommand, manifestIngestCommand, migrateClaudeMemCommand;
@@ -52444,7 +53838,7 @@ var init_migrate_claude_mem = __esm({
52444
53838
  }
52445
53839
  },
52446
53840
  async run({ args }) {
52447
- const root = getProjectRoot40();
53841
+ const root = getProjectRoot45();
52448
53842
  try {
52449
53843
  const result = await migrateClaudeMem(root, {
52450
53844
  sourcePath: args.source,
@@ -52493,7 +53887,7 @@ var init_migrate_claude_mem = __esm({
52493
53887
  }
52494
53888
  },
52495
53889
  async run({ args }) {
52496
- const projectRoot = getProjectRoot40();
53890
+ const projectRoot = getProjectRoot45();
52497
53891
  try {
52498
53892
  const db = await getDb2(projectRoot);
52499
53893
  const rcasdFlag = Boolean(args.rcasd);
@@ -52597,7 +53991,7 @@ __export(nexus_exports, {
52597
53991
  import { appendFile as appendFile2, mkdir as mkdir3 } from "node:fs/promises";
52598
53992
  import { homedir as homedir5 } from "node:os";
52599
53993
  import path4 from "node:path";
52600
- import { getProjectRoot as getProjectRoot41 } from "@cleocode/core";
53994
+ import { getProjectRoot as getProjectRoot46 } from "@cleocode/core";
52601
53995
  import { getSymbolImpact } from "@cleocode/core/nexus";
52602
53996
  import { runNexusAnalysis } from "@cleocode/core/nexus/analyze-orchestrator.js";
52603
53997
  import { exportNexusGraph } from "@cleocode/core/nexus/export.js";
@@ -52712,7 +54106,7 @@ var init_nexus3 = __esm({
52712
54106
  async run({ args }) {
52713
54107
  applyJsonFlag2(args.json);
52714
54108
  const projectIdOverride = args["project-id"];
52715
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
54109
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
52716
54110
  const startTime = Date.now();
52717
54111
  try {
52718
54112
  const [{ getNexusDb, nexusSchema }, { getIndexStats }] = await Promise.all([
@@ -53227,7 +54621,7 @@ var init_nexus3 = __esm({
53227
54621
  applyJsonFlag2(args.json);
53228
54622
  const startTime = Date.now();
53229
54623
  const projectIdOverride = args["project-id"];
53230
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
54624
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
53231
54625
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53232
54626
  const response = await dispatchRaw("query", "nexus", "clusters", { projectId, repoPath });
53233
54627
  const durationMs = Date.now() - startTime;
@@ -53271,7 +54665,7 @@ var init_nexus3 = __esm({
53271
54665
  applyJsonFlag2(args.json);
53272
54666
  const startTime = Date.now();
53273
54667
  const projectIdOverride = args["project-id"];
53274
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
54668
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
53275
54669
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53276
54670
  const response = await dispatchRaw("query", "nexus", "flows", { projectId, repoPath });
53277
54671
  const durationMs = Date.now() - startTime;
@@ -53314,7 +54708,7 @@ var init_nexus3 = __esm({
53314
54708
  void appendDeprecationTelemetry("nexus.context", "cleo graph context");
53315
54709
  const startTime = Date.now();
53316
54710
  const projectIdOverride = args["project-id"];
53317
- const repoPath = getProjectRoot41();
54711
+ const repoPath = getProjectRoot46();
53318
54712
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53319
54713
  const limit = parseInt(args.limit, 10);
53320
54714
  const symbolName = args.symbol;
@@ -53377,7 +54771,7 @@ var init_nexus3 = __esm({
53377
54771
  const startTime = Date.now();
53378
54772
  const whyFlag = !!args.why;
53379
54773
  const projectIdOverride = args["project-id"];
53380
- const repoPath = getProjectRoot41();
54774
+ const repoPath = getProjectRoot46();
53381
54775
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53382
54776
  const maxDepth = Math.min(parseInt(args.depth, 10), 5);
53383
54777
  const symbolName = args.symbol;
@@ -53449,7 +54843,7 @@ var init_nexus3 = __esm({
53449
54843
  const projectIdOverride = args["project-id"];
53450
54844
  const isIncremental = !!args.incremental;
53451
54845
  const ctx = getFormatContext();
53452
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
54846
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
53453
54847
  humanInfo(`[nexus] Analyzing: ${repoPath}${isIncremental ? " (incremental)" : ""}`);
53454
54848
  if (!isIncremental) humanInfo("[nexus] Clearing existing index for project...");
53455
54849
  try {
@@ -53552,7 +54946,7 @@ var init_nexus3 = __esm({
53552
54946
  async run({ args }) {
53553
54947
  applyJsonFlag2(args.json);
53554
54948
  const startTime = Date.now();
53555
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
54949
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
53556
54950
  const name = args.name;
53557
54951
  const response = await dispatchRaw("mutate", "nexus", "projects.register", {
53558
54952
  path: repoPath,
@@ -53910,7 +55304,7 @@ var init_nexus3 = __esm({
53910
55304
  applyJsonFlag2(args.json);
53911
55305
  const startTime = Date.now();
53912
55306
  const projectIdOverride = args["project-id"];
53913
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
55307
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
53914
55308
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
53915
55309
  const response = await dispatchRaw("mutate", "nexus", "refresh-bridge", {
53916
55310
  repoPath,
@@ -54016,7 +55410,7 @@ var init_nexus3 = __esm({
54016
55410
  async run({ args }) {
54017
55411
  applyJsonFlag2(args.json);
54018
55412
  const startTime = Date.now();
54019
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
55413
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
54020
55414
  const projectIdOverride = args["project-id"];
54021
55415
  const beforeRef = args.before ?? "HEAD~1";
54022
55416
  const afterRef = args.after ?? "HEAD";
@@ -54134,7 +55528,7 @@ var init_nexus3 = __esm({
54134
55528
  applyJsonFlag2(args.json);
54135
55529
  const startTime = Date.now();
54136
55530
  const projectIdOverride = args["project-id"];
54137
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
55531
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
54138
55532
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
54139
55533
  const response = await dispatchRaw("query", "nexus", "route-map", { projectId });
54140
55534
  const durationMs = Date.now() - startTime;
@@ -54190,7 +55584,7 @@ var init_nexus3 = __esm({
54190
55584
  const startTime = Date.now();
54191
55585
  const routeSymbol = args.routeSymbol;
54192
55586
  const projectIdOverride = args["project-id"];
54193
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
55587
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
54194
55588
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
54195
55589
  const response = await dispatchRaw("query", "nexus", "shape-check", { routeSymbol, projectId });
54196
55590
  const durationMs = Date.now() - startTime;
@@ -54580,7 +55974,7 @@ var init_nexus3 = __esm({
54580
55974
  async run({ args }) {
54581
55975
  applyJsonFlag2(args.json);
54582
55976
  const startTime = Date.now();
54583
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
55977
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
54584
55978
  const projectIdOverride = args["project-id"];
54585
55979
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
54586
55980
  const response = await dispatchRaw("mutate", "nexus", "contracts-sync", {
@@ -54684,7 +56078,7 @@ var init_nexus3 = __esm({
54684
56078
  async run({ args }) {
54685
56079
  applyJsonFlag2(args.json);
54686
56080
  const startTime = Date.now();
54687
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot41();
56081
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot46();
54688
56082
  const projectId = Buffer.from(repoPath).toString("base64url").slice(0, 32);
54689
56083
  const response = await dispatchRaw("mutate", "nexus", "contracts-link-tasks", {
54690
56084
  projectId,
@@ -54765,7 +56159,7 @@ var init_nexus3 = __esm({
54765
56159
  const isIncremental = !!args.incremental;
54766
56160
  try {
54767
56161
  const result = await runNexusWiki({
54768
- projectRoot: getProjectRoot41(),
56162
+ projectRoot: getProjectRoot46(),
54769
56163
  outputDir,
54770
56164
  communityFilter,
54771
56165
  incremental: isIncremental
@@ -56016,7 +57410,7 @@ __export(otel_exports, {
56016
57410
  import {
56017
57411
  CleoError as CleoError5,
56018
57412
  clearOtelData,
56019
- formatError as formatError6,
57413
+ formatError as formatError5,
56020
57414
  getOtelSessions,
56021
57415
  getOtelSpawns,
56022
57416
  getOtelStatus,
@@ -56037,7 +57431,7 @@ var init_otel = __esm({
56037
57431
  cliOutput(result, { command: "otel" });
56038
57432
  } catch (err) {
56039
57433
  if (err instanceof CleoError5) {
56040
- cliError(formatError6(err), err.code, { name: "E_INTERNAL" });
57434
+ cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
56041
57435
  process.exit(err.code);
56042
57436
  }
56043
57437
  throw err;
@@ -56052,7 +57446,7 @@ var init_otel = __esm({
56052
57446
  cliOutput(result, { command: "otel" });
56053
57447
  } catch (err) {
56054
57448
  if (err instanceof CleoError5) {
56055
- cliError(formatError6(err), err.code, { name: "E_INTERNAL" });
57449
+ cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
56056
57450
  process.exit(err.code);
56057
57451
  }
56058
57452
  throw err;
@@ -56080,7 +57474,7 @@ var init_otel = __esm({
56080
57474
  cliOutput(result, { command: "otel" });
56081
57475
  } catch (err) {
56082
57476
  if (err instanceof CleoError5) {
56083
- cliError(formatError6(err), err.code, { name: "E_INTERNAL" });
57477
+ cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
56084
57478
  process.exit(err.code);
56085
57479
  }
56086
57480
  throw err;
@@ -56108,7 +57502,7 @@ var init_otel = __esm({
56108
57502
  cliOutput(result, { command: "otel" });
56109
57503
  } catch (err) {
56110
57504
  if (err instanceof CleoError5) {
56111
- cliError(formatError6(err), err.code, { name: "E_INTERNAL" });
57505
+ cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
56112
57506
  process.exit(err.code);
56113
57507
  }
56114
57508
  throw err;
@@ -56136,7 +57530,7 @@ var init_otel = __esm({
56136
57530
  cliOutput(result, { command: "otel" });
56137
57531
  } catch (err) {
56138
57532
  if (err instanceof CleoError5) {
56139
- cliError(formatError6(err), err.code, { name: "E_INTERNAL" });
57533
+ cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
56140
57534
  process.exit(err.code);
56141
57535
  }
56142
57536
  throw err;
@@ -56151,7 +57545,7 @@ var init_otel = __esm({
56151
57545
  cliOutput(result, { command: "otel" });
56152
57546
  } catch (err) {
56153
57547
  if (err instanceof CleoError5) {
56154
- cliError(formatError6(err), err.code, { name: "E_INTERNAL" });
57548
+ cliError(formatError5(err), err.code, { name: "E_INTERNAL" });
56155
57549
  process.exit(err.code);
56156
57550
  }
56157
57551
  throw err;
@@ -56185,7 +57579,7 @@ var phase_exports = {};
56185
57579
  __export(phase_exports, {
56186
57580
  phaseCommand: () => phaseCommand
56187
57581
  });
56188
- var showCommand9, listCommand15, setCommand2, startCommand6, completeCommand3, advanceCommand2, renameCommand, deleteCommand2, phaseCommand;
57582
+ var showCommand9, listCommand15, setCommand, startCommand6, completeCommand3, advanceCommand2, renameCommand, deleteCommand2, phaseCommand;
56189
57583
  var init_phase = __esm({
56190
57584
  "packages/cleo/src/cli/commands/phase.ts"() {
56191
57585
  "use strict";
@@ -56211,7 +57605,7 @@ var init_phase = __esm({
56211
57605
  await dispatchFromCli("query", "pipeline", "phase.list", {}, { command: "phase" });
56212
57606
  }
56213
57607
  });
56214
- setCommand2 = defineCommand({
57608
+ setCommand = defineCommand({
56215
57609
  meta: { name: "set", description: "Set current phase" },
56216
57610
  args: {
56217
57611
  slug: {
@@ -56364,7 +57758,7 @@ var init_phase = __esm({
56364
57758
  subCommands: {
56365
57759
  show: showCommand9,
56366
57760
  list: listCommand15,
56367
- set: setCommand2,
57761
+ set: setCommand,
56368
57762
  start: startCommand6,
56369
57763
  complete: completeCommand3,
56370
57764
  advance: advanceCommand2,
@@ -56712,7 +58106,7 @@ __export(provenance_exports, {
56712
58106
  provenanceCommand: () => provenanceCommand
56713
58107
  });
56714
58108
  var backfillCommand3, verifyCommand2, provenanceCommand;
56715
- var init_provenance2 = __esm({
58109
+ var init_provenance3 = __esm({
56716
58110
  "packages/cleo/src/cli/commands/provenance.ts"() {
56717
58111
  "use strict";
56718
58112
  init_dist();
@@ -57192,7 +58586,7 @@ var refresh_memory_exports = {};
57192
58586
  __export(refresh_memory_exports, {
57193
58587
  refreshMemoryCommand: () => refreshMemoryCommand
57194
58588
  });
57195
- import { getProjectRoot as getProjectRoot42 } from "@cleocode/core";
58589
+ import { getProjectRoot as getProjectRoot47 } from "@cleocode/core";
57196
58590
  var refreshMemoryCommand;
57197
58591
  var init_refresh_memory = __esm({
57198
58592
  "packages/cleo/src/cli/commands/refresh-memory.ts"() {
@@ -57205,7 +58599,7 @@ var init_refresh_memory = __esm({
57205
58599
  description: "Regenerate .cleo/memory-bridge.md from brain.db"
57206
58600
  },
57207
58601
  async run() {
57208
- const projectDir = getProjectRoot42();
58602
+ const projectDir = getProjectRoot47();
57209
58603
  const { writeMemoryBridge } = await import("@cleocode/core/internal");
57210
58604
  const result = await writeMemoryBridge(projectDir);
57211
58605
  if (result.written) {
@@ -58606,7 +60000,7 @@ import fs3 from "node:fs";
58606
60000
  import path5 from "node:path";
58607
60001
  import {
58608
60002
  CleoError as CleoError7,
58609
- getProjectRoot as getProjectRoot43,
60003
+ getProjectRoot as getProjectRoot48,
58610
60004
  getTaskAccessor as getTaskAccessor3,
58611
60005
  parseConflictReport,
58612
60006
  setAtPath
@@ -58627,7 +60021,7 @@ var init_restore = __esm({
58627
60021
  description: "Apply manually-resolved conflicts from .cleo/restore-conflicts.md"
58628
60022
  },
58629
60023
  async run() {
58630
- const projectRoot = getProjectRoot43();
60024
+ const projectRoot = getProjectRoot48();
58631
60025
  const reportPath = path5.join(projectRoot, CLEO_DIR_NAME, RESTORE_CONFLICTS_MD);
58632
60026
  if (!fs3.existsSync(reportPath)) {
58633
60027
  humanLine("No pending restore conflicts. Nothing to finalize.");
@@ -59559,6 +60953,7 @@ var schema_exports = {};
59559
60953
  __export(schema_exports, {
59560
60954
  schemaCommand: () => schemaCommand2
59561
60955
  });
60956
+ import { getInputContract } from "@cleocode/core";
59562
60957
  import { describeOperation } from "@cleocode/lafs";
59563
60958
  function resolveOperationDef(operationArg) {
59564
60959
  const dotIdx = operationArg.indexOf(".");
@@ -59606,6 +61001,16 @@ var init_schema = __esm({
59606
61001
  type: "boolean",
59607
61002
  description: "Include usage examples in output (default: false)",
59608
61003
  default: false
61004
+ },
61005
+ input: {
61006
+ type: "boolean",
61007
+ description: "Return the JSON Schema (draft-07) for the operation input payload, from OperationInputContract.schema (T9918)",
61008
+ default: false
61009
+ },
61010
+ examples: {
61011
+ type: "boolean",
61012
+ description: "Return canned example payloads from OperationInputContract.examples \u2014 pipeline: `cleo schema <op> --examples | jq '.examples[0].value' | cleo <verb> --params -` (T9918)",
61013
+ default: false
59609
61014
  }
59610
61015
  },
59611
61016
  async run({ args, cmd }) {
@@ -59616,6 +61021,8 @@ var init_schema = __esm({
59616
61021
  const format = args.format ?? "json";
59617
61022
  const includeGates = args["include-gates"] !== false;
59618
61023
  const includeExamples = args["include-examples"] === true;
61024
+ const wantInput = args.input === true;
61025
+ const wantExamples = args.examples === true;
59619
61026
  if (format === "human") {
59620
61027
  setFormatContext({ format: "human", source: "flag", quiet: false });
59621
61028
  }
@@ -59632,6 +61039,57 @@ var init_schema = __esm({
59632
61039
  process.exit(4);
59633
61040
  return;
59634
61041
  }
61042
+ if (wantInput || wantExamples) {
61043
+ const contract = getInputContract(args.operation);
61044
+ if (contract === null) {
61045
+ cliOutput(
61046
+ {
61047
+ operation: args.operation,
61048
+ schema: null,
61049
+ examples: []
61050
+ },
61051
+ {
61052
+ command: "schema",
61053
+ operation: `schema.${args.operation}`,
61054
+ message: `No OperationInputContract registered for ${args.operation}`,
61055
+ extensions: {
61056
+ hint: `No OperationInputContract registered for ${args.operation}. Use plain flag-based invocation.`
61057
+ }
61058
+ }
61059
+ );
61060
+ return;
61061
+ }
61062
+ if (wantInput) {
61063
+ cliOutput(
61064
+ {
61065
+ operation: contract.operation,
61066
+ schema: contract.schema
61067
+ },
61068
+ {
61069
+ command: "schema",
61070
+ operation: `schema.${args.operation}`,
61071
+ message: `Input schema for ${contract.operation}`
61072
+ }
61073
+ );
61074
+ return;
61075
+ }
61076
+ cliOutput(
61077
+ {
61078
+ operation: contract.operation,
61079
+ examples: contract.examples.map((ex) => ({
61080
+ name: ex.name,
61081
+ value: ex.value,
61082
+ ...ex.description !== void 0 ? { description: ex.description } : {}
61083
+ }))
61084
+ },
61085
+ {
61086
+ command: "schema",
61087
+ operation: `schema.${args.operation}`,
61088
+ message: `Examples for ${contract.operation}`
61089
+ }
61090
+ );
61091
+ return;
61092
+ }
59635
61093
  const schema2 = describeOperation(def, {
59636
61094
  includeGates,
59637
61095
  includeExamples
@@ -61118,7 +62576,7 @@ var sequence_exports = {};
61118
62576
  __export(sequence_exports, {
61119
62577
  sequenceCommand: () => sequenceCommand
61120
62578
  });
61121
- import { getProjectRoot as getProjectRoot44 } from "@cleocode/core/internal";
62579
+ import { getProjectRoot as getProjectRoot49 } from "@cleocode/core/internal";
61122
62580
  var showCommand12, checkCommand6, repairCommand2, sequenceCommand;
61123
62581
  var init_sequence = __esm({
61124
62582
  "packages/cleo/src/cli/commands/sequence.ts"() {
@@ -61154,7 +62612,7 @@ var init_sequence = __esm({
61154
62612
  meta: { name: "repair", description: "Reset counter to max + 1 if behind" },
61155
62613
  async run() {
61156
62614
  const { repairSequence } = await import("@cleocode/core/internal");
61157
- const projectRoot = getProjectRoot44();
62615
+ const projectRoot = getProjectRoot49();
61158
62616
  const repair = await repairSequence(projectRoot);
61159
62617
  const result = {
61160
62618
  repaired: repair.repaired,
@@ -61609,8 +63067,8 @@ var init_session4 = __esm({
61609
63067
  "audit-scope": { type: "string", description: "Audit log scope (global|local)" }
61610
63068
  },
61611
63069
  async run({ args }) {
61612
- const { detectSessionDrift, getProjectRoot: getProjectRoot48 } = await import("@cleocode/core");
61613
- const projectRoot = await getProjectRoot48();
63070
+ const { detectSessionDrift, getProjectRoot: getProjectRoot53 } = await import("@cleocode/core");
63071
+ const projectRoot = await getProjectRoot53();
61614
63072
  const scope = args["audit-scope"] === "local" ? "local" : "global";
61615
63073
  const report = await detectSessionDrift({ projectRoot, auditScope: scope });
61616
63074
  cliOutput(report, { command: "session drift", operation: "session.drift" });
@@ -62312,7 +63770,7 @@ __export(show_exports, {
62312
63770
  showCommand: () => showCommand14
62313
63771
  });
62314
63772
  var showCommand14;
62315
- var init_show = __esm({
63773
+ var init_show2 = __esm({
62316
63774
  "packages/cleo/src/cli/commands/show.ts"() {
62317
63775
  "use strict";
62318
63776
  init_dist();
@@ -64146,23 +65604,23 @@ __export(telemetry_exports, {
64146
65604
  telemetryCommand: () => telemetryCommand
64147
65605
  });
64148
65606
  import { randomUUID as randomUUID6 } from "node:crypto";
64149
- import { getConfigValue, setConfigValue } from "@cleocode/core";
65607
+ import { getConfigValue as getConfigValue2, setConfigValue as setConfigValue2 } from "@cleocode/core";
64150
65608
  async function readTelemetryConfig() {
64151
- const enabledResolved = await getConfigValue("telemetry.enabled");
64152
- const periodResolved = await getConfigValue("telemetry.period");
64153
- const installIdResolved = await getConfigValue("telemetry.installId");
65609
+ const enabledResolved = await getConfigValue2("telemetry.enabled");
65610
+ const periodResolved = await getConfigValue2("telemetry.period");
65611
+ const installIdResolved = await getConfigValue2("telemetry.installId");
64154
65612
  const enabled = enabledResolved.value === true;
64155
65613
  const period = periodResolved.value === "monthly" ? "monthly" : "monthly";
64156
65614
  const installId = typeof installIdResolved.value === "string" ? installIdResolved.value : void 0;
64157
65615
  return { enabled, period, installId };
64158
65616
  }
64159
65617
  async function ensureInstallId() {
64160
- const existing = await getConfigValue("telemetry.installId");
65618
+ const existing = await getConfigValue2("telemetry.installId");
64161
65619
  if (typeof existing.value === "string" && existing.value.length > 0) {
64162
65620
  return existing.value;
64163
65621
  }
64164
65622
  const newId = randomUUID6();
64165
- await setConfigValue("telemetry.installId", newId, void 0, { global: true });
65623
+ await setConfigValue2("telemetry.installId", newId, void 0, { global: true });
64166
65624
  return newId;
64167
65625
  }
64168
65626
  var enableSub, disableSub, statusSub2, telemetryCommand;
@@ -64178,8 +65636,8 @@ var init_telemetry2 = __esm({
64178
65636
  description: "Enable anonymous skills-usage telemetry (default-on for new installs)"
64179
65637
  },
64180
65638
  async run() {
64181
- await setConfigValue("telemetry.enabled", true, void 0, { global: true });
64182
- await setConfigValue("telemetry.period", "monthly", void 0, { global: true });
65639
+ await setConfigValue2("telemetry.enabled", true, void 0, { global: true });
65640
+ await setConfigValue2("telemetry.period", "monthly", void 0, { global: true });
64183
65641
  const installId = await ensureInstallId();
64184
65642
  const config = await readTelemetryConfig();
64185
65643
  cliOutput(
@@ -64198,7 +65656,7 @@ var init_telemetry2 = __esm({
64198
65656
  description: "Disable anonymous skills-usage telemetry"
64199
65657
  },
64200
65658
  async run() {
64201
- await setConfigValue("telemetry.enabled", false, void 0, { global: true });
65659
+ await setConfigValue2("telemetry.enabled", false, void 0, { global: true });
64202
65660
  const config = await readTelemetryConfig();
64203
65661
  cliOutput(config, {
64204
65662
  command: "telemetry",
@@ -64376,7 +65834,7 @@ __export(token_exports, {
64376
65834
  tokenCommand: () => tokenCommand
64377
65835
  });
64378
65836
  import { readFileSync as readFileSync16 } from "node:fs";
64379
- import { getProjectRoot as getProjectRoot45, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
65837
+ import { getProjectRoot as getProjectRoot50, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
64380
65838
  function readPayload(args, textKey, fileKey) {
64381
65839
  const text = args[textKey];
64382
65840
  const file = args[fileKey];
@@ -64540,7 +65998,7 @@ var init_token = __esm({
64540
65998
  domain: args.domain,
64541
65999
  operation: args.operation
64542
66000
  };
64543
- const result = args.record ? await recordTokenExchange2(getProjectRoot45(), input2) : await measureTokenExchange(input2);
66001
+ const result = args.record ? await recordTokenExchange2(getProjectRoot50(), input2) : await measureTokenExchange(input2);
64544
66002
  cliOutput(result, {
64545
66003
  command: "token",
64546
66004
  operation: args.record ? "admin.token.record" : "token.estimate"
@@ -64576,7 +66034,7 @@ __export(transcript_exports, {
64576
66034
  });
64577
66035
  import { homedir as homedir6 } from "node:os";
64578
66036
  import { join as join30 } from "node:path";
64579
- import { getProjectRoot as getProjectRoot46 } from "@cleocode/core";
66037
+ import { getProjectRoot as getProjectRoot51 } from "@cleocode/core";
64580
66038
  import {
64581
66039
  parseDurationMs,
64582
66040
  pruneTranscripts,
@@ -64606,7 +66064,7 @@ var init_transcript = __esm({
64606
66064
  async run({ args }) {
64607
66065
  if (args.pending) {
64608
66066
  try {
64609
- const projectRoot = getProjectRoot46();
66067
+ const projectRoot = getProjectRoot51();
64610
66068
  const { scanPendingTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
64611
66069
  const pending = await scanPendingTranscripts(projectRoot);
64612
66070
  cliOutput(
@@ -64703,7 +66161,7 @@ var init_transcript = __esm({
64703
66161
  async run({ args }) {
64704
66162
  const tier = args.tier ?? "warm";
64705
66163
  const dryRun = args["dry-run"] ?? false;
64706
- const projectRoot = getProjectRoot46();
66164
+ const projectRoot = getProjectRoot51();
64707
66165
  try {
64708
66166
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
64709
66167
  const { findSessionTranscriptPath, listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -64815,7 +66273,7 @@ var init_transcript = __esm({
64815
66273
  const dryRun = args["dry-run"] ?? false;
64816
66274
  const olderThanHours = args["older-than-hours"] ? Number.parseInt(args["older-than-hours"], 10) : 24;
64817
66275
  const limit = args.limit ? Number.parseInt(args.limit, 10) : void 0;
64818
- const projectRoot = getProjectRoot46();
66276
+ const projectRoot = getProjectRoot51();
64819
66277
  try {
64820
66278
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
64821
66279
  const { listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -64994,11 +66452,18 @@ var update_exports = {};
64994
66452
  __export(update_exports, {
64995
66453
  updateCommand: () => updateCommand2
64996
66454
  });
64997
- import { appendSignedSeverityAttestation as appendSignedSeverityAttestation2, parseAcceptanceCriteria as parseAcceptanceCriteria2 } from "@cleocode/core";
66455
+ import {
66456
+ appendSignedSeverityAttestation as appendSignedSeverityAttestation2,
66457
+ isPipelineTransitionForward,
66458
+ isValidPipelineStage,
66459
+ parseAcceptanceCriteria as parseAcceptanceCriteria2,
66460
+ TASK_PIPELINE_STAGES
66461
+ } from "@cleocode/core";
64998
66462
  var updateCommand2;
64999
66463
  var init_update = __esm({
65000
66464
  "packages/cleo/src/cli/commands/update.ts"() {
65001
66465
  "use strict";
66466
+ init_src2();
65002
66467
  init_dist();
65003
66468
  init_cli();
65004
66469
  init_renderers();
@@ -65210,6 +66675,58 @@ var init_update = __esm({
65210
66675
  await showUsage(cmd);
65211
66676
  return;
65212
66677
  }
66678
+ if (args.severity !== void 0 && !TASK_SEVERITIES.includes(args.severity)) {
66679
+ const valid = TASK_SEVERITIES.join(", ");
66680
+ cliError(
66681
+ `severity must be one of: ${valid} \u2014 got '${args.severity}'`,
66682
+ 6,
66683
+ {
66684
+ name: "E_INVALID_SEVERITY_VALUE",
66685
+ fix: `Pass --severity with one of: ${valid}`
66686
+ },
66687
+ { operation: "tasks.update" }
66688
+ );
66689
+ process.exit(6);
66690
+ return;
66691
+ }
66692
+ if (args["pipeline-stage"] !== void 0) {
66693
+ const requestedStage = String(args["pipeline-stage"]);
66694
+ if (!isValidPipelineStage(requestedStage)) {
66695
+ const valid = TASK_PIPELINE_STAGES.join(", ");
66696
+ cliError(
66697
+ `pipeline-stage must be one of: ${valid} \u2014 got '${requestedStage}'`,
66698
+ 6,
66699
+ {
66700
+ name: "E_INVALID_PIPELINE_STAGE",
66701
+ fix: `Pass --pipeline-stage with one of: ${valid}`
66702
+ },
66703
+ { operation: "tasks.update" }
66704
+ );
66705
+ process.exit(6);
66706
+ return;
66707
+ }
66708
+ const showResponse = await dispatchRaw("query", "tasks", "show", {
66709
+ taskId: args.taskId
66710
+ });
66711
+ const existingTask = showResponse.success ? showResponse.data : void 0;
66712
+ const currentStage = typeof existingTask?.["pipelineStage"] === "string" ? existingTask["pipelineStage"] : null;
66713
+ if (currentStage && !isPipelineTransitionForward(currentStage, requestedStage)) {
66714
+ const validForward = TASK_PIPELINE_STAGES.filter((s) => {
66715
+ return isPipelineTransitionForward(currentStage, s);
66716
+ }).join(", ");
66717
+ cliError(
66718
+ `pipeline-stage transition rejected: cannot move backward from '${currentStage}' to '${requestedStage}'. Pipeline stages are forward-only.`,
66719
+ 6,
66720
+ {
66721
+ name: "E_INVALID_PIPELINE_STAGE",
66722
+ fix: `Pass --pipeline-stage with a stage at or after '${currentStage}'. Valid forward stages: ${validForward}`
66723
+ },
66724
+ { operation: "tasks.update" }
66725
+ );
66726
+ process.exit(6);
66727
+ return;
66728
+ }
66729
+ }
65213
66730
  const params = { taskId: args.taskId };
65214
66731
  if (args.title !== void 0) params["title"] = args.title;
65215
66732
  if (args.status !== void 0) params["status"] = args.status;
@@ -65613,7 +67130,7 @@ __export(web_exports, {
65613
67130
  import { execFileSync as execFileSync3, spawn as spawn3 } from "node:child_process";
65614
67131
  import { mkdir as mkdir4, open, readFile as readFile6, rm, stat as stat2, writeFile as writeFile3 } from "node:fs/promises";
65615
67132
  import { join as join31 } from "node:path";
65616
- import { CleoError as CleoError11, formatError as formatError7, getCleoHome as getCleoHome5 } from "@cleocode/core";
67133
+ import { CleoError as CleoError11, formatError as formatError6, getCleoHome as getCleoHome5 } from "@cleocode/core";
65617
67134
  function getWebPaths() {
65618
67135
  const cleoHome = getCleoHome5();
65619
67136
  return {
@@ -65766,7 +67283,7 @@ var init_web = __esm({
65766
67283
  await startWebServer(Number.parseInt(args.port, 10), args.host);
65767
67284
  } catch (err) {
65768
67285
  if (err instanceof CleoError11) {
65769
- console.error(formatError7(err));
67286
+ console.error(formatError6(err));
65770
67287
  process.exit(err.code);
65771
67288
  }
65772
67289
  throw err;
@@ -65810,7 +67327,7 @@ var init_web = __esm({
65810
67327
  cliOutput({ stopped: true }, { command: "web", message: "CLEO Web UI stopped" });
65811
67328
  } catch (err) {
65812
67329
  if (err instanceof CleoError11) {
65813
- console.error(formatError7(err));
67330
+ console.error(formatError6(err));
65814
67331
  process.exit(err.code);
65815
67332
  }
65816
67333
  throw err;
@@ -65863,7 +67380,7 @@ var init_web = __esm({
65863
67380
  await startWebServer(Number.parseInt(args.port, 10), args.host);
65864
67381
  } catch (err) {
65865
67382
  if (err instanceof CleoError11) {
65866
- console.error(formatError7(err));
67383
+ console.error(formatError6(err));
65867
67384
  process.exit(err.code);
65868
67385
  }
65869
67386
  throw err;
@@ -65878,7 +67395,7 @@ var init_web = __esm({
65878
67395
  cliOutput(status, { command: "web" });
65879
67396
  } catch (err) {
65880
67397
  if (err instanceof CleoError11) {
65881
- console.error(formatError7(err));
67398
+ console.error(formatError6(err));
65882
67399
  process.exit(err.code);
65883
67400
  }
65884
67401
  throw err;
@@ -65911,7 +67428,7 @@ var init_web = __esm({
65911
67428
  cliOutput({ url }, { command: "web", message: `Open browser to: ${url}` });
65912
67429
  } catch (err) {
65913
67430
  if (err instanceof CleoError11) {
65914
- console.error(formatError7(err));
67431
+ console.error(formatError6(err));
65915
67432
  process.exit(err.code);
65916
67433
  }
65917
67434
  throw err;
@@ -65942,7 +67459,7 @@ __export(worktree_exports, {
65942
67459
  worktreeCommand: () => worktreeCommand
65943
67460
  });
65944
67461
  import readline4 from "node:readline";
65945
- import { getProjectRoot as getProjectRoot47, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
67462
+ import { getProjectRoot as getProjectRoot52, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
65946
67463
  async function promptYesNo2(question) {
65947
67464
  return new Promise((resolve7) => {
65948
67465
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
@@ -66047,7 +67564,7 @@ var init_worktree3 = __esm({
66047
67564
  const staleDays = staleDaysRaw !== void 0 ? Number.parseInt(staleDaysRaw, 10) : void 0;
66048
67565
  const idleDaysRaw = typeof args["idle-days"] === "string" ? args["idle-days"] : void 0;
66049
67566
  const idleDays = idleDaysRaw !== void 0 ? Number.parseInt(idleDaysRaw, 10) : void 0;
66050
- const projectRoot = getProjectRoot47();
67567
+ const projectRoot = getProjectRoot52();
66051
67568
  const listResult = await listWorktrees2({
66052
67569
  projectRoot,
66053
67570
  ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
@@ -66489,8 +68006,8 @@ var COMMAND_MANIFEST = [
66489
68006
  {
66490
68007
  exportName: "configCommand",
66491
68008
  name: "config",
66492
- description: "Configuration management",
66493
- load: async () => (await Promise.resolve().then(() => (init_config2(), config_exports))).configCommand
68009
+ description: "CleoConfig SSoT registry surface (show, get, set, validate, drift-check) + legacy presets/list",
68010
+ load: async () => (await Promise.resolve().then(() => (init_config3(), config_exports))).configCommand
66494
68011
  },
66495
68012
  {
66496
68013
  exportName: "consensusCommand",
@@ -66772,7 +68289,7 @@ var COMMAND_MANIFEST = [
66772
68289
  exportName: "manifestCommand",
66773
68290
  name: "manifest",
66774
68291
  description: "Manifest operations (pipeline_manifest table)",
66775
- load: async () => (await Promise.resolve().then(() => (init_manifest(), manifest_exports))).manifestCommand
68292
+ load: async () => (await Promise.resolve().then(() => (init_manifest3(), manifest_exports))).manifestCommand
66776
68293
  },
66777
68294
  {
66778
68295
  exportName: "mapCommand",
@@ -66862,7 +68379,7 @@ var COMMAND_MANIFEST = [
66862
68379
  exportName: "provenanceCommand",
66863
68380
  name: "provenance",
66864
68381
  description: "Provenance-graph maintenance: backfill, verify, repair",
66865
- load: async () => (await Promise.resolve().then(() => (init_provenance2(), provenance_exports))).provenanceCommand
68382
+ load: async () => (await Promise.resolve().then(() => (init_provenance3(), provenance_exports))).provenanceCommand
66866
68383
  },
66867
68384
  {
66868
68385
  exportName: "providerCommand",
@@ -67012,7 +68529,7 @@ var COMMAND_MANIFEST = [
67012
68529
  exportName: "showCommand",
67013
68530
  name: "show",
67014
68531
  description: "Show full task details by ID (returns complete task record with metadata, verification, lifecycle)",
67015
- load: async () => (await Promise.resolve().then(() => (init_show(), show_exports))).showCommand
68532
+ load: async () => (await Promise.resolve().then(() => (init_show2(), show_exports))).showCommand
67016
68533
  },
67017
68534
  {
67018
68535
  exportName: "skillCommand",
@@ -67565,7 +69082,7 @@ async function runStartupMaintenance() {
67565
69082
  detectAndRemoveStrayProjectNexus,
67566
69083
  getGlobalSalt,
67567
69084
  getLogger: getLogger21,
67568
- getProjectRoot: getProjectRoot48,
69085
+ getProjectRoot: getProjectRoot53,
67569
69086
  isCleanupMarkerSet,
67570
69087
  migrateSignaldockToConduit,
67571
69088
  needsSignaldockToConduitMigration,
@@ -67574,7 +69091,7 @@ async function runStartupMaintenance() {
67574
69091
  } = await import("@cleocode/core/internal");
67575
69092
  let projectRootForCleanup = "";
67576
69093
  try {
67577
- projectRootForCleanup = getProjectRoot48();
69094
+ projectRootForCleanup = getProjectRoot53();
67578
69095
  } catch {
67579
69096
  }
67580
69097
  if (!isCleanupMarkerSet(CLI_VERSION, projectRootForCleanup)) {
@@ -67594,7 +69111,7 @@ async function runStartupMaintenance() {
67594
69111
  const isInitInvocation = process.argv.slice(2).some((a) => a === "init");
67595
69112
  if (!isInitInvocation) {
67596
69113
  try {
67597
- const _projectRootForMigration = getProjectRoot48();
69114
+ const _projectRootForMigration = getProjectRoot53();
67598
69115
  if (needsSignaldockToConduitMigration(_projectRootForMigration)) {
67599
69116
  const migrationResult = migrateSignaldockToConduit(_projectRootForMigration);
67600
69117
  if (migrationResult.status === "failed") {