@cleocode/cleo 2026.5.11 → 2026.5.14

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
@@ -1976,6 +1976,122 @@ function renderBrainExport(data, quiet) {
1976
1976
  if (quiet) return String(data["outputFile"] ?? "");
1977
1977
  return `${GREEN}Exported to ${data["outputFile"]}:${NC} ${data["nodeCount"]} nodes, ${data["edgeCount"]} edges (${String(data["format"] ?? "").toUpperCase()})`;
1978
1978
  }
1979
+ function renderAuditReconstruct(data, quiet) {
1980
+ if (quiet) return "";
1981
+ const taskId = data["taskId"];
1982
+ const directCommits = data["directCommits"] ?? [];
1983
+ const childIdRange = data["childIdRange"];
1984
+ const childCommits = data["childCommits"] ?? {};
1985
+ const releaseTags = data["releaseTags"] ?? [];
1986
+ const inferredChildren = data["inferredChildren"] ?? [];
1987
+ const firstSeenAt = data["firstSeenAt"];
1988
+ const lastSeenAt = data["lastSeenAt"];
1989
+ const lines = [
1990
+ `${BOLD}Lineage for ${taskId ?? "?"}${NC}`,
1991
+ "=".repeat(40),
1992
+ "",
1993
+ `${DIM}Direct commits:${NC} ${directCommits.length}`
1994
+ ];
1995
+ for (const c of directCommits) {
1996
+ const sha = typeof c["sha"] === "string" ? c["sha"].slice(0, 10) : "?";
1997
+ const subject = typeof c["subject"] === "string" ? c["subject"] : "";
1998
+ lines.push(` ${CYAN}${sha}${NC} ${subject}`);
1999
+ }
2000
+ lines.push("");
2001
+ if (childIdRange) {
2002
+ lines.push(
2003
+ `${DIM}Inferred children:${NC} ${inferredChildren.join(", ")} (${childIdRange.min} \u2192 ${childIdRange.max})`
2004
+ );
2005
+ } else {
2006
+ lines.push(`${DIM}Inferred children:${NC} none`);
2007
+ }
2008
+ const childEntries = Object.entries(childCommits);
2009
+ if (childEntries.length > 0) {
2010
+ lines.push("");
2011
+ lines.push(`${BOLD}Child commits:${NC}`);
2012
+ for (const [childId, commits] of childEntries) {
2013
+ lines.push(` ${CYAN}${childId}${NC}: ${commits.length} commit(s)`);
2014
+ for (const c of commits) {
2015
+ const sha = typeof c["sha"] === "string" ? c["sha"].slice(0, 10) : "?";
2016
+ const subject = typeof c["subject"] === "string" ? c["subject"] : "";
2017
+ lines.push(` ${DIM}${sha}${NC} ${subject}`);
2018
+ }
2019
+ }
2020
+ }
2021
+ lines.push("");
2022
+ if (releaseTags.length > 0) {
2023
+ lines.push(`${BOLD}Release tags (${releaseTags.length}):${NC}`);
2024
+ for (const t of releaseTags) {
2025
+ const tag = typeof t["tag"] === "string" ? t["tag"] : "?";
2026
+ const sha = typeof t["commitSha"] === "string" ? t["commitSha"].slice(0, 10) : "?";
2027
+ const subject = typeof t["subject"] === "string" ? t["subject"] : "";
2028
+ lines.push(` ${GREEN}${tag}${NC} ${DIM}${sha}${NC} ${subject}`);
2029
+ }
2030
+ } else {
2031
+ lines.push(`${DIM}Release tags:${NC} none found`);
2032
+ }
2033
+ lines.push("");
2034
+ lines.push(`${DIM}First seen:${NC} ${firstSeenAt ?? "n/a"}`);
2035
+ lines.push(`${DIM}Last seen: ${NC} ${lastSeenAt ?? "n/a"}`);
2036
+ return lines.join("\n");
2037
+ }
2038
+ function renderSchemaCommand(data, quiet) {
2039
+ if (quiet) return "";
2040
+ const lines = [];
2041
+ lines.push(`Operation : ${String(data["operation"] ?? "")}`);
2042
+ lines.push(`Gateway : ${String(data["gateway"] ?? "")}`);
2043
+ lines.push(`Description: ${String(data["description"] ?? "")}`);
2044
+ lines.push("");
2045
+ const params = data["params"] ?? [];
2046
+ lines.push("Parameters:");
2047
+ if (params.length === 0) {
2048
+ lines.push(" (none declared)");
2049
+ } else {
2050
+ for (const p of params) {
2051
+ const req = p["required"] ? "[required]" : "[optional]";
2052
+ const enumVal = p["enum"];
2053
+ const enumStr = enumVal ? ` enum: ${enumVal.join(" | ")}` : "";
2054
+ const cli = p["cli"];
2055
+ let cliStr = "";
2056
+ if (cli) {
2057
+ const parts = [];
2058
+ if (cli["positional"]) parts.push("positional");
2059
+ if (cli["short"]) parts.push(`short: ${String(cli["short"])}`);
2060
+ if (cli["flag"]) parts.push(`flag: --${String(cli["flag"])}`);
2061
+ if (parts.length > 0) cliStr = ` cli: ${parts.join(", ")}`;
2062
+ }
2063
+ lines.push(` ${String(p["name"] ?? "")} (${String(p["type"] ?? "")}) ${req}`);
2064
+ lines.push(` ${String(p["description"] ?? "")}${enumStr}${cliStr}`);
2065
+ }
2066
+ }
2067
+ const gates = data["gates"];
2068
+ if (gates !== void 0) {
2069
+ lines.push("");
2070
+ lines.push("Gates:");
2071
+ if (gates.length === 0) {
2072
+ lines.push(" (none declared \u2014 see note on static gate table)");
2073
+ } else {
2074
+ for (const g of gates) {
2075
+ lines.push(` ${String(g["name"] ?? "")} \u2192 ${String(g["errorCode"] ?? "")}`);
2076
+ lines.push(` ${String(g["description"] ?? "")}`);
2077
+ const triggers = g["triggers"] ?? [];
2078
+ for (const t of triggers) {
2079
+ lines.push(` - ${t}`);
2080
+ }
2081
+ }
2082
+ }
2083
+ }
2084
+ const examples = data["examples"];
2085
+ if (examples !== void 0 && examples.length > 0) {
2086
+ lines.push("");
2087
+ lines.push("Examples:");
2088
+ for (const ex of examples) {
2089
+ lines.push(` ${String(ex["command"] ?? "")}`);
2090
+ lines.push(` ${String(ex["description"] ?? "")}`);
2091
+ }
2092
+ }
2093
+ return lines.join("\n");
2094
+ }
1979
2095
  function renderGeneric(data, quiet) {
1980
2096
  if (quiet) return "";
1981
2097
  const lines = [];
@@ -3163,6 +3279,10 @@ var init_renderers = __esm({
3163
3279
  "brain-plasticity-stats": renderBrainPlasticityStats,
3164
3280
  "brain-quality": renderBrainQuality,
3165
3281
  "brain-export": renderBrainExport,
3282
+ // Audit subcommand renderers (T1729)
3283
+ "audit-reconstruct": renderAuditReconstruct,
3284
+ // Schema command renderer (T1729)
3285
+ schema: renderSchemaCommand,
3166
3286
  // Nexus subcommand renderers (T1720)
3167
3287
  "nexus-status": renderNexusStatus,
3168
3288
  "nexus-setup": renderNexusSetup,
@@ -9608,6 +9728,363 @@ var init_registry = __esm({
9608
9728
  description: "Task ID whose worktree should be pruned (omit for bulk prune)"
9609
9729
  }
9610
9730
  ]
9731
+ },
9732
+ // ---------------------------------------------------------------------------
9733
+ // Sentient domain — T1726 SDK surface parity
9734
+ //
9735
+ // Sentient ops were dispatched via SentientHandler (registered under 'sentient'
9736
+ // in the DomainHandler map) but absent from OPERATIONS, making them invisible
9737
+ // to public SDK consumers using @cleocode/core. Adding all 10 ops here.
9738
+ // ---------------------------------------------------------------------------
9739
+ // sentient query: propose.list
9740
+ {
9741
+ gateway: "query",
9742
+ domain: "sentient",
9743
+ operation: "propose.list",
9744
+ description: "sentient.propose.list (query) \u2014 list all pending Tier-2 proposals (status=proposed)",
9745
+ tier: 2,
9746
+ idempotent: true,
9747
+ sessionRequired: false,
9748
+ requiredParams: [],
9749
+ params: [
9750
+ {
9751
+ name: "limit",
9752
+ type: "number",
9753
+ required: false,
9754
+ description: "Maximum number of proposals to return (default: 50)"
9755
+ }
9756
+ ]
9757
+ },
9758
+ // sentient query: propose.diff
9759
+ {
9760
+ gateway: "query",
9761
+ domain: "sentient",
9762
+ operation: "propose.diff",
9763
+ description: "sentient.propose.diff (query) \u2014 show what a proposal would change (Tier-3 stub)",
9764
+ tier: 2,
9765
+ idempotent: true,
9766
+ sessionRequired: false,
9767
+ requiredParams: ["id"],
9768
+ params: [
9769
+ {
9770
+ name: "id",
9771
+ type: "string",
9772
+ required: true,
9773
+ description: "Proposal task ID",
9774
+ cli: { positional: true }
9775
+ }
9776
+ ]
9777
+ },
9778
+ // sentient query: allowlist.list
9779
+ {
9780
+ gateway: "query",
9781
+ domain: "sentient",
9782
+ operation: "allowlist.list",
9783
+ description: "sentient.allowlist.list (query) \u2014 list owner pubkeys in the sentient allowlist",
9784
+ tier: 2,
9785
+ idempotent: true,
9786
+ sessionRequired: false,
9787
+ requiredParams: [],
9788
+ params: []
9789
+ },
9790
+ // sentient mutate: propose.accept
9791
+ {
9792
+ gateway: "mutate",
9793
+ domain: "sentient",
9794
+ operation: "propose.accept",
9795
+ description: "sentient.propose.accept (mutate) \u2014 accept a Tier-2 proposal, transitioning proposed \u2192 pending",
9796
+ tier: 2,
9797
+ idempotent: false,
9798
+ sessionRequired: false,
9799
+ requiredParams: ["id"],
9800
+ params: [
9801
+ {
9802
+ name: "id",
9803
+ type: "string",
9804
+ required: true,
9805
+ description: "Proposal task ID to accept",
9806
+ cli: { positional: true }
9807
+ }
9808
+ ]
9809
+ },
9810
+ // sentient mutate: propose.reject
9811
+ {
9812
+ gateway: "mutate",
9813
+ domain: "sentient",
9814
+ operation: "propose.reject",
9815
+ description: "sentient.propose.reject (mutate) \u2014 reject a Tier-2 proposal, transitioning proposed \u2192 cancelled",
9816
+ tier: 2,
9817
+ idempotent: false,
9818
+ sessionRequired: false,
9819
+ requiredParams: ["id"],
9820
+ params: [
9821
+ {
9822
+ name: "id",
9823
+ type: "string",
9824
+ required: true,
9825
+ description: "Proposal task ID to reject",
9826
+ cli: { positional: true }
9827
+ },
9828
+ {
9829
+ name: "reason",
9830
+ type: "string",
9831
+ required: false,
9832
+ description: "Human-readable reason for rejection"
9833
+ }
9834
+ ]
9835
+ },
9836
+ // sentient mutate: propose.run
9837
+ {
9838
+ gateway: "mutate",
9839
+ domain: "sentient",
9840
+ operation: "propose.run",
9841
+ description: "sentient.propose.run (mutate) \u2014 manually trigger a single Tier-2 propose tick in-process",
9842
+ tier: 2,
9843
+ idempotent: false,
9844
+ sessionRequired: false,
9845
+ requiredParams: [],
9846
+ params: []
9847
+ },
9848
+ // sentient mutate: propose.enable
9849
+ {
9850
+ gateway: "mutate",
9851
+ domain: "sentient",
9852
+ operation: "propose.enable",
9853
+ description: "sentient.propose.enable (mutate) \u2014 enable Tier-2 autonomous proposal generation (M7 gate)",
9854
+ tier: 2,
9855
+ idempotent: true,
9856
+ sessionRequired: false,
9857
+ requiredParams: [],
9858
+ params: []
9859
+ },
9860
+ // sentient mutate: propose.disable
9861
+ {
9862
+ gateway: "mutate",
9863
+ domain: "sentient",
9864
+ operation: "propose.disable",
9865
+ description: "sentient.propose.disable (mutate) \u2014 disable Tier-2 autonomous proposal generation",
9866
+ tier: 2,
9867
+ idempotent: true,
9868
+ sessionRequired: false,
9869
+ requiredParams: [],
9870
+ params: []
9871
+ },
9872
+ // sentient mutate: allowlist.add
9873
+ {
9874
+ gateway: "mutate",
9875
+ domain: "sentient",
9876
+ operation: "allowlist.add",
9877
+ description: "sentient.allowlist.add (mutate) \u2014 add a base64-encoded owner pubkey to the sentient allowlist",
9878
+ tier: 2,
9879
+ idempotent: true,
9880
+ sessionRequired: false,
9881
+ requiredParams: ["pubkey"],
9882
+ params: [
9883
+ {
9884
+ name: "pubkey",
9885
+ type: "string",
9886
+ required: true,
9887
+ description: "Base64-encoded public key to add"
9888
+ }
9889
+ ]
9890
+ },
9891
+ // sentient mutate: allowlist.remove
9892
+ {
9893
+ gateway: "mutate",
9894
+ domain: "sentient",
9895
+ operation: "allowlist.remove",
9896
+ description: "sentient.allowlist.remove (mutate) \u2014 remove a base64-encoded owner pubkey from the sentient allowlist",
9897
+ tier: 2,
9898
+ idempotent: true,
9899
+ sessionRequired: false,
9900
+ requiredParams: ["pubkey"],
9901
+ params: [
9902
+ {
9903
+ name: "pubkey",
9904
+ type: "string",
9905
+ required: true,
9906
+ description: "Base64-encoded public key to remove"
9907
+ }
9908
+ ]
9909
+ },
9910
+ // ---------------------------------------------------------------------------
9911
+ // Release domain — T1726 SDK surface parity
9912
+ //
9913
+ // Release ops dispatched via ReleaseHandler (registered under 'release' in
9914
+ // the DomainHandler map) were absent from OPERATIONS. Adding gate +
9915
+ // ivtr-suggest (the two ops ReleaseHandler serves) plus the canonical
9916
+ // 4-step pipeline ops (start, verify, publish, reconcile) introduced by
9917
+ // T1597 / ADR-063 that route through the core release module directly.
9918
+ // ---------------------------------------------------------------------------
9919
+ // release query: gate
9920
+ {
9921
+ gateway: "query",
9922
+ domain: "release",
9923
+ operation: "gate",
9924
+ description: "release.gate (query) \u2014 check all IVTR loops in a release epic have reached the released phase before allowing release.ship (T820 RELEASE-03)",
9925
+ tier: 1,
9926
+ idempotent: true,
9927
+ sessionRequired: false,
9928
+ requiredParams: ["epicId"],
9929
+ params: [
9930
+ {
9931
+ name: "epicId",
9932
+ type: "string",
9933
+ required: true,
9934
+ description: "Epic ID whose child tasks should be inspected"
9935
+ },
9936
+ {
9937
+ name: "force",
9938
+ type: "boolean",
9939
+ required: false,
9940
+ description: "Bypass the IVTR gate \u2014 requires explicit owner confirmation"
9941
+ }
9942
+ ]
9943
+ },
9944
+ // release mutate: gate
9945
+ {
9946
+ gateway: "mutate",
9947
+ domain: "release",
9948
+ operation: "gate",
9949
+ description: "release.gate (mutate) \u2014 same IVTR gate check as query.gate; safe in both gateways (no DB writes)",
9950
+ tier: 1,
9951
+ idempotent: true,
9952
+ sessionRequired: false,
9953
+ requiredParams: ["epicId"],
9954
+ params: [
9955
+ {
9956
+ name: "epicId",
9957
+ type: "string",
9958
+ required: true,
9959
+ description: "Epic ID whose child tasks should be inspected"
9960
+ },
9961
+ {
9962
+ name: "force",
9963
+ type: "boolean",
9964
+ required: false,
9965
+ description: "Bypass the IVTR gate \u2014 requires explicit owner confirmation"
9966
+ }
9967
+ ]
9968
+ },
9969
+ // release query: ivtr-suggest
9970
+ {
9971
+ gateway: "query",
9972
+ domain: "release",
9973
+ operation: "ivtr-suggest",
9974
+ description: "release.ivtr-suggest (query) \u2014 check if all epic tasks are released and suggest cleo release ship (T820 RELEASE-07)",
9975
+ tier: 1,
9976
+ idempotent: true,
9977
+ sessionRequired: false,
9978
+ requiredParams: ["taskId"],
9979
+ params: [
9980
+ {
9981
+ name: "taskId",
9982
+ type: "string",
9983
+ required: true,
9984
+ description: "Task ID that just reached the released phase"
9985
+ }
9986
+ ]
9987
+ },
9988
+ // release mutate: ivtr-suggest
9989
+ {
9990
+ gateway: "mutate",
9991
+ domain: "release",
9992
+ operation: "ivtr-suggest",
9993
+ description: "release.ivtr-suggest (mutate) \u2014 same auto-suggest as query.ivtr-suggest; safe in both gateways (no DB writes)",
9994
+ tier: 1,
9995
+ idempotent: true,
9996
+ sessionRequired: false,
9997
+ requiredParams: ["taskId"],
9998
+ params: [
9999
+ {
10000
+ name: "taskId",
10001
+ type: "string",
10002
+ required: true,
10003
+ description: "Task ID that just reached the released phase"
10004
+ }
10005
+ ]
10006
+ },
10007
+ // release mutate: start (T1597 / ADR-063 canonical step 1)
10008
+ {
10009
+ gateway: "mutate",
10010
+ domain: "release",
10011
+ operation: "start",
10012
+ description: "release.start (mutate) \u2014 Step 1 of 4: validate version, capture branch, persist release handle (T1597 / ADR-063)",
10013
+ tier: 1,
10014
+ idempotent: false,
10015
+ sessionRequired: false,
10016
+ requiredParams: ["version"],
10017
+ params: [
10018
+ {
10019
+ name: "version",
10020
+ type: "string",
10021
+ required: true,
10022
+ description: "Version to release (e.g. 2026.5.4)",
10023
+ cli: { positional: true }
10024
+ },
10025
+ {
10026
+ name: "epicId",
10027
+ type: "string",
10028
+ required: false,
10029
+ description: "Epic ID this release ships"
10030
+ },
10031
+ {
10032
+ name: "branch",
10033
+ type: "string",
10034
+ required: false,
10035
+ description: "Override detected branch"
10036
+ }
10037
+ ]
10038
+ },
10039
+ // release query: verify (T1597 / ADR-063 canonical step 2)
10040
+ {
10041
+ gateway: "query",
10042
+ domain: "release",
10043
+ operation: "verify",
10044
+ description: "release.verify (query) \u2014 Step 2 of 4: run gates + audit child tasks of the active release epic (T1597 / ADR-063)",
10045
+ tier: 1,
10046
+ idempotent: true,
10047
+ sessionRequired: false,
10048
+ requiredParams: [],
10049
+ params: []
10050
+ },
10051
+ // release mutate: publish (T1597 / ADR-063 canonical step 3)
10052
+ {
10053
+ gateway: "mutate",
10054
+ domain: "release",
10055
+ operation: "publish",
10056
+ description: "release.publish (mutate) \u2014 Step 3 of 4: invoke project-context publish.command to publish the release artifact (T1597 / ADR-063)",
10057
+ tier: 1,
10058
+ idempotent: false,
10059
+ sessionRequired: false,
10060
+ requiredParams: [],
10061
+ params: [
10062
+ {
10063
+ name: "dryRun",
10064
+ type: "boolean",
10065
+ required: false,
10066
+ description: "Print command without executing"
10067
+ }
10068
+ ]
10069
+ },
10070
+ // release mutate: reconcile (T1597 / ADR-063 canonical step 4)
10071
+ {
10072
+ gateway: "mutate",
10073
+ domain: "release",
10074
+ operation: "reconcile",
10075
+ description: "release.reconcile (mutate) \u2014 Step 4 of 4: run post-release invariants, auto-complete tasks for the active release (T1597 / ADR-063)",
10076
+ tier: 1,
10077
+ idempotent: false,
10078
+ sessionRequired: false,
10079
+ requiredParams: [],
10080
+ params: [
10081
+ {
10082
+ name: "dryRun",
10083
+ type: "boolean",
10084
+ required: false,
10085
+ description: "Preview without mutations"
10086
+ }
10087
+ ]
9611
10088
  }
9612
10089
  ];
9613
10090
  counts = getCounts();
@@ -9957,6 +10434,7 @@ __export(engine_exports, {
9957
10434
  lifecycleReset: () => lifecycleReset,
9958
10435
  lifecycleSkip: () => lifecycleSkip,
9959
10436
  lifecycleStatus: () => lifecycleStatus,
10437
+ loadActiveReleaseHandle: () => loadActiveReleaseHandle,
9960
10438
  mapCodebase: () => mapCodebase,
9961
10439
  memoryBrainStats: () => memoryBrainStats,
9962
10440
  memoryContradictions: () => memoryContradictions,
@@ -10035,12 +10513,16 @@ __export(engine_exports, {
10035
10513
  releaseIvtrAutoSuggest: () => releaseIvtrAutoSuggest,
10036
10514
  releaseList: () => releaseList,
10037
10515
  releasePrepare: () => releasePrepare,
10516
+ releasePublish: () => releasePublish,
10038
10517
  releasePush: () => releasePush,
10518
+ releaseReconcile: () => releaseReconcile,
10039
10519
  releaseRollback: () => releaseRollback,
10040
10520
  releaseRollbackFull: () => releaseRollbackFull,
10041
10521
  releaseShip: () => releaseShip,
10042
10522
  releaseShow: () => releaseShow,
10523
+ releaseStart: () => releaseStart,
10043
10524
  releaseTag: () => releaseTag,
10525
+ releaseVerify: () => releaseVerify,
10044
10526
  sessionArchive: () => sessionArchive,
10045
10527
  sessionBriefing: () => sessionBriefing,
10046
10528
  sessionChainShow: () => sessionChainShow,
@@ -10165,6 +10647,7 @@ import {
10165
10647
  lifecycleReset,
10166
10648
  lifecycleSkip,
10167
10649
  lifecycleStatus,
10650
+ loadActiveReleaseHandle,
10168
10651
  mapCodebase,
10169
10652
  orchestrateAnalyze,
10170
10653
  orchestrateBootstrap,
@@ -10212,12 +10695,16 @@ import {
10212
10695
  releaseIvtrAutoSuggest,
10213
10696
  releaseList,
10214
10697
  releasePrepare,
10698
+ releasePublish,
10215
10699
  releasePush,
10700
+ releaseReconcile,
10216
10701
  releaseRollback,
10217
10702
  releaseRollbackFull,
10218
10703
  releaseShip,
10219
10704
  releaseShow,
10705
+ releaseStart,
10220
10706
  releaseTag,
10707
+ releaseVerify,
10221
10708
  sessionArchive,
10222
10709
  sessionBriefing,
10223
10710
  sessionChainShow,
@@ -23986,6 +24473,7 @@ var init_release2 = __esm({
23986
24473
  "use strict";
23987
24474
  init_engine();
23988
24475
  init_base();
24476
+ init_meta2();
23989
24477
  log2 = getLogger11("domain:release");
23990
24478
  coreOps3 = {
23991
24479
  gate: releaseGateOp,
@@ -24001,6 +24489,7 @@ var init_release2 = __esm({
24001
24489
  * Supported operations:
24002
24490
  * - `gate` — check IVTR phase state for all tasks in a release epic
24003
24491
  * - `ivtr-suggest` — check if all epic tasks are released and suggest `release ship`
24492
+ * - `verify` — Step 2 of 4: run gates + audit child tasks (T1597 / ADR-063)
24004
24493
  */
24005
24494
  async query(operation, params) {
24006
24495
  const startTime = Date.now();
@@ -24043,6 +24532,16 @@ var init_release2 = __esm({
24043
24532
  startTime
24044
24533
  );
24045
24534
  }
24535
+ // release.verify — Step 2 of 4: run gates + audit child tasks (T1597 / ADR-063)
24536
+ case "verify": {
24537
+ const handle = loadActiveReleaseHandle(getProjectRoot11());
24538
+ const result = await releaseVerify(handle);
24539
+ return {
24540
+ success: true,
24541
+ data: result,
24542
+ meta: dispatchMeta("query", "release", operation, startTime)
24543
+ };
24544
+ }
24046
24545
  default:
24047
24546
  return unsupportedOp("query", "release", operation, startTime);
24048
24547
  }
@@ -24064,6 +24563,9 @@ var init_release2 = __esm({
24064
24563
  * Supported operations:
24065
24564
  * - `gate` — same IVTR gate check as query.gate (no DB writes)
24066
24565
  * - `ivtr-suggest` — same auto-suggest as query.ivtr-suggest (no DB writes)
24566
+ * - `start` — Step 1 of 4: validate version, capture branch, persist handle
24567
+ * - `publish` — Step 3 of 4: invoke project-context publish.command
24568
+ * - `reconcile` — Step 4 of 4: run post-release invariants, auto-complete tasks
24067
24569
  */
24068
24570
  async mutate(operation, params) {
24069
24571
  const startTime = Date.now();
@@ -24106,6 +24608,52 @@ var init_release2 = __esm({
24106
24608
  startTime
24107
24609
  );
24108
24610
  }
24611
+ // release.start — Step 1 of 4 (T1597 / ADR-063)
24612
+ case "start": {
24613
+ const version = typeof params?.version === "string" ? params.version : void 0;
24614
+ if (!version)
24615
+ return errorResult(
24616
+ "mutate",
24617
+ "release",
24618
+ operation,
24619
+ "E_INVALID_INPUT",
24620
+ "version is required",
24621
+ startTime
24622
+ );
24623
+ const result = await releaseStart(version, {
24624
+ epicId: typeof params?.epicId === "string" ? params.epicId : void 0,
24625
+ branch: typeof params?.branch === "string" ? params.branch : void 0
24626
+ });
24627
+ return {
24628
+ success: true,
24629
+ data: result,
24630
+ meta: dispatchMeta("mutate", "release", operation, startTime)
24631
+ };
24632
+ }
24633
+ // release.publish — Step 3 of 4 (T1597 / ADR-063)
24634
+ case "publish": {
24635
+ const handle = loadActiveReleaseHandle(getProjectRoot11());
24636
+ const result = await releasePublish(handle, {
24637
+ dryRun: typeof params?.dryRun === "boolean" ? params.dryRun : false
24638
+ });
24639
+ return {
24640
+ success: true,
24641
+ data: result,
24642
+ meta: dispatchMeta("mutate", "release", operation, startTime)
24643
+ };
24644
+ }
24645
+ // release.reconcile — Step 4 of 4 (T1597 / ADR-063)
24646
+ case "reconcile": {
24647
+ const handle = loadActiveReleaseHandle(getProjectRoot11());
24648
+ const result = await releaseReconcile(handle, {
24649
+ dryRun: typeof params?.dryRun === "boolean" ? params.dryRun : false
24650
+ });
24651
+ return {
24652
+ success: true,
24653
+ data: result,
24654
+ meta: dispatchMeta("mutate", "release", operation, startTime)
24655
+ };
24656
+ }
24109
24657
  default:
24110
24658
  return unsupportedOp("mutate", "release", operation, startTime);
24111
24659
  }
@@ -24120,8 +24668,8 @@ var init_release2 = __esm({
24120
24668
  /** Return declared operations for introspection and registry validation. */
24121
24669
  getSupportedOperations() {
24122
24670
  return {
24123
- query: ["gate", "ivtr-suggest"],
24124
- mutate: ["gate", "ivtr-suggest"]
24671
+ query: ["gate", "ivtr-suggest", "verify"],
24672
+ mutate: ["gate", "ivtr-suggest", "start", "publish", "reconcile"]
24125
24673
  };
24126
24674
  }
24127
24675
  };
@@ -31508,6 +32056,7 @@ var archiveStatsCommand = defineCommand({
31508
32056
 
31509
32057
  // packages/cleo/src/cli/commands/audit.ts
31510
32058
  import { getProjectRoot as getProjectRoot19, reconstructLineage } from "@cleocode/core/internal";
32059
+ init_renderers();
31511
32060
  var reconstructCommand = defineCommand({
31512
32061
  meta: {
31513
32062
  name: "reconstruct",
@@ -31532,9 +32081,11 @@ var reconstructCommand = defineCommand({
31532
32081
  async run({ args }) {
31533
32082
  const taskId = args["taskId"];
31534
32083
  if (!taskId || !/^T\d+$/i.test(taskId)) {
31535
- process.stderr.write(
31536
- `Error: taskId must match /^T\\d+$/ (e.g. T991). Got: ${JSON.stringify(taskId)}
31537
- `
32084
+ cliError(
32085
+ `taskId must match /^T\\d+$/ (e.g. T991). Got: ${JSON.stringify(taskId)}`,
32086
+ 1,
32087
+ { name: "E_VALIDATION" },
32088
+ { operation: "audit.reconstruct" }
31538
32089
  );
31539
32090
  process.exit(1);
31540
32091
  }
@@ -31549,53 +32100,11 @@ var reconstructCommand = defineCommand({
31549
32100
  }
31550
32101
  }
31551
32102
  const result = await reconstructLineage(taskId, repoRoot);
31552
- if (args["json"]) {
31553
- process.stdout.write(`${JSON.stringify(result, null, 2)}
31554
- `);
31555
- return;
31556
- }
31557
- const lines = [
31558
- `Lineage for ${result.taskId}`,
31559
- `${"=".repeat(40)}`,
31560
- "",
31561
- `Direct commits: ${result.directCommits.length}`
31562
- ];
31563
- for (const c of result.directCommits) {
31564
- lines.push(` ${c.sha.slice(0, 10)} ${c.subject}`);
31565
- }
31566
- lines.push("");
31567
- if (result.childIdRange) {
31568
- lines.push(
31569
- `Inferred children: ${result.inferredChildren.join(", ")} (${result.childIdRange.min} \u2192 ${result.childIdRange.max})`
31570
- );
31571
- } else {
31572
- lines.push("Inferred children: none");
31573
- }
31574
- const childEntries = Object.entries(result.childCommits);
31575
- if (childEntries.length > 0) {
31576
- lines.push("");
31577
- lines.push("Child commits:");
31578
- for (const [childId, commits] of childEntries) {
31579
- lines.push(` ${childId}: ${commits.length} commit(s)`);
31580
- for (const c of commits) {
31581
- lines.push(` ${c.sha.slice(0, 10)} ${c.subject}`);
31582
- }
31583
- }
31584
- }
31585
- lines.push("");
31586
- if (result.releaseTags.length > 0) {
31587
- lines.push(`Release tags (${result.releaseTags.length}):`);
31588
- for (const t of result.releaseTags) {
31589
- lines.push(` ${t.tag} ${t.commitSha.slice(0, 10)} ${t.subject}`);
31590
- }
31591
- } else {
31592
- lines.push("Release tags: none found");
31593
- }
31594
- lines.push("");
31595
- lines.push(`First seen: ${result.firstSeenAt ?? "n/a"}`);
31596
- lines.push(`Last seen: ${result.lastSeenAt ?? "n/a"}`);
31597
- process.stdout.write(`${lines.join("\n")}
31598
- `);
32103
+ cliOutput(result, {
32104
+ command: "audit-reconstruct",
32105
+ operation: "audit.reconstruct",
32106
+ message: `Lineage for ${result.taskId}`
32107
+ });
31599
32108
  }
31600
32109
  });
31601
32110
  var auditCommand = defineCommand({
@@ -42353,7 +42862,7 @@ var analyzeCommand3 = defineCommand({
42353
42862
  try {
42354
42863
  const { runGitLogTaskLinker } = await import("@cleocode/core/nexus");
42355
42864
  const sweeperResult = await runGitLogTaskLinker(repoPath);
42356
- if (ctx.format !== "json" && sweeperResult.commitsProcessed > 0) {
42865
+ if (sweeperResult.commitsProcessed > 0) {
42357
42866
  process.stderr.write(
42358
42867
  `[nexus] Task-symbol sweep: ${sweeperResult.commitsProcessed} commit(s), ${sweeperResult.tasksFound} task(s), ${sweeperResult.linked} edge(s) linked.
42359
42868
  `
@@ -47471,6 +47980,7 @@ var safestopCommand = defineCommand({
47471
47980
  // packages/cleo/src/cli/commands/schema.ts
47472
47981
  import { describeOperation } from "@cleocode/lafs";
47473
47982
  init_registry();
47983
+ init_format_context();
47474
47984
  init_renderers();
47475
47985
  function resolveOperationDef(operationArg) {
47476
47986
  const dotIdx = operationArg.indexOf(".");
@@ -47485,56 +47995,6 @@ function resolveOperationDef(operationArg) {
47485
47995
  const operation = operationArg.slice(dotIdx + 1);
47486
47996
  return OPERATIONS.find((op) => op.domain === domain && op.operation === operation) ?? null;
47487
47997
  }
47488
- function renderSchemaHuman(schema2) {
47489
- const lines = [];
47490
- lines.push(`Operation : ${schema2.operation}`);
47491
- lines.push(`Gateway : ${schema2.gateway}`);
47492
- lines.push(`Description: ${schema2.description}`);
47493
- lines.push("");
47494
- lines.push("Parameters:");
47495
- if (schema2.params.length === 0) {
47496
- lines.push(" (none declared)");
47497
- } else {
47498
- for (const p of schema2.params) {
47499
- const req = p.required ? "[required]" : "[optional]";
47500
- const enumStr = p.enum ? ` enum: ${p.enum.join(" | ")}` : "";
47501
- let cliStr = "";
47502
- if (p.cli) {
47503
- const parts = [];
47504
- if (p.cli.positional) parts.push("positional");
47505
- if (p.cli.short) parts.push(`short: ${p.cli.short}`);
47506
- if (p.cli.flag) parts.push(`flag: --${p.cli.flag}`);
47507
- if (parts.length > 0) cliStr = ` cli: ${parts.join(", ")}`;
47508
- }
47509
- lines.push(` ${p.name} (${p.type}) ${req}`);
47510
- lines.push(` ${p.description}${enumStr}${cliStr}`);
47511
- }
47512
- }
47513
- if (schema2.gates !== void 0) {
47514
- lines.push("");
47515
- lines.push("Gates:");
47516
- if (schema2.gates.length === 0) {
47517
- lines.push(" (none declared \u2014 see note on static gate table)");
47518
- } else {
47519
- for (const g of schema2.gates) {
47520
- lines.push(` ${g.name} \u2192 ${g.errorCode}`);
47521
- lines.push(` ${g.description}`);
47522
- for (const t of g.triggers) {
47523
- lines.push(` - ${t}`);
47524
- }
47525
- }
47526
- }
47527
- }
47528
- if (schema2.examples !== void 0 && schema2.examples.length > 0) {
47529
- lines.push("");
47530
- lines.push("Examples:");
47531
- for (const ex of schema2.examples) {
47532
- lines.push(` ${ex.command}`);
47533
- lines.push(` ${ex.description}`);
47534
- }
47535
- }
47536
- return lines.join("\n");
47537
- }
47538
47998
  var schemaCommand = defineCommand({
47539
47999
  meta: {
47540
48000
  name: "schema",
@@ -47570,6 +48030,9 @@ var schemaCommand = defineCommand({
47570
48030
  const format = args.format ?? "json";
47571
48031
  const includeGates = args["include-gates"] !== false;
47572
48032
  const includeExamples = args["include-examples"] === true;
48033
+ if (format === "human") {
48034
+ setFormatContext({ format: "human", source: "flag", quiet: false });
48035
+ }
47573
48036
  const def = resolveOperationDef(args.operation);
47574
48037
  if (def === null) {
47575
48038
  cliError(
@@ -47587,10 +48050,6 @@ var schemaCommand = defineCommand({
47587
48050
  includeGates,
47588
48051
  includeExamples
47589
48052
  });
47590
- if (format === "human") {
47591
- console.log(renderSchemaHuman(schema2));
47592
- return;
47593
- }
47594
48053
  cliOutput(schema2, {
47595
48054
  command: "schema",
47596
48055
  operation: `schema.${args.operation}`,