@cleocode/cleo 2026.10.1 → 2026.10.3

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.
Files changed (61) hide show
  1. package/bin/cleo.js +17 -1
  2. package/dist/cli/hook-entry.js +372 -0
  3. package/dist/cli/index.js +1779 -329
  4. package/package.json +13 -13
  5. package/studio-dist/client/_app/immutable/chunks/Bw6J8NDM.js +1 -0
  6. package/studio-dist/client/_app/immutable/chunks/{BpRY8_m9.js → DMj27Pxj.js} +1 -1
  7. package/studio-dist/client/_app/immutable/chunks/Dc2owyvE.js +3 -0
  8. package/studio-dist/client/_app/immutable/chunks/{CMfYgGYJ.js → qq3pe1aT.js} +1 -1
  9. package/studio-dist/client/_app/immutable/entry/{app.DKqdTuYA.js → app.CHWXLeE9.js} +2 -2
  10. package/studio-dist/client/_app/immutable/entry/start.C9bwPpvc.js +1 -0
  11. package/studio-dist/client/_app/immutable/nodes/{0.BuXCTiZp.js → 0.DmKQGvFh.js} +1 -1
  12. package/studio-dist/client/_app/immutable/nodes/{1.CsO1BGsz.js → 1.DqJk_REO.js} +1 -1
  13. package/studio-dist/client/_app/immutable/nodes/{15.Bp-qXNPk.js → 15.GUy6kdW1.js} +1 -1
  14. package/studio-dist/client/_app/immutable/nodes/{16.DMXWbK7I.js → 16.CcnKZ8f9.js} +1 -1
  15. package/studio-dist/client/_app/immutable/nodes/{17.CVLdfMFL.js → 17.DAlQF3lQ.js} +1 -1
  16. package/studio-dist/client/_app/immutable/nodes/{18.CyQUos9v.js → 18.vQFr-vFj.js} +1 -1
  17. package/studio-dist/client/_app/immutable/nodes/{20.Dx3wZ86J.js → 20.GVOj5j_r.js} +1 -1
  18. package/studio-dist/client/_app/immutable/nodes/{24.CXGl5ZJ3.js → 24.2-wC6DOh.js} +1 -1
  19. package/studio-dist/client/_app/immutable/nodes/25.D1vYaH8g.js +39 -0
  20. package/studio-dist/client/_app/immutable/nodes/{26.U1MxbYsk.js → 26.C3rNqzZF.js} +1 -1
  21. package/studio-dist/client/_app/immutable/nodes/{3.CUHmTi6Q.js → 3.b-7pzc3M.js} +1 -1
  22. package/studio-dist/client/_app/version.json +1 -1
  23. package/studio-dist/server/chunks/{0-Ban8NQ70.js → 0-BaCce-O1.js} +3 -3
  24. package/studio-dist/server/chunks/1-CVo7Nk6d.js +9 -0
  25. package/studio-dist/server/chunks/{15-C2ukbZuI.js → 15-DRMOSIC9.js} +3 -3
  26. package/studio-dist/server/chunks/{16-C-gWtKZb.js → 16-BulXhoZZ.js} +3 -3
  27. package/studio-dist/server/chunks/{17-CzQ5BDNx.js → 17-DUEOCM0H.js} +3 -3
  28. package/studio-dist/server/chunks/{18-Cnqp0uMS.js → 18-DP7Q8zPs.js} +3 -3
  29. package/studio-dist/server/chunks/{20-D9243OmI.js → 20-9ta6MI7q.js} +3 -3
  30. package/studio-dist/server/chunks/{24-D-3OyyjO.js → 24-DysdL1ab.js} +3 -3
  31. package/studio-dist/server/chunks/{25-BC8dXyIT.js → 25-CYsps38R.js} +4 -4
  32. package/studio-dist/server/chunks/{26-DIYVHPeE.js → 26-Df4YXgg0.js} +3 -3
  33. package/studio-dist/server/chunks/{3-DDNPJWI0.js → 3-BEhOhYpL.js} +3 -3
  34. package/studio-dist/server/chunks/{_layout.svelte-ouauc7nn.js → _layout.svelte-CnLcXYG-.js} +4 -4
  35. package/studio-dist/server/chunks/{_page.svelte-B7CTgxGI.js → _page.svelte-C0qgUvzA.js} +4 -4
  36. package/studio-dist/server/chunks/{_page.svelte-DS8uziG5.js → _page.svelte-CbyEPj2j.js} +3 -3
  37. package/studio-dist/server/chunks/{_page.svelte-BKEo8OSf.js → _page.svelte-DGhXqeRc.js} +3 -3
  38. package/studio-dist/server/chunks/{_page.svelte-ez5VvNrn.js → _page.svelte-DOl0DGOO.js} +3 -3
  39. package/studio-dist/server/chunks/{_page.svelte-BlIGw3KR.js → _page.svelte-Da4q5l93.js} +3 -3
  40. package/studio-dist/server/chunks/{_page.svelte-DU-KSkGO.js → _page.svelte-Dv8tmDEC.js} +3 -3
  41. package/studio-dist/server/chunks/{_page.svelte-ZzSjr8MT.js → _page.svelte-DzcZljiy.js} +5 -5
  42. package/studio-dist/server/chunks/{_page.svelte-Ba45egd6.js → _page.svelte-HUqTICJR.js} +3 -3
  43. package/studio-dist/server/chunks/{_page.svelte-CkagR7NW.js → _page.svelte-ui7LnWkL.js} +3 -3
  44. package/studio-dist/server/chunks/{_server.ts-DMqfOwim.js → _server.ts-2BazvYRP.js} +3 -3
  45. package/studio-dist/server/chunks/{_server.ts-DNL_pHM3.js → _server.ts-C0evMKCk.js} +3 -3
  46. package/studio-dist/server/chunks/{_server.ts-CBaXrLT0.js → _server.ts-CnKVmf_s.js} +2 -2
  47. package/studio-dist/server/chunks/{_server.ts-D0rSedle.js → _server.ts-Cr57EKWf.js} +3 -3
  48. package/studio-dist/server/chunks/{_server.ts-DYCIQvnl.js → _server.ts-P4wVVksg.js} +3 -3
  49. package/studio-dist/server/chunks/{client-CM2Un2n3.js → client-CPM4LrO2.js} +2 -2
  50. package/studio-dist/server/chunks/{dist-BUqYzm8B.js → dist-CdoCt9zT.js} +92 -27
  51. package/studio-dist/server/chunks/{error.svelte-ZYrc30ps.js → error.svelte-ShcZo43D.js} +3 -3
  52. package/studio-dist/server/chunks/{http-Dc9ezTZW.js → http-BiQjEmVU.js} +2 -2
  53. package/studio-dist/server/chunks/{internal-BkiUrFap.js → internal-Cgsrya1j.js} +2 -2
  54. package/studio-dist/server/chunks/{stores-C00-wTzq.js → stores-BGrpEDMK.js} +2 -2
  55. package/studio-dist/server/index.js +1 -1
  56. package/studio-dist/server/manifest.js +17 -17
  57. package/studio-dist/client/_app/immutable/chunks/BhBqZa2S.js +0 -3
  58. package/studio-dist/client/_app/immutable/chunks/Cltvu8Dg.js +0 -1
  59. package/studio-dist/client/_app/immutable/entry/start.DTRTU1pq.js +0 -1
  60. package/studio-dist/client/_app/immutable/nodes/25.BKYmiCU1.js +0 -39
  61. package/studio-dist/server/chunks/1-CZPXu25_.js +0 -9
package/dist/cli/index.js CHANGED
@@ -1425,6 +1425,10 @@ function extractIdempotencyKeyArg(argv) {
1425
1425
  let idempotencyKey;
1426
1426
  for (let i = 0; i < argv.length; i++) {
1427
1427
  const token = argv[i];
1428
+ if (token === "--") {
1429
+ sanitized.push(...argv.slice(i));
1430
+ break;
1431
+ }
1428
1432
  if (token === "--idempotency-key") {
1429
1433
  const next = argv[i + 1];
1430
1434
  if (next !== void 0 && !next.startsWith("--")) {
@@ -17759,6 +17763,326 @@ var init_adr_073_saga = __esm({
17759
17763
  }
17760
17764
  });
17761
17765
 
17766
+ // packages/contracts/src/invariants/sync-write-invariants.ts
17767
+ function checkPending(task) {
17768
+ return { task, reason: "the post-apply check is not implemented yet (T12344 item)" };
17769
+ }
17770
+ function rulePending(task) {
17771
+ return { task, reason: "the typed merge-rule registry does not define it yet (T12344 item)" };
17772
+ }
17773
+ function trigger(id, tables, triggers, inventory, reason) {
17774
+ return { id, class: "trigger-covered", tables, sites: [], triggers, inventory, reason };
17775
+ }
17776
+ function pac(id, item, task, tables, footprint, reason) {
17777
+ return {
17778
+ id,
17779
+ class: "post-apply-check",
17780
+ tables,
17781
+ sites: [],
17782
+ check: { footprint },
17783
+ inventory: [item],
17784
+ pending: checkPending(task),
17785
+ reason
17786
+ };
17787
+ }
17788
+ function rule(id, task, table, columns, inventory, reason, tables = [table]) {
17789
+ return {
17790
+ id,
17791
+ class: "monotonic-merge-rule",
17792
+ tables,
17793
+ sites: [],
17794
+ mergeRule: { table, columns },
17795
+ inventory,
17796
+ pending: rulePending(task),
17797
+ reason
17798
+ };
17799
+ }
17800
+ var SYNC_WRITE_INVARIANTS;
17801
+ var init_sync_write_invariants = __esm({
17802
+ "packages/contracts/src/invariants/sync-write-invariants.ts"() {
17803
+ "use strict";
17804
+ SYNC_WRITE_INVARIANTS = Object.freeze([
17805
+ // §3.6.2: RAISE guards and UNIQUE indexes a migration creates on synced tables.
17806
+ trigger(
17807
+ "task.parent.no-cycle",
17808
+ ["tasks_tasks"],
17809
+ ["tasks_tasks_parent_cycle_guard_insert", "tasks_tasks_parent_cycle_guard_update"],
17810
+ ["V10", "V11"],
17811
+ "the parent chain is acyclic (the INSERT variant misses a self-parent, \xA73.6.3 item 2)"
17812
+ ),
17813
+ trigger(
17814
+ "task.parent.type-matrix",
17815
+ ["tasks_tasks"],
17816
+ ["tasks_tasks_parent_type_matrix_insert", "tasks_tasks_parent_type_matrix_update"],
17817
+ ["X1"],
17818
+ "parent/child type matrix; weaker than TypeScript (\xA73.6.3 item 1), the rest is PAC-01"
17819
+ ),
17820
+ trigger(
17821
+ "task.status.pipeline-consistency",
17822
+ ["tasks_tasks"],
17823
+ ["trg_tasks_tasks_status_pipeline_insert", "trg_tasks_tasks_status_pipeline_update"],
17824
+ ["V19", "C21"],
17825
+ "T877: status and pipeline_stage agree on one row"
17826
+ ),
17827
+ trigger(
17828
+ "task.relation.non-containment",
17829
+ ["tasks_task_relations"],
17830
+ ["tasks_task_relations_non_containment_insert", "tasks_task_relations_non_containment_update"],
17831
+ ["V31"],
17832
+ "no relation between a parent and its child, on relation writes only (\xA73.6.3 item 4)"
17833
+ ),
17834
+ trigger(
17835
+ "task.ac.child-target",
17836
+ ["tasks_task_acceptance_criteria"],
17837
+ ["tasks_task_acceptance_child_target_insert", "tasks_task_acceptance_child_target_update"],
17838
+ ["C28"],
17839
+ "a child_task AC targets a direct child, on AC writes only (\xA73.6.3 item 4)"
17840
+ ),
17841
+ trigger(
17842
+ "session.handoff.append-only",
17843
+ ["tasks_session_handoff_entries"],
17844
+ ["trg_tasks_session_handoff_no_update"],
17845
+ ["H2"],
17846
+ "handoff entries are never updated"
17847
+ ),
17848
+ trigger(
17849
+ "task.claim.lease-iso",
17850
+ ["tasks_tasks"],
17851
+ ["tasks_tasks_lease_iso_insert", "tasks_tasks_lease_iso_update"],
17852
+ [],
17853
+ "claim lease timestamps are ISO-8601 (t12736)"
17854
+ ),
17855
+ trigger(
17856
+ "task.ac-binding.unique",
17857
+ ["tasks_evidence_ac_bindings"],
17858
+ ["uq_tasks_evidence_ac_bindings_atom_ac_type"],
17859
+ ["C31"],
17860
+ "one binding per (evidence atom, AC, binding type)"
17861
+ ),
17862
+ trigger(
17863
+ "release.version.unique",
17864
+ ["tasks_releases"],
17865
+ ["uq_tasks_releases_version"],
17866
+ ["REL-1"],
17867
+ "one release row per version"
17868
+ ),
17869
+ trigger(
17870
+ "selfimprove.dhq.one-open",
17871
+ ["selfimprove_dhq"],
17872
+ ["ux_selfimprove_dhq_open"],
17873
+ ["D49"],
17874
+ "at most one open DHQ entry per question_hash"
17875
+ ),
17876
+ trigger(
17877
+ "account.one-active-per-provider",
17878
+ ["accounts"],
17879
+ ["ux_accounts_active_provider"],
17880
+ ["A40"],
17881
+ "at most one active account per provider (partial UNIQUE)"
17882
+ ),
17883
+ // §3.6.5: post-apply check families (T12344 items).
17884
+ pac(
17885
+ "task.tree.shape",
17886
+ "PAC-01",
17887
+ "T12922",
17888
+ ["tasks_tasks"],
17889
+ ["rows with a changed parent_id or type", "their direct children and ancestor chain"],
17890
+ "saga\u2192epic\u2192task\u2192subtask matrix, non-saga has a parent, depth \u2264 3, no self-parent"
17891
+ ),
17892
+ pac(
17893
+ "task.terminal-parent.live-children",
17894
+ "PAC-02",
17895
+ "T12923",
17896
+ ["tasks_tasks"],
17897
+ ["rows whose status, stage or parent changed", "their parent and siblings"],
17898
+ "no terminal parent with a live child; epic stage \u2265 children; rollup re-evaluated"
17899
+ ),
17900
+ pac(
17901
+ "task.dependency.graph",
17902
+ "PAC-03",
17903
+ "T12924",
17904
+ ["tasks_task_dependencies", "tasks_tasks"],
17905
+ ["dependency edges inserted in the page", "reachability from each depends_on"],
17906
+ "dependencies are acyclic, with no self-edge"
17907
+ ),
17908
+ pac(
17909
+ "task.done.evidence",
17910
+ "PAC-04",
17911
+ "T12925",
17912
+ ["tasks_tasks", "tasks_task_acceptance_criteria", "tasks_evidence_ac_bindings"],
17913
+ ["done rows in the page", "their AC rows, bindings, acceptance_json and verification_json"],
17914
+ "a done task has passed verification and every AC bound or waived"
17915
+ ),
17916
+ pac(
17917
+ "task.ac.integrity",
17918
+ "PAC-05",
17919
+ "T12926",
17920
+ ["tasks_tasks", "tasks_task_acceptance_criteria", "tasks_evidence_ac_bindings"],
17921
+ ["tasks whose AC rows, bindings, acceptance_json, parent_id or relations changed"],
17922
+ "acceptance_json \u21D4 AC rows, child_task ACs match children, bindings resolve"
17923
+ ),
17924
+ pac(
17925
+ "lifecycle.rows",
17926
+ "PAC-06",
17927
+ "T12927",
17928
+ ["tasks_lifecycle_pipelines", "tasks_lifecycle_stages", "tasks_tasks"],
17929
+ ["lifecycle pipeline, stage and gate rows in the page", "the owning task row"],
17930
+ "one pipeline per task, one stage row per name, pipeline_stage \u2265 completed stages"
17931
+ ),
17932
+ pac(
17933
+ "derived.mirrors",
17934
+ "PAC-07",
17935
+ "T12928",
17936
+ ["tasks_task_labels", "brain_sticky_tags", "docs_wikilinks", "tasks_tasks"],
17937
+ ["owning rows whose JSON or junction changed"],
17938
+ "junction tables equal their JSON source"
17939
+ ),
17940
+ pac(
17941
+ "session.goal.singletons",
17942
+ "PAC-08",
17943
+ "T12929",
17944
+ ["tasks_sessions", "tasks_task_work_history", "tasks_goal"],
17945
+ ["session rows whose status, scope or chain changed", "work-history rows per session"],
17946
+ "one active session per scope, reciprocal chain, one open interval, one live goal"
17947
+ ),
17948
+ pac(
17949
+ "audit.uniqueness",
17950
+ "PAC-09",
17951
+ "T12930",
17952
+ ["tasks_audit_log"],
17953
+ ["audit rows with a non-null idempotency key", "rollback audit rows"],
17954
+ "idempotency keys are unique across replicas; at most one rollback per receipt"
17955
+ ),
17956
+ pac(
17957
+ "identity.collisions",
17958
+ "PAC-10",
17959
+ "T12931",
17960
+ ["tasks_tasks", "tasks_sessions", "brain_observations", "docs_attachments"],
17961
+ ["inserted rows", "the natural key's index"],
17962
+ "display-id and natural-key clashes become an alias or re-mint (T12341)"
17963
+ ),
17964
+ pac(
17965
+ "dedupe.at-most-one",
17966
+ "PAC-11",
17967
+ "T12932",
17968
+ ["brain_decisions", "brain_learnings", "tasks_external_task_links"],
17969
+ ["inserted rows grouped by the natural key"],
17970
+ "duplicates created on two devices are merged"
17971
+ ),
17972
+ pac(
17973
+ "ref.soft-orphans",
17974
+ "PAC-12",
17975
+ "T12933",
17976
+ ["brain_memory_links", "brain_page_edges", "docs_attachment_refs", "tasks_task_commits"],
17977
+ ["reference columns of the rows in the page", "their targets"],
17978
+ "cross-DB and polymorphic references resolve"
17979
+ ),
17980
+ pac(
17981
+ "supersession.graph",
17982
+ "PAC-13",
17983
+ "T12934",
17984
+ ["brain_decisions", "docs_attachments", "tasks_architecture_decisions"],
17985
+ ["rows whose supersession columns changed", "a chain walk"],
17986
+ "supersession chains are acyclic with at most one successor"
17987
+ ),
17988
+ pac(
17989
+ "derived.counters",
17990
+ "PAC-14",
17991
+ "T12935",
17992
+ ["docs_attachments", "conduit_attachments", "docs_pipeline_manifest"],
17993
+ ["the owning rows"],
17994
+ "derived counters and cross-column facts agree with their rows"
17995
+ ),
17996
+ pac(
17997
+ "apply.preconditions",
17998
+ "PAC-15",
17999
+ "T12936",
18000
+ ["tasks_tasks"],
18001
+ ["the whole page"],
18002
+ "no apply while the local twin collapse has failed; restore is a re-baseline"
18003
+ ),
18004
+ // §3.6.6: typed merge rules (T12344).
18005
+ rule(
18006
+ "task.status.absorbing",
18007
+ "T12937",
18008
+ "tasks_tasks",
18009
+ ["status", "completed_at", "cancelled_at", "cancellation_reason", "pipeline_stage"],
18010
+ ["V18", "V20", "C22", "P40", "P46", "P47"],
18011
+ "done, cancelled and archived are absorbing; leaving them needs an explicit op"
18012
+ ),
18013
+ rule(
18014
+ "task.pipeline-stage.max",
18015
+ "T12938",
18016
+ "tasks_tasks",
18017
+ ["pipeline_stage"],
18018
+ ["V21", "C20", "P01", "F3"],
18019
+ "pipeline_stage is the maximum by STAGE_ORDER, except an explicit restore"
18020
+ ),
18021
+ rule(
18022
+ "task.verification.frozen-on-done",
18023
+ "T12939",
18024
+ "tasks_tasks",
18025
+ ["verification_json"],
18026
+ ["C01", "C02", "C03", "C17"],
18027
+ "verification is frozen once done; otherwise merged per gate"
18028
+ ),
18029
+ rule(
18030
+ "session.status.terminal",
18031
+ "T12940",
18032
+ "tasks_sessions",
18033
+ ["status", "ended_at"],
18034
+ ["S7", "S8", "S9", "S10", "S11", "S17", "S18", "SC2", "N1", "SK5", "P32"],
18035
+ "ended and orphaned are terminal except on an explicit resume"
18036
+ ),
18037
+ rule("audit.immutable", "T12941", "tasks_audit_log", ["*"], ["SA3"], "audit rows are immutable", [
18038
+ "tasks_audit_log",
18039
+ "audit_log"
18040
+ ]),
18041
+ rule(
18042
+ "sticky.status.one-way",
18043
+ "T12942",
18044
+ "brain_sticky_notes",
18045
+ ["status", "converted_to_json"],
18046
+ ["SK2", "SK3", "B24"],
18047
+ "active\u2192{converted, archived} is one-way; converted_to_json is write-once"
18048
+ ),
18049
+ rule(
18050
+ "release.status.absorbing",
18051
+ "T12943",
18052
+ "tasks_releases",
18053
+ ["status"],
18054
+ ["REL-2", "REL-3", "REL-4", "REL-5", "REL-6", "REL-7", "REL-8"],
18055
+ "shipped release statuses are absorbing"
18056
+ ),
18057
+ rule(
18058
+ "playbook.approval.once",
18059
+ "T12944",
18060
+ "tasks_playbook_approvals",
18061
+ ["status"],
18062
+ ["PB-1", "PB-4", "PB-7", "P33"],
18063
+ "an approval goes pending\u2192decided once"
18064
+ ),
18065
+ rule(
18066
+ "docs.lifecycle.transitions",
18067
+ "T12945",
18068
+ "docs_attachments",
18069
+ ["lifecycle_status"],
18070
+ ["D04", "D05", "D31", "D32", "D39", "D50"],
18071
+ "superseded is sticky; lifecycle transitions follow a matrix"
18072
+ ),
18073
+ // §3.6.0 identity-layer rows.
18074
+ {
18075
+ id: "identity.local-minting",
18076
+ class: "identity-layer",
18077
+ tables: ["tasks_tasks", "tasks_sessions"],
18078
+ sites: [],
18079
+ inventory: ["V12", "B07", "B12"],
18080
+ reason: "ids minted from local state (display ids, integer PKs, device-derived ids) collide across replicas; T12341 uids and re-minting own it, no validator port can"
18081
+ }
18082
+ ]);
18083
+ }
18084
+ });
18085
+
17762
18086
  // packages/contracts/src/invariants/index.ts
17763
18087
  function buildKey(invariant) {
17764
18088
  return `${invariant.adr}.${invariant.code}`;
@@ -17802,6 +18126,7 @@ var init_invariants = __esm({
17802
18126
  init_adr_056_release();
17803
18127
  init_adr_070_orchestration();
17804
18128
  init_adr_073_saga();
18129
+ init_sync_write_invariants();
17805
18130
  INVARIANTS_REGISTRY = buildRegistry();
17806
18131
  }
17807
18132
  });
@@ -20673,7 +20998,7 @@ var init_render2 = __esm({
20673
20998
  function isResourceGrant(r) {
20674
20999
  return r.deferred === false;
20675
21000
  }
20676
- var RESOURCE_CLASSES, RESOURCE_DEFERRED_CODE, RESOURCE_BACKPRESSURE_CODE, DEFAULT_RESOURCE_RETRY_AFTER_MS;
21001
+ var RESOURCE_CLASSES, RESOURCE_DEFERRED_CODE, RUN_COMMAND_FAILED_CODE, RUN_DEFERRED_EXIT_CODE, RESOURCE_BACKPRESSURE_CODE, DEFAULT_RESOURCE_RETRY_AFTER_MS;
20677
21002
  var init_resource_governor = __esm({
20678
21003
  "packages/contracts/src/resource-governor.ts"() {
20679
21004
  "use strict";
@@ -20688,6 +21013,8 @@ var init_resource_governor = __esm({
20688
21013
  "background-autonomous"
20689
21014
  ]);
20690
21015
  RESOURCE_DEFERRED_CODE = "E_RESOURCE_DEFERRED";
21016
+ RUN_COMMAND_FAILED_CODE = "E_COMMAND_FAILED";
21017
+ RUN_DEFERRED_EXIT_CODE = 75;
20691
21018
  RESOURCE_BACKPRESSURE_CODE = "E_RESOURCE_BACKPRESSURE";
20692
21019
  DEFAULT_RESOURCE_RETRY_AFTER_MS = 2e3;
20693
21020
  }
@@ -21624,11 +21951,11 @@ var init_taxonomy = __esm({
21624
21951
  * @throws TaxonomyError when any tag is not canonical.
21625
21952
  */
21626
21953
  validateOrThrow(tags, context) {
21627
- const invalid = this.validate(tags);
21628
- if (invalid.length > 0) {
21954
+ const invalid2 = this.validate(tags);
21955
+ if (invalid2.length > 0) {
21629
21956
  throw new TaxonomyError(
21630
- `${context}: unknown tags [${invalid.join(", ")}]. Use canonical tags. Run 'cleo taxonomy list' to see all valid tags.`,
21631
- invalid
21957
+ `${context}: unknown tags [${invalid2.join(", ")}]. Use canonical tags. Run 'cleo taxonomy list' to see all valid tags.`,
21958
+ invalid2
21632
21959
  );
21633
21960
  }
21634
21961
  }
@@ -22762,7 +23089,39 @@ var init_nexus_account = __esm({
22762
23089
  /** An option that needs device credentials (`--read-only`) with `CLEO_NEXUS_DEVICE=0`. */
22763
23090
  "E_NEXUS_DEVICE_REQUIRED",
22764
23091
  /** `.cleo/nexus-link.json` is in a format this CLEO cannot update (written by a newer CLEO). */
22765
- "E_NEXUS_LINK_FILE_UNSUPPORTED"
23092
+ "E_NEXUS_LINK_FILE_UNSUPPORTED",
23093
+ // Cloud vault (encrypted snapshots, T12336 / T12337 / T12338).
23094
+ /** Another device holds this stream's write lease (`--force` takes it and labels a fork). */
23095
+ "E_NEXUS_VAULT_LEASE_HELD",
23096
+ /** Another device pushed a newer snapshot than this machine last pushed or restored: pull first. */
23097
+ "E_NEXUS_VAULT_BEHIND",
23098
+ /** Local data changed since the last push or restore; pulling would overwrite it. */
23099
+ "E_NEXUS_VAULT_LOCAL_CHANGES",
23100
+ /** A snapshot's counts or hashes do not match its manifest; nothing was activated. */
23101
+ "E_NEXUS_VAULT_VERIFY_FAILED",
23102
+ /** The account encryption key could not be obtained for this device. */
23103
+ "E_NEXUS_VAULT_KEY_UNAVAILABLE",
23104
+ /** The project is not linked to Cleo Nexus (`cleo project link`). */
23105
+ "E_NEXUS_VAULT_NOT_LINKED",
23106
+ /** The cloud holds no snapshot to restore. */
23107
+ "E_NEXUS_VAULT_EMPTY",
23108
+ /**
23109
+ * The Cleo Nexus server predates account key escrow (cleo-nexus T082), so it cannot hold a
23110
+ * vault (T13049). Nothing was written.
23111
+ */
23112
+ "E_NEXUS_VAULT_UNSUPPORTED",
23113
+ /** The server refused the snapshot (lineage or regression check). */
23114
+ "E_NEXUS_VAULT_REFUSED",
23115
+ /**
23116
+ * The stream moved past what this CLEO's vault writes (T13034): it takes only checkpoint/v3
23117
+ * snapshots (the server's `E_STREAM_VERSION`), or it holds data of a newer sync schema.
23118
+ * Pull, restore and verify still work; nothing was written.
23119
+ */
23120
+ "E_NEXUS_VAULT_STREAM_UPGRADED",
23121
+ /** Another CLEO process is writing to the store a restore would replace. */
23122
+ "E_NEXUS_VAULT_STORE_BUSY",
23123
+ /** A project restore target already holds a different project. */
23124
+ "E_NEXUS_VAULT_TARGET_OCCUPIED"
22766
23125
  ];
22767
23126
  nexusAccountUserSchema = z25.object({
22768
23127
  id: z25.string(),
@@ -23009,7 +23368,9 @@ var init_nexus_cloud = __esm({
23009
23368
  "route-undeclared",
23010
23369
  "bearer-session-required",
23011
23370
  "session-not-fresh",
23012
- "device-limit"
23371
+ "device-limit",
23372
+ "device-flow-session-required",
23373
+ "device-not-enrolled"
23013
23374
  ];
23014
23375
  NEXUS_REVOKED_REASONS = ["signed-out", "revoked", "rotated", "reenrolled"];
23015
23376
  LOGIN = "run `cleo login nexus`";
@@ -23100,6 +23461,16 @@ var init_nexus_cloud = __esm({
23100
23461
  code: "E_NEXUS_REQUEST_FAILED",
23101
23462
  message: "the account has reached its device limit",
23102
23463
  fix: "revoke unused devices on cleocode.dev, then retry"
23464
+ },
23465
+ "device-flow-session-required": {
23466
+ code: "E_NEXUS_SESSION_EXPIRED",
23467
+ message: "this session was not issued to the CLI by `cleo login nexus`, so it cannot enrol a device",
23468
+ fix: SESSION_EXPIRED_LOGIN.fix
23469
+ },
23470
+ "device-not-enrolled": {
23471
+ code: "E_NEXUS_NOT_SIGNED_IN",
23472
+ message: "this device is not enrolled with Cleo Nexus",
23473
+ fix: LOGIN
23103
23474
  }
23104
23475
  };
23105
23476
  NEXUS_CONFLICT_ERRORS = {
@@ -23118,6 +23489,69 @@ var init_nexus_cloud = __esm({
23118
23489
  }
23119
23490
  });
23120
23491
 
23492
+ // packages/contracts/src/nexus-vault.ts
23493
+ import { z as z27 } from "zod";
23494
+ var isoTime2, uuid, nexusUserKeysSchema, nexusProjectKeysSchema, NEXUS_VAULT_LEASE_ROLE, nexusLeaseSchema, nexusLeaseAcquireSchema, nexusStreamHeadSchema, nexusActivityEventSchema, nexusActivityPageSchema;
23495
+ var init_nexus_vault = __esm({
23496
+ "packages/contracts/src/nexus-vault.ts"() {
23497
+ "use strict";
23498
+ isoTime2 = z27.iso.datetime({ offset: true });
23499
+ uuid = z27.string().regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i);
23500
+ nexusUserKeysSchema = z27.looseObject({
23501
+ keyVersion: z27.number().int().positive(),
23502
+ masterKeyVerifier: z27.string()
23503
+ });
23504
+ nexusProjectKeysSchema = z27.looseObject({
23505
+ keys: z27.array(
23506
+ z27.looseObject({ wrappedProjectKey: z27.string(), keyVersion: z27.number().int().positive() })
23507
+ )
23508
+ });
23509
+ NEXUS_VAULT_LEASE_ROLE = "writer";
23510
+ nexusLeaseSchema = z27.looseObject({
23511
+ streamId: z27.string(),
23512
+ role: z27.string(),
23513
+ replicaId: uuid,
23514
+ expiresAt: isoTime2,
23515
+ forkedFromReplicaId: uuid.nullable().optional()
23516
+ });
23517
+ nexusLeaseAcquireSchema = z27.looseObject({ lease: nexusLeaseSchema });
23518
+ nexusStreamHeadSchema = z27.looseObject({
23519
+ streamId: z27.string(),
23520
+ kind: z27.string().optional(),
23521
+ headSeq: z27.number().int().nonnegative(),
23522
+ headCheckpointId: z27.string().nullable(),
23523
+ /**
23524
+ * The highest segment `schemaVersion` the stream holds (the server raises it on every append).
23525
+ * Absent from an older server.
23526
+ */
23527
+ maxSchemaVersion: z27.number().int().nonnegative().optional()
23528
+ });
23529
+ nexusActivityEventSchema = z27.looseObject({
23530
+ id: z27.union([z27.string(), z27.number()]),
23531
+ at: isoTime2,
23532
+ actorUserId: z27.string().nullable().optional(),
23533
+ actorDeviceId: z27.string().nullable().optional(),
23534
+ requestId: z27.string().nullable().optional(),
23535
+ action: z27.string(),
23536
+ target: z27.string().nullable().optional(),
23537
+ detail: z27.unknown().optional()
23538
+ });
23539
+ nexusActivityPageSchema = z27.looseObject({
23540
+ events: z27.array(nexusActivityEventSchema),
23541
+ nextBefore: z27.union([z27.string(), z27.number()]).nullable().optional()
23542
+ });
23543
+ }
23544
+ });
23545
+
23546
+ // packages/contracts/src/sync-schema.ts
23547
+ var SYNC_SCHEMA_VERSION;
23548
+ var init_sync_schema = __esm({
23549
+ "packages/contracts/src/sync-schema.ts"() {
23550
+ "use strict";
23551
+ SYNC_SCHEMA_VERSION = 2;
23552
+ }
23553
+ });
23554
+
23121
23555
  // packages/contracts/src/task-id.ts
23122
23556
  function isTaskId(value) {
23123
23557
  return typeof value === "string" && TASK_ID_REGEX.test(value);
@@ -23321,6 +23755,7 @@ __export(src_exports, {
23321
23755
  NEXUS_UNAUTHENTICATED_ERRORS: () => NEXUS_UNAUTHENTICATED_ERRORS,
23322
23756
  NEXUS_UNAUTHENTICATED_REASONS: () => NEXUS_UNAUTHENTICATED_REASONS,
23323
23757
  NEXUS_UNREACHABLE_ERROR: () => NEXUS_UNREACHABLE_ERROR,
23758
+ NEXUS_VAULT_LEASE_ROLE: () => NEXUS_VAULT_LEASE_ROLE,
23324
23759
  OPEN_SYSTEM_KEY_PREFIXES: () => OPEN_SYSTEM_KEY_PREFIXES,
23325
23760
  OPERATIONS: () => OPERATIONS,
23326
23761
  OPERATION_RESULT_SCHEMAS: () => OPERATION_RESULT_SCHEMAS,
@@ -23366,6 +23801,8 @@ __export(src_exports, {
23366
23801
  RESOURCE_CLASSES: () => RESOURCE_CLASSES,
23367
23802
  RESOURCE_DEFERRED_CODE: () => RESOURCE_DEFERRED_CODE,
23368
23803
  ROLE_SYSTEM_IDS: () => ROLE_SYSTEM_IDS,
23804
+ RUN_COMMAND_FAILED_CODE: () => RUN_COMMAND_FAILED_CODE,
23805
+ RUN_DEFERRED_EXIT_CODE: () => RUN_DEFERRED_EXIT_CODE,
23369
23806
  RateCheckRequestSchema: () => RateCheckRequestSchema,
23370
23807
  RateResultResponseSchema: () => RateResultResponseSchema,
23371
23808
  ReleaseChannelSchema: () => ReleaseChannelSchema,
@@ -23401,6 +23838,8 @@ __export(src_exports, {
23401
23838
  SUPERVISOR_IPC_PROTOCOL_VERSION: () => SUPERVISOR_IPC_PROTOCOL_VERSION,
23402
23839
  SUPERVISOR_IPC_REQUEST_KINDS: () => SUPERVISOR_IPC_REQUEST_KINDS,
23403
23840
  SUPERVISOR_IPC_RESPONSE_KINDS: () => SUPERVISOR_IPC_RESPONSE_KINDS,
23841
+ SYNC_SCHEMA_VERSION: () => SYNC_SCHEMA_VERSION,
23842
+ SYNC_WRITE_INVARIANTS: () => SYNC_WRITE_INVARIANTS,
23404
23843
  SYSTEM_ROLE_MAP: () => SYSTEM_ROLE_MAP,
23405
23844
  SessionView: () => SessionView,
23406
23845
  SpawnRequestSchema: () => SpawnRequestSchema,
@@ -23600,6 +24039,8 @@ __export(src_exports, {
23600
24039
  nexusAccountMeSchema: () => nexusAccountMeSchema,
23601
24040
  nexusAccountOrganizationSchema: () => nexusAccountOrganizationSchema,
23602
24041
  nexusAccountUserSchema: () => nexusAccountUserSchema,
24042
+ nexusActivityEventSchema: () => nexusActivityEventSchema,
24043
+ nexusActivityPageSchema: () => nexusActivityPageSchema,
23603
24044
  nexusCloudCredentialSchema: () => nexusCloudCredentialSchema,
23604
24045
  nexusCloudDeviceCountsSchema: () => nexusCloudDeviceCountsSchema,
23605
24046
  nexusCloudDevicePageSchema: () => nexusCloudDevicePageSchema,
@@ -23615,6 +24056,11 @@ __export(src_exports, {
23615
24056
  nexusCloudStatusSchema: () => nexusCloudStatusSchema,
23616
24057
  nexusCloudUserSchema: () => nexusCloudUserSchema,
23617
24058
  nexusCloudWhoamiSchema: () => nexusCloudWhoamiSchema,
24059
+ nexusLeaseAcquireSchema: () => nexusLeaseAcquireSchema,
24060
+ nexusLeaseSchema: () => nexusLeaseSchema,
24061
+ nexusProjectKeysSchema: () => nexusProjectKeysSchema,
24062
+ nexusStreamHeadSchema: () => nexusStreamHeadSchema,
24063
+ nexusUserKeysSchema: () => nexusUserKeysSchema,
23618
24064
  normalizeError: () => normalizeError,
23619
24065
  noteAtomSchema: () => noteAtomSchema,
23620
24066
  noulDecisionAnswerSchema: () => noulDecisionAnswerSchema,
@@ -23796,6 +24242,8 @@ var init_src2 = __esm({
23796
24242
  init_decide_sites();
23797
24243
  init_nexus_account();
23798
24244
  init_nexus_cloud();
24245
+ init_nexus_vault();
24246
+ init_sync_schema();
23799
24247
  init_task_id();
23800
24248
  }
23801
24249
  });
@@ -24651,7 +25099,7 @@ function humanProgress(text) {
24651
25099
  function isHumanOutput() {
24652
25100
  return humanEnabled();
24653
25101
  }
24654
- function cliError(message, code, details, meta) {
25102
+ function cliError(message, code, details, meta, options) {
24655
25103
  const ctx = getFormatContext();
24656
25104
  const outputMode = getOutputMode();
24657
25105
  if (outputMode === "silent") {
@@ -24693,6 +25141,11 @@ function cliError(message, code, details, meta) {
24693
25141
  error: errorObj,
24694
25142
  meta: errorMeta
24695
25143
  };
25144
+ if (options?.stderr === true) {
25145
+ process.stderr.write(`${JSON.stringify(envelope)}
25146
+ `);
25147
+ return;
25148
+ }
24696
25149
  process.stdout.write(JSON.stringify(envelope) + "\n");
24697
25150
  }
24698
25151
  var renderers;
@@ -37285,21 +37738,21 @@ var init_migrate_e4 = __esm({
37285
37738
 
37286
37739
  // packages/playbooks/src/policy.ts
37287
37740
  function evaluatePolicy(command, rules = DEFAULT_POLICY_RULES) {
37288
- for (const rule of rules) {
37289
- if (rule.action === "require-human" && rule.pattern.test(command)) {
37741
+ for (const rule2 of rules) {
37742
+ if (rule2.action === "require-human" && rule2.pattern.test(command)) {
37290
37743
  return {
37291
37744
  action: "require-human",
37292
- reason: rule.reason,
37293
- matchedPattern: rule.pattern.source
37745
+ reason: rule2.reason,
37746
+ matchedPattern: rule2.pattern.source
37294
37747
  };
37295
37748
  }
37296
37749
  }
37297
- for (const rule of rules) {
37298
- if (rule.action === "auto-approve" && rule.pattern.test(command)) {
37750
+ for (const rule2 of rules) {
37751
+ if (rule2.action === "auto-approve" && rule2.pattern.test(command)) {
37299
37752
  return {
37300
37753
  action: "auto-approve",
37301
- reason: rule.reason,
37302
- matchedPattern: rule.pattern.source
37754
+ reason: rule2.reason,
37755
+ matchedPattern: rule2.pattern.source
37303
37756
  };
37304
37757
  }
37305
37758
  }
@@ -37874,9 +38327,9 @@ function auditContractViolation(projectRoot, runId, nodeId, field, key, playbook
37874
38327
  } catch {
37875
38328
  }
37876
38329
  }
37877
- function handleContractErrorHandler(playbook, trigger, _message) {
38330
+ function handleContractErrorHandler(playbook, trigger2, _message) {
37878
38331
  if (!playbook.error_handlers) return null;
37879
- const handler = playbook.error_handlers.find((h) => h.on === trigger);
38332
+ const handler = playbook.error_handlers.find((h) => h.on === trigger2);
37880
38333
  return handler?.action ?? null;
37881
38334
  }
37882
38335
  function iterationCapFor(node, runtimeDefault) {
@@ -38399,8 +38852,8 @@ async function loadPlaybookByName(name) {
38399
38852
  return null;
38400
38853
  }
38401
38854
  try {
38402
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/internal");
38403
- const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot75();
38855
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/internal");
38856
+ const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot76();
38404
38857
  const resolved = resolvePlaybook(name, {
38405
38858
  projectRoot,
38406
38859
  globalPlaybooksDir: __playbookRuntimeOverrides.globalPlaybooksDir,
@@ -38445,7 +38898,7 @@ async function buildDefaultDispatcher() {
38445
38898
  if (__playbookRuntimeOverrides.dispatcher) return __playbookRuntimeOverrides.dispatcher;
38446
38899
  const { orchestrateSpawnExecute: orchestrateSpawnExecute2 } = await import("@cleocode/runtime/gateway");
38447
38900
  const {
38448
- getProjectRoot: getProjectRoot75,
38901
+ getProjectRoot: getProjectRoot76,
38449
38902
  createToolGuard,
38450
38903
  runSkillNodeOrSpawn,
38451
38904
  maybeCreatePiRunner,
@@ -38453,7 +38906,7 @@ async function buildDefaultDispatcher() {
38453
38906
  hasCantbookProfilePin,
38454
38907
  DEFAULT_DETERMINISTIC_DENIED_COMMANDS
38455
38908
  } = await import("@cleocode/core/internal");
38456
- const projectRoot = getProjectRoot75();
38909
+ const projectRoot = getProjectRoot76();
38457
38910
  const tools = createToolGuard({
38458
38911
  allowedRoots: [projectRoot],
38459
38912
  deniedCommands: DEFAULT_DETERMINISTIC_DENIED_COMMANDS,
@@ -38546,12 +38999,12 @@ async function buildDefaultDeterministicRunner() {
38546
38999
  return void 0;
38547
39000
  }
38548
39001
  const {
38549
- getProjectRoot: getProjectRoot75,
39002
+ getProjectRoot: getProjectRoot76,
38550
39003
  createToolGuard,
38551
39004
  createGuardedDeterministicRunner,
38552
39005
  DEFAULT_DETERMINISTIC_DENIED_COMMANDS
38553
39006
  } = await import("@cleocode/core/internal");
38554
- const projectRoot = getProjectRoot75();
39007
+ const projectRoot = getProjectRoot76();
38555
39008
  const tools = createToolGuard({
38556
39009
  allowedRoots: [projectRoot],
38557
39010
  deniedCommands: DEFAULT_DETERMINISTIC_DENIED_COMMANDS,
@@ -38709,8 +39162,8 @@ var init_playbook2 = __esm({
38709
39162
  projectRoot = __playbookRuntimeOverrides.projectRoot;
38710
39163
  } else {
38711
39164
  try {
38712
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/internal");
38713
- projectRoot = getProjectRoot75();
39165
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/internal");
39166
+ projectRoot = getProjectRoot76();
38714
39167
  } catch {
38715
39168
  projectRoot = void 0;
38716
39169
  }
@@ -38775,14 +39228,14 @@ var init_playbook2 = __esm({
38775
39228
  const deterministicRunner = await buildDefaultDeterministicRunner();
38776
39229
  let result;
38777
39230
  try {
38778
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/internal");
39231
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/internal");
38779
39232
  const opts = {
38780
39233
  db,
38781
39234
  playbook: parsed.definition,
38782
39235
  playbookHash: parsed.sourceHash,
38783
39236
  initialContext,
38784
39237
  dispatcher,
38785
- projectRoot: getProjectRoot75()
39238
+ projectRoot: getProjectRoot76()
38786
39239
  };
38787
39240
  if (deterministicRunner !== void 0) opts.deterministicRunner = deterministicRunner;
38788
39241
  if (__playbookRuntimeOverrides.approvalSecret !== void 0) {
@@ -39241,16 +39694,16 @@ async function orchestrateClassify(request, context, projectRoot, taskId) {
39241
39694
  }
39242
39695
  try {
39243
39696
  const { getCleoCantWorkflowsDir } = await import("@cleocode/core/internal");
39244
- const { readFileSync: readFileSync22, readdirSync: readdirSync3, existsSync: existsSync22 } = await import("node:fs");
39245
- const { join: join40 } = await import("node:path");
39697
+ const { readFileSync: readFileSync23, readdirSync: readdirSync4, existsSync: existsSync22 } = await import("node:fs");
39698
+ const { join: join41 } = await import("node:path");
39246
39699
  const workflowsDir = getCleoCantWorkflowsDir();
39247
39700
  const combined = `${request} ${context ?? ""}`.toLowerCase();
39248
39701
  const matches = [];
39249
39702
  if (existsSync22(workflowsDir)) {
39250
- const files = readdirSync3(workflowsDir).filter((f) => f.endsWith(".cant"));
39703
+ const files = readdirSync4(workflowsDir).filter((f) => f.endsWith(".cant"));
39251
39704
  for (const file of files) {
39252
39705
  try {
39253
- const src = readFileSync22(join40(workflowsDir, file), "utf-8");
39706
+ const src = readFileSync23(join41(workflowsDir, file), "utf-8");
39254
39707
  const teamMatch = /^team\s+(\S+):/m.exec(src);
39255
39708
  if (!teamMatch) continue;
39256
39709
  const teamName = teamMatch[1];
@@ -39265,12 +39718,12 @@ async function orchestrateClassify(request, context, projectRoot, taskId) {
39265
39718
  }
39266
39719
  }
39267
39720
  }
39268
- const localCantDir = join40(projectRoot, CLEO_DIR_NAME2, WORKFLOWS_SUBDIR);
39721
+ const localCantDir = join41(projectRoot, CLEO_DIR_NAME2, WORKFLOWS_SUBDIR);
39269
39722
  if (existsSync22(localCantDir)) {
39270
- const files = readdirSync3(localCantDir).filter((f) => f.endsWith(".cant"));
39723
+ const files = readdirSync4(localCantDir).filter((f) => f.endsWith(".cant"));
39271
39724
  for (const file of files) {
39272
39725
  try {
39273
- const src = readFileSync22(join40(localCantDir, file), "utf-8");
39726
+ const src = readFileSync23(join41(localCantDir, file), "utf-8");
39274
39727
  const teamMatch = /^team\s+(\S+):/m.exec(src);
39275
39728
  if (!teamMatch) continue;
39276
39729
  const teamName = teamMatch[1];
@@ -46121,11 +46574,11 @@ var init_security = __esm({
46121
46574
  });
46122
46575
 
46123
46576
  // packages/cleo/src/dispatch/middleware/sanitizer.ts
46124
- function createSanitizer(getProjectRoot75) {
46577
+ function createSanitizer(getProjectRoot76) {
46125
46578
  return async (req, next) => {
46126
46579
  if (req.params) {
46127
46580
  try {
46128
- const root = getProjectRoot75 ? getProjectRoot75() : void 0;
46581
+ const root = getProjectRoot76 ? getProjectRoot76() : void 0;
46129
46582
  req.params = sanitizeParams(req.params, root, {
46130
46583
  domain: req.domain,
46131
46584
  operation: req.operation
@@ -46227,14 +46680,14 @@ var init_session_resolver = __esm({
46227
46680
  });
46228
46681
 
46229
46682
  // packages/cleo/src/dispatch/middleware/store-write-guard.ts
46230
- function createStoreWriteGuard(getProjectRoot75) {
46683
+ function createStoreWriteGuard(getProjectRoot76) {
46231
46684
  return async (req, next) => {
46232
46685
  if (req.gateway !== "mutate" || ALLOWED_WHILE_READ_ONLY.has(`${req.domain}.${req.operation}`)) {
46233
46686
  return next();
46234
46687
  }
46235
46688
  let projectRoot;
46236
46689
  try {
46237
- projectRoot = getProjectRoot75();
46690
+ projectRoot = getProjectRoot76();
46238
46691
  } catch {
46239
46692
  return next();
46240
46693
  }
@@ -48084,9 +48537,9 @@ var init_agent = __esm({
48084
48537
  isActive: true
48085
48538
  });
48086
48539
  const { existsSync: existsSync22, mkdirSync: mkdirSync7, writeFileSync: writeFileSync8 } = await import("node:fs");
48087
- const { join: join40 } = await import("node:path");
48088
- const cantDir = join40(CLEO_DIR_NAME3, AGENTS_SUBDIR);
48089
- const cantPath = join40(cantDir, `${agentId}.cant`);
48540
+ const { join: join41 } = await import("node:path");
48541
+ const cantDir = join41(CLEO_DIR_NAME3, AGENTS_SUBDIR);
48542
+ const cantPath = join41(cantDir, `${agentId}.cant`);
48090
48543
  let cantScaffolded = false;
48091
48544
  if (!existsSync22(cantPath)) {
48092
48545
  mkdirSync7(cantDir, { recursive: true });
@@ -48267,8 +48720,8 @@ agent ${agentId}:
48267
48720
  try {
48268
48721
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
48269
48722
  const { createRuntime } = await import("@cleocode/runtime");
48270
- const { existsSync: existsSync22, readFileSync: readFileSync22 } = await import("node:fs");
48271
- const { join: join40 } = await import("node:path");
48723
+ const { existsSync: existsSync22, readFileSync: readFileSync23 } = await import("node:fs");
48724
+ const { join: join41 } = await import("node:path");
48272
48725
  await openCleoDb("project");
48273
48726
  const registry = new AgentRegistryAccessor(getProjectRoot25());
48274
48727
  const credential = await registry.get(args.agentId);
@@ -48288,9 +48741,9 @@ agent ${agentId}:
48288
48741
  }
48289
48742
  let profile2 = null;
48290
48743
  let cantValidation = null;
48291
- const cantPath = args.cant ?? join40(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
48744
+ const cantPath = args.cant ?? join41(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
48292
48745
  if (existsSync22(cantPath)) {
48293
- profile2 = readFileSync22(cantPath, "utf-8");
48746
+ profile2 = readFileSync23(cantPath, "utf-8");
48294
48747
  try {
48295
48748
  const cantModule = await import("@cleocode/cant");
48296
48749
  const validate = "validate" in cantModule ? cantModule.validate : null;
@@ -48814,7 +49267,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
48814
49267
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
48815
49268
  const { createRuntime } = await import("@cleocode/runtime");
48816
49269
  const { existsSync: existsSync22 } = await import("node:fs");
48817
- const { join: join40 } = await import("node:path");
49270
+ const { join: join41 } = await import("node:path");
48818
49271
  await openCleoDb("project");
48819
49272
  const registry = new AgentRegistryAccessor(getProjectRoot25());
48820
49273
  const credential = await registry.get(args.agentId);
@@ -48831,7 +49284,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
48831
49284
  }
48832
49285
  await registry.update(args.agentId, { isActive: true });
48833
49286
  await registry.markUsed(args.agentId);
48834
- const cantPath = join40(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
49287
+ const cantPath = join41(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
48835
49288
  const hasProfile = existsSync22(cantPath);
48836
49289
  const runtime = await createRuntime(registry, {
48837
49290
  agentId: args.agentId,
@@ -49782,8 +50235,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
49782
50235
  process.exitCode = 4;
49783
50236
  return;
49784
50237
  }
49785
- const { join: join40 } = await import("node:path");
49786
- const personaPath = join40(resolvedDir, "persona.cant");
50238
+ const { join: join41 } = await import("node:path");
50239
+ const personaPath = join41(resolvedDir, "persona.cant");
49787
50240
  if (!existsSync22(personaPath)) {
49788
50241
  cliOutput(
49789
50242
  {
@@ -49823,15 +50276,15 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
49823
50276
  return;
49824
50277
  }
49825
50278
  const archiveStats = statSync3(archivePath);
49826
- const { readdirSync: readdirSync3 } = await import("node:fs");
50279
+ const { readdirSync: readdirSync4 } = await import("node:fs");
49827
50280
  let fileCount = 0;
49828
50281
  const countFiles = (dirPath) => {
49829
- const entries = readdirSync3(dirPath, { withFileTypes: true });
50282
+ const entries = readdirSync4(dirPath, { withFileTypes: true });
49830
50283
  for (const entry of entries) {
49831
50284
  if (entry.isFile()) {
49832
50285
  fileCount++;
49833
50286
  } else if (entry.isDirectory()) {
49834
- countFiles(join40(dirPath, entry.name));
50287
+ countFiles(join41(dirPath, entry.name));
49835
50288
  }
49836
50289
  }
49837
50290
  };
@@ -50079,17 +50532,17 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
50079
50532
  },
50080
50533
  async run({ args }) {
50081
50534
  try {
50082
- const { existsSync: existsSync22, readFileSync: readFileSync22, mkdirSync: mkdirSync7 } = await import("node:fs");
50083
- const { resolve: resolve13, join: join40 } = await import("node:path");
50535
+ const { existsSync: existsSync22, readFileSync: readFileSync23, mkdirSync: mkdirSync7 } = await import("node:fs");
50536
+ const { resolve: resolve13, join: join41 } = await import("node:path");
50084
50537
  const specPath = resolve13(args.spec);
50085
50538
  if (!existsSync22(specPath)) {
50086
50539
  cliError(`spec file not found: ${specPath}`, 4, { name: "E_NOT_FOUND" });
50087
50540
  process.exitCode = 4;
50088
50541
  return;
50089
50542
  }
50090
- const specContent = readFileSync22(specPath, "utf-8");
50543
+ const specContent = readFileSync23(specPath, "utf-8");
50091
50544
  const projectRoot = getProjectRoot25();
50092
- const outputDir = args["output-dir"] ? resolve13(args["output-dir"]) : join40(projectRoot, ".cleo", "cant", "agents");
50545
+ const outputDir = args["output-dir"] ? resolve13(args["output-dir"]) : join41(projectRoot, ".cleo", "cant", "agents");
50093
50546
  mkdirSync7(outputDir, { recursive: true });
50094
50547
  if (args["dry-run"]) {
50095
50548
  cliOutput(
@@ -51017,7 +51470,7 @@ function nexusApiUrlArg(args) {
51017
51470
  function failNexus(err, operation) {
51018
51471
  const code = err instanceof Error && "code" in err && typeof err.code === "string" ? err.code : void 0;
51019
51472
  const fix = err instanceof Error && "fix" in err && typeof err.fix === "string" ? err.fix : void 0;
51020
- const exitCode = code === "E_NEXUS_INVALID_API_URL" || code === "E_NEXUS_INVALID_LABEL" || code === "E_NEXUS_DEVICE_REQUIRED" || code === "E_VALIDATION" ? 6 : 1;
51473
+ const exitCode = code === "E_NEXUS_INVALID_API_URL" || code === "E_NEXUS_INVALID_LABEL" || code === "E_NEXUS_DEVICE_REQUIRED" || code === "E_VALIDATION" ? 6 : VAULT_REFUSAL_EXIT_CODES[code ?? ""] ?? 1;
51021
51474
  const details = err instanceof Error && "publicDetails" in err && typeof err.publicDetails === "object" && err.publicDetails ? err.publicDetails : void 0;
51022
51475
  cliError(
51023
51476
  err instanceof Error ? err.message : String(err),
@@ -51084,6 +51537,24 @@ async function runNexusLogin(args, openBrowser2) {
51084
51537
  readOnly,
51085
51538
  ...name !== void 0 ? { name } : {}
51086
51539
  });
51540
+ if (!readOnly) {
51541
+ const { attachNexusGlobalStore } = await import(
51542
+ /* webpackIgnore: true */
51543
+ "@cleocode/core/cloud/nexus-home.js"
51544
+ );
51545
+ try {
51546
+ const global = await attachNexusGlobalStore({ apiUrl: hooks2.apiUrl });
51547
+ result = { ...result, warnings: [...result.warnings, ...global.warnings] };
51548
+ } catch (err) {
51549
+ result = {
51550
+ ...result,
51551
+ warnings: [
51552
+ ...result.warnings,
51553
+ `signed in, but attaching this device's global store failed (${err instanceof Error ? err.message : String(err)}); run \`cleo login nexus\` again`
51554
+ ]
51555
+ };
51556
+ }
51557
+ }
51087
51558
  } else {
51088
51559
  if (name !== void 0) {
51089
51560
  process.stderr.write(
@@ -51112,10 +51583,10 @@ async function runNexusLogin(args, openBrowser2) {
51112
51583
  }
51113
51584
  }
51114
51585
  function nexusLoginSummary(r) {
51115
- const who = r.user?.email ?? "your account";
51586
+ const who2 = r.user?.email ?? "your account";
51116
51587
  const org = r.organization ? ` (${r.organization.name})` : "";
51117
51588
  const device = r.device ? ` This machine is device ${r.device.deviceId}${r.device.name ? ` (${r.device.name})` : ""}, profile ${r.device.profile ?? "unknown"}.` : "";
51118
- return `Signed in to ${r.apiUrl} as ${who}${org}.${device}`;
51589
+ return `Signed in to ${r.apiUrl} as ${who2}${org}.${device}`;
51119
51590
  }
51120
51591
  function nexusDeviceLogoutSummary(r) {
51121
51592
  const count = (o) => r.devices.filter((d) => d.outcome === o).length;
@@ -51152,10 +51623,11 @@ async function runNexusDeviceLogout(args) {
51152
51623
  `);
51153
51624
  emitNexusResult(result, nexusDeviceLogoutSummary(result), "logout", "logout.run");
51154
51625
  }
51155
- var SERVICE_NAME, NEXUS_API_URL_ARG;
51626
+ var SERVICE_NAME, NEXUS_API_URL_ARG, VAULT_REFUSAL_EXIT_CODES;
51156
51627
  var init_nexus_account_cli = __esm({
51157
51628
  "packages/cleo/src/cli/lib/nexus-account-cli.ts"() {
51158
51629
  "use strict";
51630
+ init_src2();
51159
51631
  init_renderers();
51160
51632
  init_device_code_prompt();
51161
51633
  init_negated_flag();
@@ -51164,6 +51636,14 @@ var init_nexus_account_cli = __esm({
51164
51636
  type: "string",
51165
51637
  description: "Cleo Nexus API URL (default: $CLEO_NEXUS_API_URL, else https://api.cleocode.dev; staging: https://api.staging.cleocode.dev)."
51166
51638
  };
51639
+ VAULT_REFUSAL_EXIT_CODES = {
51640
+ E_NEXUS_VAULT_LEASE_HELD: 7 /* LOCK_TIMEOUT */,
51641
+ E_NEXUS_VAULT_STORE_BUSY: 7 /* LOCK_TIMEOUT */,
51642
+ E_NEXUS_VAULT_BEHIND: 23 /* VERSION_CONFLICT */,
51643
+ E_NEXUS_VAULT_LOCAL_CHANGES: 21 /* CONCURRENT_MODIFICATION */,
51644
+ E_NEXUS_VAULT_VERIFY_FAILED: 20 /* CHECKSUM_MISMATCH */,
51645
+ E_NEXUS_VAULT_TARGET_OCCUPIED: 22 /* ID_COLLISION */
51646
+ };
51167
51647
  }
51168
51648
  });
51169
51649
 
@@ -53351,14 +53831,14 @@ var init_backup = __esm({
53351
53831
  return;
53352
53832
  }
53353
53833
  const { exportPortableBundle, PortableBundleError } = await import("@cleocode/core/store/portable-bundle.js");
53354
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
53834
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
53355
53835
  const passphrase = args.encrypt === true ? await resolvePassphrase() : void 0;
53356
53836
  if (args.encrypt === true && passphrase === void 0) return;
53357
53837
  const encSuffix = args.encrypt === true ? "enc." : "";
53358
53838
  try {
53359
53839
  const result = await exportPortableBundle({
53360
53840
  scope,
53361
- projectRoot: scope === "project" || scope === "all" ? getProjectRoot75() : void 0,
53841
+ projectRoot: scope === "project" || scope === "all" ? getProjectRoot76() : void 0,
53362
53842
  outputPath: args.out ?? `./${args.name}.${encSuffix}cleobundle.tar.gz`,
53363
53843
  encrypt: args.encrypt === true,
53364
53844
  passphrase,
@@ -53415,12 +53895,12 @@ var init_backup = __esm({
53415
53895
  );
53416
53896
  return;
53417
53897
  }
53418
- const { getProjectRoot: getProjectRoot75, getCleoHome: getCleoHome8, getCleoVersion } = await import("@cleocode/core");
53898
+ const { getProjectRoot: getProjectRoot76, getCleoHome: getCleoHome8, getCleoVersion } = await import("@cleocode/core");
53419
53899
  const { BundleError, cleanupStaging, unpackBundle } = await import("@cleocode/core/store/backup-unpack.js");
53420
53900
  const { regenerateConfigJson, regenerateProjectContextJson, regenerateProjectInfoJson } = await import("@cleocode/core/store/regenerators.js");
53421
53901
  const { regenerateAndCompare } = await import("@cleocode/core/store/restore-json-merge.js");
53422
53902
  const { buildConflictReport, writeConflictReport } = await import("@cleocode/core/store/restore-conflict-report.js");
53423
- const projectRoot = getProjectRoot75();
53903
+ const projectRoot = getProjectRoot76();
53424
53904
  const { assertOwnerStoreRewriteConfirmed } = await import("@cleocode/core/store/worktree-isolation-guard.js");
53425
53905
  try {
53426
53906
  assertOwnerStoreRewriteConfirmed("backup import", path2.join(projectRoot, ".cleo"), {
@@ -55313,7 +55793,7 @@ var init_check3 = __esm({
55313
55793
  async run({ args }) {
55314
55794
  const { spawnSync: spawnSync2 } = await import("node:child_process");
55315
55795
  const { existsSync: existsSync22 } = await import("node:fs");
55316
- const { join: join40, resolve: resolve13 } = await import("node:path");
55796
+ const { join: join41, resolve: resolve13 } = await import("node:path");
55317
55797
  const strict = Boolean(args.strict);
55318
55798
  const jsonOnly = Boolean(args.json);
55319
55799
  const repoRoot = resolve13(process.cwd());
@@ -55621,13 +56101,48 @@ var init_check3 = __esm({
55621
56101
  task: "T12663",
55622
56102
  script: "scripts/lint-model-call-sites.mjs",
55623
56103
  description: "Every model call site is a registered decision site (ratchet)"
56104
+ },
56105
+ {
56106
+ // T12819 / T12827 (journal spec §2.3a, §3.5 Rule 4): nothing drops
56107
+ // cleo_trigger_suspend; only dropSyncMachinery drops _sync_* tables;
56108
+ // migrations never mention capture triggers; forward-only migration
56109
+ // rules (owned triggers carry the suspension clause, deterministic
56110
+ // DML, no parent DELETE in a rebuild file); released migration files
56111
+ // are byte-identical to the base ref (#1719).
56112
+ id: "gate-36",
56113
+ task: "T12819",
56114
+ script: "scripts/lint-sync-schema.mjs",
56115
+ description: "Change-journal schema rules (suspend table, migrations)"
56116
+ },
56117
+ {
56118
+ // T12897: every syncing cleo.db table is declared in ROW_IDENTITY or
56119
+ // exempt with a reason and a task in ROW_IDENTITY_EXEMPT; a stale
56120
+ // exemption (table gone, no longer syncing, or declared) fails too.
56121
+ // The fresh-store check is store/__tests__/row-identity-gate.test.ts.
56122
+ id: "gate-37",
56123
+ task: "T12897",
56124
+ script: "scripts/lint-row-identity-coverage.mjs",
56125
+ description: "Every syncing cleo.db table has declared row identity or an exemption"
56126
+ },
56127
+ {
56128
+ // T12881: the raw sync applier never runs TypeScript write paths, so
56129
+ // every rejection site on a synced write path is tagged
56130
+ // `// @sync-invariant <id>` (contracts sync-write-invariants
56131
+ // registry) or an escape with a reason. Untagged sites are baselined
56132
+ // per (file, symbol, code); the baseline only shrinks. Registry
56133
+ // closure: tables classified, triggers created by migrations, no
56134
+ // dead gates (spec t12859 §3.6.7).
56135
+ id: "gate-38",
56136
+ task: "T12881",
56137
+ script: "scripts/lint-sync-write-invariants.mjs",
56138
+ description: "Every synced-write rejection site is classified (ratchet)"
55624
56139
  }
55625
56140
  ];
55626
56141
  const scriptArgs = strict ? ["--strict"] : ["--check"];
55627
56142
  const results = [];
55628
56143
  let anyFailed = false;
55629
56144
  for (const gate of gates) {
55630
- const scriptPath = join40(repoRoot, gate.script);
56145
+ const scriptPath = join41(repoRoot, gate.script);
55631
56146
  if (!existsSync22(scriptPath)) {
55632
56147
  results.push({
55633
56148
  id: gate.id,
@@ -56214,12 +56729,163 @@ var init_nexus_cloud_cli = __esm({
56214
56729
  }
56215
56730
  });
56216
56731
 
56732
+ // packages/cleo/src/cli/lib/nexus-vault-cli.ts
56733
+ function scopeArg(args, operation) {
56734
+ const raw = stringArg(args, "scope") ?? "project";
56735
+ if (raw === "project" || raw === "global") return raw;
56736
+ failNexus(
56737
+ Object.assign(new Error(`unknown scope '${raw}'`), {
56738
+ code: "E_VALIDATION",
56739
+ fix: "use --scope project (default) or --scope global"
56740
+ }),
56741
+ operation
56742
+ );
56743
+ }
56744
+ function common2(args, operation) {
56745
+ return { apiUrl: nexusApiUrlArg(args), scope: scopeArg(args, operation) };
56746
+ }
56747
+ function activityLimitArg(args) {
56748
+ const raw = stringArg(args, "limit");
56749
+ if (raw === void 0) return void 0;
56750
+ const limit = Number(raw);
56751
+ if (/^\d+$/.test(raw) && Number.isSafeInteger(limit) && limit >= 1 && limit <= 200) return limit;
56752
+ throw Object.assign(new Error(`--limit must be a whole number from 1 to 200, got '${raw}'`), {
56753
+ code: "E_VALIDATION",
56754
+ fix: "pass --limit 1..200 (default 50)"
56755
+ });
56756
+ }
56757
+ async function runCloudPush(args) {
56758
+ await runCloudRead(
56759
+ "cloud.push",
56760
+ async () => (await vaultModule()).pushNexusVault({
56761
+ ...common2(args, "cloud.push"),
56762
+ force: args["force"] === true,
56763
+ hold: args["hold"] === true
56764
+ }),
56765
+ (r) => r.status === "up-to-date" ? `Up to date: ${r.streamId} already holds this ${r.scope} store (snapshot ${r.snapshot?.checkpointId ?? "none"}).` : `Pushed ${r.scope} snapshot ${r.snapshot?.checkpointId} to ${r.streamId} (${r.snapshot?.rows ?? 0} rows${r.parentCheckpointId ? `, parent ${r.parentCheckpointId}` : ", first snapshot"}${r.forked ? ", FORK: lease taken by force" : ""}).`
56766
+ );
56767
+ }
56768
+ async function runCloudPull(args) {
56769
+ await runCloudRestoreLike(args, "cloud.pull", "pull");
56770
+ }
56771
+ async function runCloudRestore(args) {
56772
+ await runCloudRestoreLike(args, "cloud.restore", "restore");
56773
+ }
56774
+ async function runCloudRestoreLike(args, operation, mode) {
56775
+ await runCloudRead(
56776
+ operation,
56777
+ async () => {
56778
+ const checkpointId = stringArg(args, "checkpoint");
56779
+ const projectId = stringArg(args, "project");
56780
+ const into = stringArg(args, "into");
56781
+ return (await vaultModule()).restoreNexusVault({
56782
+ ...common2(args, operation),
56783
+ mode,
56784
+ force: args["force"] === true,
56785
+ ...mode === "restore" && checkpointId !== void 0 ? { checkpointId } : {},
56786
+ ...mode === "restore" && projectId !== void 0 ? { projectId } : {},
56787
+ ...mode === "restore" && into !== void 0 ? { into } : {},
56788
+ relink: async (projectRoot) => {
56789
+ const { linkProjectToNexus } = await import(
56790
+ /* webpackIgnore: true */
56791
+ "@cleocode/core/cloud/nexus-link.js"
56792
+ );
56793
+ try {
56794
+ const linked = await linkProjectToNexus({ apiUrl: nexusApiUrlArg(args), projectRoot });
56795
+ return linked.warnings;
56796
+ } catch (err) {
56797
+ return [
56798
+ `restored, but attaching this copy failed (${err instanceof Error ? err.message : String(err)}); run \`cleo project link\``
56799
+ ];
56800
+ }
56801
+ }
56802
+ });
56803
+ },
56804
+ (r) => r.status === "up-to-date" ? `Up to date: this ${r.scope} store already holds snapshot ${r.snapshot?.checkpointId ?? "none"}.` : `Restored ${r.scope} snapshot ${r.snapshot?.checkpointId} into ${r.target}: ${r.tables} table(s) verified by count and hash${r.safetyBackup ? `; previous state saved to ${r.safetyBackup}` : ""}.`
56805
+ );
56806
+ }
56807
+ async function runCloudVerify(args) {
56808
+ await runCloudRead(
56809
+ "cloud.verify",
56810
+ async () => (await vaultModule()).verifyNexusVault(common2(args, "cloud.verify")),
56811
+ (r) => {
56812
+ const bad = r.tables.filter((t) => !t.match).map((t) => t.table);
56813
+ const devices = r.devices.map(
56814
+ (d) => `${who(d.deviceName, d.deviceId)} ${d.matchesHead ? "matches" : "differs from"} head`
56815
+ ).join("; ");
56816
+ return `Verify ${r.scope}: ${r.verdict}${bad.length ? ` (${bad.length} table(s) differ: ${bad.slice(0, 8).join(", ")}${bad.length > 8 ? ", \u2026" : ""})` : ""}; local integrity ${r.localIntegrity ? "ok" : "FAILED"}${devices ? `; ${devices}` : ""}.`;
56817
+ }
56818
+ );
56819
+ }
56820
+ async function runCloudVault(args) {
56821
+ await runCloudRead(
56822
+ "cloud.vault",
56823
+ async () => (await vaultModule()).nexusVaultStatus(common2(args, "cloud.vault")),
56824
+ (r) => `Vault ${r.scope} ${r.streamId}: ${r.lineage.length} snapshot(s), head ${r.head?.checkpointId ?? "none"}${r.head ? ` by ${who(r.head.deviceName, r.head.deviceId)}` : ""}; this store last synced ${r.lastSynced ?? "never"}; ${r.pendingChanges.length} table(s) changed since; leases: ${r.leases.map((l) => `${l.role} ${who(l.deviceName, l.deviceId ?? l.replicaId)} until ${l.expiresAt}${l.mine ? " (this machine)" : ""}${l.forkedFromReplicaId ? " (forked)" : ""}`).join("; ") || "none"}.`
56825
+ );
56826
+ }
56827
+ async function runCloudLease(args) {
56828
+ const action = stringArg(args, "action") ?? "release";
56829
+ if (action !== "release") {
56830
+ failNexus(
56831
+ Object.assign(new Error(`unknown action '${action}'`), {
56832
+ code: "E_VALIDATION",
56833
+ fix: "use `cleo cloud lease release` (see `cleo cloud vault` for holders)"
56834
+ }),
56835
+ "cloud.lease.release"
56836
+ );
56837
+ }
56838
+ await runCloudRead(
56839
+ "cloud.lease.release",
56840
+ async () => (await vaultModule()).releaseNexusVaultLease(common2(args, "cloud.lease.release")),
56841
+ (r) => r.released ? `Released the write lease on ${r.streamId}: another device may push now.` : `This machine held no write lease on ${r.streamId}.`
56842
+ );
56843
+ }
56844
+ async function runCloudActivity(args) {
56845
+ await runCloudRead(
56846
+ "cloud.activity",
56847
+ async () => {
56848
+ const { nexusCloudActivity } = await import(
56849
+ /* webpackIgnore: true */
56850
+ "@cleocode/core/cloud/nexus-cloud-activity.js"
56851
+ );
56852
+ const limit = activityLimitArg(args);
56853
+ const before = stringArg(args, "before");
56854
+ const projectId = stringArg(args, "project");
56855
+ const deviceId = stringArg(args, "device");
56856
+ return nexusCloudActivity({
56857
+ ...deviceId !== void 0 ? { deviceId } : {},
56858
+ apiUrl: nexusApiUrlArg(args),
56859
+ ...limit !== void 0 ? { limit } : {},
56860
+ ...before !== void 0 ? { before } : {},
56861
+ ...projectId !== void 0 ? { projectId } : {}
56862
+ });
56863
+ },
56864
+ (r) => `${r.items.length} event(s)${r.projectId ? ` for project ${r.projectId}` : ""}: ${r.items.slice(0, 10).map(
56865
+ (i) => `${i.at} ${who(i.deviceName, i.deviceId ?? "account")}${i.thisDevice ? " (this machine)" : ""} ${i.action}${i.target ? ` ${i.target}` : ""}`
56866
+ ).join("; ")}${r.items.length > 10 ? "; \u2026" : ""}`
56867
+ );
56868
+ }
56869
+ var vaultModule, who;
56870
+ var init_nexus_vault_cli = __esm({
56871
+ "packages/cleo/src/cli/lib/nexus-vault-cli.ts"() {
56872
+ "use strict";
56873
+ init_nexus_account_cli();
56874
+ init_nexus_cloud_cli();
56875
+ vaultModule = () => import(
56876
+ /* webpackIgnore: true */
56877
+ "@cleocode/core/cloud/nexus-vault.js"
56878
+ );
56879
+ who = (name, id) => name ?? id;
56880
+ }
56881
+ });
56882
+
56217
56883
  // packages/cleo/src/cli/commands/cloud.ts
56218
56884
  var cloud_exports = {};
56219
56885
  __export(cloud_exports, {
56220
56886
  cloudCommand: () => cloudCommand
56221
56887
  });
56222
- var JSON_ARG, statusSubCommand, whoamiSubCommand, devicesSubCommand, projectsSubCommand, cloudCommand;
56888
+ var JSON_ARG, SCOPE_ARG, statusSubCommand, whoamiSubCommand, devicesSubCommand, projectsSubCommand, pushSubCommand, pullSubCommand, restoreSubCommand, verifyVaultSubCommand, vaultSubCommand, leaseSubCommand, activitySubCommand, cloudCommand;
56223
56889
  var init_cloud = __esm({
56224
56890
  "packages/cleo/src/cli/commands/cloud.ts"() {
56225
56891
  "use strict";
@@ -56227,7 +56893,12 @@ var init_cloud = __esm({
56227
56893
  init_define_cli_command();
56228
56894
  init_nexus_account_cli();
56229
56895
  init_nexus_cloud_cli();
56896
+ init_nexus_vault_cli();
56230
56897
  JSON_ARG = { type: "boolean", description: "Output as JSON envelope" };
56898
+ SCOPE_ARG = {
56899
+ type: "string",
56900
+ description: "Which store: 'project' (the current project, default) or 'global' (this account's global store: the main brain)."
56901
+ };
56231
56902
  statusSubCommand = defineCommand({
56232
56903
  meta: {
56233
56904
  name: "status",
@@ -56296,16 +56967,139 @@ var init_cloud = __esm({
56296
56967
  await runCloudProjects(args);
56297
56968
  }
56298
56969
  });
56970
+ pushSubCommand = defineCommand({
56971
+ meta: {
56972
+ name: "push",
56973
+ description: "Back up this store to Cleo Nexus as an encrypted snapshot; the key is escrowed on Cleo Nexus (released only to your approved devices), so this is encrypted at rest, not zero-knowledge. The server also stores per-table row counts and keyed hashes in plaintext. Refused when another device holds the write lease or pushed since this machine last synced (pull first); --force takes the lease and pushes anyway as a labelled fork. The lease is released when the push ends unless --hold."
56974
+ },
56975
+ args: {
56976
+ scope: SCOPE_ARG,
56977
+ force: {
56978
+ type: "boolean",
56979
+ description: "Take the lease from another device / push over a newer snapshot (a labelled fork)."
56980
+ },
56981
+ hold: {
56982
+ type: "boolean",
56983
+ description: "Keep the write lease after the push (another device cannot push until it expires or `cleo cloud lease release`)."
56984
+ },
56985
+ "api-url": NEXUS_API_URL_ARG,
56986
+ json: JSON_ARG
56987
+ },
56988
+ async run({ args }) {
56989
+ await runCloudPush(args);
56990
+ }
56991
+ });
56992
+ pullSubCommand = defineCommand({
56993
+ meta: {
56994
+ name: "pull",
56995
+ description: "Bring this store to the cloud's newest snapshot, verified by per-table count and hash before anything is replaced; this machine's local-only state is kept. Refuses to overwrite local changes made since the last sync unless --force (a safety backup is taken first)."
56996
+ },
56997
+ args: {
56998
+ scope: SCOPE_ARG,
56999
+ force: { type: "boolean", description: "Overwrite local changes (after a safety backup)." },
57000
+ "api-url": NEXUS_API_URL_ARG,
57001
+ json: JSON_ARG
57002
+ },
57003
+ async run({ args }) {
57004
+ await runCloudPull(args);
57005
+ }
57006
+ });
57007
+ restoreSubCommand = defineCommand({
57008
+ meta: {
57009
+ name: "restore",
57010
+ description: "Restore a snapshot: the newest, or --checkpoint <id> (point in time); or a project this machine does not have yet with --project <id> [--into <dir>] (then it is linked to this device). Verified by count and hash before activation; a safety backup of existing data is taken first."
57011
+ },
57012
+ args: {
57013
+ scope: SCOPE_ARG,
57014
+ checkpoint: { type: "string", description: "Snapshot id to restore (see `cleo cloud vault`)." },
57015
+ project: {
57016
+ type: "string",
57017
+ description: "Server project id to restore onto this machine (see `cleo cloud projects`)."
57018
+ },
57019
+ into: {
57020
+ type: "string",
57021
+ description: "Directory for --project (default: the current directory)."
57022
+ },
57023
+ force: { type: "boolean", description: "Overwrite local changes (after a safety backup)." },
57024
+ "api-url": NEXUS_API_URL_ARG,
57025
+ json: JSON_ARG
57026
+ },
57027
+ async run({ args }) {
57028
+ await runCloudRestore(args);
57029
+ }
57030
+ });
57031
+ verifyVaultSubCommand = defineCommand({
57032
+ meta: {
57033
+ name: "verify",
57034
+ description: "Integrity check across machines: SQLite integrity of this store, its per-table counts and keyed hashes against the cloud's newest snapshot, and every device's newest snapshot against it. Verdict: match, ahead, behind, diverged, empty, or untrusted (the newest snapshot's signature does not verify)."
57035
+ },
57036
+ args: { scope: SCOPE_ARG, "api-url": NEXUS_API_URL_ARG, json: JSON_ARG },
57037
+ async run({ args }) {
57038
+ await runCloudVerify(args);
57039
+ }
57040
+ });
57041
+ vaultSubCommand = defineCommand({
57042
+ meta: {
57043
+ name: "vault",
57044
+ description: "The store's cloud vault: snapshot lineage (newest first), the last push of each device, tables changed since this machine's last sync, and who holds the write lease until when."
57045
+ },
57046
+ args: { scope: SCOPE_ARG, "api-url": NEXUS_API_URL_ARG, json: JSON_ARG },
57047
+ async run({ args }) {
57048
+ await runCloudVault(args);
57049
+ }
57050
+ });
57051
+ leaseSubCommand = defineCommand({
57052
+ meta: {
57053
+ name: "lease",
57054
+ description: "Hand the write lease back so another device can push: cleo cloud lease release."
57055
+ },
57056
+ args: {
57057
+ action: { type: "positional", description: "'release'.", required: false },
57058
+ scope: SCOPE_ARG,
57059
+ "api-url": NEXUS_API_URL_ARG,
57060
+ json: JSON_ARG
57061
+ },
57062
+ async run({ args }) {
57063
+ await runCloudLease(args);
57064
+ }
57065
+ });
57066
+ activitySubCommand = defineCommand({
57067
+ meta: {
57068
+ name: "activity",
57069
+ description: "What this account's devices did on Cleo Nexus and when (snapshots pushed or refused, leases taken, forced or released, projects linked, devices enrolled), newest first."
57070
+ },
57071
+ args: {
57072
+ limit: { type: "string", description: "Events to show (1-200, default 50)." },
57073
+ before: { type: "string", description: "Older page: the nextBefore of a previous call." },
57074
+ project: { type: "string", description: "Only events about this server project id." },
57075
+ device: {
57076
+ type: "string",
57077
+ description: "Only events by this device id (see `cleo cloud devices`)."
57078
+ },
57079
+ "api-url": NEXUS_API_URL_ARG,
57080
+ json: JSON_ARG
57081
+ },
57082
+ async run({ args }) {
57083
+ await runCloudActivity(args);
57084
+ }
57085
+ });
56299
57086
  cloudCommand = defineCommand({
56300
57087
  meta: {
56301
57088
  name: "cloud",
56302
- description: "Cleo Nexus reads with the device credential (GET only; getting the credential may upgrade a 9.24 session or retry unsettled logouts): status (one-call verification), whoami, devices, projects [show]."
57089
+ description: "Cleo Nexus with the device credential: status (one-call verification), whoami, devices, projects [show], activity; the encrypted vault: push, pull, restore, verify, vault, lease release."
56303
57090
  },
56304
57091
  subCommands: {
56305
57092
  status: statusSubCommand,
56306
57093
  whoami: whoamiSubCommand,
56307
57094
  devices: devicesSubCommand,
56308
- projects: projectsSubCommand
57095
+ projects: projectsSubCommand,
57096
+ activity: activitySubCommand,
57097
+ push: pushSubCommand,
57098
+ pull: pullSubCommand,
57099
+ restore: restoreSubCommand,
57100
+ verify: verifyVaultSubCommand,
57101
+ vault: vaultSubCommand,
57102
+ lease: leaseSubCommand
56309
57103
  }
56310
57104
  });
56311
57105
  }
@@ -56358,9 +57152,9 @@ var init_code = __esm({
56358
57152
  async run({ args }) {
56359
57153
  await requireTreeSitter();
56360
57154
  const { smartOutline } = await import("@cleocode/core/internal");
56361
- const { join: join40 } = await import("node:path");
57155
+ const { join: join41 } = await import("node:path");
56362
57156
  const root = process.cwd();
56363
- const absPath = args.file.startsWith("/") ? args.file : join40(root, args.file);
57157
+ const absPath = args.file.startsWith("/") ? args.file : join41(root, args.file);
56364
57158
  const result = smartOutline(absPath, root);
56365
57159
  if (result.errors.length > 0 && result.symbols.length === 0) {
56366
57160
  cliError(result.errors.join(", "), 1, { name: "E_OUTLINE_FAILED" });
@@ -56451,9 +57245,9 @@ var init_code = __esm({
56451
57245
  async run({ args }) {
56452
57246
  await requireTreeSitter();
56453
57247
  const { smartUnfold } = await import("@cleocode/core/internal");
56454
- const { join: join40 } = await import("node:path");
57248
+ const { join: join41 } = await import("node:path");
56455
57249
  const root = process.cwd();
56456
- const absPath = args.file.startsWith("/") ? args.file : join40(root, args.file);
57250
+ const absPath = args.file.startsWith("/") ? args.file : join41(root, args.file);
56457
57251
  const result = smartUnfold(absPath, args.symbol, root);
56458
57252
  if (!result.found) {
56459
57253
  const errs = result.errors.length > 0 ? `: ${result.errors.join(", ")}` : "";
@@ -64442,15 +65236,15 @@ var init_doctor_fk_check = __esm({
64442
65236
  }
64443
65237
  },
64444
65238
  async run({ args }) {
64445
- const scopeArg = args.scope;
64446
- if (scopeArg !== void 0 && scopeArg !== "project" && scopeArg !== "global") {
64447
- cliError(`--scope must be 'project' or 'global' (received: ${scopeArg})`, "E_INVALID_INPUT", {
65239
+ const scopeArg2 = args.scope;
65240
+ if (scopeArg2 !== void 0 && scopeArg2 !== "project" && scopeArg2 !== "global") {
65241
+ cliError(`--scope must be 'project' or 'global' (received: ${scopeArg2})`, "E_INVALID_INPUT", {
64448
65242
  fix: "Run 'cleo doctor fk-check --scope project' or omit --scope to check both."
64449
65243
  });
64450
65244
  process.exitCode = 6;
64451
65245
  return;
64452
65246
  }
64453
- const scopeOpt = scopeArg ? { scopes: [scopeArg] } : {};
65247
+ const scopeOpt = scopeArg2 ? { scopes: [scopeArg2] } : {};
64454
65248
  if (args.fix === true) {
64455
65249
  const fixReport = await repairForeignKeyViolations({ cwd: process.cwd(), ...scopeOpt });
64456
65250
  humanInfo(
@@ -64867,12 +65661,44 @@ var init_doctor_memory_guard = __esm({
64867
65661
  }
64868
65662
  });
64869
65663
 
65664
+ // packages/cleo/src/cli/commands/doctor-migrations.ts
65665
+ var doctor_migrations_exports = {};
65666
+ __export(doctor_migrations_exports, {
65667
+ doctorMigrationsCommand: () => doctorMigrationsCommand
65668
+ });
65669
+ import { getProjectRoot as getProjectRoot49 } from "@cleocode/core";
65670
+ import { inspectMigrations } from "@cleocode/core/doctor/migrations.js";
65671
+ var doctorMigrationsCommand;
65672
+ var init_doctor_migrations = __esm({
65673
+ "packages/cleo/src/cli/commands/doctor-migrations.ts"() {
65674
+ "use strict";
65675
+ init_define_cli_command();
65676
+ init_renderers();
65677
+ doctorMigrationsCommand = defineCommand({
65678
+ meta: {
65679
+ name: "migrations",
65680
+ description: "Report the migration journal of the project and global stores: row count, head, applied and pending files per lineage, and hash drift. Read-only."
65681
+ },
65682
+ args: {
65683
+ json: { type: "boolean", description: "Output as JSON" },
65684
+ human: { type: "boolean", description: "Force human-readable output" },
65685
+ quiet: { type: "boolean", description: "Suppress non-essential output" }
65686
+ },
65687
+ async run() {
65688
+ const report = inspectMigrations(getProjectRoot49());
65689
+ cliOutput(report, { command: "doctor", operation: "doctor.migrations.run" });
65690
+ if (report.scopes.some((s) => s.drift.length > 0)) process.exitCode = 1;
65691
+ }
65692
+ });
65693
+ }
65694
+ });
65695
+
64870
65696
  // packages/cleo/src/cli/commands/doctor-nexus-residency.ts
64871
65697
  var doctor_nexus_residency_exports = {};
64872
65698
  __export(doctor_nexus_residency_exports, {
64873
65699
  doctorNexusResidencyCommand: () => doctorNexusResidencyCommand
64874
65700
  });
64875
- import { getCleoHome as getCleoHome6, getProjectRoot as getProjectRoot49 } from "@cleocode/core";
65701
+ import { getCleoHome as getCleoHome6, getProjectRoot as getProjectRoot50 } from "@cleocode/core";
64876
65702
  import { scanNexusSchemaResidency } from "@cleocode/core/doctor/nexus-schema-residency.js";
64877
65703
  var doctorNexusResidencyCommand;
64878
65704
  var init_doctor_nexus_residency = __esm({
@@ -64891,7 +65717,7 @@ var init_doctor_nexus_residency = __esm({
64891
65717
  quiet: { type: "boolean", description: "Suppress non-essential output" }
64892
65718
  },
64893
65719
  async run() {
64894
- const result = scanNexusSchemaResidency(getProjectRoot49(), getCleoHome6());
65720
+ const result = scanNexusSchemaResidency(getProjectRoot50(), getCleoHome6());
64895
65721
  cliOutput(result, {
64896
65722
  command: "doctor",
64897
65723
  operation: "doctor.nexus-residency.run"
@@ -64909,7 +65735,7 @@ var doctor_project_identity_exports = {};
64909
65735
  __export(doctor_project_identity_exports, {
64910
65736
  doctorProjectIdentityCommand: () => doctorProjectIdentityCommand
64911
65737
  });
64912
- import { getProjectRoot as getProjectRoot50 } from "@cleocode/core";
65738
+ import { getProjectRoot as getProjectRoot51 } from "@cleocode/core";
64913
65739
  import {
64914
65740
  inspectProjectIdentity,
64915
65741
  inspectProjectNameDrift,
@@ -64934,7 +65760,7 @@ var init_doctor_project_identity = __esm({
64934
65760
  quiet: { type: "boolean", description: "Suppress non-essential output" }
64935
65761
  },
64936
65762
  async run({ args }) {
64937
- const projectRoot = getProjectRoot50();
65763
+ const projectRoot = getProjectRoot51();
64938
65764
  if (!args.resolve) {
64939
65765
  const report = inspectProjectIdentity(projectRoot);
64940
65766
  const nameDrift = await inspectProjectNameDrift(projectRoot);
@@ -65473,7 +66299,7 @@ var doctor_repair_exports = {};
65473
66299
  __export(doctor_repair_exports, {
65474
66300
  doctorRepairCommand: () => doctorRepairCommand
65475
66301
  });
65476
- import { getLogger as getLogger21, getProjectRoot as getProjectRoot51 } from "@cleocode/core";
66302
+ import { getLogger as getLogger21, getProjectRoot as getProjectRoot52 } from "@cleocode/core";
65477
66303
  import { repairMalformedDbs } from "@cleocode/core/store/repair-malformed-dbs.js";
65478
66304
  var doctorRepairCommand;
65479
66305
  var init_doctor_repair = __esm({
@@ -65522,7 +66348,7 @@ var init_doctor_repair = __esm({
65522
66348
  return;
65523
66349
  }
65524
66350
  const result = repairMalformedDbs({
65525
- projectRoot: getProjectRoot51(),
66351
+ projectRoot: getProjectRoot52(),
65526
66352
  roles: roleArg.length > 0 ? [roleArg] : void 0,
65527
66353
  dryRun,
65528
66354
  logger: getLogger21("doctor-repair"),
@@ -65724,7 +66550,7 @@ var doctor_superseded_store_exports = {};
65724
66550
  __export(doctor_superseded_store_exports, {
65725
66551
  doctorSupersededStoreCommand: () => doctorSupersededStoreCommand
65726
66552
  });
65727
- import { getProjectRoot as getProjectRoot52 } from "@cleocode/core";
66553
+ import { getProjectRoot as getProjectRoot53 } from "@cleocode/core";
65728
66554
  import { scanSupersededStores } from "@cleocode/core/doctor/superseded-store.js";
65729
66555
  import { reconcileSupersededStores } from "@cleocode/core/store/exodus/index.js";
65730
66556
  var doctorSupersededStoreCommand;
@@ -65757,7 +66583,7 @@ var init_doctor_superseded_store = __esm({
65757
66583
  },
65758
66584
  async run({ args }) {
65759
66585
  if (args.reconcile === true) {
65760
- const receipt = await reconcileSupersededStores(getProjectRoot52(), {
66586
+ const receipt = await reconcileSupersededStores(getProjectRoot53(), {
65761
66587
  dryRun: args["dry-run"] === true,
65762
66588
  additive: args.additive === true
65763
66589
  });
@@ -65779,7 +66605,7 @@ var init_doctor_superseded_store = __esm({
65779
66605
  );
65780
66606
  return;
65781
66607
  }
65782
- const result = scanSupersededStores(getProjectRoot52());
66608
+ const result = scanSupersededStores(getProjectRoot53());
65783
66609
  cliOutput(result, {
65784
66610
  command: "doctor",
65785
66611
  operation: "doctor.superseded-store.run"
@@ -65880,7 +66706,7 @@ import {
65880
66706
  rollbackTwinCollapse
65881
66707
  } from "@cleocode/core/doctor/twin-collapse.js";
65882
66708
  import { CleoError as CleoError8 } from "@cleocode/core/errors";
65883
- import { getProjectRoot as getProjectRoot53 } from "@cleocode/core/paths.js";
66709
+ import { getProjectRoot as getProjectRoot54 } from "@cleocode/core/paths.js";
65884
66710
  function reportTwinCollapseError(error, retry) {
65885
66711
  if (retry && !(error instanceof CleoError8)) throw error;
65886
66712
  const message = error instanceof Error ? error.message : String(error);
@@ -65951,7 +66777,7 @@ var init_doctor_twin_collapse = __esm({
65951
66777
  quiet: { type: "boolean", description: "Suppress non-essential output" }
65952
66778
  },
65953
66779
  async run({ args }) {
65954
- const projectRoot = getProjectRoot53();
66780
+ const projectRoot = getProjectRoot54();
65955
66781
  const guard = { cwd: process.cwd(), confirmOwnerStore: args["confirm-owner-store"] === true };
65956
66782
  const actions = twinCollapseActions(args);
65957
66783
  if (actions.length > 1) {
@@ -66029,7 +66855,7 @@ __export(doctor_worktree_stores_exports, {
66029
66855
  doctorWorktreeStoresCommand: () => doctorWorktreeStoresCommand
66030
66856
  });
66031
66857
  import { scanWorktreeStores } from "@cleocode/core/doctor/worktree-stores.js";
66032
- import { getProjectRoot as getProjectRoot54, resolveStoreOwnerRoot } from "@cleocode/core/paths.js";
66858
+ import { getProjectRoot as getProjectRoot55, resolveStoreOwnerRoot } from "@cleocode/core/paths.js";
66033
66859
  var doctorWorktreeStoresCommand;
66034
66860
  var init_doctor_worktree_stores = __esm({
66035
66861
  "packages/cleo/src/cli/commands/doctor-worktree-stores.ts"() {
@@ -66051,7 +66877,7 @@ var init_doctor_worktree_stores = __esm({
66051
66877
  quiet: { type: "boolean", description: "Suppress non-essential output" }
66052
66878
  },
66053
66879
  async run({ args }) {
66054
- const projectRoot = resolveStoreOwnerRoot(getProjectRoot54());
66880
+ const projectRoot = resolveStoreOwnerRoot(getProjectRoot55());
66055
66881
  const result = scanWorktreeStores(projectRoot, { skipCompare: args["skip-compare"] === true });
66056
66882
  cliOutput(result, {
66057
66883
  command: "doctor",
@@ -66203,7 +67029,7 @@ import {
66203
67029
  resumePreparedKnowledgeRepair,
66204
67030
  runKnowledgeDoctor as runKnowledgeDoctor2
66205
67031
  } from "@cleocode/core/doctor/knowledge.js";
66206
- import { getProjectRoot as getProjectRoot55 } from "@cleocode/core/paths.js";
67032
+ import { getProjectRoot as getProjectRoot56 } from "@cleocode/core/paths.js";
66207
67033
  var doctorKnowledgeSubcommand;
66208
67034
  var init_doctor_knowledge = __esm({
66209
67035
  "packages/cleo/src/cli/commands/doctor-knowledge.ts"() {
@@ -66278,7 +67104,7 @@ var init_doctor_knowledge = __esm({
66278
67104
  },
66279
67105
  async run({ args }) {
66280
67106
  const startedAt = Date.now();
66281
- const root = getProjectRoot55();
67107
+ const root = getProjectRoot56();
66282
67108
  let context;
66283
67109
  let pending;
66284
67110
  try {
@@ -66446,7 +67272,7 @@ import { join as join24 } from "node:path";
66446
67272
  import {
66447
67273
  ensureGlobalAgentRegistryDb,
66448
67274
  getGlobalAgentRegistryNativeDb,
66449
- getProjectRoot as getProjectRoot56,
67275
+ getProjectRoot as getProjectRoot57,
66450
67276
  installAgentFromCant
66451
67277
  } from "@cleocode/core/internal";
66452
67278
  function sha256Hex(bytes) {
@@ -66634,7 +67460,7 @@ var init_migrate_agents_v2 = __esm({
66634
67460
  }
66635
67461
  },
66636
67462
  async run({ args }) {
66637
- const projectRoot = getProjectRoot56();
67463
+ const projectRoot = getProjectRoot57();
66638
67464
  const verbose = args.quiet !== true;
66639
67465
  if (verbose) {
66640
67466
  humanInfo("Scanning .cleo/cant/agents/ and .cleo/agents/ for unregistered agents...");
@@ -66678,7 +67504,7 @@ __export(doctor_exports, {
66678
67504
  });
66679
67505
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
66680
67506
  import { join as join25 } from "node:path";
66681
- import { getProjectRoot as getProjectRoot57, pushWarning as pushWarning5 } from "@cleocode/core";
67507
+ import { getProjectRoot as getProjectRoot58, pushWarning as pushWarning5 } from "@cleocode/core";
66682
67508
  import { renderInvariantAuditLines } from "@cleocode/core/doctor/invariant-audit-render.js";
66683
67509
  import {
66684
67510
  quarantineRogueCleoDir,
@@ -66809,6 +67635,7 @@ var init_doctor = __esm({
66809
67635
  init_doctor_malformed_ids();
66810
67636
  init_doctor_manifest_rows();
66811
67637
  init_doctor_memory_guard();
67638
+ init_doctor_migrations();
66812
67639
  init_doctor_nexus_residency();
66813
67640
  init_doctor_project_identity();
66814
67641
  init_doctor_projects();
@@ -66841,6 +67668,8 @@ var init_doctor = __esm({
66841
67668
  "legacy-reaper": doctorLegacyReaperCommand,
66842
67669
  // T12128 — task ids that fail the write-path validator
66843
67670
  "malformed-ids": doctorMalformedIdsCommand,
67671
+ // T12796 — the migration journal of each store (read-only; the live journal count)
67672
+ migrations: doctorMigrationsCommand,
66844
67673
  // T12686 — manifest rows whose metadata violates the stored field contract (+ --repair/--rollback)
66845
67674
  "manifest-rows": doctorManifestRowsCommand,
66846
67675
  // T12095 — pre-dual-scope store files still on disk under their old LIVE names
@@ -67085,7 +67914,7 @@ var init_doctor = __esm({
67085
67914
  const { join: pathJoin } = await import("node:path");
67086
67915
  const { existsSync: existsSync22 } = await import("node:fs");
67087
67916
  const { detectAndHealCoreWorktreeLeak } = await import("@cleocode/worktree");
67088
- const projectRoot = getProjectRoot57();
67917
+ const projectRoot = getProjectRoot58();
67089
67918
  let gitRoot = projectRoot;
67090
67919
  try {
67091
67920
  gitRoot = execFile2("git", ["rev-parse", "--show-toplevel"], {
@@ -67137,7 +67966,7 @@ var init_doctor = __esm({
67137
67966
  }
67138
67967
  if (args.brain) {
67139
67968
  const { computeBrainHealthDashboard } = await import("@cleocode/core/memory/brain-health-dashboard.js");
67140
- const projectRoot = getProjectRoot57();
67969
+ const projectRoot = getProjectRoot58();
67141
67970
  const dashboard = await computeBrainHealthDashboard(projectRoot);
67142
67971
  cliOutput(dashboard, { command: "doctor", operation: "doctor.brain" });
67143
67972
  if (dashboard.hasP0Failure) {
@@ -67146,7 +67975,7 @@ var init_doctor = __esm({
67146
67975
  return;
67147
67976
  }
67148
67977
  if (args["scan-test-fixtures-in-prod"]) {
67149
- const projectRoot = getProjectRoot57();
67978
+ const projectRoot = getProjectRoot58();
67150
67979
  const matches = await scanTestFixturesInProd(projectRoot);
67151
67980
  const dryRun = args["dry-run"] !== false && args.quarantine !== true;
67152
67981
  const quarantined = !dryRun && matches.length > 0 ? await quarantineTestFixtures(projectRoot, matches) : void 0;
@@ -67234,7 +68063,7 @@ var init_doctor = __esm({
67234
68063
  progress.complete("Comprehensive diagnostics complete");
67235
68064
  } else if (args["scan-rogue-cleo-dirs"]) {
67236
68065
  progress.step(0, "Scanning for rogue .cleo/ directories");
67237
- const projectRoot = getProjectRoot57();
68066
+ const projectRoot = getProjectRoot58();
67238
68067
  const reports = scanRogueCleoDirs(projectRoot);
67239
68068
  progress.complete(
67240
68069
  `Found ${reports.length} rogue .cleo/ director${reports.length === 1 ? "y" : "ies"}`
@@ -67243,7 +68072,7 @@ var init_doctor = __esm({
67243
68072
  } else if (args["quarantine-rogue-cleo-dirs"]) {
67244
68073
  const isDryRun = args["dry-run"] === true;
67245
68074
  progress.step(0, `${isDryRun ? "[DRY RUN] " : ""}Scanning for rogue .cleo/ directories`);
67246
- const projectRoot = getProjectRoot57();
68075
+ const projectRoot = getProjectRoot58();
67247
68076
  const reports = scanRogueCleoDirs(projectRoot);
67248
68077
  if (reports.length === 0) {
67249
68078
  progress.complete("No rogue .cleo/ directories found \u2014 nothing to quarantine");
@@ -67297,7 +68126,7 @@ var init_doctor = __esm({
67297
68126
  const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/store/cleanup-legacy.js");
67298
68127
  const { getCleoHome: getCleoHome8 } = await import("@cleocode/core");
67299
68128
  const cleoHome = getCleoHome8();
67300
- const projectRoot = getProjectRoot57();
68129
+ const projectRoot = getProjectRoot58();
67301
68130
  const legacyResult = detectAndRemoveLegacyGlobalFiles(cleoHome);
67302
68131
  const strayResult = detectAndRemoveStrayProjectNexus(projectRoot);
67303
68132
  const isDryRun = args["dry-run"] === true;
@@ -67330,7 +68159,7 @@ var init_doctor = __esm({
67330
68159
  } else if (args["audit-worktree-orphans"]) {
67331
68160
  progress.step(0, "Comprehensive worktree anomaly audit (T9808 / council D009)");
67332
68161
  const { auditWorktreeOrphansComprehensive, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
67333
- const projectRoot = getProjectRoot57();
68162
+ const projectRoot = getProjectRoot58();
67334
68163
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
67335
68164
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
67336
68165
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -67387,7 +68216,7 @@ var init_doctor = __esm({
67387
68216
  `${isDryRun ? "[DRY RUN] " : ""}Scanning + pruning worktree-orphan .cleo/ directories`
67388
68217
  );
67389
68218
  const { pruneWorktreeOrphans, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
67390
- const projectRoot = getProjectRoot57();
68219
+ const projectRoot = getProjectRoot58();
67391
68220
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
67392
68221
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
67393
68222
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -67466,7 +68295,7 @@ var init_doctor = __esm({
67466
68295
  `${isDryRun ? "[DRY RUN] " : ""}Migrating .cleo/worktree-include \u2192 .worktreeinclude`
67467
68296
  );
67468
68297
  const { migrateWorktreeIncludeFile } = await import("@cleocode/core");
67469
- const projectRoot = getProjectRoot57();
68298
+ const projectRoot = getProjectRoot58();
67470
68299
  const result = await migrateWorktreeIncludeFile(projectRoot, { dryRun: isDryRun });
67471
68300
  progress.complete(`Migration ${result.action}`);
67472
68301
  cliOutput(result, { command: "doctor", operation: "doctor.migrate-worktree-include" });
@@ -67485,7 +68314,7 @@ var init_doctor = __esm({
67485
68314
  const stepLabel = isFocusedAlias ? "Auditing Saga hierarchy for ADR-073 invariants" : "Walking central INVARIANTS_REGISTRY";
67486
68315
  progress.step(0, stepLabel);
67487
68316
  const { auditInvariantRegistry } = await import("@cleocode/core/doctor/invariant-audit.js");
67488
- const projectRoot = getProjectRoot57();
68317
+ const projectRoot = getProjectRoot58();
67489
68318
  const result = await auditInvariantRegistry(projectRoot, { adrFilter });
67490
68319
  const operation = isFocusedAlias ? "doctor.audit-sagas" : "doctor.audit-invariants";
67491
68320
  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`;
@@ -67507,7 +68336,7 @@ var init_doctor = __esm({
67507
68336
  { command: "doctor", operation: "admin.health" }
67508
68337
  );
67509
68338
  try {
67510
- const projectRoot = getProjectRoot57();
68339
+ const projectRoot = getProjectRoot58();
67511
68340
  const conflicts = readMigrationConflicts(projectRoot);
67512
68341
  if (conflicts.length > 0) {
67513
68342
  progress.complete(
@@ -67538,7 +68367,7 @@ var init_doctor = __esm({
67538
68367
  progress.complete("Health check complete");
67539
68368
  }
67540
68369
  try {
67541
- const projectRoot = getProjectRoot57();
68370
+ const projectRoot = getProjectRoot58();
67542
68371
  const { auditSagaHierarchy } = await import("@cleocode/core/doctor/saga-audit.js");
67543
68372
  const sagaAudit = await auditSagaHierarchy(projectRoot);
67544
68373
  if (sagaAudit.sagas.length === 0) {
@@ -67567,7 +68396,7 @@ Saga Hierarchy: audit skipped (${msg})`);
67567
68396
  }
67568
68397
  try {
67569
68398
  const { scanDependencyCycles: scanDependencyCycles2 } = await import("@cleocode/core/doctor/dependency-cycles.js");
67570
- const cycles = await scanDependencyCycles2(getProjectRoot57());
68399
+ const cycles = await scanDependencyCycles2(getProjectRoot58());
67571
68400
  humanLine(
67572
68401
  `
67573
68402
  Dependency cycles: ${cycles.cycleCount} (${cycles.edgeCount} edge(s) checked)`
@@ -67678,14 +68507,14 @@ var init_done = __esm({
67678
68507
  process.exitCode = 2;
67679
68508
  return;
67680
68509
  }
67681
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/paths.js");
67682
- const options = { projectRoot: getProjectRoot75(), ...parsed.options };
68510
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/paths.js");
68511
+ const options = { projectRoot: getProjectRoot76(), ...parsed.options };
67683
68512
  const requested = [
67684
68513
  ...new Set([args.taskId, ...args._ ?? []].map(String))
67685
68514
  ];
67686
- const invalid = requested.filter((id) => !/^T\d+$/.test(id));
67687
- if (invalid.length > 0) {
67688
- cliError(`Not task ids: ${invalid.join(", ")} (expected T<digits>)`, "E_INVALID_INPUT");
68515
+ const invalid2 = requested.filter((id) => !/^T\d+$/.test(id));
68516
+ if (invalid2.length > 0) {
68517
+ cliError(`Not task ids: ${invalid2.join(", ")} (expected T<digits>)`, "E_INVALID_INPUT");
67689
68518
  process.exitCode = 2;
67690
68519
  return;
67691
68520
  }
@@ -67949,8 +68778,8 @@ var init_event = __esm({
67949
68778
  }
67950
68779
  for (const file of filesToTail) {
67951
68780
  const agentId = file.replace(".jsonl", "");
67952
- const { readFileSync: readFileSync22 } = await import("node:fs");
67953
- const content = readFileSync22(join26(eventsDir, file), "utf-8");
68781
+ const { readFileSync: readFileSync23 } = await import("node:fs");
68782
+ const content = readFileSync23(join26(eventsDir, file), "utf-8");
67954
68783
  const eventLines = content.trim().split("\n").filter(Boolean);
67955
68784
  const tail = eventLines.slice(-lines);
67956
68785
  if (jsonMode) {
@@ -68045,8 +68874,8 @@ var init_event = __esm({
68045
68874
  const printAgentLog = async (file) => {
68046
68875
  const agentId = file.replace(".jsonl", "");
68047
68876
  try {
68048
- const { readFileSync: readFileSync22 } = await import("node:fs");
68049
- const content = readFileSync22(join26(eventsDir, file), "utf-8");
68877
+ const { readFileSync: readFileSync23 } = await import("node:fs");
68878
+ const content = readFileSync23(join26(eventsDir, file), "utf-8");
68050
68879
  const eventLines = content.trim().split("\n").filter(Boolean);
68051
68880
  const tail = eventLines.slice(-lines);
68052
68881
  if (jsonMode) {
@@ -69041,7 +69870,7 @@ __export(gateway_exports, {
69041
69870
  gatewayOpenapiSubCommand: () => gatewayOpenapiSubCommand
69042
69871
  });
69043
69872
  import { resolve as resolve8 } from "node:path";
69044
- import { generateOpenApi, getProjectRoot as getProjectRoot58 } from "@cleocode/core";
69873
+ import { generateOpenApi, getProjectRoot as getProjectRoot59 } from "@cleocode/core";
69045
69874
  var gatewayOpenapiSubCommand, gatewayCommand;
69046
69875
  var init_gateway = __esm({
69047
69876
  "packages/cleo/src/cli/commands/gateway.ts"() {
@@ -69073,7 +69902,7 @@ var init_gateway = __esm({
69073
69902
  const pathCount = Object.keys(doc.paths).length;
69074
69903
  if (typeof args.out === "string" && args.out.length > 0) {
69075
69904
  const { writeFileSync: writeFileSync8 } = await import("node:fs");
69076
- const target = resolve8(getProjectRoot58(), args.out);
69905
+ const target = resolve8(getProjectRoot59(), args.out);
69077
69906
  writeFileSync8(target, json2, "utf8");
69078
69907
  cliOutput(
69079
69908
  { out: target, pathCount, version: doc.info.version, openapi: doc.openapi },
@@ -69534,7 +70363,7 @@ var go_exports = {};
69534
70363
  __export(go_exports, {
69535
70364
  goCommand: () => goCommand
69536
70365
  });
69537
- import { getProjectRoot as getProjectRoot59, go } from "@cleocode/core";
70366
+ import { getProjectRoot as getProjectRoot60, go } from "@cleocode/core";
69538
70367
  var goCommand;
69539
70368
  var init_go = __esm({
69540
70369
  "packages/cleo/src/cli/commands/go.ts"() {
@@ -69560,7 +70389,7 @@ var init_go = __esm({
69560
70389
  }
69561
70390
  },
69562
70391
  async run({ args }) {
69563
- const projectRoot = getProjectRoot59();
70392
+ const projectRoot = getProjectRoot60();
69564
70393
  const { getCurrentSessionId, resolveBoundSessionId } = await import("@cleocode/core/internal");
69565
70394
  let sessionId = getCurrentSessionId(projectRoot) ?? void 0;
69566
70395
  if (sessionId === void 0) {
@@ -69588,7 +70417,7 @@ var goal_exports = {};
69588
70417
  __export(goal_exports, {
69589
70418
  goalCommand: () => goalCommand
69590
70419
  });
69591
- import { getProjectRoot as getProjectRoot60, goal } from "@cleocode/core";
70420
+ import { getProjectRoot as getProjectRoot61, goal } from "@cleocode/core";
69592
70421
  function resolveGoalKind(task) {
69593
70422
  if (typeof task === "string" && task.length > 0) {
69594
70423
  if (!isValidGoalTargetTaskId(task)) {
@@ -69635,7 +70464,7 @@ var init_goal2 = __esm({
69635
70464
  }
69636
70465
  const record = await goal.createGoal(
69637
70466
  { goalKind: kindResult.kind, intent, turnBudget: resolveTurnBudget(args.turns) },
69638
- getProjectRoot60()
70467
+ getProjectRoot61()
69639
70468
  );
69640
70469
  cliOutput(record, { command: "goal set", operation: "goal.set" });
69641
70470
  }
@@ -69646,7 +70475,7 @@ var init_goal2 = __esm({
69646
70475
  description: "Show the current agent's active goal (per-agent scoped)."
69647
70476
  },
69648
70477
  async run() {
69649
- const record = await goal.getActiveGoal(getProjectRoot60());
70478
+ const record = await goal.getActiveGoal(getProjectRoot61());
69650
70479
  cliOutput(record ?? { active: null }, { command: "goal status", operation: "goal.status" });
69651
70480
  }
69652
70481
  });
@@ -69668,7 +70497,7 @@ var init_goal2 = __esm({
69668
70497
  });
69669
70498
  return;
69670
70499
  }
69671
- const cwd = getProjectRoot60();
70500
+ const cwd = getProjectRoot61();
69672
70501
  const parent = await goal.getActiveGoal(cwd);
69673
70502
  if (!parent) {
69674
70503
  cliError(
@@ -69716,7 +70545,7 @@ var init_goal2 = __esm({
69716
70545
  });
69717
70546
  return;
69718
70547
  }
69719
- const cwd = getProjectRoot60();
70548
+ const cwd = getProjectRoot61();
69720
70549
  const result = await goal.advanceGoalWithPersist(goalId, { cwd });
69721
70550
  if (!result) {
69722
70551
  cliError(`Goal '${goalId}' not found.`, 4 /* NOT_FOUND */, { name: "E_NOT_FOUND" });
@@ -69741,7 +70570,7 @@ var init_goal2 = __esm({
69741
70570
  });
69742
70571
  return;
69743
70572
  }
69744
- const cwd = getProjectRoot60();
70573
+ const cwd = getProjectRoot61();
69745
70574
  const active = await goal.getActiveGoal(cwd);
69746
70575
  if (!active) {
69747
70576
  cliError(
@@ -70783,12 +71612,422 @@ var init_history = __esm({
70783
71612
  }
70784
71613
  });
70785
71614
 
71615
+ // packages/cleo/src/cli/hook-entry.ts
71616
+ var hook_entry_exports = {};
71617
+ __export(hook_entry_exports, {
71618
+ HEAVY_HOOK_PROVIDERS: () => HEAVY_HOOK_PROVIDERS,
71619
+ claudeGuardedBashRules: () => claudeGuardedBashRules,
71620
+ claudeRuleFiles: () => claudeRuleFiles,
71621
+ codexGuardedWords: () => codexGuardedWords,
71622
+ guardedHeavyCommand: () => guardedHeavyCommand,
71623
+ heavyCommandHook: () => heavyCommandHook,
71624
+ heavyHookContext: () => heavyHookContext,
71625
+ heavyHookWaitBudget: () => heavyHookWaitBudget,
71626
+ heavyRuleWords: () => heavyRuleWords,
71627
+ parseHookInput: () => parseHookInput,
71628
+ processHookIo: () => processHookIo,
71629
+ renderHeavyHookAnswer: () => renderHeavyHookAnswer,
71630
+ runHookCli: () => runHookCli
71631
+ });
71632
+ import { readdirSync as readdirSync3, readFileSync as readFileSync12 } from "node:fs";
71633
+ import { homedir as homedir3 } from "node:os";
71634
+ import { join as join28 } from "node:path";
71635
+ async function readProcessStdin() {
71636
+ if (process.stdin.isTTY) return "";
71637
+ const chunks = [];
71638
+ let size = 0;
71639
+ for await (const chunk of process.stdin) {
71640
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
71641
+ size += buf.length;
71642
+ if (size > MAX_STDIN_BYTES) return "";
71643
+ chunks.push(buf);
71644
+ }
71645
+ return Buffer.concat(chunks).toString("utf-8");
71646
+ }
71647
+ function processHookIo() {
71648
+ return {
71649
+ readStdin: readProcessStdin,
71650
+ writeStdout: (text) => process.stdout.write(text),
71651
+ // stdout-discipline-allowed: PreToolUse hook protocol, the harness parses this JSON (not LAFS, not rendered output) // stdout-write-allowed: PreToolUse hook protocol output read raw by the harness
71652
+ writeStderr: (text) => process.stderr.write(text),
71653
+ env: process.env,
71654
+ cwd: process.cwd()
71655
+ };
71656
+ }
71657
+ function isRecord4(value) {
71658
+ return typeof value === "object" && value !== null && !Array.isArray(value);
71659
+ }
71660
+ function parseHookInput(text) {
71661
+ let raw;
71662
+ try {
71663
+ raw = JSON.parse(text);
71664
+ } catch {
71665
+ return null;
71666
+ }
71667
+ if (!isRecord4(raw)) return null;
71668
+ const toolInput = raw.tool_input;
71669
+ if (!isRecord4(toolInput) || typeof toolInput.command !== "string") return null;
71670
+ const toolName = typeof raw.tool_name === "string" ? raw.tool_name : void 0;
71671
+ if (toolName !== void 0 && !/^(bash|shell|exec_command)$/i.test(toolName)) return null;
71672
+ const str3 = (v) => typeof v === "string" ? v : void 0;
71673
+ return {
71674
+ ...toolName === void 0 ? {} : { tool_name: toolName },
71675
+ tool_input: { ...toolInput, command: toolInput.command },
71676
+ ...str3(raw.cwd) === void 0 ? {} : { cwd: str3(raw.cwd) },
71677
+ ...str3(raw.permission_mode) === void 0 ? {} : { permission_mode: str3(raw.permission_mode) }
71678
+ };
71679
+ }
71680
+ function positiveMs(value) {
71681
+ const n = value === void 0 ? Number.NaN : Number(value);
71682
+ return Number.isFinite(n) && n > 0 ? Math.floor(n) : void 0;
71683
+ }
71684
+ function heavyHookWaitBudget(provider, toolInput, env = {}) {
71685
+ if (toolInput.run_in_background === true) return {};
71686
+ if (provider !== "claude-code" && provider !== "opencode") {
71687
+ return { waitTimeoutSec: DEFAULT_WAIT_SEC };
71688
+ }
71689
+ const fromEnv = provider === "claude-code";
71690
+ const def = (fromEnv ? positiveMs(env.BASH_DEFAULT_TIMEOUT_MS) : void 0) ?? BASH_DEFAULT_MS;
71691
+ const max = Math.max(
71692
+ (fromEnv ? positiveMs(env.BASH_MAX_TIMEOUT_MS) : void 0) ?? BASH_MAX_MS,
71693
+ def
71694
+ );
71695
+ const asked = typeof toolInput.timeout === "number" && toolInput.timeout > 0 ? toolInput.timeout : def;
71696
+ const effective = Math.min(asked, max);
71697
+ const room = Math.floor((max - effective) / 1e3);
71698
+ const waitTimeoutSec = Math.max(
71699
+ MIN_WAIT_SEC,
71700
+ Math.min(MAX_WAIT_SEC, Math.round(effective / 1e3), room)
71701
+ );
71702
+ return { waitTimeoutSec, timeoutMs: Math.min(max, effective + waitTimeoutSec * 1e3) };
71703
+ }
71704
+ function heavyHookContext(plan, pressure, provider = "claude-code") {
71705
+ const lines = [];
71706
+ const governed = plan.action === "none" ? "" : plan.segments.map((s) => s.governed).join(" ; ");
71707
+ if (plan.action === "rewrite" && provider === "kimi") {
71708
+ lines.push(
71709
+ `[cleo] Not run: heavy commands share the machine-wide resource budget. Re-run it as: ${plan.command}`
71710
+ );
71711
+ } else if (plan.action === "rewrite") {
71712
+ lines.push(
71713
+ `[cleo] Routed heavy work through the machine-wide budget: ${governed}. cleo run passes the command its stdin, stdout, stderr and exit code; exit 75 means it was not admitted before the wait ran out (E_RESOURCE_DEFERRED on stderr lists holders and ways forward).`
71714
+ );
71715
+ } else if (plan.action === "warn") {
71716
+ lines.push(
71717
+ `[cleo] Heavy command not rewritten because ${plan.reason}. Run it governed so it shares the machine-wide budget: ${governed}`
71718
+ );
71719
+ }
71720
+ if (pressure !== null) lines.push(pressure);
71721
+ return lines.join("\n");
71722
+ }
71723
+ function demote(plan, reason) {
71724
+ return plan.action === "rewrite" ? { action: "warn", reason, segments: plan.segments } : plan;
71725
+ }
71726
+ function renderHeavyHookAnswer(provider, toolInput, plan, context, timeoutMs) {
71727
+ if (plan.action === "none" && context === "") return "";
71728
+ const rewrite = plan.action === "rewrite";
71729
+ if (provider === "opencode") {
71730
+ const answer = {
71731
+ ...rewrite ? { command: plan.command } : {},
71732
+ ...rewrite && timeoutMs !== void 0 ? { timeout: timeoutMs } : {},
71733
+ ...context === "" ? {} : { context }
71734
+ };
71735
+ return `${JSON.stringify(answer)}
71736
+ `;
71737
+ }
71738
+ if (provider === "kimi") {
71739
+ if (!rewrite) return `${context}
71740
+ `;
71741
+ const deny = {
71742
+ hookSpecificOutput: {
71743
+ hookEventName: "PreToolUse",
71744
+ permissionDecision: "deny",
71745
+ permissionDecisionReason: context
71746
+ }
71747
+ };
71748
+ return `${JSON.stringify(deny)}
71749
+ `;
71750
+ }
71751
+ const updatedInput = rewrite ? {
71752
+ ...toolInput,
71753
+ command: plan.command,
71754
+ ...provider === "claude-code" && timeoutMs !== void 0 ? { timeout: timeoutMs } : {}
71755
+ } : void 0;
71756
+ const output2 = {
71757
+ hookSpecificOutput: {
71758
+ hookEventName: "PreToolUse",
71759
+ ...rewrite && provider === "codex" ? { permissionDecision: "allow" } : {},
71760
+ ...updatedInput === void 0 ? {} : { updatedInput },
71761
+ ...context === "" ? {} : { additionalContext: context }
71762
+ }
71763
+ };
71764
+ return `${JSON.stringify(output2)}
71765
+ `;
71766
+ }
71767
+ function wordBase(word) {
71768
+ return word.split("/").pop() ?? word;
71769
+ }
71770
+ function heavyRuleWords(argv) {
71771
+ const out = [];
71772
+ for (const w of argv) {
71773
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(w) || w.startsWith("-") || /^\d+$/.test(w)) continue;
71774
+ out.push(wordBase(w));
71775
+ if (out.length === 4) break;
71776
+ }
71777
+ return out;
71778
+ }
71779
+ function ruleWords(pattern) {
71780
+ return pattern.split(/[\s:*()]+/).filter((w) => w !== "" && !w.startsWith("-")).map(wordBase);
71781
+ }
71782
+ function claudeRuleFiles(projectDir, env) {
71783
+ const managed = process.platform === "darwin" ? "/Library/Application Support/ClaudeCode/managed-settings.json" : process.platform === "win32" ? "C:\\Program Files\\ClaudeCode\\managed-settings.json" : "/etc/claude-code/managed-settings.json";
71784
+ const configDir = env.CLAUDE_CONFIG_DIR || join28(env.HOME || homedir3(), ".claude");
71785
+ return [
71786
+ managed,
71787
+ join28(configDir, "settings.json"),
71788
+ join28(projectDir, ".claude", "settings.json"),
71789
+ join28(projectDir, ".claude", "settings.local.json")
71790
+ ];
71791
+ }
71792
+ function claudeGuardedBashRules(files) {
71793
+ const patterns = [];
71794
+ let unreadable = null;
71795
+ for (const file of files) {
71796
+ let raw;
71797
+ try {
71798
+ raw = JSON.parse(readFileSync12(file, "utf-8"));
71799
+ } catch (err) {
71800
+ const code = err.code;
71801
+ if (code !== "ENOENT" && code !== "ENOTDIR") unreadable ??= file;
71802
+ continue;
71803
+ }
71804
+ const permissions = isRecord4(raw) ? raw.permissions : void 0;
71805
+ if (!isRecord4(permissions)) continue;
71806
+ for (const key of ["deny", "ask"]) {
71807
+ const rules = permissions[key];
71808
+ if (!Array.isArray(rules)) continue;
71809
+ for (const rule2 of rules) {
71810
+ if (typeof rule2 !== "string") continue;
71811
+ const trimmed = rule2.trim();
71812
+ if (trimmed === "Bash") {
71813
+ patterns.push("*");
71814
+ continue;
71815
+ }
71816
+ const match = /^Bash\((.*)\)$/s.exec(trimmed);
71817
+ if (match?.[1] !== void 0) patterns.push(match[1]);
71818
+ }
71819
+ }
71820
+ }
71821
+ return { patterns, unreadable };
71822
+ }
71823
+ function codexGuardedWords(projectDir, env) {
71824
+ const home = env.CODEX_HOME || join28(env.HOME || homedir3(), ".codex");
71825
+ const out = [];
71826
+ for (const dir of [join28(home, "rules"), join28(projectDir, ".codex", "rules")]) {
71827
+ let names;
71828
+ try {
71829
+ names = readdirSync3(dir).filter((n) => n.endsWith(".rules"));
71830
+ } catch {
71831
+ continue;
71832
+ }
71833
+ for (const name of names) {
71834
+ let text;
71835
+ try {
71836
+ text = readFileSync12(join28(dir, name), "utf-8");
71837
+ } catch {
71838
+ continue;
71839
+ }
71840
+ if (!/decision\s*=\s*["'](forbidden|prompt)["']/.test(text)) continue;
71841
+ for (const m of text.matchAll(/"([^"\\]*)"|'([^'\\]*)'/g)) {
71842
+ for (const w of ruleWords(m[1] ?? m[2] ?? "")) out.push(w);
71843
+ }
71844
+ }
71845
+ }
71846
+ return out;
71847
+ }
71848
+ function guardedHeavyCommand(provider, segments, projectDir, env, files = claudeRuleFiles(projectDir, env)) {
71849
+ let rules;
71850
+ if (provider === "claude-code") {
71851
+ const found = claudeGuardedBashRules(files);
71852
+ if (found.unreadable !== null) return { kind: "unreadable", file: found.unreadable };
71853
+ rules = found.patterns.map(ruleWords);
71854
+ if (rules.some((words) => words.length === 0)) return { kind: "all" };
71855
+ } else if (provider === "codex") {
71856
+ const words = codexGuardedWords(projectDir, env);
71857
+ rules = words.length === 0 ? [] : [words];
71858
+ } else {
71859
+ return null;
71860
+ }
71861
+ for (const segment of segments) {
71862
+ const words = heavyRuleWords(segment.argv);
71863
+ const first = words[0];
71864
+ if (first === void 0) continue;
71865
+ for (const rule2 of rules) {
71866
+ if (provider === "codex") {
71867
+ const hit = words.slice(0, 3).find((w) => rule2.includes(w));
71868
+ if (hit !== void 0) return { kind: "word", word: hit };
71869
+ continue;
71870
+ }
71871
+ const lead = rule2[0];
71872
+ if (lead !== void 0 && words.includes(lead)) return { kind: "word", word: lead };
71873
+ if (rule2.includes(first)) return { kind: "word", word: first };
71874
+ }
71875
+ }
71876
+ return null;
71877
+ }
71878
+ function providerProjectDir(provider, env) {
71879
+ return provider === "claude-code" ? env.CLAUDE_PROJECT_DIR || void 0 : void 0;
71880
+ }
71881
+ async function heavyCommandHook(provider, stdin2, io) {
71882
+ const envMode = io.env.CLEO_HEAVY_COMMAND_HOOK?.trim().toLowerCase();
71883
+ if (envMode === "off") return "";
71884
+ const input2 = parseHookInput(stdin2);
71885
+ if (input2?.tool_input === void 0) return "";
71886
+ const core2 = await import("@cleocode/core/resources/heavy-command.js");
71887
+ const cwd = input2.cwd ?? io.cwd;
71888
+ const budget = heavyHookWaitBudget(provider, input2.tool_input, io.env);
71889
+ let plan = core2.planHeavyCommand(input2.tool_input.command, {
71890
+ cwd,
71891
+ ...budget.waitTimeoutSec === void 0 ? {} : { waitTimeoutSec: budget.waitTimeoutSec }
71892
+ });
71893
+ if (plan.action === "none") return "";
71894
+ const projectRoot = providerProjectDir(provider, io.env) ?? core2.heavyHookProjectRoot(cwd);
71895
+ const mode = core2.resolveHeavyHookMode(
71896
+ envMode,
71897
+ core2.isHeavyCommandHookMode(envMode) ? void 0 : await core2.configuredHeavyHookMode(projectRoot)
71898
+ );
71899
+ if (mode === "off") return "";
71900
+ if (mode === "warn") {
71901
+ plan = demote(
71902
+ plan,
71903
+ "the hook is in warn mode (CLEO_HEAVY_COMMAND_HOOK or resources.heavyCommandHook)"
71904
+ );
71905
+ }
71906
+ if (!core2.executableOnPath("cleo", io.env.PATH)) plan = demote(plan, "`cleo` is not on PATH");
71907
+ if (provider !== "kimi" && !REWRITE_MODES.has(input2.permission_mode ?? "")) {
71908
+ plan = demote(
71909
+ plan,
71910
+ `rewriting it would change which permission rules match it, so the hook rewrites only in bypassPermissions or auto mode (this session: ${input2.permission_mode ?? "unknown"})`
71911
+ );
71912
+ }
71913
+ if (plan.action === "rewrite") {
71914
+ const hit = guardedHeavyCommand(provider, plan.segments, projectRoot, io.env);
71915
+ const where = provider === "codex" ? "Codex rules" : "Claude Code settings";
71916
+ if (hit?.kind === "word") {
71917
+ plan = demote(
71918
+ plan,
71919
+ `a deny or ask rule in your ${where} names \`${hit.word}\`, and a rewrite would hide the command from it`
71920
+ );
71921
+ } else if (hit?.kind === "all") {
71922
+ plan = demote(
71923
+ plan,
71924
+ `a deny or ask rule in your ${where} covers every Bash command, and a rewrite would hide the command from it`
71925
+ );
71926
+ } else if (hit?.kind === "unreadable") {
71927
+ plan = demote(
71928
+ plan,
71929
+ `${hit.file} could not be read or parsed, so the hook cannot tell whether a deny or ask rule names the command`
71930
+ );
71931
+ }
71932
+ }
71933
+ const context = heavyHookContext(plan, await core2.heavyPressureNotice(), provider);
71934
+ return renderHeavyHookAnswer(provider, input2.tool_input, plan, context, budget.timeoutMs);
71935
+ }
71936
+ async function runHookCli(argv, io = processHookIo()) {
71937
+ const [name, ...rest] = argv;
71938
+ if (name !== "heavy-command") {
71939
+ io.writeStderr(USAGE);
71940
+ return 1;
71941
+ }
71942
+ const flag = rest.findIndex((a) => a === "--provider" || a.startsWith("--provider="));
71943
+ const value = flag === -1 ? "claude-code" : rest[flag]?.split("=")[1] ?? rest[flag + 1];
71944
+ const provider = HEAVY_HOOK_PROVIDERS.find((p) => p === value);
71945
+ if (provider === void 0) {
71946
+ io.writeStderr(USAGE);
71947
+ return 1;
71948
+ }
71949
+ try {
71950
+ const answer = await heavyCommandHook(provider, await io.readStdin(), io);
71951
+ if (answer !== "") io.writeStdout(answer);
71952
+ } catch (err) {
71953
+ io.writeStderr(
71954
+ `[cleo hook] heavy-command skipped: ${err instanceof Error ? err.message : String(err)}
71955
+ `
71956
+ );
71957
+ }
71958
+ return 0;
71959
+ }
71960
+ var HEAVY_HOOK_PROVIDERS, BASH_DEFAULT_MS, BASH_MAX_MS, MIN_WAIT_SEC, MAX_WAIT_SEC, DEFAULT_WAIT_SEC, REWRITE_MODES, MAX_STDIN_BYTES, USAGE;
71961
+ var init_hook_entry = __esm({
71962
+ "packages/cleo/src/cli/hook-entry.ts"() {
71963
+ "use strict";
71964
+ HEAVY_HOOK_PROVIDERS = [
71965
+ "claude-code",
71966
+ "codex",
71967
+ "kimi",
71968
+ "opencode"
71969
+ ];
71970
+ BASH_DEFAULT_MS = 12e4;
71971
+ BASH_MAX_MS = 6e5;
71972
+ MIN_WAIT_SEC = 30;
71973
+ MAX_WAIT_SEC = 300;
71974
+ DEFAULT_WAIT_SEC = 60;
71975
+ REWRITE_MODES = /* @__PURE__ */ new Set(["bypassPermissions", "auto"]);
71976
+ MAX_STDIN_BYTES = 1024 * 1024;
71977
+ USAGE = "usage: cleo hook heavy-command [--provider claude-code|codex|kimi|opencode] < hook-input.json\n";
71978
+ }
71979
+ });
71980
+
71981
+ // packages/cleo/src/cli/commands/hook.ts
71982
+ var hook_exports = {};
71983
+ __export(hook_exports, {
71984
+ hookCommand: () => hookCommand
71985
+ });
71986
+ var heavyCommandSubcommand, hookCommand;
71987
+ var init_hook = __esm({
71988
+ "packages/cleo/src/cli/commands/hook.ts"() {
71989
+ "use strict";
71990
+ init_define_cli_command();
71991
+ heavyCommandSubcommand = defineCommand({
71992
+ meta: {
71993
+ name: "heavy-command",
71994
+ description: "PreToolUse hook: route heavy shell commands (tests, builds, typechecks, installs) through cleo run. Reads the hook JSON on stdin; prints the harness answer."
71995
+ },
71996
+ args: {
71997
+ provider: {
71998
+ type: "string",
71999
+ description: "Harness protocol to answer in: claude-code (default), codex, kimi, opencode"
72000
+ }
72001
+ },
72002
+ async run({ args }) {
72003
+ const { runHookCli: runHookCli2 } = await Promise.resolve().then(() => (init_hook_entry(), hook_entry_exports));
72004
+ const provider = typeof args.provider === "string" ? args.provider : "claude-code";
72005
+ process.exitCode = await runHookCli2(["heavy-command", "--provider", provider]);
72006
+ }
72007
+ });
72008
+ hookCommand = defineCommand({
72009
+ meta: {
72010
+ name: "hook",
72011
+ description: "Agent-harness hooks installed by cleo init/upgrade; stdout is the harness hook protocol, not LAFS: cleo hook heavy-command --provider claude-code|codex|kimi|opencode"
72012
+ },
72013
+ subCommands: {
72014
+ "heavy-command": heavyCommandSubcommand
72015
+ },
72016
+ async run({ cmd, rawArgs }) {
72017
+ const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
72018
+ if (firstArg && cmd.subCommands && firstArg in cmd.subCommands) return;
72019
+ await showUsage(cmd);
72020
+ }
72021
+ });
72022
+ }
72023
+ });
72024
+
70786
72025
  // packages/cleo/src/cli/commands/hygiene.ts
70787
72026
  var hygiene_exports = {};
70788
72027
  __export(hygiene_exports, {
70789
72028
  hygieneCommand: () => hygieneCommand
70790
72029
  });
70791
- import { getProjectRoot as getProjectRoot61 } from "@cleocode/core";
72030
+ import { getProjectRoot as getProjectRoot62 } from "@cleocode/core";
70792
72031
  import { runSpawnReadinessHygieneCli } from "@cleocode/core/hygiene/validate-spawn-readiness.js";
70793
72032
  var hygieneCommand;
70794
72033
  var init_hygiene = __esm({
@@ -70817,7 +72056,7 @@ var init_hygiene = __esm({
70817
72056
  }
70818
72057
  },
70819
72058
  async run({ args }) {
70820
- const projectRoot = args["project-root"] || getProjectRoot61() || process.cwd();
72059
+ const projectRoot = args["project-root"] || getProjectRoot62() || process.cwd();
70821
72060
  const worktreePath = args["worktree-path"];
70822
72061
  await runSpawnReadinessHygieneCli(projectRoot, worktreePath);
70823
72062
  }
@@ -70992,8 +72231,8 @@ __export(init_exports, {
70992
72231
  isCredentialPoolEmpty: () => isCredentialPoolEmpty,
70993
72232
  maybeNudgeFirstRunLogin: () => maybeNudgeFirstRunLogin
70994
72233
  });
70995
- import { existsSync as existsSync16, readFileSync as readFileSync12 } from "node:fs";
70996
- import { join as join28 } from "node:path";
72234
+ import { existsSync as existsSync16, readFileSync as readFileSync13 } from "node:fs";
72235
+ import { join as join29 } from "node:path";
70997
72236
  import { fileURLToPath as fileURLToPath5 } from "node:url";
70998
72237
  import {
70999
72238
  CleoError as CleoError9,
@@ -71008,12 +72247,12 @@ import { getTemplatesByKind } from "@cleocode/core/templates/registry";
71008
72247
  function getGitignoreTemplate() {
71009
72248
  try {
71010
72249
  const thisFile = fileURLToPath5(import.meta.url);
71011
- const packageRoot = join28(thisFile, "..", "..", "..", "..");
71012
- const localTemplatePath = join28(packageRoot, "templates", "cleo-gitignore");
71013
- const monorepoTemplatePath = join28(packageRoot, "..", "..", "templates", "cleo-gitignore");
72250
+ const packageRoot = join29(thisFile, "..", "..", "..", "..");
72251
+ const localTemplatePath = join29(packageRoot, "templates", "cleo-gitignore");
72252
+ const monorepoTemplatePath = join29(packageRoot, "..", "..", "templates", "cleo-gitignore");
71014
72253
  const templatePath = existsSync16(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
71015
72254
  if (existsSync16(templatePath)) {
71016
- return readFileSync12(templatePath, "utf-8");
72255
+ return readFileSync13(templatePath, "utf-8");
71017
72256
  }
71018
72257
  } catch {
71019
72258
  }
@@ -72160,7 +73399,7 @@ var llm_cost_exports = {};
72160
73399
  __export(llm_cost_exports, {
72161
73400
  costCommand: () => costCommand
72162
73401
  });
72163
- import { getProjectRoot as getProjectRoot62 } from "@cleocode/core/internal";
73402
+ import { getProjectRoot as getProjectRoot63 } from "@cleocode/core/internal";
72164
73403
  import { computeCost } from "@cleocode/core/llm/usage-pricing";
72165
73404
  function resolveSessionId(raw) {
72166
73405
  if (raw === "current") {
@@ -72233,7 +73472,7 @@ var init_llm_cost = __esm({
72233
73472
  process.exit(6);
72234
73473
  }
72235
73474
  const sessionId = resolveSessionId(rawSessionId);
72236
- const projectRoot = getProjectRoot62(process.cwd());
73475
+ const projectRoot = getProjectRoot63(process.cwd());
72237
73476
  let breakdown;
72238
73477
  try {
72239
73478
  breakdown = await loadSessionCostBreakdown(projectRoot, sessionId);
@@ -73610,7 +74849,7 @@ var memory_exports = {};
73610
74849
  __export(memory_exports, {
73611
74850
  memoryCommand: () => memoryCommand
73612
74851
  });
73613
- import { getProjectRoot as getProjectRoot63 } from "@cleocode/core";
74852
+ import { getProjectRoot as getProjectRoot64 } from "@cleocode/core";
73614
74853
  import {
73615
74854
  getBrainDb as getBrainDb2,
73616
74855
  getDreamStatus,
@@ -74568,7 +75807,7 @@ var init_memory3 = __esm({
74568
75807
  },
74569
75808
  args: {},
74570
75809
  async run() {
74571
- const root = getProjectRoot63();
75810
+ const root = getProjectRoot64();
74572
75811
  try {
74573
75812
  const result = await runConsolidation(root);
74574
75813
  cliOutput(result, { command: "memory-consolidate", operation: "memory.consolidate" });
@@ -74592,7 +75831,7 @@ var init_memory3 = __esm({
74592
75831
  }
74593
75832
  },
74594
75833
  async run({ args }) {
74595
- const root = getProjectRoot63();
75834
+ const root = getProjectRoot64();
74596
75835
  if (args.status) {
74597
75836
  try {
74598
75837
  const status = await getDreamStatus(root);
@@ -74629,7 +75868,7 @@ var init_memory3 = __esm({
74629
75868
  }
74630
75869
  },
74631
75870
  async run({ args }) {
74632
- const root = getProjectRoot63();
75871
+ const root = getProjectRoot64();
74633
75872
  try {
74634
75873
  const { runObserver, runReflector } = await import("@cleocode/core/memory");
74635
75874
  const observerResult = await runObserver(root, args.session, {
@@ -74669,7 +75908,7 @@ var init_memory3 = __esm({
74669
75908
  }
74670
75909
  },
74671
75910
  async run({ args }) {
74672
- const root = getProjectRoot63();
75911
+ const root = getProjectRoot64();
74673
75912
  await getBrainDb2(root);
74674
75913
  const { getBrainNativeDb: getBrainNativeDb3 } = await import("@cleocode/core/internal");
74675
75914
  const nativeDb = getBrainNativeDb3();
@@ -74707,7 +75946,7 @@ var init_memory3 = __esm({
74707
75946
  },
74708
75947
  async run({ args }) {
74709
75948
  const core2 = await import("@cleocode/core/internal");
74710
- const nexusDb = await core2.getNexusDb(getProjectRoot63());
75949
+ const nexusDb = await core2.getNexusDb(getProjectRoot64());
74711
75950
  const result = args.restore ? await core2.restorePrunedTraits(
74712
75951
  nexusDb,
74713
75952
  String(args.restore),
@@ -74737,7 +75976,7 @@ var init_memory3 = __esm({
74737
75976
  return;
74738
75977
  }
74739
75978
  const core2 = await import("@cleocode/core/internal");
74740
- const nexusDb = await core2.getNexusDb(getProjectRoot63());
75979
+ const nexusDb = await core2.getNexusDb(getProjectRoot64());
74741
75980
  const previous = await core2.setUserProfileTraitScope(nexusDb, String(args.key), scope);
74742
75981
  if (previous === null) {
74743
75982
  cliError(`No user-profile trait "${args.key}"`, "E_NOT_FOUND", { name: "E_NOT_FOUND" });
@@ -74761,7 +76000,7 @@ var init_memory3 = __esm({
74761
76000
  }
74762
76001
  },
74763
76002
  async run({ args }) {
74764
- const root = getProjectRoot63();
76003
+ const root = getProjectRoot64();
74765
76004
  try {
74766
76005
  await getBrainDb2(root);
74767
76006
  const { totalDuplicateRows, groups } = await scanDuplicateEntries();
@@ -74807,7 +76046,7 @@ var init_memory3 = __esm({
74807
76046
  async run({ args }) {
74808
76047
  const sourceDir = args.from;
74809
76048
  const isDryRun = !!args["dry-run"];
74810
- const projectRoot = getProjectRoot63();
76049
+ const projectRoot = getProjectRoot64();
74811
76050
  try {
74812
76051
  const result = await importMemoryFiles({
74813
76052
  sourceDir,
@@ -74958,7 +76197,7 @@ var init_memory3 = __esm({
74958
76197
  },
74959
76198
  args: {},
74960
76199
  async run() {
74961
- const root = getProjectRoot63();
76200
+ const root = getProjectRoot64();
74962
76201
  try {
74963
76202
  await getBrainDb2(root);
74964
76203
  const result = await getTierStats(root);
@@ -75001,7 +76240,7 @@ var init_memory3 = __esm({
75001
76240
  }
75002
76241
  },
75003
76242
  async run({ args }) {
75004
- const root = getProjectRoot63();
76243
+ const root = getProjectRoot64();
75005
76244
  const targetTier = args.to;
75006
76245
  const reason = args.reason;
75007
76246
  const validTiers = ["medium", "long"];
@@ -75067,7 +76306,7 @@ var init_memory3 = __esm({
75067
76306
  }
75068
76307
  },
75069
76308
  async run({ args }) {
75070
- const root = getProjectRoot63();
76309
+ const root = getProjectRoot64();
75071
76310
  const targetTier = args.to;
75072
76311
  const reason = args.reason;
75073
76312
  const validTiers = ["short", "medium"];
@@ -75540,7 +76779,7 @@ var migrate_claude_mem_exports = {};
75540
76779
  __export(migrate_claude_mem_exports, {
75541
76780
  migrateClaudeMemCommand: () => migrateClaudeMemCommand
75542
76781
  });
75543
- import { getProjectRoot as getProjectRoot64, migrateClaudeMem } from "@cleocode/core/internal";
76782
+ import { getProjectRoot as getProjectRoot65, migrateClaudeMem } from "@cleocode/core/internal";
75544
76783
  import { ingestLooseAgentOutputs, ingestRcasdDirectories } from "@cleocode/core/memory";
75545
76784
  import { getDb as getDb2 } from "@cleocode/core/store/sqlite";
75546
76785
  var storageCommand, claudeMemCommand, manifestIngestCommand, migrateClaudeMemCommand;
@@ -75603,7 +76842,7 @@ var init_migrate_claude_mem = __esm({
75603
76842
  }
75604
76843
  },
75605
76844
  async run({ args }) {
75606
- const root = getProjectRoot64();
76845
+ const root = getProjectRoot65();
75607
76846
  try {
75608
76847
  const result = await migrateClaudeMem(root, {
75609
76848
  sourcePath: args.source,
@@ -75652,7 +76891,7 @@ var init_migrate_claude_mem = __esm({
75652
76891
  }
75653
76892
  },
75654
76893
  async run({ args }) {
75655
- const projectRoot = getProjectRoot64();
76894
+ const projectRoot = getProjectRoot65();
75656
76895
  try {
75657
76896
  const db = await getDb2(projectRoot);
75658
76897
  const rcasdFlag = Boolean(args.rcasd);
@@ -75770,7 +77009,7 @@ __export(nexus_exports, {
75770
77009
  import { statSync as statSync2 } from "node:fs";
75771
77010
  import { appendFile as appendFile2, mkdir as mkdir5 } from "node:fs/promises";
75772
77011
  import path4 from "node:path";
75773
- import { getProjectRoot as getProjectRoot65 } from "@cleocode/core";
77012
+ import { getProjectRoot as getProjectRoot66 } from "@cleocode/core";
75774
77013
  import { getSymbolImpact } from "@cleocode/core/nexus";
75775
77014
  import { runNexusAnalysis } from "@cleocode/core/nexus/analyze-orchestrator.js";
75776
77015
  import {
@@ -75941,7 +77180,7 @@ var init_nexus3 = __esm({
75941
77180
  async run({ args }) {
75942
77181
  applyJsonFlag2(args.json);
75943
77182
  const projectIdOverride = args["project-id"];
75944
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
77183
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
75945
77184
  const startTime = Date.now();
75946
77185
  if (args.path) {
75947
77186
  let isDir = false;
@@ -76001,7 +77240,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648), so the coun
76001
77240
  process.exitCode = 2 /* INVALID_INPUT */;
76002
77241
  return;
76003
77242
  }
76004
- const currentRoot = getProjectRoot65();
77243
+ const currentRoot = getProjectRoot66();
76005
77244
  if (args.path && path4.resolve(repoPath) !== path4.resolve(currentRoot)) {
76006
77245
  cliError(
76007
77246
  `nexus status cannot report on '${repoPath}' from this project.
@@ -76179,9 +77418,9 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76179
77418
  args: {},
76180
77419
  async run() {
76181
77420
  try {
76182
- const { homedir: homedir4 } = await import("node:os");
77421
+ const { homedir: homedir5 } = await import("node:os");
76183
77422
  const { installNexusAugmentHook } = await import("@cleocode/core/internal");
76184
- const homeDir = homedir4();
77423
+ const homeDir = homedir5();
76185
77424
  installNexusAugmentHook(homeDir);
76186
77425
  cliOutput({ homeDir }, { command: "nexus-setup", operation: "nexus.setup" });
76187
77426
  } catch (err) {
@@ -76555,7 +77794,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76555
77794
  applyJsonFlag2(args.json);
76556
77795
  const startTime = Date.now();
76557
77796
  const projectIdOverride = args["project-id"];
76558
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
77797
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76559
77798
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
76560
77799
  const response = await dispatchRaw("query", "nexus", "clusters", { projectId, repoPath });
76561
77800
  const durationMs = Date.now() - startTime;
@@ -76599,7 +77838,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76599
77838
  applyJsonFlag2(args.json);
76600
77839
  const startTime = Date.now();
76601
77840
  const projectIdOverride = args["project-id"];
76602
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
77841
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76603
77842
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
76604
77843
  const response = await dispatchRaw("query", "nexus", "flows", { projectId, repoPath });
76605
77844
  const durationMs = Date.now() - startTime;
@@ -76642,7 +77881,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76642
77881
  void appendDeprecationTelemetry("nexus.context", "cleo graph context");
76643
77882
  const startTime = Date.now();
76644
77883
  const projectIdOverride = args["project-id"];
76645
- const repoPath = getProjectRoot65();
77884
+ const repoPath = getProjectRoot66();
76646
77885
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
76647
77886
  const limit = parseInt(args.limit, 10);
76648
77887
  const symbolName = args.symbol;
@@ -76705,7 +77944,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76705
77944
  const startTime = Date.now();
76706
77945
  const whyFlag = !!args.why;
76707
77946
  const projectIdOverride = args["project-id"];
76708
- const repoPath = getProjectRoot65();
77947
+ const repoPath = getProjectRoot66();
76709
77948
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
76710
77949
  const maxDepth = Math.min(parseInt(args.depth, 10), 5);
76711
77950
  const symbolName = args.symbol;
@@ -76809,7 +78048,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76809
78048
  const projectIdOverride = args["project-id"];
76810
78049
  const full = !!args.full;
76811
78050
  const ctx = getFormatContext();
76812
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78051
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76813
78052
  if (args.incremental)
76814
78053
  humanWarn(
76815
78054
  "[nexus] --incremental is deprecated and has no effect: incremental is the default."
@@ -76939,7 +78178,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76939
78178
  async run({ args }) {
76940
78179
  applyJsonFlag2(args.json);
76941
78180
  const startTime = Date.now();
76942
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78181
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76943
78182
  const name = args.name;
76944
78183
  const response = await dispatchRaw("mutate", "nexus", "projects.register", {
76945
78184
  path: repoPath,
@@ -77458,7 +78697,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77458
78697
  applyJsonFlag2(args.json);
77459
78698
  const startTime = Date.now();
77460
78699
  const projectIdOverride = args["project-id"];
77461
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78700
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77462
78701
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
77463
78702
  const response = await dispatchRaw("mutate", "nexus", "refresh-bridge", {
77464
78703
  repoPath,
@@ -77564,7 +78803,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77564
78803
  async run({ args }) {
77565
78804
  applyJsonFlag2(args.json);
77566
78805
  const startTime = Date.now();
77567
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78806
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77568
78807
  const projectIdOverride = args["project-id"];
77569
78808
  const beforeRef = args.before ?? "HEAD~1";
77570
78809
  const afterRef = args.after ?? "HEAD";
@@ -77682,7 +78921,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77682
78921
  applyJsonFlag2(args.json);
77683
78922
  const startTime = Date.now();
77684
78923
  const projectIdOverride = args["project-id"];
77685
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78924
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77686
78925
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
77687
78926
  const response = await dispatchRaw("query", "nexus", "route-map", { projectId });
77688
78927
  const durationMs = Date.now() - startTime;
@@ -77738,7 +78977,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77738
78977
  const startTime = Date.now();
77739
78978
  const routeSymbol = args.routeSymbol;
77740
78979
  const projectIdOverride = args["project-id"];
77741
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78980
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77742
78981
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
77743
78982
  const response = await dispatchRaw("query", "nexus", "shape-check", { routeSymbol, projectId });
77744
78983
  const durationMs = Date.now() - startTime;
@@ -78134,7 +79373,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
78134
79373
  async run({ args }) {
78135
79374
  applyJsonFlag2(args.json);
78136
79375
  const startTime = Date.now();
78137
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
79376
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
78138
79377
  const projectIdOverride = args["project-id"];
78139
79378
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
78140
79379
  const response = await dispatchRaw("mutate", "nexus", "contracts-sync", {
@@ -78244,7 +79483,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
78244
79483
  async run({ args }) {
78245
79484
  applyJsonFlag2(args.json);
78246
79485
  const startTime = Date.now();
78247
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
79486
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
78248
79487
  const projectId = Buffer.from(repoPath).toString("base64url").slice(0, 32);
78249
79488
  const response = await dispatchRaw("mutate", "nexus", "contracts-link-tasks", {
78250
79489
  projectId,
@@ -78328,7 +79567,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
78328
79567
  const isIncremental = !!args.incremental;
78329
79568
  try {
78330
79569
  const result = await runNexusWiki({
78331
- projectRoot: getProjectRoot65(),
79570
+ projectRoot: getProjectRoot66(),
78332
79571
  outputDir,
78333
79572
  communityFilter,
78334
79573
  incremental: isIncremental
@@ -78678,7 +79917,7 @@ __export(orchestrate_exports, {
78678
79917
  });
78679
79918
  import { execFileSync as execFileSync5 } from "node:child_process";
78680
79919
  import { orchestration } from "@cleocode/core";
78681
- import { BUILD_CONFIG as BUILD_CONFIG2, getProjectRoot as getProjectRoot66 } from "@cleocode/core/internal";
79920
+ import { BUILD_CONFIG as BUILD_CONFIG2, getProjectRoot as getProjectRoot67 } from "@cleocode/core/internal";
78682
79921
  function formatRollupTable(rollup) {
78683
79922
  const waves = "waves" in rollup ? rollup.waves : [rollup];
78684
79923
  const lines = [];
@@ -78821,7 +80060,7 @@ var init_orchestrate3 = __esm({
78821
80060
  },
78822
80061
  async run({ args }) {
78823
80062
  const rateWindowHours = args.window !== void 0 ? Number.parseFloat(String(args.window)) : void 0;
78824
- const metrics = await orchestration.collectOrchestrateDashboard(getProjectRoot66(), {
80063
+ const metrics = await orchestration.collectOrchestrateDashboard(getProjectRoot67(), {
78825
80064
  ...rateWindowHours !== void 0 && Number.isFinite(rateWindowHours) && rateWindowHours > 0 ? { rateWindowHours } : {}
78826
80065
  });
78827
80066
  cliOutput(metrics, {
@@ -80281,7 +81520,7 @@ __export(project_exports, {
80281
81520
  import { resolve as resolve9 } from "node:path";
80282
81521
  import {
80283
81522
  CleoError as CleoError11,
80284
- getProjectRoot as getProjectRoot67,
81523
+ getProjectRoot as getProjectRoot68,
80285
81524
  moveProject,
80286
81525
  projectLifecycle,
80287
81526
  renameProject,
@@ -80303,7 +81542,7 @@ function emitEngineFailure(error, operation) {
80303
81542
  }
80304
81543
  function resolveRootOrFail(operation) {
80305
81544
  try {
80306
- return getProjectRoot67();
81545
+ return getProjectRoot68();
80307
81546
  } catch (err) {
80308
81547
  const code = err instanceof CleoError11 && typeof err.details?.["code"] === "string" ? err.details["code"] : "E_NOT_CLEO_PROJECT";
80309
81548
  emitEngineFailure(
@@ -81138,7 +82377,7 @@ var refresh_memory_exports = {};
81138
82377
  __export(refresh_memory_exports, {
81139
82378
  refreshMemoryCommand: () => refreshMemoryCommand
81140
82379
  });
81141
- import { getProjectRoot as getProjectRoot68 } from "@cleocode/core";
82380
+ import { getProjectRoot as getProjectRoot69 } from "@cleocode/core";
81142
82381
  var refreshMemoryCommand;
81143
82382
  var init_refresh_memory = __esm({
81144
82383
  "packages/cleo/src/cli/commands/refresh-memory.ts"() {
@@ -81151,7 +82390,7 @@ var init_refresh_memory = __esm({
81151
82390
  description: "Regenerate .cleo/memory-bridge.md from brain.db"
81152
82391
  },
81153
82392
  async run() {
81154
- const projectDir = getProjectRoot68();
82393
+ const projectDir = getProjectRoot69();
81155
82394
  const { writeMemoryBridge } = await import("@cleocode/core/internal");
81156
82395
  const result = await writeMemoryBridge(projectDir);
81157
82396
  if (result.written) {
@@ -82737,7 +83976,7 @@ import fs3 from "node:fs";
82737
83976
  import path5 from "node:path";
82738
83977
  import {
82739
83978
  CleoError as CleoError13,
82740
- getProjectRoot as getProjectRoot69,
83979
+ getProjectRoot as getProjectRoot70,
82741
83980
  getTaskAccessor as getTaskAccessor3,
82742
83981
  parseConflictReport,
82743
83982
  setAtPath
@@ -82758,7 +83997,7 @@ var init_restore = __esm({
82758
83997
  description: "Apply manually-resolved conflicts from .cleo/restore-conflicts.md"
82759
83998
  },
82760
83999
  async run() {
82761
- const projectRoot = getProjectRoot69();
84000
+ const projectRoot = getProjectRoot70();
82762
84001
  const reportPath = path5.join(projectRoot, CLEO_DIR_NAME3, RESTORE_CONFLICTS_MD);
82763
84002
  if (!fs3.existsSync(reportPath)) {
82764
84003
  humanLine("No pending restore conflicts. Nothing to finalize.");
@@ -83130,7 +84369,7 @@ __export(revert_exports, {
83130
84369
  revertCommand: () => revertCommand2
83131
84370
  });
83132
84371
  import { readFile as readFile8 } from "node:fs/promises";
83133
- import { join as join29 } from "node:path";
84372
+ import { join as join30 } from "node:path";
83134
84373
  import { cwd as processCwd2 } from "node:process";
83135
84374
  import { E_RECEIPT_NOT_FOUND } from "@cleocode/core/sentient/chain-walker.js";
83136
84375
  import { SENTIENT_STATE_FILE } from "@cleocode/core/sentient/daemon.js";
@@ -83183,7 +84422,7 @@ async function loadOwnerAttestation(attestationFilePath) {
83183
84422
  return obj;
83184
84423
  }
83185
84424
  async function loadOwnerPubkeys(projectRoot) {
83186
- const path6 = join29(projectRoot, OWNER_PUBKEYS_FILE);
84425
+ const path6 = join30(projectRoot, OWNER_PUBKEYS_FILE);
83187
84426
  try {
83188
84427
  const raw = await readFile8(path6, "utf-8");
83189
84428
  const parsed = JSON.parse(raw);
@@ -83267,7 +84506,7 @@ var init_revert = __esm({
83267
84506
  if (attestation && allowedPubkeys.size > 0 && !allowedPubkeys.has(attestation.ownerPubkey)) {
83268
84507
  emitFailure2(
83269
84508
  E_OWNER_ATTESTATION_REQUIRED,
83270
- `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join29(projectRoot, OWNER_PUBKEYS_FILE)}`,
84509
+ `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join30(projectRoot, OWNER_PUBKEYS_FILE)}`,
83271
84510
  jsonMode
83272
84511
  );
83273
84512
  }
@@ -83320,7 +84559,7 @@ ${lines}`
83320
84559
  identity,
83321
84560
  includeHuman
83322
84561
  });
83323
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE);
84562
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE);
83324
84563
  const state = await readSentientState(statePath);
83325
84564
  emitSuccess(
83326
84565
  {
@@ -83391,6 +84630,185 @@ var init_roadmap = __esm({
83391
84630
  }
83392
84631
  });
83393
84632
 
84633
+ // packages/cleo/src/cli/commands/run.ts
84634
+ var run_exports = {};
84635
+ __export(run_exports, {
84636
+ runCommand: () => runCommand6,
84637
+ runExitCode: () => runExitCode
84638
+ });
84639
+ import { constants } from "node:os";
84640
+ import {
84641
+ canonicalForClass,
84642
+ isWatchCommand,
84643
+ resolveRunClass
84644
+ } from "@cleocode/core/resources/run-admission.js";
84645
+ import { runGoverned } from "@cleocode/core/resources/run-governed.js";
84646
+ import { heavyToolEnv } from "@cleocode/core/tasks/heavy-tool-env.js";
84647
+ function commandAfterDashes(rawArgs) {
84648
+ const idx = rawArgs.indexOf("--");
84649
+ return idx === -1 ? [] : rawArgs.slice(idx + 1);
84650
+ }
84651
+ function invalid(message, fix, stderr2) {
84652
+ cliError(
84653
+ message,
84654
+ "E_VALIDATION",
84655
+ { name: "E_VALIDATION", fix },
84656
+ { operation: "resources.run" },
84657
+ { stderr: stderr2 }
84658
+ );
84659
+ process.exit(6);
84660
+ }
84661
+ function runExitCode(r) {
84662
+ if (r.spawnError !== null) return 127;
84663
+ if (r.signal !== null) return 128 + (constants.signals[r.signal] ?? 0);
84664
+ return r.exitCode ?? 1;
84665
+ }
84666
+ function exitFailed(result, code, passthrough) {
84667
+ const { kind: _kind, ...data } = result;
84668
+ const message = result.spawnError !== null ? `could not start command: ${result.spawnError}` : `command ${result.signal !== null ? `killed by ${result.signal}` : `exited with ${result.exitCode}`}`;
84669
+ if (passthrough && result.spawnError === null) {
84670
+ process.stderr.write(`[cleo run] ${RUN_COMMAND_FAILED_CODE}: ${message}
84671
+ `);
84672
+ } else {
84673
+ cliError(
84674
+ message,
84675
+ RUN_COMMAND_FAILED_CODE,
84676
+ { name: RUN_COMMAND_FAILED_CODE, details: data },
84677
+ { operation: "resources.run" },
84678
+ { stderr: passthrough }
84679
+ );
84680
+ }
84681
+ process.exit(code);
84682
+ }
84683
+ var runCommand6;
84684
+ var init_run = __esm({
84685
+ "packages/cleo/src/cli/commands/run.ts"() {
84686
+ "use strict";
84687
+ init_src2();
84688
+ init_define_cli_command();
84689
+ init_renderers();
84690
+ runCommand6 = defineCommand({
84691
+ meta: {
84692
+ name: "run",
84693
+ description: "Run a heavy command (tests, builds, installs) under the machine-wide resource budget: cleo run [--class test|build|full-build] [--wait] [--passthrough] -- <command...>"
84694
+ },
84695
+ args: {
84696
+ class: {
84697
+ type: "string",
84698
+ description: "Resource class: test, build, typecheck, install, scan, full-build, db (default: inferred from the command)"
84699
+ },
84700
+ wait: {
84701
+ type: "boolean",
84702
+ description: "Join the FIFO queue for the class instead of returning E_RESOURCE_DEFERRED",
84703
+ default: false
84704
+ },
84705
+ timeout: {
84706
+ type: "string",
84707
+ description: "With --wait: give up after this many seconds (default 1800)"
84708
+ },
84709
+ passthrough: {
84710
+ type: "boolean",
84711
+ description: "Give the command this process's stdin, stdout and stderr and exit with its code. cleo run then writes nothing to stdout (an explicit ADR-086 exception, like docs fetch --content): its own envelopes go to stderr, and it prints only a deferral (exit 75), an ungoverned run, a pause or a failure",
84712
+ default: false
84713
+ }
84714
+ },
84715
+ async run({ args, rawArgs }) {
84716
+ const passthrough = args.passthrough === true;
84717
+ const argv = commandAfterDashes(rawArgs ?? []);
84718
+ if (argv.length === 0) {
84719
+ invalid(
84720
+ "cleo run needs a command after --",
84721
+ "cleo run --class test -- npx vitest run path/to/file.test.ts",
84722
+ passthrough
84723
+ );
84724
+ }
84725
+ if (args.class === void 0 && isWatchCommand(argv)) {
84726
+ invalid(
84727
+ `cleo run refuses watch/dev/serve commands, which never exit and would hold a resource slot forever: ${argv.join(" ")}`,
84728
+ "Run the watcher directly, without cleo run. If it is a bounded job, say so with --class (cleo run --class test -- <cmd>)",
84729
+ passthrough
84730
+ );
84731
+ }
84732
+ let timeoutMs = 18e5;
84733
+ if (args.timeout !== void 0) {
84734
+ if (!args.wait)
84735
+ invalid("--timeout requires --wait", "cleo run --wait --timeout 600 -- <cmd>", passthrough);
84736
+ const seconds = Number(args.timeout);
84737
+ if (!Number.isFinite(seconds) || seconds <= 0) {
84738
+ invalid(
84739
+ `--timeout must be a positive number of seconds (got '${args.timeout}')`,
84740
+ "--timeout 600",
84741
+ passthrough
84742
+ );
84743
+ }
84744
+ timeoutMs = seconds * 1e3;
84745
+ }
84746
+ let cls;
84747
+ try {
84748
+ cls = resolveRunClass(args.class, argv, process.cwd());
84749
+ } catch (err) {
84750
+ invalid(
84751
+ err instanceof Error ? err.message : String(err),
84752
+ "cleo run --class test -- <cmd>",
84753
+ passthrough
84754
+ );
84755
+ }
84756
+ let result;
84757
+ try {
84758
+ result = await runGoverned({
84759
+ argv,
84760
+ cls,
84761
+ cwd: process.cwd(),
84762
+ env: { ...process.env, ...heavyToolEnv(canonicalForClass(cls)) },
84763
+ sessionId: process.env.CLEO_SESSION_ID ?? process.env.CLAUDE_CODE_SESSION_ID ?? null,
84764
+ wait: Boolean(args.wait),
84765
+ timeoutMs,
84766
+ passthrough,
84767
+ // A terminal on stdin: keep the child in its foreground group.
84768
+ foreground: passthrough && process.stdin.isTTY === true,
84769
+ // Notices go to stderr; stdout carries only the final LAFS envelope, or
84770
+ // with --passthrough only the child's output (and then only warnings).
84771
+ notice: (line, level) => {
84772
+ if (passthrough && level === "info") return;
84773
+ process.stderr.write(`[cleo run] ${line}
84774
+ `);
84775
+ }
84776
+ });
84777
+ } catch (err) {
84778
+ cliError(
84779
+ `cleo run failed: ${err instanceof Error ? err.message : String(err)}`,
84780
+ 1,
84781
+ { name: "E_GENERAL" },
84782
+ { operation: "resources.run" },
84783
+ { stderr: passthrough }
84784
+ );
84785
+ process.exit(1);
84786
+ }
84787
+ if (result.kind === "deferred") {
84788
+ cliError(
84789
+ `not started: ${result.reason}`,
84790
+ RESOURCE_DEFERRED_CODE,
84791
+ {
84792
+ name: RESOURCE_DEFERRED_CODE,
84793
+ details: result.details,
84794
+ fix: result.fix,
84795
+ alternatives: result.alternatives
84796
+ },
84797
+ { operation: "resources.run" },
84798
+ { stderr: passthrough }
84799
+ );
84800
+ process.exit(RUN_DEFERRED_EXIT_CODE);
84801
+ }
84802
+ const code = runExitCode(result);
84803
+ if (code !== 0) exitFailed(result, code, passthrough);
84804
+ if (passthrough) return;
84805
+ const { kind: _kind, ...data } = result;
84806
+ cliOutput(data, { command: "run", operation: "resources.run" });
84807
+ }
84808
+ });
84809
+ }
84810
+ });
84811
+
83394
84812
  // packages/cleo/src/cli/commands/safestop.ts
83395
84813
  var safestop_exports = {};
83396
84814
  __export(safestop_exports, {
@@ -83687,8 +85105,8 @@ var init_saga = __esm({
83687
85105
  }
83688
85106
  },
83689
85107
  async run({ args }) {
83690
- const { sagas: sagas2, getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
83691
- const projectRoot = getProjectRoot75();
85108
+ const { sagas: sagas2, getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
85109
+ const projectRoot = getProjectRoot76();
83692
85110
  const sagaId = typeof args.sagaId === "string" && args.sagaId.length > 0 ? args.sagaId : void 0;
83693
85111
  const result = await sagas2.sagaNext(projectRoot, { sagaId });
83694
85112
  cliOutput(result.success ? result.data : result, { command: "saga", operation: "saga.next" });
@@ -83902,7 +85320,7 @@ __export(self_update_exports, {
83902
85320
  });
83903
85321
  import { execFile } from "node:child_process";
83904
85322
  import { readFile as readFile9 } from "node:fs/promises";
83905
- import { join as join30 } from "node:path";
85323
+ import { join as join31 } from "node:path";
83906
85324
  import * as readline3 from "node:readline";
83907
85325
  import { promisify } from "node:util";
83908
85326
  import {
@@ -83917,7 +85335,7 @@ import {
83917
85335
  async function getCurrentVersion() {
83918
85336
  const cleoHome = getCleoHome7();
83919
85337
  try {
83920
- const content = await readFile9(join30(cleoHome, "VERSION"), "utf-8");
85338
+ const content = await readFile9(join31(cleoHome, "VERSION"), "utf-8");
83921
85339
  return (content.split("\n")[0] ?? "unknown").trim();
83922
85340
  } catch {
83923
85341
  return "unknown";
@@ -83971,7 +85389,7 @@ async function writeRuntimeVersionMetadata(mode, source, version) {
83971
85389
  ];
83972
85390
  await import("node:fs/promises").then(
83973
85391
  ({ writeFile: writeFile4, mkdir: mkdir7 }) => mkdir7(cleoHome, { recursive: true }).then(
83974
- () => writeFile4(join30(cleoHome, "VERSION"), `${lines.join("\n")}
85392
+ () => writeFile4(join31(cleoHome, "VERSION"), `${lines.join("\n")}
83975
85393
  `, "utf-8")
83976
85394
  )
83977
85395
  );
@@ -84383,13 +85801,13 @@ var selfimprove_exports = {};
84383
85801
  __export(selfimprove_exports, {
84384
85802
  selfimproveCommand: () => selfimproveCommand
84385
85803
  });
84386
- var runCommand6, selfimproveCommand;
85804
+ var runCommand7, selfimproveCommand;
84387
85805
  var init_selfimprove2 = __esm({
84388
85806
  "packages/cleo/src/cli/commands/selfimprove.ts"() {
84389
85807
  "use strict";
84390
85808
  init_cli();
84391
85809
  init_define_cli_command();
84392
- runCommand6 = defineCommand({
85810
+ runCommand7 = defineCommand({
84393
85811
  meta: {
84394
85812
  name: "run",
84395
85813
  description: "Run ONE self-improvement loop iteration: boot a sandbox, replay a canned scenario, diff vs golden; on regression emit ONE leased DHQ row + ONE DRAFT PR. DEFAULT OFF \u2014 pass --execute to act (else DRY-RUN: replay + diff + report only)."
@@ -84434,7 +85852,7 @@ var init_selfimprove2 = __esm({
84434
85852
  description: "Self-improvement loop \u2014 replay a canned dogfood scenario, diff vs golden, and surface regressions as leased DHQ rows + DRAFT PRs. Default OFF (requires --execute to act)."
84435
85853
  },
84436
85854
  subCommands: {
84437
- run: runCommand6
85855
+ run: runCommand7
84438
85856
  },
84439
85857
  async run({ cmd, rawArgs }) {
84440
85858
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
@@ -84452,7 +85870,7 @@ __export(sentient_exports, {
84452
85870
  promptAcceptExecution: () => promptAcceptExecution,
84453
85871
  sentientCommand: () => sentientCommand
84454
85872
  });
84455
- import { join as join31 } from "node:path";
85873
+ import { join as join32 } from "node:path";
84456
85874
  import { cwd as processCwd3, stdin, stdout } from "node:process";
84457
85875
  import { createInterface as createInterface4 } from "node:readline/promises";
84458
85876
  import {
@@ -84542,7 +85960,7 @@ var init_sentient3 = __esm({
84542
85960
  return;
84543
85961
  }
84544
85962
  if (dryRun) {
84545
- const statePath2 = join31(projectRoot, SENTIENT_STATE_FILE2);
85963
+ const statePath2 = join32(projectRoot, SENTIENT_STATE_FILE2);
84546
85964
  const outcome = await safeRunTick({ projectRoot, statePath: statePath2, dryRun: true });
84547
85965
  emitSuccess2(
84548
85966
  { dryRun: true, outcome },
@@ -84658,7 +86076,7 @@ Logs: ${logPath}`
84658
86076
  const jsonMode = args.json === true;
84659
86077
  const dryRun = args["dry-run"] === true;
84660
86078
  try {
84661
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86079
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84662
86080
  const outcome = await safeRunTick({ projectRoot, statePath, dryRun });
84663
86081
  emitSuccess2(
84664
86082
  { outcome, dryRun },
@@ -84750,7 +86168,7 @@ Logs: ${logPath}`
84750
86168
  return;
84751
86169
  }
84752
86170
  await db.update(tasks).set({ status: "pending", updatedAt: now }).where(eq2(tasks.id, id)).run();
84753
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86171
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84754
86172
  const state = await readSentientState2(statePath);
84755
86173
  await patchSentientState(statePath, {
84756
86174
  tier2Stats: {
@@ -84846,7 +86264,7 @@ Logs: ${logPath}`
84846
86264
  return;
84847
86265
  }
84848
86266
  await db.update(tasks).set({ status: "cancelled", cancellationReason: reason, cancelledAt: now, updatedAt: now }).where(eq2(tasks.id, id)).run();
84849
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86267
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84850
86268
  const state = await readSentientState2(statePath);
84851
86269
  await patchSentientState(statePath, {
84852
86270
  tier2Stats: {
@@ -84891,7 +86309,7 @@ Logs: ${logPath}`
84891
86309
  const projectRoot = resolveProjectRoot5(args.project);
84892
86310
  const jsonMode = args.json === true;
84893
86311
  try {
84894
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86312
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84895
86313
  const outcome = await safeRunProposeTick({ projectRoot, statePath });
84896
86314
  emitSuccess2(
84897
86315
  { outcome },
@@ -84911,7 +86329,7 @@ Logs: ${logPath}`
84911
86329
  const projectRoot = resolveProjectRoot5(args.project);
84912
86330
  const jsonMode = args.json === true;
84913
86331
  try {
84914
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86332
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84915
86333
  const updated = await patchSentientState(statePath, { tier2Enabled: true });
84916
86334
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals enabled");
84917
86335
  } catch (err) {
@@ -84930,7 +86348,7 @@ Logs: ${logPath}`
84930
86348
  const projectRoot = resolveProjectRoot5(args.project);
84931
86349
  const jsonMode = args.json === true;
84932
86350
  try {
84933
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86351
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84934
86352
  const updated = await patchSentientState(statePath, { tier2Enabled: false });
84935
86353
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals disabled");
84936
86354
  } catch (err) {
@@ -84961,7 +86379,7 @@ Logs: ${logPath}`
84961
86379
  const projectRoot = resolveProjectRoot5(args.project);
84962
86380
  const jsonMode = args.json === true;
84963
86381
  try {
84964
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86382
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84965
86383
  const state = await readSentientState2(statePath);
84966
86384
  emitSuccess2(
84967
86385
  {
@@ -85519,7 +86937,7 @@ var sequence_exports = {};
85519
86937
  __export(sequence_exports, {
85520
86938
  sequenceCommand: () => sequenceCommand
85521
86939
  });
85522
- import { getProjectRoot as getProjectRoot70 } from "@cleocode/core/internal";
86940
+ import { getProjectRoot as getProjectRoot71 } from "@cleocode/core/internal";
85523
86941
  var showCommand12, checkCommand7, repairCommand3, sequenceCommand;
85524
86942
  var init_sequence = __esm({
85525
86943
  "packages/cleo/src/cli/commands/sequence.ts"() {
@@ -85555,7 +86973,7 @@ var init_sequence = __esm({
85555
86973
  meta: { name: "repair", description: "Reset counter to max + 1 if behind" },
85556
86974
  async run() {
85557
86975
  const { repairSequence } = await import("@cleocode/core/internal");
85558
- const projectRoot = getProjectRoot70();
86976
+ const projectRoot = getProjectRoot71();
85559
86977
  const repair = await repairSequence(projectRoot);
85560
86978
  const result = {
85561
86979
  repaired: repair.repaired,
@@ -86152,8 +87570,8 @@ var init_session4 = __esm({
86152
87570
  "audit-scope": { type: "string", description: "Audit log scope (global|local)" }
86153
87571
  },
86154
87572
  async run({ args }) {
86155
- const { detectSessionDrift, getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
86156
- const projectRoot = await getProjectRoot75();
87573
+ const { detectSessionDrift, getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
87574
+ const projectRoot = await getProjectRoot76();
86157
87575
  const scope = args["audit-scope"] === "local" ? "local" : "global";
86158
87576
  const report = await detectSessionDrift({ projectRoot, auditScope: scope });
86159
87577
  cliOutput(report, { command: "session drift", operation: "session.drift" });
@@ -88552,10 +89970,10 @@ var init_sync = __esm({
88552
89970
  }
88553
89971
  },
88554
89972
  async run({ args }) {
88555
- const { readFileSync: readFileSync22 } = await import("node:fs");
89973
+ const { readFileSync: readFileSync23 } = await import("node:fs");
88556
89974
  let externalTasks;
88557
89975
  try {
88558
- externalTasks = JSON.parse(readFileSync22(args.file, "utf8"));
89976
+ externalTasks = JSON.parse(readFileSync23(args.file, "utf8"));
88559
89977
  } catch (err) {
88560
89978
  const message = err instanceof Error ? err.message : String(err);
88561
89979
  cliError(`Failed to read or parse external tasks file: ${message}`, 2, {
@@ -88852,19 +90270,19 @@ var init_telemetry2 = __esm({
88852
90270
  });
88853
90271
 
88854
90272
  // packages/cleo/src/cli/commands/templates/lib.ts
88855
- import { readFileSync as readFileSync13 } from "node:fs";
90273
+ import { readFileSync as readFileSync14 } from "node:fs";
88856
90274
  import { isAbsolute as isAbsolute3, resolve as resolve10 } from "node:path";
88857
- import { getProjectRoot as getProjectRoot71 } from "@cleocode/core";
90275
+ import { getProjectRoot as getProjectRoot72 } from "@cleocode/core";
88858
90276
  import { resolveSourcePathAbsolute } from "@cleocode/core/templates/registry";
88859
90277
  function resolveProjectRoot6(raw) {
88860
90278
  if (typeof raw === "string" && raw.length > 0) {
88861
90279
  return isAbsolute3(raw) ? raw : resolve10(process.cwd(), raw);
88862
90280
  }
88863
- return getProjectRoot71();
90281
+ return getProjectRoot72();
88864
90282
  }
88865
90283
  function readTemplateSource(entry) {
88866
90284
  const sourceAbsolute = resolveSourcePathAbsolute(entry);
88867
- return readFileSync13(sourceAbsolute, "utf8");
90285
+ return readFileSync14(sourceAbsolute, "utf8");
88868
90286
  }
88869
90287
  function applySubstitution(entry, source) {
88870
90288
  if (entry.substitution === "static") {
@@ -88879,8 +90297,8 @@ var init_lib = __esm({
88879
90297
  });
88880
90298
 
88881
90299
  // packages/cleo/src/cli/commands/templates/diff.ts
88882
- import { existsSync as existsSync17, readFileSync as readFileSync14 } from "node:fs";
88883
- import { join as join32 } from "node:path";
90300
+ import { existsSync as existsSync17, readFileSync as readFileSync15 } from "node:fs";
90301
+ import { join as join33 } from "node:path";
88884
90302
  import { getTemplateById } from "@cleocode/core/templates/registry";
88885
90303
  function unifiedDiff(a, b) {
88886
90304
  const aLines = a.length === 0 ? [] : a.split("\n");
@@ -88950,7 +90368,7 @@ var init_diff = __esm({
88950
90368
  let rendered;
88951
90369
  try {
88952
90370
  projectRoot = resolveProjectRoot6(args["project"]);
88953
- installPath = join32(projectRoot, entry.installPath);
90371
+ installPath = join33(projectRoot, entry.installPath);
88954
90372
  const source = readTemplateSource(entry);
88955
90373
  rendered = applySubstitution(entry, source).rendered;
88956
90374
  } catch (err) {
@@ -88978,7 +90396,7 @@ ${unifiedDiff("", rendered)}`
88978
90396
  process.exit(1 /* GENERAL_ERROR */);
88979
90397
  return;
88980
90398
  }
88981
- const current = readFileSync14(installPath, "utf8");
90399
+ const current = readFileSync15(installPath, "utf8");
88982
90400
  const same = current === rendered;
88983
90401
  const result = {
88984
90402
  id,
@@ -89000,8 +90418,8 @@ ${unifiedDiff("", rendered)}`
89000
90418
  });
89001
90419
 
89002
90420
  // packages/cleo/src/cli/commands/templates/install.ts
89003
- import { existsSync as existsSync18, mkdirSync as mkdirSync5, readFileSync as readFileSync15, writeFileSync as writeFileSync6 } from "node:fs";
89004
- import { dirname as dirname10, join as join33 } from "node:path";
90421
+ import { existsSync as existsSync18, mkdirSync as mkdirSync5, readFileSync as readFileSync16, writeFileSync as writeFileSync6 } from "node:fs";
90422
+ import { dirname as dirname10, join as join34 } from "node:path";
89005
90423
  import { getTemplateById as getTemplateById2 } from "@cleocode/core/templates/registry";
89006
90424
  var templatesInstallCommand;
89007
90425
  var init_install = __esm({
@@ -89055,7 +90473,7 @@ var init_install = __esm({
89055
90473
  let substituted;
89056
90474
  try {
89057
90475
  projectRoot = resolveProjectRoot6(args["project"]);
89058
- installPath = join33(projectRoot, entry.installPath);
90476
+ installPath = join34(projectRoot, entry.installPath);
89059
90477
  const source = readTemplateSource(entry);
89060
90478
  const sub = applySubstitution(entry, source);
89061
90479
  rendered = sub.rendered;
@@ -89069,7 +90487,7 @@ var init_install = __esm({
89069
90487
  return;
89070
90488
  }
89071
90489
  if (existsSync18(installPath)) {
89072
- const current = readFileSync15(installPath, "utf8");
90490
+ const current = readFileSync16(installPath, "utf8");
89073
90491
  if (current === rendered) {
89074
90492
  const noopResult = {
89075
90493
  id,
@@ -89217,8 +90635,8 @@ var init_show3 = __esm({
89217
90635
  });
89218
90636
 
89219
90637
  // packages/cleo/src/cli/commands/templates/upgrade.ts
89220
- import { existsSync as existsSync19, mkdirSync as mkdirSync6, readFileSync as readFileSync16, writeFileSync as writeFileSync7 } from "node:fs";
89221
- import { dirname as dirname11, join as join34 } from "node:path";
90638
+ import { existsSync as existsSync19, mkdirSync as mkdirSync6, readFileSync as readFileSync17, writeFileSync as writeFileSync7 } from "node:fs";
90639
+ import { dirname as dirname11, join as join35 } from "node:path";
89222
90640
  import { getTemplateById as getTemplateById4 } from "@cleocode/core/templates/registry";
89223
90641
  var templatesUpgradeCommand;
89224
90642
  var init_upgrade2 = __esm({
@@ -89280,7 +90698,7 @@ var init_upgrade2 = __esm({
89280
90698
  let rendered;
89281
90699
  try {
89282
90700
  projectRoot = resolveProjectRoot6(args["project"]);
89283
- installPath = join34(projectRoot, entry.installPath);
90701
+ installPath = join35(projectRoot, entry.installPath);
89284
90702
  const source = readTemplateSource(entry);
89285
90703
  rendered = applySubstitution(entry, source).rendered;
89286
90704
  } catch (err) {
@@ -89293,7 +90711,7 @@ var init_upgrade2 = __esm({
89293
90711
  }
89294
90712
  const previewOnly = args["diff"] === true;
89295
90713
  const accept = args["accept"] === true;
89296
- const current = existsSync19(installPath) ? readFileSync16(installPath, "utf8") : null;
90714
+ const current = existsSync19(installPath) ? readFileSync17(installPath, "utf8") : null;
89297
90715
  const diffBody = current === null ? "" : current === rendered ? "" : unifiedDiff(current, rendered);
89298
90716
  let outcome;
89299
90717
  let reason;
@@ -89517,7 +90935,7 @@ var testing_exports = {};
89517
90935
  __export(testing_exports, {
89518
90936
  testingCommand: () => testingCommand
89519
90937
  });
89520
- var validateCommand9, checkCommand8, statusCommand18, coverageCommand, runCommand7, testingCommand;
90938
+ var validateCommand9, checkCommand8, statusCommand18, coverageCommand, runCommand8, testingCommand;
89521
90939
  var init_testing = __esm({
89522
90940
  "packages/cleo/src/cli/commands/testing.ts"() {
89523
90941
  "use strict";
@@ -89602,7 +91020,7 @@ var init_testing = __esm({
89602
91020
  );
89603
91021
  }
89604
91022
  });
89605
- runCommand7 = defineCommand({
91023
+ runCommand8 = defineCommand({
89606
91024
  meta: { name: "run", description: "Run test suite" },
89607
91025
  args: {
89608
91026
  filter: {
@@ -89627,7 +91045,7 @@ var init_testing = __esm({
89627
91045
  check: checkCommand8,
89628
91046
  status: statusCommand18,
89629
91047
  coverage: coverageCommand,
89630
- run: runCommand7
91048
+ run: runCommand8
89631
91049
  },
89632
91050
  async run({ cmd, rawArgs }) {
89633
91051
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
@@ -89643,12 +91061,12 @@ var token_exports = {};
89643
91061
  __export(token_exports, {
89644
91062
  tokenCommand: () => tokenCommand
89645
91063
  });
89646
- import { readFileSync as readFileSync17 } from "node:fs";
89647
- import { getProjectRoot as getProjectRoot72, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
91064
+ import { readFileSync as readFileSync18 } from "node:fs";
91065
+ import { getProjectRoot as getProjectRoot73, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
89648
91066
  function readPayload(args, textKey, fileKey) {
89649
91067
  const text = args[textKey];
89650
91068
  const file = args[fileKey];
89651
- if (file) return readFileSync17(file, "utf-8");
91069
+ if (file) return readFileSync18(file, "utf-8");
89652
91070
  return text;
89653
91071
  }
89654
91072
  var filterArgs, summaryCommand3, listCommand26, showCommand16, deleteCommand3, clearCommand2, estimateCommand, tokenCommand;
@@ -89808,7 +91226,7 @@ var init_token = __esm({
89808
91226
  domain: args.domain,
89809
91227
  operation: args.operation
89810
91228
  };
89811
- const result = args.record ? await recordTokenExchange2(getProjectRoot72(), input2) : await measureTokenExchange(input2);
91229
+ const result = args.record ? await recordTokenExchange2(getProjectRoot73(), input2) : await measureTokenExchange(input2);
89812
91230
  cliOutput(result, {
89813
91231
  command: "token",
89814
91232
  operation: args.record ? "admin.token.record" : "token.estimate"
@@ -89842,9 +91260,9 @@ var transcript_exports = {};
89842
91260
  __export(transcript_exports, {
89843
91261
  transcriptCommand: () => transcriptCommand
89844
91262
  });
89845
- import { homedir as homedir3 } from "node:os";
89846
- import { join as join35 } from "node:path";
89847
- import { getProjectRoot as getProjectRoot73 } from "@cleocode/core";
91263
+ import { homedir as homedir4 } from "node:os";
91264
+ import { join as join36 } from "node:path";
91265
+ import { getProjectRoot as getProjectRoot74 } from "@cleocode/core";
89848
91266
  import {
89849
91267
  parseDurationMs,
89850
91268
  pruneTranscripts,
@@ -89874,7 +91292,7 @@ var init_transcript = __esm({
89874
91292
  async run({ args }) {
89875
91293
  if (args.pending) {
89876
91294
  try {
89877
- const projectRoot = getProjectRoot73();
91295
+ const projectRoot = getProjectRoot74();
89878
91296
  const { scanPendingTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
89879
91297
  const pending = await scanPendingTranscripts(projectRoot);
89880
91298
  cliOutput(
@@ -89897,7 +91315,7 @@ var init_transcript = __esm({
89897
91315
  }
89898
91316
  return;
89899
91317
  }
89900
- const projectsDir = args["projects-dir"] ?? join35(homedir3(), ".claude", "projects");
91318
+ const projectsDir = args["projects-dir"] ?? join36(homedir4(), ".claude", "projects");
89901
91319
  try {
89902
91320
  const result = await scanTranscripts(projectsDir);
89903
91321
  cliOutput(
@@ -89971,7 +91389,7 @@ var init_transcript = __esm({
89971
91389
  async run({ args }) {
89972
91390
  const tier = args.tier ?? "warm";
89973
91391
  const dryRun = args["dry-run"] ?? false;
89974
- const projectRoot = getProjectRoot73();
91392
+ const projectRoot = getProjectRoot74();
89975
91393
  try {
89976
91394
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
89977
91395
  const { findSessionTranscriptPath, listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -90087,7 +91505,7 @@ var init_transcript = __esm({
90087
91505
  const dryRun = args["dry-run"] ?? false;
90088
91506
  const olderThanHours = args["older-than-hours"] ? Number.parseInt(args["older-than-hours"], 10) : 24;
90089
91507
  const limit = args.limit ? Number.parseInt(args.limit, 10) : void 0;
90090
- const projectRoot = getProjectRoot73();
91508
+ const projectRoot = getProjectRoot74();
90091
91509
  try {
90092
91510
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
90093
91511
  const { listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -90207,7 +91625,7 @@ var init_transcript = __esm({
90207
91625
  process.exit(2);
90208
91626
  return;
90209
91627
  }
90210
- const projectsDir = args["projects-dir"] ?? join35(homedir3(), ".claude", "projects");
91628
+ const projectsDir = args["projects-dir"] ?? join36(homedir4(), ".claude", "projects");
90211
91629
  try {
90212
91630
  const pruneResult = await pruneTranscripts({
90213
91631
  olderThanMs,
@@ -90274,10 +91692,10 @@ __export(gateway_auto_start_exports, {
90274
91692
  spawnGatewayIfDown: () => spawnGatewayIfDown
90275
91693
  });
90276
91694
  import { once } from "node:events";
90277
- import { createWriteStream, existsSync as existsSync20, readFileSync as readFileSync18, realpathSync } from "node:fs";
91695
+ import { createWriteStream, existsSync as existsSync20, readFileSync as readFileSync19, realpathSync } from "node:fs";
90278
91696
  import { mkdir as mkdir6 } from "node:fs/promises";
90279
91697
  import * as net from "node:net";
90280
- import { dirname as dirname12, join as join36 } from "node:path";
91698
+ import { dirname as dirname12, join as join37 } from "node:path";
90281
91699
  import { fileURLToPath as fileURLToPath6 } from "node:url";
90282
91700
  import { spawnWrapped } from "@cleocode/core/resources/spawn-wrapper.js";
90283
91701
  function shouldAutoStartGateway(config) {
@@ -90321,17 +91739,17 @@ function resolveCliEntryPath(startUrl = import.meta.url) {
90321
91739
  const startFile = realpathSync(fileURLToPath6(startUrl));
90322
91740
  let current = dirname12(startFile);
90323
91741
  for (let i = 0; i < 20; i++) {
90324
- const pkgJsonPath = join36(current, "package.json");
91742
+ const pkgJsonPath = join37(current, "package.json");
90325
91743
  if (existsSync20(pkgJsonPath)) {
90326
91744
  let pkgName;
90327
91745
  try {
90328
- const raw = readFileSync18(pkgJsonPath, "utf8");
91746
+ const raw = readFileSync19(pkgJsonPath, "utf8");
90329
91747
  const parsed = JSON.parse(raw);
90330
91748
  pkgName = typeof parsed["name"] === "string" ? parsed["name"] : void 0;
90331
91749
  } catch {
90332
91750
  }
90333
91751
  if (pkgName === CLEO_PACKAGE_NAME) {
90334
- const entry = join36(current, "dist", "cli", "index.js");
91752
+ const entry = join37(current, "dist", "cli", "index.js");
90335
91753
  if (!existsSync20(entry)) {
90336
91754
  throw new Error(
90337
91755
  `@cleocode/cleo package root found at ${current} but dist/cli/index.js is missing \u2014 run \`pnpm --filter @cleocode/cleo run build\` to generate it`
@@ -90368,8 +91786,8 @@ async function spawnGatewayIfDown(opts = {}) {
90368
91786
  const { getCleoLogDir } = await import("@cleocode/core");
90369
91787
  const logDir = getCleoLogDir();
90370
91788
  await mkdir6(logDir, { recursive: true });
90371
- const outStream = createWriteStream(join36(logDir, "gateway.log"), { flags: "a" });
90372
- const errStream = createWriteStream(join36(logDir, "gateway.err"), { flags: "a" });
91789
+ const outStream = createWriteStream(join37(logDir, "gateway.log"), { flags: "a" });
91790
+ const errStream = createWriteStream(join37(logDir, "gateway.err"), { flags: "a" });
90373
91791
  await Promise.all([once(outStream, "open"), once(errStream, "open")]);
90374
91792
  outFd = outStream;
90375
91793
  errFd = errStream;
@@ -90828,8 +92246,8 @@ __export(cockpit_exports, {
90828
92246
  KanbanBoardComponent: () => KanbanBoardComponent,
90829
92247
  runCockpit: () => runCockpit
90830
92248
  });
90831
- import { readFileSync as readFileSync19 } from "node:fs";
90832
- import { join as join37 } from "node:path";
92249
+ import { readFileSync as readFileSync20 } from "node:fs";
92250
+ import { join as join38 } from "node:path";
90833
92251
  import { createCleoClient as createCleoClient2 } from "@cleocode/core/gateway-client";
90834
92252
  async function fetchTaskRows(baseUrl) {
90835
92253
  const client = createCleoClient2({ baseUrl });
@@ -90946,8 +92364,8 @@ async function runCockpit(options = {}, sink = (line) => process.stdout.write(`$
90946
92364
  }
90947
92365
  try {
90948
92366
  const { getCleoLogDir } = await import("@cleocode/core");
90949
- const errPath = join37(getCleoLogDir(), "gateway.err");
90950
- const errContent = readFileSync19(errPath, "utf8").trimEnd();
92367
+ const errPath = join38(getCleoLogDir(), "gateway.err");
92368
+ const errContent = readFileSync20(errPath, "utf8").trimEnd();
90951
92369
  if (errContent.length > 0) {
90952
92370
  const lastLine = errContent.split("\n").at(-1) ?? "";
90953
92371
  if (lastLine.length > 0) {
@@ -91975,7 +93393,7 @@ var init_verify = __esm({
91975
93393
  },
91976
93394
  evidence: {
91977
93395
  type: "string",
91978
- description: "Evidence for the gate (T832/ADR-051). Semicolon-separated atoms: 'commit:<sha>', 'files:<p1,p2>', 'test-run:<json>', 'tool:<name>', 'url:<url>', 'note:<text>', 'ci:<pr>' (required CI green on the merged PR's merge commit; testsPassed/qaPassed, opt-in via evidence.ciSatisfies)."
93396
+ description: "Evidence for the gate (T832/ADR-051). Semicolon-separated atoms: 'commit:<sha>', 'files:<p1,p2>', 'test-run:<json>', 'tool:<name>' (e.g. tool:test, tool:test-affected, tool:lint), 'url:<url>', 'note:<text>', 'ci:<pr>' (required CI green on the merged PR's merge commit; testsPassed/qaPassed, opt-in via evidence.ciSatisfies)."
91979
93397
  },
91980
93398
  explain: {
91981
93399
  type: "boolean",
@@ -91997,6 +93415,10 @@ var init_verify = __esm({
91997
93415
  type: "string",
91998
93416
  description: "With --auto: the merged PR that implements the task"
91999
93417
  },
93418
+ fresh: {
93419
+ type: "boolean",
93420
+ description: "Bypass the ADR-061 tool cache and re-run every tool: atom (same as CLEO_EVIDENCE_FRESH=1, which still works). Use only when a cached result is suspect, e.g. after adding an untracked file (T12964)."
93421
+ },
92000
93422
  "shared-evidence": {
92001
93423
  type: "boolean",
92002
93424
  description: "Acknowledge that the same evidence atom is applied to >3 distinct tasks in this session (T1502 / ADR-059). Without this flag, such reuse triggers a warning; in strict mode (CLEO_STRICT_EVIDENCE=1) it is a hard reject."
@@ -92008,76 +93430,85 @@ var init_verify = __esm({
92008
93430
  return;
92009
93431
  }
92010
93432
  const isWrite = !!(args.gate || args.all || args.reset);
92011
- if (args.auto === true) {
92012
- if (isWrite || args.evidence || args.run === true) {
92013
- cliError(
92014
- "--auto derives its own evidence; drop --gate/--all/--reset/--evidence/--run",
92015
- "E_INVALID_INPUT"
92016
- );
92017
- process.exitCode = 6 /* VALIDATION_ERROR */;
93433
+ const priorFresh = process.env["CLEO_EVIDENCE_FRESH"];
93434
+ if (args.fresh === true) process.env["CLEO_EVIDENCE_FRESH"] = "1";
93435
+ try {
93436
+ if (args.auto === true) {
93437
+ if (isWrite || args.evidence || args.run === true) {
93438
+ cliError(
93439
+ "--auto derives its own evidence; drop --gate/--all/--reset/--evidence/--run",
93440
+ "E_INVALID_INPUT"
93441
+ );
93442
+ process.exitCode = 6 /* VALIDATION_ERROR */;
93443
+ return;
93444
+ }
93445
+ const { parseDoneOptions } = await import("@cleocode/core/tasks/done-plan.js");
93446
+ const parsed = parseDoneOptions(args.satisfies, args.pr);
93447
+ if (!parsed.ok) {
93448
+ cliError(parsed.message, "E_INVALID_INPUT");
93449
+ process.exitCode = 6 /* VALIDATION_ERROR */;
93450
+ return;
93451
+ }
93452
+ const { recordTaskDone } = await import("@cleocode/core/tasks/done-record.js");
93453
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/paths.js");
93454
+ const r = await recordTaskDone(args.taskId, {
93455
+ projectRoot: getProjectRoot76(),
93456
+ ...parsed.options,
93457
+ ...args.agent ? { agent: args.agent } : {}
93458
+ });
93459
+ if (!r.success) {
93460
+ cliError(r.error.message, r.error.code, { fix: r.error.fix, details: r.error.details });
93461
+ process.exitCode = r.error.exitCode ?? 1;
93462
+ return;
93463
+ }
93464
+ const { plan: _plan, ...summary } = r.data;
93465
+ cliOutput(summary, { command: "verify", operation: "check.gate.auto" });
92018
93466
  return;
92019
93467
  }
92020
- const { parseDoneOptions } = await import("@cleocode/core/tasks/done-plan.js");
92021
- const parsed = parseDoneOptions(args.satisfies, args.pr);
92022
- if (!parsed.ok) {
92023
- cliError(parsed.message, "E_INVALID_INPUT");
93468
+ if (args.satisfies !== void 0 || args.pr !== void 0) {
93469
+ cliError("--satisfies and --pr apply only with --auto (or cleo done)", "E_INVALID_INPUT");
92024
93470
  process.exitCode = 6 /* VALIDATION_ERROR */;
92025
93471
  return;
92026
93472
  }
92027
- const { recordTaskDone } = await import("@cleocode/core/tasks/done-record.js");
92028
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/paths.js");
92029
- const r = await recordTaskDone(args.taskId, {
92030
- projectRoot: getProjectRoot75(),
92031
- ...parsed.options,
92032
- ...args.agent ? { agent: args.agent } : {}
92033
- });
92034
- if (!r.success) {
92035
- cliError(r.error.message, r.error.code, { fix: r.error.fix, details: r.error.details });
92036
- process.exitCode = r.error.exitCode ?? 1;
93473
+ if (args.run === true && isWrite) {
93474
+ cliError(
93475
+ "--run reports typed gate results and records nothing; it cannot be combined with --gate/--all/--reset.",
93476
+ 6 /* VALIDATION_ERROR */,
93477
+ {
93478
+ name: "E_VALIDATION",
93479
+ fix: "Run `cleo verify <id> --run` first, then attest with `cleo verify <id> --gate <name> --evidence <atoms>`"
93480
+ },
93481
+ { operation: "check.gate.run" }
93482
+ );
93483
+ process.exitCode = 6 /* VALIDATION_ERROR */;
92037
93484
  return;
92038
93485
  }
92039
- const { plan: _plan, ...summary } = r.data;
92040
- cliOutput(summary, { command: "verify", operation: "check.gate.auto" });
92041
- return;
92042
- }
92043
- if (args.satisfies !== void 0 || args.pr !== void 0) {
92044
- cliError("--satisfies and --pr apply only with --auto (or cleo done)", "E_INVALID_INPUT");
92045
- process.exitCode = 6 /* VALIDATION_ERROR */;
92046
- return;
92047
- }
92048
- if (args.run === true && isWrite) {
92049
- cliError(
92050
- "--run reports typed gate results and records nothing; it cannot be combined with --gate/--all/--reset.",
92051
- 6 /* VALIDATION_ERROR */,
93486
+ const useExplain = !isWrite && args.explain === true;
93487
+ const operation = isWrite ? "gate.set" : args.run === true ? "gate.run" : useExplain ? "verify.explain" : "gate.status";
93488
+ await dispatchFromCli(
93489
+ isWrite ? "mutate" : "query",
93490
+ "check",
93491
+ operation,
92052
93492
  {
92053
- name: "E_VALIDATION",
92054
- fix: "Run `cleo verify <id> --run` first, then attest with `cleo verify <id> --gate <name> --evidence <atoms>`"
93493
+ taskId: args.taskId,
93494
+ gate: args.gate,
93495
+ value: args.value === "false" ? false : args.gate ? true : void 0,
93496
+ agent: args.agent,
93497
+ all: args.all,
93498
+ reset: args.reset,
93499
+ evidence: args.evidence,
93500
+ sharedEvidence: args["shared-evidence"] ?? false,
93501
+ // T12621: citty turns `--no-run` into `run: false`; read it through the helper.
93502
+ ...isWrite && negatedFlag(args, "run") ? { noRun: true } : {}
92055
93503
  },
92056
- { operation: "check.gate.run" }
93504
+ { command: "verify" }
92057
93505
  );
92058
- process.exitCode = 6 /* VALIDATION_ERROR */;
92059
- return;
93506
+ } finally {
93507
+ if (args.fresh === true) {
93508
+ if (priorFresh === void 0) delete process.env["CLEO_EVIDENCE_FRESH"];
93509
+ else process.env["CLEO_EVIDENCE_FRESH"] = priorFresh;
93510
+ }
92060
93511
  }
92061
- const useExplain = !isWrite && args.explain === true;
92062
- const operation = isWrite ? "gate.set" : args.run === true ? "gate.run" : useExplain ? "verify.explain" : "gate.status";
92063
- await dispatchFromCli(
92064
- isWrite ? "mutate" : "query",
92065
- "check",
92066
- operation,
92067
- {
92068
- taskId: args.taskId,
92069
- gate: args.gate,
92070
- value: args.value === "false" ? false : args.gate ? true : void 0,
92071
- agent: args.agent,
92072
- all: args.all,
92073
- reset: args.reset,
92074
- evidence: args.evidence,
92075
- sharedEvidence: args["shared-evidence"] ?? false,
92076
- // T12621: citty turns `--no-run` into `run: false`; read it through the helper.
92077
- ...isWrite && negatedFlag(args, "run") ? { noRun: true } : {}
92078
- },
92079
- { command: "verify" }
92080
- );
92081
93512
  }
92082
93513
  });
92083
93514
  }
@@ -92338,7 +93769,7 @@ var workgraph_exports = {};
92338
93769
  __export(workgraph_exports, {
92339
93770
  workgraphCommand: () => workgraphCommand
92340
93771
  });
92341
- import { readFileSync as readFileSync20 } from "node:fs";
93772
+ import { readFileSync as readFileSync21 } from "node:fs";
92342
93773
  import { resolve as resolve12 } from "node:path";
92343
93774
  var validateCommand10, applyCommand, planCommand4, structureCommand, statusCommand20, workgraphCommand;
92344
93775
  var init_workgraph2 = __esm({
@@ -92363,7 +93794,7 @@ var init_workgraph2 = __esm({
92363
93794
  const filePath = resolve12(String(args.file));
92364
93795
  let raw;
92365
93796
  try {
92366
- raw = readFileSync20(filePath, "utf-8");
93797
+ raw = readFileSync21(filePath, "utf-8");
92367
93798
  } catch {
92368
93799
  cliOutput2(
92369
93800
  { error: `Cannot read file: ${filePath}` },
@@ -92408,7 +93839,7 @@ var init_workgraph2 = __esm({
92408
93839
  const filePath = resolve12(String(args.file));
92409
93840
  let raw;
92410
93841
  try {
92411
- raw = readFileSync20(filePath, "utf-8");
93842
+ raw = readFileSync21(filePath, "utf-8");
92412
93843
  } catch {
92413
93844
  cliOutput2(
92414
93845
  { error: `Cannot read file: ${filePath}` },
@@ -92450,9 +93881,9 @@ var init_workgraph2 = __esm({
92450
93881
  },
92451
93882
  async run({ args }) {
92452
93883
  const { generatePlanningDoc } = await import("@cleocode/core/workgraph");
92453
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
93884
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
92454
93885
  const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
92455
- const projectRoot = getProjectRoot75();
93886
+ const projectRoot = getProjectRoot76();
92456
93887
  const audience = String(args.audience) === "agent" ? "agent" : "maintainer";
92457
93888
  const result = await generatePlanningDoc(projectRoot, {
92458
93889
  sagaId: String(args.sagaId),
@@ -92469,9 +93900,9 @@ var init_workgraph2 = __esm({
92469
93900
  async run() {
92470
93901
  const { validateWorkGraphStructure } = await import("@cleocode/core/workgraph");
92471
93902
  const { taskList: taskList2 } = await import("@cleocode/core/internal");
92472
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
93903
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
92473
93904
  const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
92474
- const projectRoot = getProjectRoot75();
93905
+ const projectRoot = getProjectRoot76();
92475
93906
  const listResult = await taskList2(projectRoot, { limit: 5e3 });
92476
93907
  const tasks = listResult.success ? listResult.data?.tasks ?? [] : [];
92477
93908
  const nodes = tasks.map((t) => ({
@@ -92490,9 +93921,9 @@ var init_workgraph2 = __esm({
92490
93921
  description: "One-shot saga-to-saga workgraph dashboard (tracking checklist)"
92491
93922
  },
92492
93923
  async run() {
92493
- const { sagas: sagas2, getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
93924
+ const { sagas: sagas2, getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
92494
93925
  const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
92495
- const projectRoot = getProjectRoot75();
93926
+ const projectRoot = getProjectRoot76();
92496
93927
  const listResult = await sagas2.sagaList(projectRoot);
92497
93928
  if (!listResult.success) {
92498
93929
  cliOutput2(listResult, { command: "workgraph", operation: "workgraph.status" });
@@ -92558,7 +93989,7 @@ __export(worktree_exports, {
92558
93989
  worktreeCommand: () => worktreeCommand
92559
93990
  });
92560
93991
  import readline4 from "node:readline";
92561
- import { getProjectRoot as getProjectRoot74, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
93992
+ import { getProjectRoot as getProjectRoot75, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
92562
93993
  async function promptYesNo2(question) {
92563
93994
  return new Promise((resolve13) => {
92564
93995
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
@@ -92663,7 +94094,7 @@ var init_worktree3 = __esm({
92663
94094
  const staleDays = staleDaysRaw !== void 0 ? Number.parseInt(staleDaysRaw, 10) : void 0;
92664
94095
  const idleDaysRaw = typeof args["idle-days"] === "string" ? args["idle-days"] : void 0;
92665
94096
  const idleDays = idleDaysRaw !== void 0 ? Number.parseInt(idleDaysRaw, 10) : void 0;
92666
- const projectRoot = getProjectRoot74();
94097
+ const projectRoot = getProjectRoot75();
92667
94098
  const listResult = await listWorktrees2({
92668
94099
  projectRoot,
92669
94100
  ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
@@ -92902,8 +94333,8 @@ var init_worktree3 = __esm({
92902
94333
 
92903
94334
  // packages/cleo/src/cli/index.ts
92904
94335
  init_dist();
92905
- import { readFileSync as readFileSync21 } from "node:fs";
92906
- import { dirname as dirname13, join as join39 } from "node:path";
94336
+ import { readFileSync as readFileSync22 } from "node:fs";
94337
+ import { dirname as dirname13, join as join40 } from "node:path";
92907
94338
  import { fileURLToPath as fileURLToPath7 } from "node:url";
92908
94339
  import { enforceNodeVersion } from "@cleocode/paths";
92909
94340
 
@@ -93116,7 +94547,7 @@ var COMMAND_MANIFEST = [
93116
94547
  {
93117
94548
  exportName: "cloudCommand",
93118
94549
  name: "cloud",
93119
- description: "Cleo Nexus reads with the device credential (GET only; getting the credential may upgrade a 9.24 session or retry unsettled logouts): status (one-call verification), whoami, devices, projects [show].",
94550
+ description: "Cleo Nexus with the device credential: status (one-call verification), whoami, devices, projects [show], activity; the encrypted vault: push, pull, restore, verify, vault, lease release.",
93120
94551
  load: async () => (await Promise.resolve().then(() => (init_cloud(), cloud_exports))).cloudCommand
93121
94552
  },
93122
94553
  {
@@ -93347,6 +94778,12 @@ var COMMAND_MANIFEST = [
93347
94778
  description: "Audit the machine-wide memory guard that bounds test runs an agent starts OUTSIDE cleo ",
93348
94779
  load: async () => (await Promise.resolve().then(() => (init_doctor_memory_guard(), doctor_memory_guard_exports))).doctorMemoryGuardCommand
93349
94780
  },
94781
+ {
94782
+ exportName: "doctorMigrationsCommand",
94783
+ name: "migrations",
94784
+ description: "Report the migration journal of the project and global stores: row count, head, applied ",
94785
+ load: async () => (await Promise.resolve().then(() => (init_doctor_migrations(), doctor_migrations_exports))).doctorMigrationsCommand
94786
+ },
93350
94787
  {
93351
94788
  exportName: "doctorNexusResidencyCommand",
93352
94789
  name: "nexus-residency",
@@ -93539,6 +94976,12 @@ var COMMAND_MANIFEST = [
93539
94976
  description: "Completion timeline and productivity analytics",
93540
94977
  load: async () => (await Promise.resolve().then(() => (init_history(), history_exports))).historyCommand
93541
94978
  },
94979
+ {
94980
+ exportName: "hookCommand",
94981
+ name: "hook",
94982
+ description: "Agent-harness hooks installed by cleo init/upgrade; stdout is the harness hook protocol, not LAFS: cleo hook heavy-command --provider claude-code|codex|kimi|opencode",
94983
+ load: async () => (await Promise.resolve().then(() => (init_hook(), hook_exports))).hookCommand
94984
+ },
93542
94985
  {
93543
94986
  exportName: "hygieneCommand",
93544
94987
  name: "hygiene",
@@ -93845,6 +95288,12 @@ var COMMAND_MANIFEST = [
93845
95288
  description: "Generate project roadmap from task provenance \u2014 epics grouped by status with progress",
93846
95289
  load: async () => (await Promise.resolve().then(() => (init_roadmap(), roadmap_exports))).roadmapCommand
93847
95290
  },
95291
+ {
95292
+ exportName: "runCommand",
95293
+ name: "run",
95294
+ description: "Run a heavy command (tests, builds, installs) under the machine-wide resource budget: cleo run [--class test|build|full-build] [--wait] [--passthrough] -- <command...>",
95295
+ load: async () => (await Promise.resolve().then(() => (init_run(), run_exports))).runCommand
95296
+ },
93848
95297
  {
93849
95298
  exportName: "safestopCommand",
93850
95299
  name: "safestop",
@@ -94252,12 +95701,12 @@ init_did_you_mean();
94252
95701
 
94253
95702
  // packages/cleo/src/cli/lib/first-run-detection.ts
94254
95703
  import { existsSync as existsSync21 } from "node:fs";
94255
- import { join as join38 } from "node:path";
95704
+ import { join as join39 } from "node:path";
94256
95705
  async function detectFirstRun() {
94257
95706
  const envKey = process.env["ANTHROPIC_API_KEY"];
94258
95707
  if (typeof envKey === "string" && envKey.length > 0) return false;
94259
95708
  const { getCleoPlatformPaths } = await import("@cleocode/paths");
94260
- const configPath = join38(getCleoPlatformPaths().config, "config.json");
95709
+ const configPath = join39(getCleoPlatformPaths().config, "config.json");
94261
95710
  if (existsSync21(configPath)) return false;
94262
95711
  try {
94263
95712
  const { getCredentialPool: getCredentialPool2 } = await import("@cleocode/core/llm/credential-pool.js");
@@ -94389,8 +95838,8 @@ async function resolveSubCommandForHelp(cmd, rawArgs) {
94389
95838
  init_summary_context();
94390
95839
  enforceNodeVersion();
94391
95840
  function getPackageVersion() {
94392
- const pkgPath = join39(dirname13(fileURLToPath7(import.meta.url)), "../../package.json");
94393
- const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
95841
+ const pkgPath = join40(dirname13(fileURLToPath7(import.meta.url)), "../../package.json");
95842
+ const pkg = JSON.parse(readFileSync22(pkgPath, "utf-8"));
94394
95843
  return pkg.version;
94395
95844
  }
94396
95845
  var CLI_VERSION = getPackageVersion();
@@ -94431,6 +95880,7 @@ async function startCli() {
94431
95880
  let describeFlag = false;
94432
95881
  for (let i = 0; i < argv.length; i++) {
94433
95882
  const arg = argv[i];
95883
+ if (arg === "--") break;
94434
95884
  if (arg === "--json") rawOpts["json"] = true;
94435
95885
  else if (arg === "--human") rawOpts["human"] = true;
94436
95886
  else if (arg === "--quiet") rawOpts["quiet"] = true;
@@ -94641,7 +96091,7 @@ async function runStartupMaintenance() {
94641
96091
  detectAndRemoveStrayProjectNexus,
94642
96092
  getGlobalSalt,
94643
96093
  getLogger: getLogger22,
94644
- getProjectRoot: getProjectRoot75,
96094
+ getProjectRoot: getProjectRoot76,
94645
96095
  isCleanupMarkerSet,
94646
96096
  isMissingProjectError,
94647
96097
  migrateSignaldockToConduit,
@@ -94651,7 +96101,7 @@ async function runStartupMaintenance() {
94651
96101
  } = await import("@cleocode/core/internal");
94652
96102
  let projectRootForCleanup = "";
94653
96103
  try {
94654
- projectRootForCleanup = getProjectRoot75();
96104
+ projectRootForCleanup = getProjectRoot76();
94655
96105
  } catch {
94656
96106
  }
94657
96107
  if (!isCleanupMarkerSet(CLI_VERSION, projectRootForCleanup)) {
@@ -94671,7 +96121,7 @@ async function runStartupMaintenance() {
94671
96121
  const isInitInvocation = process.argv.slice(2).some((a) => a === "init");
94672
96122
  if (!isInitInvocation) {
94673
96123
  try {
94674
- const _projectRootForMigration = getProjectRoot75();
96124
+ const _projectRootForMigration = getProjectRoot76();
94675
96125
  if (needsSignaldockToConduitMigration(_projectRootForMigration)) {
94676
96126
  const migrationResult = await migrateSignaldockToConduit(_projectRootForMigration);
94677
96127
  if (migrationResult.status === "failed") {