@cleocode/cleo 2026.10.1 → 2026.10.2

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 +1774 -329
  4. package/package.json +13 -13
  5. package/studio-dist/client/_app/immutable/chunks/{CMfYgGYJ.js → BJp57kf2.js} +1 -1
  6. package/studio-dist/client/_app/immutable/chunks/{BpRY8_m9.js → Buaay_Q8.js} +1 -1
  7. package/studio-dist/client/_app/immutable/chunks/C3l-lTkq.js +1 -0
  8. package/studio-dist/client/_app/immutable/chunks/CLP4JZvZ.js +3 -0
  9. package/studio-dist/client/_app/immutable/entry/{app.DKqdTuYA.js → app.CczVILch.js} +2 -2
  10. package/studio-dist/client/_app/immutable/entry/start.D7gHmBNS.js +1 -0
  11. package/studio-dist/client/_app/immutable/nodes/{0.BuXCTiZp.js → 0.Zy2IsLEl.js} +1 -1
  12. package/studio-dist/client/_app/immutable/nodes/{1.CsO1BGsz.js → 1.DJN1QI3l.js} +1 -1
  13. package/studio-dist/client/_app/immutable/nodes/{15.Bp-qXNPk.js → 15.B4rwqbHV.js} +1 -1
  14. package/studio-dist/client/_app/immutable/nodes/{16.DMXWbK7I.js → 16.jn-5BG_L.js} +1 -1
  15. package/studio-dist/client/_app/immutable/nodes/{17.CVLdfMFL.js → 17.DnWGC4t9.js} +1 -1
  16. package/studio-dist/client/_app/immutable/nodes/{18.CyQUos9v.js → 18.0zddLZOY.js} +1 -1
  17. package/studio-dist/client/_app/immutable/nodes/{20.Dx3wZ86J.js → 20.DEKHq9Tc.js} +1 -1
  18. package/studio-dist/client/_app/immutable/nodes/{24.CXGl5ZJ3.js → 24.CQB9KP-p.js} +1 -1
  19. package/studio-dist/client/_app/immutable/nodes/25.BaqToZD-.js +39 -0
  20. package/studio-dist/client/_app/immutable/nodes/{26.U1MxbYsk.js → 26.BiE1i4iE.js} +1 -1
  21. package/studio-dist/client/_app/immutable/nodes/{3.CUHmTi6Q.js → 3.BObAOu_-.js} +1 -1
  22. package/studio-dist/client/_app/version.json +1 -1
  23. package/studio-dist/server/chunks/{0-Ban8NQ70.js → 0-BmUoS2yd.js} +3 -3
  24. package/studio-dist/server/chunks/1-CTjj2MYz.js +9 -0
  25. package/studio-dist/server/chunks/{15-C2ukbZuI.js → 15-Dt4kqUxW.js} +3 -3
  26. package/studio-dist/server/chunks/{16-C-gWtKZb.js → 16-kgTLJvbO.js} +3 -3
  27. package/studio-dist/server/chunks/{17-CzQ5BDNx.js → 17-mRYB5141.js} +3 -3
  28. package/studio-dist/server/chunks/{18-Cnqp0uMS.js → 18-BjZ325q5.js} +3 -3
  29. package/studio-dist/server/chunks/{20-D9243OmI.js → 20-DQ2Vrujq.js} +3 -3
  30. package/studio-dist/server/chunks/{24-D-3OyyjO.js → 24-DAeuAfXN.js} +3 -3
  31. package/studio-dist/server/chunks/{25-BC8dXyIT.js → 25-DGCNmzAS.js} +4 -4
  32. package/studio-dist/server/chunks/{26-DIYVHPeE.js → 26-CiN6bbmR.js} +3 -3
  33. package/studio-dist/server/chunks/{3-DDNPJWI0.js → 3-BS2FXYjP.js} +3 -3
  34. package/studio-dist/server/chunks/{_layout.svelte-ouauc7nn.js → _layout.svelte-DJ_UWmGp.js} +4 -4
  35. package/studio-dist/server/chunks/{_page.svelte-ez5VvNrn.js → _page.svelte-BUq8_eQH.js} +3 -3
  36. package/studio-dist/server/chunks/{_page.svelte-ZzSjr8MT.js → _page.svelte-CRnYa4cW.js} +5 -5
  37. package/studio-dist/server/chunks/{_page.svelte-B7CTgxGI.js → _page.svelte-Ca7x-ZvH.js} +4 -4
  38. package/studio-dist/server/chunks/{_page.svelte-BKEo8OSf.js → _page.svelte-CcP_KW3Y.js} +3 -3
  39. package/studio-dist/server/chunks/{_page.svelte-DS8uziG5.js → _page.svelte-Cfv9tDBA.js} +3 -3
  40. package/studio-dist/server/chunks/{_page.svelte-BlIGw3KR.js → _page.svelte-D8dLEr7O.js} +3 -3
  41. package/studio-dist/server/chunks/{_page.svelte-DU-KSkGO.js → _page.svelte-Dk0znswQ.js} +3 -3
  42. package/studio-dist/server/chunks/{_page.svelte-CkagR7NW.js → _page.svelte-J4HjPhfO.js} +3 -3
  43. package/studio-dist/server/chunks/{_page.svelte-Ba45egd6.js → _page.svelte-WR6jUiQE.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-CBaXrLT0.js → _server.ts-Bih2-_5O.js} +2 -2
  46. package/studio-dist/server/chunks/{_server.ts-DNL_pHM3.js → _server.ts-C0evMKCk.js} +3 -3
  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-Cl295FWH.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-ajn1HNOb.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-D9MtKHIF.js} +2 -2
  54. package/studio-dist/server/chunks/{stores-C00-wTzq.js → stores-BlknvZ80.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,34 @@ 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
+ /** The server refused the snapshot (lineage or regression check). */
23109
+ "E_NEXUS_VAULT_REFUSED",
23110
+ /**
23111
+ * The stream moved past what this CLEO's vault writes (T13034): it takes only checkpoint/v3
23112
+ * snapshots (the server's `E_STREAM_VERSION`), or it holds data of a newer sync schema.
23113
+ * Pull, restore and verify still work; nothing was written.
23114
+ */
23115
+ "E_NEXUS_VAULT_STREAM_UPGRADED",
23116
+ /** Another CLEO process is writing to the store a restore would replace. */
23117
+ "E_NEXUS_VAULT_STORE_BUSY",
23118
+ /** A project restore target already holds a different project. */
23119
+ "E_NEXUS_VAULT_TARGET_OCCUPIED"
22766
23120
  ];
22767
23121
  nexusAccountUserSchema = z25.object({
22768
23122
  id: z25.string(),
@@ -23009,7 +23363,9 @@ var init_nexus_cloud = __esm({
23009
23363
  "route-undeclared",
23010
23364
  "bearer-session-required",
23011
23365
  "session-not-fresh",
23012
- "device-limit"
23366
+ "device-limit",
23367
+ "device-flow-session-required",
23368
+ "device-not-enrolled"
23013
23369
  ];
23014
23370
  NEXUS_REVOKED_REASONS = ["signed-out", "revoked", "rotated", "reenrolled"];
23015
23371
  LOGIN = "run `cleo login nexus`";
@@ -23100,6 +23456,16 @@ var init_nexus_cloud = __esm({
23100
23456
  code: "E_NEXUS_REQUEST_FAILED",
23101
23457
  message: "the account has reached its device limit",
23102
23458
  fix: "revoke unused devices on cleocode.dev, then retry"
23459
+ },
23460
+ "device-flow-session-required": {
23461
+ code: "E_NEXUS_SESSION_EXPIRED",
23462
+ message: "this session was not issued to the CLI by `cleo login nexus`, so it cannot enrol a device",
23463
+ fix: SESSION_EXPIRED_LOGIN.fix
23464
+ },
23465
+ "device-not-enrolled": {
23466
+ code: "E_NEXUS_NOT_SIGNED_IN",
23467
+ message: "this device is not enrolled with Cleo Nexus",
23468
+ fix: LOGIN
23103
23469
  }
23104
23470
  };
23105
23471
  NEXUS_CONFLICT_ERRORS = {
@@ -23118,6 +23484,69 @@ var init_nexus_cloud = __esm({
23118
23484
  }
23119
23485
  });
23120
23486
 
23487
+ // packages/contracts/src/nexus-vault.ts
23488
+ import { z as z27 } from "zod";
23489
+ var isoTime2, uuid, nexusUserKeysSchema, nexusProjectKeysSchema, NEXUS_VAULT_LEASE_ROLE, nexusLeaseSchema, nexusLeaseAcquireSchema, nexusStreamHeadSchema, nexusActivityEventSchema, nexusActivityPageSchema;
23490
+ var init_nexus_vault = __esm({
23491
+ "packages/contracts/src/nexus-vault.ts"() {
23492
+ "use strict";
23493
+ isoTime2 = z27.iso.datetime({ offset: true });
23494
+ 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);
23495
+ nexusUserKeysSchema = z27.looseObject({
23496
+ keyVersion: z27.number().int().positive(),
23497
+ masterKeyVerifier: z27.string()
23498
+ });
23499
+ nexusProjectKeysSchema = z27.looseObject({
23500
+ keys: z27.array(
23501
+ z27.looseObject({ wrappedProjectKey: z27.string(), keyVersion: z27.number().int().positive() })
23502
+ )
23503
+ });
23504
+ NEXUS_VAULT_LEASE_ROLE = "writer";
23505
+ nexusLeaseSchema = z27.looseObject({
23506
+ streamId: z27.string(),
23507
+ role: z27.string(),
23508
+ replicaId: uuid,
23509
+ expiresAt: isoTime2,
23510
+ forkedFromReplicaId: uuid.nullable().optional()
23511
+ });
23512
+ nexusLeaseAcquireSchema = z27.looseObject({ lease: nexusLeaseSchema });
23513
+ nexusStreamHeadSchema = z27.looseObject({
23514
+ streamId: z27.string(),
23515
+ kind: z27.string().optional(),
23516
+ headSeq: z27.number().int().nonnegative(),
23517
+ headCheckpointId: z27.string().nullable(),
23518
+ /**
23519
+ * The highest segment `schemaVersion` the stream holds (the server raises it on every append).
23520
+ * Absent from an older server.
23521
+ */
23522
+ maxSchemaVersion: z27.number().int().nonnegative().optional()
23523
+ });
23524
+ nexusActivityEventSchema = z27.looseObject({
23525
+ id: z27.union([z27.string(), z27.number()]),
23526
+ at: isoTime2,
23527
+ actorUserId: z27.string().nullable().optional(),
23528
+ actorDeviceId: z27.string().nullable().optional(),
23529
+ requestId: z27.string().nullable().optional(),
23530
+ action: z27.string(),
23531
+ target: z27.string().nullable().optional(),
23532
+ detail: z27.unknown().optional()
23533
+ });
23534
+ nexusActivityPageSchema = z27.looseObject({
23535
+ events: z27.array(nexusActivityEventSchema),
23536
+ nextBefore: z27.union([z27.string(), z27.number()]).nullable().optional()
23537
+ });
23538
+ }
23539
+ });
23540
+
23541
+ // packages/contracts/src/sync-schema.ts
23542
+ var SYNC_SCHEMA_VERSION;
23543
+ var init_sync_schema = __esm({
23544
+ "packages/contracts/src/sync-schema.ts"() {
23545
+ "use strict";
23546
+ SYNC_SCHEMA_VERSION = 2;
23547
+ }
23548
+ });
23549
+
23121
23550
  // packages/contracts/src/task-id.ts
23122
23551
  function isTaskId(value) {
23123
23552
  return typeof value === "string" && TASK_ID_REGEX.test(value);
@@ -23321,6 +23750,7 @@ __export(src_exports, {
23321
23750
  NEXUS_UNAUTHENTICATED_ERRORS: () => NEXUS_UNAUTHENTICATED_ERRORS,
23322
23751
  NEXUS_UNAUTHENTICATED_REASONS: () => NEXUS_UNAUTHENTICATED_REASONS,
23323
23752
  NEXUS_UNREACHABLE_ERROR: () => NEXUS_UNREACHABLE_ERROR,
23753
+ NEXUS_VAULT_LEASE_ROLE: () => NEXUS_VAULT_LEASE_ROLE,
23324
23754
  OPEN_SYSTEM_KEY_PREFIXES: () => OPEN_SYSTEM_KEY_PREFIXES,
23325
23755
  OPERATIONS: () => OPERATIONS,
23326
23756
  OPERATION_RESULT_SCHEMAS: () => OPERATION_RESULT_SCHEMAS,
@@ -23366,6 +23796,8 @@ __export(src_exports, {
23366
23796
  RESOURCE_CLASSES: () => RESOURCE_CLASSES,
23367
23797
  RESOURCE_DEFERRED_CODE: () => RESOURCE_DEFERRED_CODE,
23368
23798
  ROLE_SYSTEM_IDS: () => ROLE_SYSTEM_IDS,
23799
+ RUN_COMMAND_FAILED_CODE: () => RUN_COMMAND_FAILED_CODE,
23800
+ RUN_DEFERRED_EXIT_CODE: () => RUN_DEFERRED_EXIT_CODE,
23369
23801
  RateCheckRequestSchema: () => RateCheckRequestSchema,
23370
23802
  RateResultResponseSchema: () => RateResultResponseSchema,
23371
23803
  ReleaseChannelSchema: () => ReleaseChannelSchema,
@@ -23401,6 +23833,8 @@ __export(src_exports, {
23401
23833
  SUPERVISOR_IPC_PROTOCOL_VERSION: () => SUPERVISOR_IPC_PROTOCOL_VERSION,
23402
23834
  SUPERVISOR_IPC_REQUEST_KINDS: () => SUPERVISOR_IPC_REQUEST_KINDS,
23403
23835
  SUPERVISOR_IPC_RESPONSE_KINDS: () => SUPERVISOR_IPC_RESPONSE_KINDS,
23836
+ SYNC_SCHEMA_VERSION: () => SYNC_SCHEMA_VERSION,
23837
+ SYNC_WRITE_INVARIANTS: () => SYNC_WRITE_INVARIANTS,
23404
23838
  SYSTEM_ROLE_MAP: () => SYSTEM_ROLE_MAP,
23405
23839
  SessionView: () => SessionView,
23406
23840
  SpawnRequestSchema: () => SpawnRequestSchema,
@@ -23600,6 +24034,8 @@ __export(src_exports, {
23600
24034
  nexusAccountMeSchema: () => nexusAccountMeSchema,
23601
24035
  nexusAccountOrganizationSchema: () => nexusAccountOrganizationSchema,
23602
24036
  nexusAccountUserSchema: () => nexusAccountUserSchema,
24037
+ nexusActivityEventSchema: () => nexusActivityEventSchema,
24038
+ nexusActivityPageSchema: () => nexusActivityPageSchema,
23603
24039
  nexusCloudCredentialSchema: () => nexusCloudCredentialSchema,
23604
24040
  nexusCloudDeviceCountsSchema: () => nexusCloudDeviceCountsSchema,
23605
24041
  nexusCloudDevicePageSchema: () => nexusCloudDevicePageSchema,
@@ -23615,6 +24051,11 @@ __export(src_exports, {
23615
24051
  nexusCloudStatusSchema: () => nexusCloudStatusSchema,
23616
24052
  nexusCloudUserSchema: () => nexusCloudUserSchema,
23617
24053
  nexusCloudWhoamiSchema: () => nexusCloudWhoamiSchema,
24054
+ nexusLeaseAcquireSchema: () => nexusLeaseAcquireSchema,
24055
+ nexusLeaseSchema: () => nexusLeaseSchema,
24056
+ nexusProjectKeysSchema: () => nexusProjectKeysSchema,
24057
+ nexusStreamHeadSchema: () => nexusStreamHeadSchema,
24058
+ nexusUserKeysSchema: () => nexusUserKeysSchema,
23618
24059
  normalizeError: () => normalizeError,
23619
24060
  noteAtomSchema: () => noteAtomSchema,
23620
24061
  noulDecisionAnswerSchema: () => noulDecisionAnswerSchema,
@@ -23796,6 +24237,8 @@ var init_src2 = __esm({
23796
24237
  init_decide_sites();
23797
24238
  init_nexus_account();
23798
24239
  init_nexus_cloud();
24240
+ init_nexus_vault();
24241
+ init_sync_schema();
23799
24242
  init_task_id();
23800
24243
  }
23801
24244
  });
@@ -24651,7 +25094,7 @@ function humanProgress(text) {
24651
25094
  function isHumanOutput() {
24652
25095
  return humanEnabled();
24653
25096
  }
24654
- function cliError(message, code, details, meta) {
25097
+ function cliError(message, code, details, meta, options) {
24655
25098
  const ctx = getFormatContext();
24656
25099
  const outputMode = getOutputMode();
24657
25100
  if (outputMode === "silent") {
@@ -24693,6 +25136,11 @@ function cliError(message, code, details, meta) {
24693
25136
  error: errorObj,
24694
25137
  meta: errorMeta
24695
25138
  };
25139
+ if (options?.stderr === true) {
25140
+ process.stderr.write(`${JSON.stringify(envelope)}
25141
+ `);
25142
+ return;
25143
+ }
24696
25144
  process.stdout.write(JSON.stringify(envelope) + "\n");
24697
25145
  }
24698
25146
  var renderers;
@@ -37285,21 +37733,21 @@ var init_migrate_e4 = __esm({
37285
37733
 
37286
37734
  // packages/playbooks/src/policy.ts
37287
37735
  function evaluatePolicy(command, rules = DEFAULT_POLICY_RULES) {
37288
- for (const rule of rules) {
37289
- if (rule.action === "require-human" && rule.pattern.test(command)) {
37736
+ for (const rule2 of rules) {
37737
+ if (rule2.action === "require-human" && rule2.pattern.test(command)) {
37290
37738
  return {
37291
37739
  action: "require-human",
37292
- reason: rule.reason,
37293
- matchedPattern: rule.pattern.source
37740
+ reason: rule2.reason,
37741
+ matchedPattern: rule2.pattern.source
37294
37742
  };
37295
37743
  }
37296
37744
  }
37297
- for (const rule of rules) {
37298
- if (rule.action === "auto-approve" && rule.pattern.test(command)) {
37745
+ for (const rule2 of rules) {
37746
+ if (rule2.action === "auto-approve" && rule2.pattern.test(command)) {
37299
37747
  return {
37300
37748
  action: "auto-approve",
37301
- reason: rule.reason,
37302
- matchedPattern: rule.pattern.source
37749
+ reason: rule2.reason,
37750
+ matchedPattern: rule2.pattern.source
37303
37751
  };
37304
37752
  }
37305
37753
  }
@@ -37874,9 +38322,9 @@ function auditContractViolation(projectRoot, runId, nodeId, field, key, playbook
37874
38322
  } catch {
37875
38323
  }
37876
38324
  }
37877
- function handleContractErrorHandler(playbook, trigger, _message) {
38325
+ function handleContractErrorHandler(playbook, trigger2, _message) {
37878
38326
  if (!playbook.error_handlers) return null;
37879
- const handler = playbook.error_handlers.find((h) => h.on === trigger);
38327
+ const handler = playbook.error_handlers.find((h) => h.on === trigger2);
37880
38328
  return handler?.action ?? null;
37881
38329
  }
37882
38330
  function iterationCapFor(node, runtimeDefault) {
@@ -38399,8 +38847,8 @@ async function loadPlaybookByName(name) {
38399
38847
  return null;
38400
38848
  }
38401
38849
  try {
38402
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/internal");
38403
- const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot75();
38850
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/internal");
38851
+ const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot76();
38404
38852
  const resolved = resolvePlaybook(name, {
38405
38853
  projectRoot,
38406
38854
  globalPlaybooksDir: __playbookRuntimeOverrides.globalPlaybooksDir,
@@ -38445,7 +38893,7 @@ async function buildDefaultDispatcher() {
38445
38893
  if (__playbookRuntimeOverrides.dispatcher) return __playbookRuntimeOverrides.dispatcher;
38446
38894
  const { orchestrateSpawnExecute: orchestrateSpawnExecute2 } = await import("@cleocode/runtime/gateway");
38447
38895
  const {
38448
- getProjectRoot: getProjectRoot75,
38896
+ getProjectRoot: getProjectRoot76,
38449
38897
  createToolGuard,
38450
38898
  runSkillNodeOrSpawn,
38451
38899
  maybeCreatePiRunner,
@@ -38453,7 +38901,7 @@ async function buildDefaultDispatcher() {
38453
38901
  hasCantbookProfilePin,
38454
38902
  DEFAULT_DETERMINISTIC_DENIED_COMMANDS
38455
38903
  } = await import("@cleocode/core/internal");
38456
- const projectRoot = getProjectRoot75();
38904
+ const projectRoot = getProjectRoot76();
38457
38905
  const tools = createToolGuard({
38458
38906
  allowedRoots: [projectRoot],
38459
38907
  deniedCommands: DEFAULT_DETERMINISTIC_DENIED_COMMANDS,
@@ -38546,12 +38994,12 @@ async function buildDefaultDeterministicRunner() {
38546
38994
  return void 0;
38547
38995
  }
38548
38996
  const {
38549
- getProjectRoot: getProjectRoot75,
38997
+ getProjectRoot: getProjectRoot76,
38550
38998
  createToolGuard,
38551
38999
  createGuardedDeterministicRunner,
38552
39000
  DEFAULT_DETERMINISTIC_DENIED_COMMANDS
38553
39001
  } = await import("@cleocode/core/internal");
38554
- const projectRoot = getProjectRoot75();
39002
+ const projectRoot = getProjectRoot76();
38555
39003
  const tools = createToolGuard({
38556
39004
  allowedRoots: [projectRoot],
38557
39005
  deniedCommands: DEFAULT_DETERMINISTIC_DENIED_COMMANDS,
@@ -38709,8 +39157,8 @@ var init_playbook2 = __esm({
38709
39157
  projectRoot = __playbookRuntimeOverrides.projectRoot;
38710
39158
  } else {
38711
39159
  try {
38712
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/internal");
38713
- projectRoot = getProjectRoot75();
39160
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/internal");
39161
+ projectRoot = getProjectRoot76();
38714
39162
  } catch {
38715
39163
  projectRoot = void 0;
38716
39164
  }
@@ -38775,14 +39223,14 @@ var init_playbook2 = __esm({
38775
39223
  const deterministicRunner = await buildDefaultDeterministicRunner();
38776
39224
  let result;
38777
39225
  try {
38778
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/internal");
39226
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/internal");
38779
39227
  const opts = {
38780
39228
  db,
38781
39229
  playbook: parsed.definition,
38782
39230
  playbookHash: parsed.sourceHash,
38783
39231
  initialContext,
38784
39232
  dispatcher,
38785
- projectRoot: getProjectRoot75()
39233
+ projectRoot: getProjectRoot76()
38786
39234
  };
38787
39235
  if (deterministicRunner !== void 0) opts.deterministicRunner = deterministicRunner;
38788
39236
  if (__playbookRuntimeOverrides.approvalSecret !== void 0) {
@@ -39241,16 +39689,16 @@ async function orchestrateClassify(request, context, projectRoot, taskId) {
39241
39689
  }
39242
39690
  try {
39243
39691
  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");
39692
+ const { readFileSync: readFileSync23, readdirSync: readdirSync4, existsSync: existsSync22 } = await import("node:fs");
39693
+ const { join: join41 } = await import("node:path");
39246
39694
  const workflowsDir = getCleoCantWorkflowsDir();
39247
39695
  const combined = `${request} ${context ?? ""}`.toLowerCase();
39248
39696
  const matches = [];
39249
39697
  if (existsSync22(workflowsDir)) {
39250
- const files = readdirSync3(workflowsDir).filter((f) => f.endsWith(".cant"));
39698
+ const files = readdirSync4(workflowsDir).filter((f) => f.endsWith(".cant"));
39251
39699
  for (const file of files) {
39252
39700
  try {
39253
- const src = readFileSync22(join40(workflowsDir, file), "utf-8");
39701
+ const src = readFileSync23(join41(workflowsDir, file), "utf-8");
39254
39702
  const teamMatch = /^team\s+(\S+):/m.exec(src);
39255
39703
  if (!teamMatch) continue;
39256
39704
  const teamName = teamMatch[1];
@@ -39265,12 +39713,12 @@ async function orchestrateClassify(request, context, projectRoot, taskId) {
39265
39713
  }
39266
39714
  }
39267
39715
  }
39268
- const localCantDir = join40(projectRoot, CLEO_DIR_NAME2, WORKFLOWS_SUBDIR);
39716
+ const localCantDir = join41(projectRoot, CLEO_DIR_NAME2, WORKFLOWS_SUBDIR);
39269
39717
  if (existsSync22(localCantDir)) {
39270
- const files = readdirSync3(localCantDir).filter((f) => f.endsWith(".cant"));
39718
+ const files = readdirSync4(localCantDir).filter((f) => f.endsWith(".cant"));
39271
39719
  for (const file of files) {
39272
39720
  try {
39273
- const src = readFileSync22(join40(localCantDir, file), "utf-8");
39721
+ const src = readFileSync23(join41(localCantDir, file), "utf-8");
39274
39722
  const teamMatch = /^team\s+(\S+):/m.exec(src);
39275
39723
  if (!teamMatch) continue;
39276
39724
  const teamName = teamMatch[1];
@@ -46121,11 +46569,11 @@ var init_security = __esm({
46121
46569
  });
46122
46570
 
46123
46571
  // packages/cleo/src/dispatch/middleware/sanitizer.ts
46124
- function createSanitizer(getProjectRoot75) {
46572
+ function createSanitizer(getProjectRoot76) {
46125
46573
  return async (req, next) => {
46126
46574
  if (req.params) {
46127
46575
  try {
46128
- const root = getProjectRoot75 ? getProjectRoot75() : void 0;
46576
+ const root = getProjectRoot76 ? getProjectRoot76() : void 0;
46129
46577
  req.params = sanitizeParams(req.params, root, {
46130
46578
  domain: req.domain,
46131
46579
  operation: req.operation
@@ -46227,14 +46675,14 @@ var init_session_resolver = __esm({
46227
46675
  });
46228
46676
 
46229
46677
  // packages/cleo/src/dispatch/middleware/store-write-guard.ts
46230
- function createStoreWriteGuard(getProjectRoot75) {
46678
+ function createStoreWriteGuard(getProjectRoot76) {
46231
46679
  return async (req, next) => {
46232
46680
  if (req.gateway !== "mutate" || ALLOWED_WHILE_READ_ONLY.has(`${req.domain}.${req.operation}`)) {
46233
46681
  return next();
46234
46682
  }
46235
46683
  let projectRoot;
46236
46684
  try {
46237
- projectRoot = getProjectRoot75();
46685
+ projectRoot = getProjectRoot76();
46238
46686
  } catch {
46239
46687
  return next();
46240
46688
  }
@@ -48084,9 +48532,9 @@ var init_agent = __esm({
48084
48532
  isActive: true
48085
48533
  });
48086
48534
  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`);
48535
+ const { join: join41 } = await import("node:path");
48536
+ const cantDir = join41(CLEO_DIR_NAME3, AGENTS_SUBDIR);
48537
+ const cantPath = join41(cantDir, `${agentId}.cant`);
48090
48538
  let cantScaffolded = false;
48091
48539
  if (!existsSync22(cantPath)) {
48092
48540
  mkdirSync7(cantDir, { recursive: true });
@@ -48267,8 +48715,8 @@ agent ${agentId}:
48267
48715
  try {
48268
48716
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
48269
48717
  const { createRuntime } = await import("@cleocode/runtime");
48270
- const { existsSync: existsSync22, readFileSync: readFileSync22 } = await import("node:fs");
48271
- const { join: join40 } = await import("node:path");
48718
+ const { existsSync: existsSync22, readFileSync: readFileSync23 } = await import("node:fs");
48719
+ const { join: join41 } = await import("node:path");
48272
48720
  await openCleoDb("project");
48273
48721
  const registry = new AgentRegistryAccessor(getProjectRoot25());
48274
48722
  const credential = await registry.get(args.agentId);
@@ -48288,9 +48736,9 @@ agent ${agentId}:
48288
48736
  }
48289
48737
  let profile2 = null;
48290
48738
  let cantValidation = null;
48291
- const cantPath = args.cant ?? join40(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
48739
+ const cantPath = args.cant ?? join41(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
48292
48740
  if (existsSync22(cantPath)) {
48293
- profile2 = readFileSync22(cantPath, "utf-8");
48741
+ profile2 = readFileSync23(cantPath, "utf-8");
48294
48742
  try {
48295
48743
  const cantModule = await import("@cleocode/cant");
48296
48744
  const validate = "validate" in cantModule ? cantModule.validate : null;
@@ -48814,7 +49262,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
48814
49262
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
48815
49263
  const { createRuntime } = await import("@cleocode/runtime");
48816
49264
  const { existsSync: existsSync22 } = await import("node:fs");
48817
- const { join: join40 } = await import("node:path");
49265
+ const { join: join41 } = await import("node:path");
48818
49266
  await openCleoDb("project");
48819
49267
  const registry = new AgentRegistryAccessor(getProjectRoot25());
48820
49268
  const credential = await registry.get(args.agentId);
@@ -48831,7 +49279,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
48831
49279
  }
48832
49280
  await registry.update(args.agentId, { isActive: true });
48833
49281
  await registry.markUsed(args.agentId);
48834
- const cantPath = join40(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
49282
+ const cantPath = join41(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
48835
49283
  const hasProfile = existsSync22(cantPath);
48836
49284
  const runtime = await createRuntime(registry, {
48837
49285
  agentId: args.agentId,
@@ -49782,8 +50230,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
49782
50230
  process.exitCode = 4;
49783
50231
  return;
49784
50232
  }
49785
- const { join: join40 } = await import("node:path");
49786
- const personaPath = join40(resolvedDir, "persona.cant");
50233
+ const { join: join41 } = await import("node:path");
50234
+ const personaPath = join41(resolvedDir, "persona.cant");
49787
50235
  if (!existsSync22(personaPath)) {
49788
50236
  cliOutput(
49789
50237
  {
@@ -49823,15 +50271,15 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
49823
50271
  return;
49824
50272
  }
49825
50273
  const archiveStats = statSync3(archivePath);
49826
- const { readdirSync: readdirSync3 } = await import("node:fs");
50274
+ const { readdirSync: readdirSync4 } = await import("node:fs");
49827
50275
  let fileCount = 0;
49828
50276
  const countFiles = (dirPath) => {
49829
- const entries = readdirSync3(dirPath, { withFileTypes: true });
50277
+ const entries = readdirSync4(dirPath, { withFileTypes: true });
49830
50278
  for (const entry of entries) {
49831
50279
  if (entry.isFile()) {
49832
50280
  fileCount++;
49833
50281
  } else if (entry.isDirectory()) {
49834
- countFiles(join40(dirPath, entry.name));
50282
+ countFiles(join41(dirPath, entry.name));
49835
50283
  }
49836
50284
  }
49837
50285
  };
@@ -50079,17 +50527,17 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
50079
50527
  },
50080
50528
  async run({ args }) {
50081
50529
  try {
50082
- const { existsSync: existsSync22, readFileSync: readFileSync22, mkdirSync: mkdirSync7 } = await import("node:fs");
50083
- const { resolve: resolve13, join: join40 } = await import("node:path");
50530
+ const { existsSync: existsSync22, readFileSync: readFileSync23, mkdirSync: mkdirSync7 } = await import("node:fs");
50531
+ const { resolve: resolve13, join: join41 } = await import("node:path");
50084
50532
  const specPath = resolve13(args.spec);
50085
50533
  if (!existsSync22(specPath)) {
50086
50534
  cliError(`spec file not found: ${specPath}`, 4, { name: "E_NOT_FOUND" });
50087
50535
  process.exitCode = 4;
50088
50536
  return;
50089
50537
  }
50090
- const specContent = readFileSync22(specPath, "utf-8");
50538
+ const specContent = readFileSync23(specPath, "utf-8");
50091
50539
  const projectRoot = getProjectRoot25();
50092
- const outputDir = args["output-dir"] ? resolve13(args["output-dir"]) : join40(projectRoot, ".cleo", "cant", "agents");
50540
+ const outputDir = args["output-dir"] ? resolve13(args["output-dir"]) : join41(projectRoot, ".cleo", "cant", "agents");
50093
50541
  mkdirSync7(outputDir, { recursive: true });
50094
50542
  if (args["dry-run"]) {
50095
50543
  cliOutput(
@@ -51017,7 +51465,7 @@ function nexusApiUrlArg(args) {
51017
51465
  function failNexus(err, operation) {
51018
51466
  const code = err instanceof Error && "code" in err && typeof err.code === "string" ? err.code : void 0;
51019
51467
  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;
51468
+ 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
51469
  const details = err instanceof Error && "publicDetails" in err && typeof err.publicDetails === "object" && err.publicDetails ? err.publicDetails : void 0;
51022
51470
  cliError(
51023
51471
  err instanceof Error ? err.message : String(err),
@@ -51084,6 +51532,24 @@ async function runNexusLogin(args, openBrowser2) {
51084
51532
  readOnly,
51085
51533
  ...name !== void 0 ? { name } : {}
51086
51534
  });
51535
+ if (!readOnly) {
51536
+ const { attachNexusGlobalStore } = await import(
51537
+ /* webpackIgnore: true */
51538
+ "@cleocode/core/cloud/nexus-home.js"
51539
+ );
51540
+ try {
51541
+ const global = await attachNexusGlobalStore({ apiUrl: hooks2.apiUrl });
51542
+ result = { ...result, warnings: [...result.warnings, ...global.warnings] };
51543
+ } catch (err) {
51544
+ result = {
51545
+ ...result,
51546
+ warnings: [
51547
+ ...result.warnings,
51548
+ `signed in, but attaching this device's global store failed (${err instanceof Error ? err.message : String(err)}); run \`cleo login nexus\` again`
51549
+ ]
51550
+ };
51551
+ }
51552
+ }
51087
51553
  } else {
51088
51554
  if (name !== void 0) {
51089
51555
  process.stderr.write(
@@ -51112,10 +51578,10 @@ async function runNexusLogin(args, openBrowser2) {
51112
51578
  }
51113
51579
  }
51114
51580
  function nexusLoginSummary(r) {
51115
- const who = r.user?.email ?? "your account";
51581
+ const who2 = r.user?.email ?? "your account";
51116
51582
  const org = r.organization ? ` (${r.organization.name})` : "";
51117
51583
  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}`;
51584
+ return `Signed in to ${r.apiUrl} as ${who2}${org}.${device}`;
51119
51585
  }
51120
51586
  function nexusDeviceLogoutSummary(r) {
51121
51587
  const count = (o) => r.devices.filter((d) => d.outcome === o).length;
@@ -51152,10 +51618,11 @@ async function runNexusDeviceLogout(args) {
51152
51618
  `);
51153
51619
  emitNexusResult(result, nexusDeviceLogoutSummary(result), "logout", "logout.run");
51154
51620
  }
51155
- var SERVICE_NAME, NEXUS_API_URL_ARG;
51621
+ var SERVICE_NAME, NEXUS_API_URL_ARG, VAULT_REFUSAL_EXIT_CODES;
51156
51622
  var init_nexus_account_cli = __esm({
51157
51623
  "packages/cleo/src/cli/lib/nexus-account-cli.ts"() {
51158
51624
  "use strict";
51625
+ init_src2();
51159
51626
  init_renderers();
51160
51627
  init_device_code_prompt();
51161
51628
  init_negated_flag();
@@ -51164,6 +51631,14 @@ var init_nexus_account_cli = __esm({
51164
51631
  type: "string",
51165
51632
  description: "Cleo Nexus API URL (default: $CLEO_NEXUS_API_URL, else https://api.cleocode.dev; staging: https://api.staging.cleocode.dev)."
51166
51633
  };
51634
+ VAULT_REFUSAL_EXIT_CODES = {
51635
+ E_NEXUS_VAULT_LEASE_HELD: 7 /* LOCK_TIMEOUT */,
51636
+ E_NEXUS_VAULT_STORE_BUSY: 7 /* LOCK_TIMEOUT */,
51637
+ E_NEXUS_VAULT_BEHIND: 23 /* VERSION_CONFLICT */,
51638
+ E_NEXUS_VAULT_LOCAL_CHANGES: 21 /* CONCURRENT_MODIFICATION */,
51639
+ E_NEXUS_VAULT_VERIFY_FAILED: 20 /* CHECKSUM_MISMATCH */,
51640
+ E_NEXUS_VAULT_TARGET_OCCUPIED: 22 /* ID_COLLISION */
51641
+ };
51167
51642
  }
51168
51643
  });
51169
51644
 
@@ -53351,14 +53826,14 @@ var init_backup = __esm({
53351
53826
  return;
53352
53827
  }
53353
53828
  const { exportPortableBundle, PortableBundleError } = await import("@cleocode/core/store/portable-bundle.js");
53354
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
53829
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
53355
53830
  const passphrase = args.encrypt === true ? await resolvePassphrase() : void 0;
53356
53831
  if (args.encrypt === true && passphrase === void 0) return;
53357
53832
  const encSuffix = args.encrypt === true ? "enc." : "";
53358
53833
  try {
53359
53834
  const result = await exportPortableBundle({
53360
53835
  scope,
53361
- projectRoot: scope === "project" || scope === "all" ? getProjectRoot75() : void 0,
53836
+ projectRoot: scope === "project" || scope === "all" ? getProjectRoot76() : void 0,
53362
53837
  outputPath: args.out ?? `./${args.name}.${encSuffix}cleobundle.tar.gz`,
53363
53838
  encrypt: args.encrypt === true,
53364
53839
  passphrase,
@@ -53415,12 +53890,12 @@ var init_backup = __esm({
53415
53890
  );
53416
53891
  return;
53417
53892
  }
53418
- const { getProjectRoot: getProjectRoot75, getCleoHome: getCleoHome8, getCleoVersion } = await import("@cleocode/core");
53893
+ const { getProjectRoot: getProjectRoot76, getCleoHome: getCleoHome8, getCleoVersion } = await import("@cleocode/core");
53419
53894
  const { BundleError, cleanupStaging, unpackBundle } = await import("@cleocode/core/store/backup-unpack.js");
53420
53895
  const { regenerateConfigJson, regenerateProjectContextJson, regenerateProjectInfoJson } = await import("@cleocode/core/store/regenerators.js");
53421
53896
  const { regenerateAndCompare } = await import("@cleocode/core/store/restore-json-merge.js");
53422
53897
  const { buildConflictReport, writeConflictReport } = await import("@cleocode/core/store/restore-conflict-report.js");
53423
- const projectRoot = getProjectRoot75();
53898
+ const projectRoot = getProjectRoot76();
53424
53899
  const { assertOwnerStoreRewriteConfirmed } = await import("@cleocode/core/store/worktree-isolation-guard.js");
53425
53900
  try {
53426
53901
  assertOwnerStoreRewriteConfirmed("backup import", path2.join(projectRoot, ".cleo"), {
@@ -55313,7 +55788,7 @@ var init_check3 = __esm({
55313
55788
  async run({ args }) {
55314
55789
  const { spawnSync: spawnSync2 } = await import("node:child_process");
55315
55790
  const { existsSync: existsSync22 } = await import("node:fs");
55316
- const { join: join40, resolve: resolve13 } = await import("node:path");
55791
+ const { join: join41, resolve: resolve13 } = await import("node:path");
55317
55792
  const strict = Boolean(args.strict);
55318
55793
  const jsonOnly = Boolean(args.json);
55319
55794
  const repoRoot = resolve13(process.cwd());
@@ -55621,13 +56096,48 @@ var init_check3 = __esm({
55621
56096
  task: "T12663",
55622
56097
  script: "scripts/lint-model-call-sites.mjs",
55623
56098
  description: "Every model call site is a registered decision site (ratchet)"
56099
+ },
56100
+ {
56101
+ // T12819 / T12827 (journal spec §2.3a, §3.5 Rule 4): nothing drops
56102
+ // cleo_trigger_suspend; only dropSyncMachinery drops _sync_* tables;
56103
+ // migrations never mention capture triggers; forward-only migration
56104
+ // rules (owned triggers carry the suspension clause, deterministic
56105
+ // DML, no parent DELETE in a rebuild file); released migration files
56106
+ // are byte-identical to the base ref (#1719).
56107
+ id: "gate-36",
56108
+ task: "T12819",
56109
+ script: "scripts/lint-sync-schema.mjs",
56110
+ description: "Change-journal schema rules (suspend table, migrations)"
56111
+ },
56112
+ {
56113
+ // T12897: every syncing cleo.db table is declared in ROW_IDENTITY or
56114
+ // exempt with a reason and a task in ROW_IDENTITY_EXEMPT; a stale
56115
+ // exemption (table gone, no longer syncing, or declared) fails too.
56116
+ // The fresh-store check is store/__tests__/row-identity-gate.test.ts.
56117
+ id: "gate-37",
56118
+ task: "T12897",
56119
+ script: "scripts/lint-row-identity-coverage.mjs",
56120
+ description: "Every syncing cleo.db table has declared row identity or an exemption"
56121
+ },
56122
+ {
56123
+ // T12881: the raw sync applier never runs TypeScript write paths, so
56124
+ // every rejection site on a synced write path is tagged
56125
+ // `// @sync-invariant <id>` (contracts sync-write-invariants
56126
+ // registry) or an escape with a reason. Untagged sites are baselined
56127
+ // per (file, symbol, code); the baseline only shrinks. Registry
56128
+ // closure: tables classified, triggers created by migrations, no
56129
+ // dead gates (spec t12859 §3.6.7).
56130
+ id: "gate-38",
56131
+ task: "T12881",
56132
+ script: "scripts/lint-sync-write-invariants.mjs",
56133
+ description: "Every synced-write rejection site is classified (ratchet)"
55624
56134
  }
55625
56135
  ];
55626
56136
  const scriptArgs = strict ? ["--strict"] : ["--check"];
55627
56137
  const results = [];
55628
56138
  let anyFailed = false;
55629
56139
  for (const gate of gates) {
55630
- const scriptPath = join40(repoRoot, gate.script);
56140
+ const scriptPath = join41(repoRoot, gate.script);
55631
56141
  if (!existsSync22(scriptPath)) {
55632
56142
  results.push({
55633
56143
  id: gate.id,
@@ -56214,12 +56724,163 @@ var init_nexus_cloud_cli = __esm({
56214
56724
  }
56215
56725
  });
56216
56726
 
56727
+ // packages/cleo/src/cli/lib/nexus-vault-cli.ts
56728
+ function scopeArg(args, operation) {
56729
+ const raw = stringArg(args, "scope") ?? "project";
56730
+ if (raw === "project" || raw === "global") return raw;
56731
+ failNexus(
56732
+ Object.assign(new Error(`unknown scope '${raw}'`), {
56733
+ code: "E_VALIDATION",
56734
+ fix: "use --scope project (default) or --scope global"
56735
+ }),
56736
+ operation
56737
+ );
56738
+ }
56739
+ function common2(args, operation) {
56740
+ return { apiUrl: nexusApiUrlArg(args), scope: scopeArg(args, operation) };
56741
+ }
56742
+ function activityLimitArg(args) {
56743
+ const raw = stringArg(args, "limit");
56744
+ if (raw === void 0) return void 0;
56745
+ const limit = Number(raw);
56746
+ if (/^\d+$/.test(raw) && Number.isSafeInteger(limit) && limit >= 1 && limit <= 200) return limit;
56747
+ throw Object.assign(new Error(`--limit must be a whole number from 1 to 200, got '${raw}'`), {
56748
+ code: "E_VALIDATION",
56749
+ fix: "pass --limit 1..200 (default 50)"
56750
+ });
56751
+ }
56752
+ async function runCloudPush(args) {
56753
+ await runCloudRead(
56754
+ "cloud.push",
56755
+ async () => (await vaultModule()).pushNexusVault({
56756
+ ...common2(args, "cloud.push"),
56757
+ force: args["force"] === true,
56758
+ hold: args["hold"] === true
56759
+ }),
56760
+ (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" : ""}).`
56761
+ );
56762
+ }
56763
+ async function runCloudPull(args) {
56764
+ await runCloudRestoreLike(args, "cloud.pull", "pull");
56765
+ }
56766
+ async function runCloudRestore(args) {
56767
+ await runCloudRestoreLike(args, "cloud.restore", "restore");
56768
+ }
56769
+ async function runCloudRestoreLike(args, operation, mode) {
56770
+ await runCloudRead(
56771
+ operation,
56772
+ async () => {
56773
+ const checkpointId = stringArg(args, "checkpoint");
56774
+ const projectId = stringArg(args, "project");
56775
+ const into = stringArg(args, "into");
56776
+ return (await vaultModule()).restoreNexusVault({
56777
+ ...common2(args, operation),
56778
+ mode,
56779
+ force: args["force"] === true,
56780
+ ...mode === "restore" && checkpointId !== void 0 ? { checkpointId } : {},
56781
+ ...mode === "restore" && projectId !== void 0 ? { projectId } : {},
56782
+ ...mode === "restore" && into !== void 0 ? { into } : {},
56783
+ relink: async (projectRoot) => {
56784
+ const { linkProjectToNexus } = await import(
56785
+ /* webpackIgnore: true */
56786
+ "@cleocode/core/cloud/nexus-link.js"
56787
+ );
56788
+ try {
56789
+ const linked = await linkProjectToNexus({ apiUrl: nexusApiUrlArg(args), projectRoot });
56790
+ return linked.warnings;
56791
+ } catch (err) {
56792
+ return [
56793
+ `restored, but attaching this copy failed (${err instanceof Error ? err.message : String(err)}); run \`cleo project link\``
56794
+ ];
56795
+ }
56796
+ }
56797
+ });
56798
+ },
56799
+ (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}` : ""}.`
56800
+ );
56801
+ }
56802
+ async function runCloudVerify(args) {
56803
+ await runCloudRead(
56804
+ "cloud.verify",
56805
+ async () => (await vaultModule()).verifyNexusVault(common2(args, "cloud.verify")),
56806
+ (r) => {
56807
+ const bad = r.tables.filter((t) => !t.match).map((t) => t.table);
56808
+ const devices = r.devices.map(
56809
+ (d) => `${who(d.deviceName, d.deviceId)} ${d.matchesHead ? "matches" : "differs from"} head`
56810
+ ).join("; ");
56811
+ 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}` : ""}.`;
56812
+ }
56813
+ );
56814
+ }
56815
+ async function runCloudVault(args) {
56816
+ await runCloudRead(
56817
+ "cloud.vault",
56818
+ async () => (await vaultModule()).nexusVaultStatus(common2(args, "cloud.vault")),
56819
+ (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"}.`
56820
+ );
56821
+ }
56822
+ async function runCloudLease(args) {
56823
+ const action = stringArg(args, "action") ?? "release";
56824
+ if (action !== "release") {
56825
+ failNexus(
56826
+ Object.assign(new Error(`unknown action '${action}'`), {
56827
+ code: "E_VALIDATION",
56828
+ fix: "use `cleo cloud lease release` (see `cleo cloud vault` for holders)"
56829
+ }),
56830
+ "cloud.lease.release"
56831
+ );
56832
+ }
56833
+ await runCloudRead(
56834
+ "cloud.lease.release",
56835
+ async () => (await vaultModule()).releaseNexusVaultLease(common2(args, "cloud.lease.release")),
56836
+ (r) => r.released ? `Released the write lease on ${r.streamId}: another device may push now.` : `This machine held no write lease on ${r.streamId}.`
56837
+ );
56838
+ }
56839
+ async function runCloudActivity(args) {
56840
+ await runCloudRead(
56841
+ "cloud.activity",
56842
+ async () => {
56843
+ const { nexusCloudActivity } = await import(
56844
+ /* webpackIgnore: true */
56845
+ "@cleocode/core/cloud/nexus-cloud-activity.js"
56846
+ );
56847
+ const limit = activityLimitArg(args);
56848
+ const before = stringArg(args, "before");
56849
+ const projectId = stringArg(args, "project");
56850
+ const deviceId = stringArg(args, "device");
56851
+ return nexusCloudActivity({
56852
+ ...deviceId !== void 0 ? { deviceId } : {},
56853
+ apiUrl: nexusApiUrlArg(args),
56854
+ ...limit !== void 0 ? { limit } : {},
56855
+ ...before !== void 0 ? { before } : {},
56856
+ ...projectId !== void 0 ? { projectId } : {}
56857
+ });
56858
+ },
56859
+ (r) => `${r.items.length} event(s)${r.projectId ? ` for project ${r.projectId}` : ""}: ${r.items.slice(0, 10).map(
56860
+ (i) => `${i.at} ${who(i.deviceName, i.deviceId ?? "account")}${i.thisDevice ? " (this machine)" : ""} ${i.action}${i.target ? ` ${i.target}` : ""}`
56861
+ ).join("; ")}${r.items.length > 10 ? "; \u2026" : ""}`
56862
+ );
56863
+ }
56864
+ var vaultModule, who;
56865
+ var init_nexus_vault_cli = __esm({
56866
+ "packages/cleo/src/cli/lib/nexus-vault-cli.ts"() {
56867
+ "use strict";
56868
+ init_nexus_account_cli();
56869
+ init_nexus_cloud_cli();
56870
+ vaultModule = () => import(
56871
+ /* webpackIgnore: true */
56872
+ "@cleocode/core/cloud/nexus-vault.js"
56873
+ );
56874
+ who = (name, id) => name ?? id;
56875
+ }
56876
+ });
56877
+
56217
56878
  // packages/cleo/src/cli/commands/cloud.ts
56218
56879
  var cloud_exports = {};
56219
56880
  __export(cloud_exports, {
56220
56881
  cloudCommand: () => cloudCommand
56221
56882
  });
56222
- var JSON_ARG, statusSubCommand, whoamiSubCommand, devicesSubCommand, projectsSubCommand, cloudCommand;
56883
+ var JSON_ARG, SCOPE_ARG, statusSubCommand, whoamiSubCommand, devicesSubCommand, projectsSubCommand, pushSubCommand, pullSubCommand, restoreSubCommand, verifyVaultSubCommand, vaultSubCommand, leaseSubCommand, activitySubCommand, cloudCommand;
56223
56884
  var init_cloud = __esm({
56224
56885
  "packages/cleo/src/cli/commands/cloud.ts"() {
56225
56886
  "use strict";
@@ -56227,7 +56888,12 @@ var init_cloud = __esm({
56227
56888
  init_define_cli_command();
56228
56889
  init_nexus_account_cli();
56229
56890
  init_nexus_cloud_cli();
56891
+ init_nexus_vault_cli();
56230
56892
  JSON_ARG = { type: "boolean", description: "Output as JSON envelope" };
56893
+ SCOPE_ARG = {
56894
+ type: "string",
56895
+ description: "Which store: 'project' (the current project, default) or 'global' (this account's global store: the main brain)."
56896
+ };
56231
56897
  statusSubCommand = defineCommand({
56232
56898
  meta: {
56233
56899
  name: "status",
@@ -56296,16 +56962,139 @@ var init_cloud = __esm({
56296
56962
  await runCloudProjects(args);
56297
56963
  }
56298
56964
  });
56965
+ pushSubCommand = defineCommand({
56966
+ meta: {
56967
+ name: "push",
56968
+ 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."
56969
+ },
56970
+ args: {
56971
+ scope: SCOPE_ARG,
56972
+ force: {
56973
+ type: "boolean",
56974
+ description: "Take the lease from another device / push over a newer snapshot (a labelled fork)."
56975
+ },
56976
+ hold: {
56977
+ type: "boolean",
56978
+ description: "Keep the write lease after the push (another device cannot push until it expires or `cleo cloud lease release`)."
56979
+ },
56980
+ "api-url": NEXUS_API_URL_ARG,
56981
+ json: JSON_ARG
56982
+ },
56983
+ async run({ args }) {
56984
+ await runCloudPush(args);
56985
+ }
56986
+ });
56987
+ pullSubCommand = defineCommand({
56988
+ meta: {
56989
+ name: "pull",
56990
+ 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)."
56991
+ },
56992
+ args: {
56993
+ scope: SCOPE_ARG,
56994
+ force: { type: "boolean", description: "Overwrite local changes (after a safety backup)." },
56995
+ "api-url": NEXUS_API_URL_ARG,
56996
+ json: JSON_ARG
56997
+ },
56998
+ async run({ args }) {
56999
+ await runCloudPull(args);
57000
+ }
57001
+ });
57002
+ restoreSubCommand = defineCommand({
57003
+ meta: {
57004
+ name: "restore",
57005
+ 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."
57006
+ },
57007
+ args: {
57008
+ scope: SCOPE_ARG,
57009
+ checkpoint: { type: "string", description: "Snapshot id to restore (see `cleo cloud vault`)." },
57010
+ project: {
57011
+ type: "string",
57012
+ description: "Server project id to restore onto this machine (see `cleo cloud projects`)."
57013
+ },
57014
+ into: {
57015
+ type: "string",
57016
+ description: "Directory for --project (default: the current directory)."
57017
+ },
57018
+ force: { type: "boolean", description: "Overwrite local changes (after a safety backup)." },
57019
+ "api-url": NEXUS_API_URL_ARG,
57020
+ json: JSON_ARG
57021
+ },
57022
+ async run({ args }) {
57023
+ await runCloudRestore(args);
57024
+ }
57025
+ });
57026
+ verifyVaultSubCommand = defineCommand({
57027
+ meta: {
57028
+ name: "verify",
57029
+ 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)."
57030
+ },
57031
+ args: { scope: SCOPE_ARG, "api-url": NEXUS_API_URL_ARG, json: JSON_ARG },
57032
+ async run({ args }) {
57033
+ await runCloudVerify(args);
57034
+ }
57035
+ });
57036
+ vaultSubCommand = defineCommand({
57037
+ meta: {
57038
+ name: "vault",
57039
+ 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."
57040
+ },
57041
+ args: { scope: SCOPE_ARG, "api-url": NEXUS_API_URL_ARG, json: JSON_ARG },
57042
+ async run({ args }) {
57043
+ await runCloudVault(args);
57044
+ }
57045
+ });
57046
+ leaseSubCommand = defineCommand({
57047
+ meta: {
57048
+ name: "lease",
57049
+ description: "Hand the write lease back so another device can push: cleo cloud lease release."
57050
+ },
57051
+ args: {
57052
+ action: { type: "positional", description: "'release'.", required: false },
57053
+ scope: SCOPE_ARG,
57054
+ "api-url": NEXUS_API_URL_ARG,
57055
+ json: JSON_ARG
57056
+ },
57057
+ async run({ args }) {
57058
+ await runCloudLease(args);
57059
+ }
57060
+ });
57061
+ activitySubCommand = defineCommand({
57062
+ meta: {
57063
+ name: "activity",
57064
+ 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."
57065
+ },
57066
+ args: {
57067
+ limit: { type: "string", description: "Events to show (1-200, default 50)." },
57068
+ before: { type: "string", description: "Older page: the nextBefore of a previous call." },
57069
+ project: { type: "string", description: "Only events about this server project id." },
57070
+ device: {
57071
+ type: "string",
57072
+ description: "Only events by this device id (see `cleo cloud devices`)."
57073
+ },
57074
+ "api-url": NEXUS_API_URL_ARG,
57075
+ json: JSON_ARG
57076
+ },
57077
+ async run({ args }) {
57078
+ await runCloudActivity(args);
57079
+ }
57080
+ });
56299
57081
  cloudCommand = defineCommand({
56300
57082
  meta: {
56301
57083
  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]."
57084
+ 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
57085
  },
56304
57086
  subCommands: {
56305
57087
  status: statusSubCommand,
56306
57088
  whoami: whoamiSubCommand,
56307
57089
  devices: devicesSubCommand,
56308
- projects: projectsSubCommand
57090
+ projects: projectsSubCommand,
57091
+ activity: activitySubCommand,
57092
+ push: pushSubCommand,
57093
+ pull: pullSubCommand,
57094
+ restore: restoreSubCommand,
57095
+ verify: verifyVaultSubCommand,
57096
+ vault: vaultSubCommand,
57097
+ lease: leaseSubCommand
56309
57098
  }
56310
57099
  });
56311
57100
  }
@@ -56358,9 +57147,9 @@ var init_code = __esm({
56358
57147
  async run({ args }) {
56359
57148
  await requireTreeSitter();
56360
57149
  const { smartOutline } = await import("@cleocode/core/internal");
56361
- const { join: join40 } = await import("node:path");
57150
+ const { join: join41 } = await import("node:path");
56362
57151
  const root = process.cwd();
56363
- const absPath = args.file.startsWith("/") ? args.file : join40(root, args.file);
57152
+ const absPath = args.file.startsWith("/") ? args.file : join41(root, args.file);
56364
57153
  const result = smartOutline(absPath, root);
56365
57154
  if (result.errors.length > 0 && result.symbols.length === 0) {
56366
57155
  cliError(result.errors.join(", "), 1, { name: "E_OUTLINE_FAILED" });
@@ -56451,9 +57240,9 @@ var init_code = __esm({
56451
57240
  async run({ args }) {
56452
57241
  await requireTreeSitter();
56453
57242
  const { smartUnfold } = await import("@cleocode/core/internal");
56454
- const { join: join40 } = await import("node:path");
57243
+ const { join: join41 } = await import("node:path");
56455
57244
  const root = process.cwd();
56456
- const absPath = args.file.startsWith("/") ? args.file : join40(root, args.file);
57245
+ const absPath = args.file.startsWith("/") ? args.file : join41(root, args.file);
56457
57246
  const result = smartUnfold(absPath, args.symbol, root);
56458
57247
  if (!result.found) {
56459
57248
  const errs = result.errors.length > 0 ? `: ${result.errors.join(", ")}` : "";
@@ -64442,15 +65231,15 @@ var init_doctor_fk_check = __esm({
64442
65231
  }
64443
65232
  },
64444
65233
  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", {
65234
+ const scopeArg2 = args.scope;
65235
+ if (scopeArg2 !== void 0 && scopeArg2 !== "project" && scopeArg2 !== "global") {
65236
+ cliError(`--scope must be 'project' or 'global' (received: ${scopeArg2})`, "E_INVALID_INPUT", {
64448
65237
  fix: "Run 'cleo doctor fk-check --scope project' or omit --scope to check both."
64449
65238
  });
64450
65239
  process.exitCode = 6;
64451
65240
  return;
64452
65241
  }
64453
- const scopeOpt = scopeArg ? { scopes: [scopeArg] } : {};
65242
+ const scopeOpt = scopeArg2 ? { scopes: [scopeArg2] } : {};
64454
65243
  if (args.fix === true) {
64455
65244
  const fixReport = await repairForeignKeyViolations({ cwd: process.cwd(), ...scopeOpt });
64456
65245
  humanInfo(
@@ -64867,12 +65656,44 @@ var init_doctor_memory_guard = __esm({
64867
65656
  }
64868
65657
  });
64869
65658
 
65659
+ // packages/cleo/src/cli/commands/doctor-migrations.ts
65660
+ var doctor_migrations_exports = {};
65661
+ __export(doctor_migrations_exports, {
65662
+ doctorMigrationsCommand: () => doctorMigrationsCommand
65663
+ });
65664
+ import { getProjectRoot as getProjectRoot49 } from "@cleocode/core";
65665
+ import { inspectMigrations } from "@cleocode/core/doctor/migrations.js";
65666
+ var doctorMigrationsCommand;
65667
+ var init_doctor_migrations = __esm({
65668
+ "packages/cleo/src/cli/commands/doctor-migrations.ts"() {
65669
+ "use strict";
65670
+ init_define_cli_command();
65671
+ init_renderers();
65672
+ doctorMigrationsCommand = defineCommand({
65673
+ meta: {
65674
+ name: "migrations",
65675
+ 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."
65676
+ },
65677
+ args: {
65678
+ json: { type: "boolean", description: "Output as JSON" },
65679
+ human: { type: "boolean", description: "Force human-readable output" },
65680
+ quiet: { type: "boolean", description: "Suppress non-essential output" }
65681
+ },
65682
+ async run() {
65683
+ const report = inspectMigrations(getProjectRoot49());
65684
+ cliOutput(report, { command: "doctor", operation: "doctor.migrations.run" });
65685
+ if (report.scopes.some((s) => s.drift.length > 0)) process.exitCode = 1;
65686
+ }
65687
+ });
65688
+ }
65689
+ });
65690
+
64870
65691
  // packages/cleo/src/cli/commands/doctor-nexus-residency.ts
64871
65692
  var doctor_nexus_residency_exports = {};
64872
65693
  __export(doctor_nexus_residency_exports, {
64873
65694
  doctorNexusResidencyCommand: () => doctorNexusResidencyCommand
64874
65695
  });
64875
- import { getCleoHome as getCleoHome6, getProjectRoot as getProjectRoot49 } from "@cleocode/core";
65696
+ import { getCleoHome as getCleoHome6, getProjectRoot as getProjectRoot50 } from "@cleocode/core";
64876
65697
  import { scanNexusSchemaResidency } from "@cleocode/core/doctor/nexus-schema-residency.js";
64877
65698
  var doctorNexusResidencyCommand;
64878
65699
  var init_doctor_nexus_residency = __esm({
@@ -64891,7 +65712,7 @@ var init_doctor_nexus_residency = __esm({
64891
65712
  quiet: { type: "boolean", description: "Suppress non-essential output" }
64892
65713
  },
64893
65714
  async run() {
64894
- const result = scanNexusSchemaResidency(getProjectRoot49(), getCleoHome6());
65715
+ const result = scanNexusSchemaResidency(getProjectRoot50(), getCleoHome6());
64895
65716
  cliOutput(result, {
64896
65717
  command: "doctor",
64897
65718
  operation: "doctor.nexus-residency.run"
@@ -64909,7 +65730,7 @@ var doctor_project_identity_exports = {};
64909
65730
  __export(doctor_project_identity_exports, {
64910
65731
  doctorProjectIdentityCommand: () => doctorProjectIdentityCommand
64911
65732
  });
64912
- import { getProjectRoot as getProjectRoot50 } from "@cleocode/core";
65733
+ import { getProjectRoot as getProjectRoot51 } from "@cleocode/core";
64913
65734
  import {
64914
65735
  inspectProjectIdentity,
64915
65736
  inspectProjectNameDrift,
@@ -64934,7 +65755,7 @@ var init_doctor_project_identity = __esm({
64934
65755
  quiet: { type: "boolean", description: "Suppress non-essential output" }
64935
65756
  },
64936
65757
  async run({ args }) {
64937
- const projectRoot = getProjectRoot50();
65758
+ const projectRoot = getProjectRoot51();
64938
65759
  if (!args.resolve) {
64939
65760
  const report = inspectProjectIdentity(projectRoot);
64940
65761
  const nameDrift = await inspectProjectNameDrift(projectRoot);
@@ -65473,7 +66294,7 @@ var doctor_repair_exports = {};
65473
66294
  __export(doctor_repair_exports, {
65474
66295
  doctorRepairCommand: () => doctorRepairCommand
65475
66296
  });
65476
- import { getLogger as getLogger21, getProjectRoot as getProjectRoot51 } from "@cleocode/core";
66297
+ import { getLogger as getLogger21, getProjectRoot as getProjectRoot52 } from "@cleocode/core";
65477
66298
  import { repairMalformedDbs } from "@cleocode/core/store/repair-malformed-dbs.js";
65478
66299
  var doctorRepairCommand;
65479
66300
  var init_doctor_repair = __esm({
@@ -65522,7 +66343,7 @@ var init_doctor_repair = __esm({
65522
66343
  return;
65523
66344
  }
65524
66345
  const result = repairMalformedDbs({
65525
- projectRoot: getProjectRoot51(),
66346
+ projectRoot: getProjectRoot52(),
65526
66347
  roles: roleArg.length > 0 ? [roleArg] : void 0,
65527
66348
  dryRun,
65528
66349
  logger: getLogger21("doctor-repair"),
@@ -65724,7 +66545,7 @@ var doctor_superseded_store_exports = {};
65724
66545
  __export(doctor_superseded_store_exports, {
65725
66546
  doctorSupersededStoreCommand: () => doctorSupersededStoreCommand
65726
66547
  });
65727
- import { getProjectRoot as getProjectRoot52 } from "@cleocode/core";
66548
+ import { getProjectRoot as getProjectRoot53 } from "@cleocode/core";
65728
66549
  import { scanSupersededStores } from "@cleocode/core/doctor/superseded-store.js";
65729
66550
  import { reconcileSupersededStores } from "@cleocode/core/store/exodus/index.js";
65730
66551
  var doctorSupersededStoreCommand;
@@ -65757,7 +66578,7 @@ var init_doctor_superseded_store = __esm({
65757
66578
  },
65758
66579
  async run({ args }) {
65759
66580
  if (args.reconcile === true) {
65760
- const receipt = await reconcileSupersededStores(getProjectRoot52(), {
66581
+ const receipt = await reconcileSupersededStores(getProjectRoot53(), {
65761
66582
  dryRun: args["dry-run"] === true,
65762
66583
  additive: args.additive === true
65763
66584
  });
@@ -65779,7 +66600,7 @@ var init_doctor_superseded_store = __esm({
65779
66600
  );
65780
66601
  return;
65781
66602
  }
65782
- const result = scanSupersededStores(getProjectRoot52());
66603
+ const result = scanSupersededStores(getProjectRoot53());
65783
66604
  cliOutput(result, {
65784
66605
  command: "doctor",
65785
66606
  operation: "doctor.superseded-store.run"
@@ -65880,7 +66701,7 @@ import {
65880
66701
  rollbackTwinCollapse
65881
66702
  } from "@cleocode/core/doctor/twin-collapse.js";
65882
66703
  import { CleoError as CleoError8 } from "@cleocode/core/errors";
65883
- import { getProjectRoot as getProjectRoot53 } from "@cleocode/core/paths.js";
66704
+ import { getProjectRoot as getProjectRoot54 } from "@cleocode/core/paths.js";
65884
66705
  function reportTwinCollapseError(error, retry) {
65885
66706
  if (retry && !(error instanceof CleoError8)) throw error;
65886
66707
  const message = error instanceof Error ? error.message : String(error);
@@ -65951,7 +66772,7 @@ var init_doctor_twin_collapse = __esm({
65951
66772
  quiet: { type: "boolean", description: "Suppress non-essential output" }
65952
66773
  },
65953
66774
  async run({ args }) {
65954
- const projectRoot = getProjectRoot53();
66775
+ const projectRoot = getProjectRoot54();
65955
66776
  const guard = { cwd: process.cwd(), confirmOwnerStore: args["confirm-owner-store"] === true };
65956
66777
  const actions = twinCollapseActions(args);
65957
66778
  if (actions.length > 1) {
@@ -66029,7 +66850,7 @@ __export(doctor_worktree_stores_exports, {
66029
66850
  doctorWorktreeStoresCommand: () => doctorWorktreeStoresCommand
66030
66851
  });
66031
66852
  import { scanWorktreeStores } from "@cleocode/core/doctor/worktree-stores.js";
66032
- import { getProjectRoot as getProjectRoot54, resolveStoreOwnerRoot } from "@cleocode/core/paths.js";
66853
+ import { getProjectRoot as getProjectRoot55, resolveStoreOwnerRoot } from "@cleocode/core/paths.js";
66033
66854
  var doctorWorktreeStoresCommand;
66034
66855
  var init_doctor_worktree_stores = __esm({
66035
66856
  "packages/cleo/src/cli/commands/doctor-worktree-stores.ts"() {
@@ -66051,7 +66872,7 @@ var init_doctor_worktree_stores = __esm({
66051
66872
  quiet: { type: "boolean", description: "Suppress non-essential output" }
66052
66873
  },
66053
66874
  async run({ args }) {
66054
- const projectRoot = resolveStoreOwnerRoot(getProjectRoot54());
66875
+ const projectRoot = resolveStoreOwnerRoot(getProjectRoot55());
66055
66876
  const result = scanWorktreeStores(projectRoot, { skipCompare: args["skip-compare"] === true });
66056
66877
  cliOutput(result, {
66057
66878
  command: "doctor",
@@ -66203,7 +67024,7 @@ import {
66203
67024
  resumePreparedKnowledgeRepair,
66204
67025
  runKnowledgeDoctor as runKnowledgeDoctor2
66205
67026
  } from "@cleocode/core/doctor/knowledge.js";
66206
- import { getProjectRoot as getProjectRoot55 } from "@cleocode/core/paths.js";
67027
+ import { getProjectRoot as getProjectRoot56 } from "@cleocode/core/paths.js";
66207
67028
  var doctorKnowledgeSubcommand;
66208
67029
  var init_doctor_knowledge = __esm({
66209
67030
  "packages/cleo/src/cli/commands/doctor-knowledge.ts"() {
@@ -66278,7 +67099,7 @@ var init_doctor_knowledge = __esm({
66278
67099
  },
66279
67100
  async run({ args }) {
66280
67101
  const startedAt = Date.now();
66281
- const root = getProjectRoot55();
67102
+ const root = getProjectRoot56();
66282
67103
  let context;
66283
67104
  let pending;
66284
67105
  try {
@@ -66446,7 +67267,7 @@ import { join as join24 } from "node:path";
66446
67267
  import {
66447
67268
  ensureGlobalAgentRegistryDb,
66448
67269
  getGlobalAgentRegistryNativeDb,
66449
- getProjectRoot as getProjectRoot56,
67270
+ getProjectRoot as getProjectRoot57,
66450
67271
  installAgentFromCant
66451
67272
  } from "@cleocode/core/internal";
66452
67273
  function sha256Hex(bytes) {
@@ -66634,7 +67455,7 @@ var init_migrate_agents_v2 = __esm({
66634
67455
  }
66635
67456
  },
66636
67457
  async run({ args }) {
66637
- const projectRoot = getProjectRoot56();
67458
+ const projectRoot = getProjectRoot57();
66638
67459
  const verbose = args.quiet !== true;
66639
67460
  if (verbose) {
66640
67461
  humanInfo("Scanning .cleo/cant/agents/ and .cleo/agents/ for unregistered agents...");
@@ -66678,7 +67499,7 @@ __export(doctor_exports, {
66678
67499
  });
66679
67500
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
66680
67501
  import { join as join25 } from "node:path";
66681
- import { getProjectRoot as getProjectRoot57, pushWarning as pushWarning5 } from "@cleocode/core";
67502
+ import { getProjectRoot as getProjectRoot58, pushWarning as pushWarning5 } from "@cleocode/core";
66682
67503
  import { renderInvariantAuditLines } from "@cleocode/core/doctor/invariant-audit-render.js";
66683
67504
  import {
66684
67505
  quarantineRogueCleoDir,
@@ -66809,6 +67630,7 @@ var init_doctor = __esm({
66809
67630
  init_doctor_malformed_ids();
66810
67631
  init_doctor_manifest_rows();
66811
67632
  init_doctor_memory_guard();
67633
+ init_doctor_migrations();
66812
67634
  init_doctor_nexus_residency();
66813
67635
  init_doctor_project_identity();
66814
67636
  init_doctor_projects();
@@ -66841,6 +67663,8 @@ var init_doctor = __esm({
66841
67663
  "legacy-reaper": doctorLegacyReaperCommand,
66842
67664
  // T12128 — task ids that fail the write-path validator
66843
67665
  "malformed-ids": doctorMalformedIdsCommand,
67666
+ // T12796 — the migration journal of each store (read-only; the live journal count)
67667
+ migrations: doctorMigrationsCommand,
66844
67668
  // T12686 — manifest rows whose metadata violates the stored field contract (+ --repair/--rollback)
66845
67669
  "manifest-rows": doctorManifestRowsCommand,
66846
67670
  // T12095 — pre-dual-scope store files still on disk under their old LIVE names
@@ -67085,7 +67909,7 @@ var init_doctor = __esm({
67085
67909
  const { join: pathJoin } = await import("node:path");
67086
67910
  const { existsSync: existsSync22 } = await import("node:fs");
67087
67911
  const { detectAndHealCoreWorktreeLeak } = await import("@cleocode/worktree");
67088
- const projectRoot = getProjectRoot57();
67912
+ const projectRoot = getProjectRoot58();
67089
67913
  let gitRoot = projectRoot;
67090
67914
  try {
67091
67915
  gitRoot = execFile2("git", ["rev-parse", "--show-toplevel"], {
@@ -67137,7 +67961,7 @@ var init_doctor = __esm({
67137
67961
  }
67138
67962
  if (args.brain) {
67139
67963
  const { computeBrainHealthDashboard } = await import("@cleocode/core/memory/brain-health-dashboard.js");
67140
- const projectRoot = getProjectRoot57();
67964
+ const projectRoot = getProjectRoot58();
67141
67965
  const dashboard = await computeBrainHealthDashboard(projectRoot);
67142
67966
  cliOutput(dashboard, { command: "doctor", operation: "doctor.brain" });
67143
67967
  if (dashboard.hasP0Failure) {
@@ -67146,7 +67970,7 @@ var init_doctor = __esm({
67146
67970
  return;
67147
67971
  }
67148
67972
  if (args["scan-test-fixtures-in-prod"]) {
67149
- const projectRoot = getProjectRoot57();
67973
+ const projectRoot = getProjectRoot58();
67150
67974
  const matches = await scanTestFixturesInProd(projectRoot);
67151
67975
  const dryRun = args["dry-run"] !== false && args.quarantine !== true;
67152
67976
  const quarantined = !dryRun && matches.length > 0 ? await quarantineTestFixtures(projectRoot, matches) : void 0;
@@ -67234,7 +68058,7 @@ var init_doctor = __esm({
67234
68058
  progress.complete("Comprehensive diagnostics complete");
67235
68059
  } else if (args["scan-rogue-cleo-dirs"]) {
67236
68060
  progress.step(0, "Scanning for rogue .cleo/ directories");
67237
- const projectRoot = getProjectRoot57();
68061
+ const projectRoot = getProjectRoot58();
67238
68062
  const reports = scanRogueCleoDirs(projectRoot);
67239
68063
  progress.complete(
67240
68064
  `Found ${reports.length} rogue .cleo/ director${reports.length === 1 ? "y" : "ies"}`
@@ -67243,7 +68067,7 @@ var init_doctor = __esm({
67243
68067
  } else if (args["quarantine-rogue-cleo-dirs"]) {
67244
68068
  const isDryRun = args["dry-run"] === true;
67245
68069
  progress.step(0, `${isDryRun ? "[DRY RUN] " : ""}Scanning for rogue .cleo/ directories`);
67246
- const projectRoot = getProjectRoot57();
68070
+ const projectRoot = getProjectRoot58();
67247
68071
  const reports = scanRogueCleoDirs(projectRoot);
67248
68072
  if (reports.length === 0) {
67249
68073
  progress.complete("No rogue .cleo/ directories found \u2014 nothing to quarantine");
@@ -67297,7 +68121,7 @@ var init_doctor = __esm({
67297
68121
  const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/store/cleanup-legacy.js");
67298
68122
  const { getCleoHome: getCleoHome8 } = await import("@cleocode/core");
67299
68123
  const cleoHome = getCleoHome8();
67300
- const projectRoot = getProjectRoot57();
68124
+ const projectRoot = getProjectRoot58();
67301
68125
  const legacyResult = detectAndRemoveLegacyGlobalFiles(cleoHome);
67302
68126
  const strayResult = detectAndRemoveStrayProjectNexus(projectRoot);
67303
68127
  const isDryRun = args["dry-run"] === true;
@@ -67330,7 +68154,7 @@ var init_doctor = __esm({
67330
68154
  } else if (args["audit-worktree-orphans"]) {
67331
68155
  progress.step(0, "Comprehensive worktree anomaly audit (T9808 / council D009)");
67332
68156
  const { auditWorktreeOrphansComprehensive, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
67333
- const projectRoot = getProjectRoot57();
68157
+ const projectRoot = getProjectRoot58();
67334
68158
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
67335
68159
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
67336
68160
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -67387,7 +68211,7 @@ var init_doctor = __esm({
67387
68211
  `${isDryRun ? "[DRY RUN] " : ""}Scanning + pruning worktree-orphan .cleo/ directories`
67388
68212
  );
67389
68213
  const { pruneWorktreeOrphans, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
67390
- const projectRoot = getProjectRoot57();
68214
+ const projectRoot = getProjectRoot58();
67391
68215
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
67392
68216
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
67393
68217
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -67466,7 +68290,7 @@ var init_doctor = __esm({
67466
68290
  `${isDryRun ? "[DRY RUN] " : ""}Migrating .cleo/worktree-include \u2192 .worktreeinclude`
67467
68291
  );
67468
68292
  const { migrateWorktreeIncludeFile } = await import("@cleocode/core");
67469
- const projectRoot = getProjectRoot57();
68293
+ const projectRoot = getProjectRoot58();
67470
68294
  const result = await migrateWorktreeIncludeFile(projectRoot, { dryRun: isDryRun });
67471
68295
  progress.complete(`Migration ${result.action}`);
67472
68296
  cliOutput(result, { command: "doctor", operation: "doctor.migrate-worktree-include" });
@@ -67485,7 +68309,7 @@ var init_doctor = __esm({
67485
68309
  const stepLabel = isFocusedAlias ? "Auditing Saga hierarchy for ADR-073 invariants" : "Walking central INVARIANTS_REGISTRY";
67486
68310
  progress.step(0, stepLabel);
67487
68311
  const { auditInvariantRegistry } = await import("@cleocode/core/doctor/invariant-audit.js");
67488
- const projectRoot = getProjectRoot57();
68312
+ const projectRoot = getProjectRoot58();
67489
68313
  const result = await auditInvariantRegistry(projectRoot, { adrFilter });
67490
68314
  const operation = isFocusedAlias ? "doctor.audit-sagas" : "doctor.audit-invariants";
67491
68315
  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 +68331,7 @@ var init_doctor = __esm({
67507
68331
  { command: "doctor", operation: "admin.health" }
67508
68332
  );
67509
68333
  try {
67510
- const projectRoot = getProjectRoot57();
68334
+ const projectRoot = getProjectRoot58();
67511
68335
  const conflicts = readMigrationConflicts(projectRoot);
67512
68336
  if (conflicts.length > 0) {
67513
68337
  progress.complete(
@@ -67538,7 +68362,7 @@ var init_doctor = __esm({
67538
68362
  progress.complete("Health check complete");
67539
68363
  }
67540
68364
  try {
67541
- const projectRoot = getProjectRoot57();
68365
+ const projectRoot = getProjectRoot58();
67542
68366
  const { auditSagaHierarchy } = await import("@cleocode/core/doctor/saga-audit.js");
67543
68367
  const sagaAudit = await auditSagaHierarchy(projectRoot);
67544
68368
  if (sagaAudit.sagas.length === 0) {
@@ -67567,7 +68391,7 @@ Saga Hierarchy: audit skipped (${msg})`);
67567
68391
  }
67568
68392
  try {
67569
68393
  const { scanDependencyCycles: scanDependencyCycles2 } = await import("@cleocode/core/doctor/dependency-cycles.js");
67570
- const cycles = await scanDependencyCycles2(getProjectRoot57());
68394
+ const cycles = await scanDependencyCycles2(getProjectRoot58());
67571
68395
  humanLine(
67572
68396
  `
67573
68397
  Dependency cycles: ${cycles.cycleCount} (${cycles.edgeCount} edge(s) checked)`
@@ -67678,14 +68502,14 @@ var init_done = __esm({
67678
68502
  process.exitCode = 2;
67679
68503
  return;
67680
68504
  }
67681
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/paths.js");
67682
- const options = { projectRoot: getProjectRoot75(), ...parsed.options };
68505
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/paths.js");
68506
+ const options = { projectRoot: getProjectRoot76(), ...parsed.options };
67683
68507
  const requested = [
67684
68508
  ...new Set([args.taskId, ...args._ ?? []].map(String))
67685
68509
  ];
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");
68510
+ const invalid2 = requested.filter((id) => !/^T\d+$/.test(id));
68511
+ if (invalid2.length > 0) {
68512
+ cliError(`Not task ids: ${invalid2.join(", ")} (expected T<digits>)`, "E_INVALID_INPUT");
67689
68513
  process.exitCode = 2;
67690
68514
  return;
67691
68515
  }
@@ -67949,8 +68773,8 @@ var init_event = __esm({
67949
68773
  }
67950
68774
  for (const file of filesToTail) {
67951
68775
  const agentId = file.replace(".jsonl", "");
67952
- const { readFileSync: readFileSync22 } = await import("node:fs");
67953
- const content = readFileSync22(join26(eventsDir, file), "utf-8");
68776
+ const { readFileSync: readFileSync23 } = await import("node:fs");
68777
+ const content = readFileSync23(join26(eventsDir, file), "utf-8");
67954
68778
  const eventLines = content.trim().split("\n").filter(Boolean);
67955
68779
  const tail = eventLines.slice(-lines);
67956
68780
  if (jsonMode) {
@@ -68045,8 +68869,8 @@ var init_event = __esm({
68045
68869
  const printAgentLog = async (file) => {
68046
68870
  const agentId = file.replace(".jsonl", "");
68047
68871
  try {
68048
- const { readFileSync: readFileSync22 } = await import("node:fs");
68049
- const content = readFileSync22(join26(eventsDir, file), "utf-8");
68872
+ const { readFileSync: readFileSync23 } = await import("node:fs");
68873
+ const content = readFileSync23(join26(eventsDir, file), "utf-8");
68050
68874
  const eventLines = content.trim().split("\n").filter(Boolean);
68051
68875
  const tail = eventLines.slice(-lines);
68052
68876
  if (jsonMode) {
@@ -69041,7 +69865,7 @@ __export(gateway_exports, {
69041
69865
  gatewayOpenapiSubCommand: () => gatewayOpenapiSubCommand
69042
69866
  });
69043
69867
  import { resolve as resolve8 } from "node:path";
69044
- import { generateOpenApi, getProjectRoot as getProjectRoot58 } from "@cleocode/core";
69868
+ import { generateOpenApi, getProjectRoot as getProjectRoot59 } from "@cleocode/core";
69045
69869
  var gatewayOpenapiSubCommand, gatewayCommand;
69046
69870
  var init_gateway = __esm({
69047
69871
  "packages/cleo/src/cli/commands/gateway.ts"() {
@@ -69073,7 +69897,7 @@ var init_gateway = __esm({
69073
69897
  const pathCount = Object.keys(doc.paths).length;
69074
69898
  if (typeof args.out === "string" && args.out.length > 0) {
69075
69899
  const { writeFileSync: writeFileSync8 } = await import("node:fs");
69076
- const target = resolve8(getProjectRoot58(), args.out);
69900
+ const target = resolve8(getProjectRoot59(), args.out);
69077
69901
  writeFileSync8(target, json2, "utf8");
69078
69902
  cliOutput(
69079
69903
  { out: target, pathCount, version: doc.info.version, openapi: doc.openapi },
@@ -69534,7 +70358,7 @@ var go_exports = {};
69534
70358
  __export(go_exports, {
69535
70359
  goCommand: () => goCommand
69536
70360
  });
69537
- import { getProjectRoot as getProjectRoot59, go } from "@cleocode/core";
70361
+ import { getProjectRoot as getProjectRoot60, go } from "@cleocode/core";
69538
70362
  var goCommand;
69539
70363
  var init_go = __esm({
69540
70364
  "packages/cleo/src/cli/commands/go.ts"() {
@@ -69560,7 +70384,7 @@ var init_go = __esm({
69560
70384
  }
69561
70385
  },
69562
70386
  async run({ args }) {
69563
- const projectRoot = getProjectRoot59();
70387
+ const projectRoot = getProjectRoot60();
69564
70388
  const { getCurrentSessionId, resolveBoundSessionId } = await import("@cleocode/core/internal");
69565
70389
  let sessionId = getCurrentSessionId(projectRoot) ?? void 0;
69566
70390
  if (sessionId === void 0) {
@@ -69588,7 +70412,7 @@ var goal_exports = {};
69588
70412
  __export(goal_exports, {
69589
70413
  goalCommand: () => goalCommand
69590
70414
  });
69591
- import { getProjectRoot as getProjectRoot60, goal } from "@cleocode/core";
70415
+ import { getProjectRoot as getProjectRoot61, goal } from "@cleocode/core";
69592
70416
  function resolveGoalKind(task) {
69593
70417
  if (typeof task === "string" && task.length > 0) {
69594
70418
  if (!isValidGoalTargetTaskId(task)) {
@@ -69635,7 +70459,7 @@ var init_goal2 = __esm({
69635
70459
  }
69636
70460
  const record = await goal.createGoal(
69637
70461
  { goalKind: kindResult.kind, intent, turnBudget: resolveTurnBudget(args.turns) },
69638
- getProjectRoot60()
70462
+ getProjectRoot61()
69639
70463
  );
69640
70464
  cliOutput(record, { command: "goal set", operation: "goal.set" });
69641
70465
  }
@@ -69646,7 +70470,7 @@ var init_goal2 = __esm({
69646
70470
  description: "Show the current agent's active goal (per-agent scoped)."
69647
70471
  },
69648
70472
  async run() {
69649
- const record = await goal.getActiveGoal(getProjectRoot60());
70473
+ const record = await goal.getActiveGoal(getProjectRoot61());
69650
70474
  cliOutput(record ?? { active: null }, { command: "goal status", operation: "goal.status" });
69651
70475
  }
69652
70476
  });
@@ -69668,7 +70492,7 @@ var init_goal2 = __esm({
69668
70492
  });
69669
70493
  return;
69670
70494
  }
69671
- const cwd = getProjectRoot60();
70495
+ const cwd = getProjectRoot61();
69672
70496
  const parent = await goal.getActiveGoal(cwd);
69673
70497
  if (!parent) {
69674
70498
  cliError(
@@ -69716,7 +70540,7 @@ var init_goal2 = __esm({
69716
70540
  });
69717
70541
  return;
69718
70542
  }
69719
- const cwd = getProjectRoot60();
70543
+ const cwd = getProjectRoot61();
69720
70544
  const result = await goal.advanceGoalWithPersist(goalId, { cwd });
69721
70545
  if (!result) {
69722
70546
  cliError(`Goal '${goalId}' not found.`, 4 /* NOT_FOUND */, { name: "E_NOT_FOUND" });
@@ -69741,7 +70565,7 @@ var init_goal2 = __esm({
69741
70565
  });
69742
70566
  return;
69743
70567
  }
69744
- const cwd = getProjectRoot60();
70568
+ const cwd = getProjectRoot61();
69745
70569
  const active = await goal.getActiveGoal(cwd);
69746
70570
  if (!active) {
69747
70571
  cliError(
@@ -70783,12 +71607,422 @@ var init_history = __esm({
70783
71607
  }
70784
71608
  });
70785
71609
 
71610
+ // packages/cleo/src/cli/hook-entry.ts
71611
+ var hook_entry_exports = {};
71612
+ __export(hook_entry_exports, {
71613
+ HEAVY_HOOK_PROVIDERS: () => HEAVY_HOOK_PROVIDERS,
71614
+ claudeGuardedBashRules: () => claudeGuardedBashRules,
71615
+ claudeRuleFiles: () => claudeRuleFiles,
71616
+ codexGuardedWords: () => codexGuardedWords,
71617
+ guardedHeavyCommand: () => guardedHeavyCommand,
71618
+ heavyCommandHook: () => heavyCommandHook,
71619
+ heavyHookContext: () => heavyHookContext,
71620
+ heavyHookWaitBudget: () => heavyHookWaitBudget,
71621
+ heavyRuleWords: () => heavyRuleWords,
71622
+ parseHookInput: () => parseHookInput,
71623
+ processHookIo: () => processHookIo,
71624
+ renderHeavyHookAnswer: () => renderHeavyHookAnswer,
71625
+ runHookCli: () => runHookCli
71626
+ });
71627
+ import { readdirSync as readdirSync3, readFileSync as readFileSync12 } from "node:fs";
71628
+ import { homedir as homedir3 } from "node:os";
71629
+ import { join as join28 } from "node:path";
71630
+ async function readProcessStdin() {
71631
+ if (process.stdin.isTTY) return "";
71632
+ const chunks = [];
71633
+ let size = 0;
71634
+ for await (const chunk of process.stdin) {
71635
+ const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk));
71636
+ size += buf.length;
71637
+ if (size > MAX_STDIN_BYTES) return "";
71638
+ chunks.push(buf);
71639
+ }
71640
+ return Buffer.concat(chunks).toString("utf-8");
71641
+ }
71642
+ function processHookIo() {
71643
+ return {
71644
+ readStdin: readProcessStdin,
71645
+ writeStdout: (text) => process.stdout.write(text),
71646
+ // 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
71647
+ writeStderr: (text) => process.stderr.write(text),
71648
+ env: process.env,
71649
+ cwd: process.cwd()
71650
+ };
71651
+ }
71652
+ function isRecord4(value) {
71653
+ return typeof value === "object" && value !== null && !Array.isArray(value);
71654
+ }
71655
+ function parseHookInput(text) {
71656
+ let raw;
71657
+ try {
71658
+ raw = JSON.parse(text);
71659
+ } catch {
71660
+ return null;
71661
+ }
71662
+ if (!isRecord4(raw)) return null;
71663
+ const toolInput = raw.tool_input;
71664
+ if (!isRecord4(toolInput) || typeof toolInput.command !== "string") return null;
71665
+ const toolName = typeof raw.tool_name === "string" ? raw.tool_name : void 0;
71666
+ if (toolName !== void 0 && !/^(bash|shell|exec_command)$/i.test(toolName)) return null;
71667
+ const str3 = (v) => typeof v === "string" ? v : void 0;
71668
+ return {
71669
+ ...toolName === void 0 ? {} : { tool_name: toolName },
71670
+ tool_input: { ...toolInput, command: toolInput.command },
71671
+ ...str3(raw.cwd) === void 0 ? {} : { cwd: str3(raw.cwd) },
71672
+ ...str3(raw.permission_mode) === void 0 ? {} : { permission_mode: str3(raw.permission_mode) }
71673
+ };
71674
+ }
71675
+ function positiveMs(value) {
71676
+ const n = value === void 0 ? Number.NaN : Number(value);
71677
+ return Number.isFinite(n) && n > 0 ? Math.floor(n) : void 0;
71678
+ }
71679
+ function heavyHookWaitBudget(provider, toolInput, env = {}) {
71680
+ if (toolInput.run_in_background === true) return {};
71681
+ if (provider !== "claude-code" && provider !== "opencode") {
71682
+ return { waitTimeoutSec: DEFAULT_WAIT_SEC };
71683
+ }
71684
+ const fromEnv = provider === "claude-code";
71685
+ const def = (fromEnv ? positiveMs(env.BASH_DEFAULT_TIMEOUT_MS) : void 0) ?? BASH_DEFAULT_MS;
71686
+ const max = Math.max(
71687
+ (fromEnv ? positiveMs(env.BASH_MAX_TIMEOUT_MS) : void 0) ?? BASH_MAX_MS,
71688
+ def
71689
+ );
71690
+ const asked = typeof toolInput.timeout === "number" && toolInput.timeout > 0 ? toolInput.timeout : def;
71691
+ const effective = Math.min(asked, max);
71692
+ const room = Math.floor((max - effective) / 1e3);
71693
+ const waitTimeoutSec = Math.max(
71694
+ MIN_WAIT_SEC,
71695
+ Math.min(MAX_WAIT_SEC, Math.round(effective / 1e3), room)
71696
+ );
71697
+ return { waitTimeoutSec, timeoutMs: Math.min(max, effective + waitTimeoutSec * 1e3) };
71698
+ }
71699
+ function heavyHookContext(plan, pressure, provider = "claude-code") {
71700
+ const lines = [];
71701
+ const governed = plan.action === "none" ? "" : plan.segments.map((s) => s.governed).join(" ; ");
71702
+ if (plan.action === "rewrite" && provider === "kimi") {
71703
+ lines.push(
71704
+ `[cleo] Not run: heavy commands share the machine-wide resource budget. Re-run it as: ${plan.command}`
71705
+ );
71706
+ } else if (plan.action === "rewrite") {
71707
+ lines.push(
71708
+ `[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).`
71709
+ );
71710
+ } else if (plan.action === "warn") {
71711
+ lines.push(
71712
+ `[cleo] Heavy command not rewritten because ${plan.reason}. Run it governed so it shares the machine-wide budget: ${governed}`
71713
+ );
71714
+ }
71715
+ if (pressure !== null) lines.push(pressure);
71716
+ return lines.join("\n");
71717
+ }
71718
+ function demote(plan, reason) {
71719
+ return plan.action === "rewrite" ? { action: "warn", reason, segments: plan.segments } : plan;
71720
+ }
71721
+ function renderHeavyHookAnswer(provider, toolInput, plan, context, timeoutMs) {
71722
+ if (plan.action === "none" && context === "") return "";
71723
+ const rewrite = plan.action === "rewrite";
71724
+ if (provider === "opencode") {
71725
+ const answer = {
71726
+ ...rewrite ? { command: plan.command } : {},
71727
+ ...rewrite && timeoutMs !== void 0 ? { timeout: timeoutMs } : {},
71728
+ ...context === "" ? {} : { context }
71729
+ };
71730
+ return `${JSON.stringify(answer)}
71731
+ `;
71732
+ }
71733
+ if (provider === "kimi") {
71734
+ if (!rewrite) return `${context}
71735
+ `;
71736
+ const deny = {
71737
+ hookSpecificOutput: {
71738
+ hookEventName: "PreToolUse",
71739
+ permissionDecision: "deny",
71740
+ permissionDecisionReason: context
71741
+ }
71742
+ };
71743
+ return `${JSON.stringify(deny)}
71744
+ `;
71745
+ }
71746
+ const updatedInput = rewrite ? {
71747
+ ...toolInput,
71748
+ command: plan.command,
71749
+ ...provider === "claude-code" && timeoutMs !== void 0 ? { timeout: timeoutMs } : {}
71750
+ } : void 0;
71751
+ const output2 = {
71752
+ hookSpecificOutput: {
71753
+ hookEventName: "PreToolUse",
71754
+ ...rewrite && provider === "codex" ? { permissionDecision: "allow" } : {},
71755
+ ...updatedInput === void 0 ? {} : { updatedInput },
71756
+ ...context === "" ? {} : { additionalContext: context }
71757
+ }
71758
+ };
71759
+ return `${JSON.stringify(output2)}
71760
+ `;
71761
+ }
71762
+ function wordBase(word) {
71763
+ return word.split("/").pop() ?? word;
71764
+ }
71765
+ function heavyRuleWords(argv) {
71766
+ const out = [];
71767
+ for (const w of argv) {
71768
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(w) || w.startsWith("-") || /^\d+$/.test(w)) continue;
71769
+ out.push(wordBase(w));
71770
+ if (out.length === 4) break;
71771
+ }
71772
+ return out;
71773
+ }
71774
+ function ruleWords(pattern) {
71775
+ return pattern.split(/[\s:*()]+/).filter((w) => w !== "" && !w.startsWith("-")).map(wordBase);
71776
+ }
71777
+ function claudeRuleFiles(projectDir, env) {
71778
+ 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";
71779
+ const configDir = env.CLAUDE_CONFIG_DIR || join28(env.HOME || homedir3(), ".claude");
71780
+ return [
71781
+ managed,
71782
+ join28(configDir, "settings.json"),
71783
+ join28(projectDir, ".claude", "settings.json"),
71784
+ join28(projectDir, ".claude", "settings.local.json")
71785
+ ];
71786
+ }
71787
+ function claudeGuardedBashRules(files) {
71788
+ const patterns = [];
71789
+ let unreadable = null;
71790
+ for (const file of files) {
71791
+ let raw;
71792
+ try {
71793
+ raw = JSON.parse(readFileSync12(file, "utf-8"));
71794
+ } catch (err) {
71795
+ const code = err.code;
71796
+ if (code !== "ENOENT" && code !== "ENOTDIR") unreadable ??= file;
71797
+ continue;
71798
+ }
71799
+ const permissions = isRecord4(raw) ? raw.permissions : void 0;
71800
+ if (!isRecord4(permissions)) continue;
71801
+ for (const key of ["deny", "ask"]) {
71802
+ const rules = permissions[key];
71803
+ if (!Array.isArray(rules)) continue;
71804
+ for (const rule2 of rules) {
71805
+ if (typeof rule2 !== "string") continue;
71806
+ const trimmed = rule2.trim();
71807
+ if (trimmed === "Bash") {
71808
+ patterns.push("*");
71809
+ continue;
71810
+ }
71811
+ const match = /^Bash\((.*)\)$/s.exec(trimmed);
71812
+ if (match?.[1] !== void 0) patterns.push(match[1]);
71813
+ }
71814
+ }
71815
+ }
71816
+ return { patterns, unreadable };
71817
+ }
71818
+ function codexGuardedWords(projectDir, env) {
71819
+ const home = env.CODEX_HOME || join28(env.HOME || homedir3(), ".codex");
71820
+ const out = [];
71821
+ for (const dir of [join28(home, "rules"), join28(projectDir, ".codex", "rules")]) {
71822
+ let names;
71823
+ try {
71824
+ names = readdirSync3(dir).filter((n) => n.endsWith(".rules"));
71825
+ } catch {
71826
+ continue;
71827
+ }
71828
+ for (const name of names) {
71829
+ let text;
71830
+ try {
71831
+ text = readFileSync12(join28(dir, name), "utf-8");
71832
+ } catch {
71833
+ continue;
71834
+ }
71835
+ if (!/decision\s*=\s*["'](forbidden|prompt)["']/.test(text)) continue;
71836
+ for (const m of text.matchAll(/"([^"\\]*)"|'([^'\\]*)'/g)) {
71837
+ for (const w of ruleWords(m[1] ?? m[2] ?? "")) out.push(w);
71838
+ }
71839
+ }
71840
+ }
71841
+ return out;
71842
+ }
71843
+ function guardedHeavyCommand(provider, segments, projectDir, env, files = claudeRuleFiles(projectDir, env)) {
71844
+ let rules;
71845
+ if (provider === "claude-code") {
71846
+ const found = claudeGuardedBashRules(files);
71847
+ if (found.unreadable !== null) return { kind: "unreadable", file: found.unreadable };
71848
+ rules = found.patterns.map(ruleWords);
71849
+ if (rules.some((words) => words.length === 0)) return { kind: "all" };
71850
+ } else if (provider === "codex") {
71851
+ const words = codexGuardedWords(projectDir, env);
71852
+ rules = words.length === 0 ? [] : [words];
71853
+ } else {
71854
+ return null;
71855
+ }
71856
+ for (const segment of segments) {
71857
+ const words = heavyRuleWords(segment.argv);
71858
+ const first = words[0];
71859
+ if (first === void 0) continue;
71860
+ for (const rule2 of rules) {
71861
+ if (provider === "codex") {
71862
+ const hit = words.slice(0, 3).find((w) => rule2.includes(w));
71863
+ if (hit !== void 0) return { kind: "word", word: hit };
71864
+ continue;
71865
+ }
71866
+ const lead = rule2[0];
71867
+ if (lead !== void 0 && words.includes(lead)) return { kind: "word", word: lead };
71868
+ if (rule2.includes(first)) return { kind: "word", word: first };
71869
+ }
71870
+ }
71871
+ return null;
71872
+ }
71873
+ function providerProjectDir(provider, env) {
71874
+ return provider === "claude-code" ? env.CLAUDE_PROJECT_DIR || void 0 : void 0;
71875
+ }
71876
+ async function heavyCommandHook(provider, stdin2, io) {
71877
+ const envMode = io.env.CLEO_HEAVY_COMMAND_HOOK?.trim().toLowerCase();
71878
+ if (envMode === "off") return "";
71879
+ const input2 = parseHookInput(stdin2);
71880
+ if (input2?.tool_input === void 0) return "";
71881
+ const core2 = await import("@cleocode/core/resources/heavy-command.js");
71882
+ const cwd = input2.cwd ?? io.cwd;
71883
+ const budget = heavyHookWaitBudget(provider, input2.tool_input, io.env);
71884
+ let plan = core2.planHeavyCommand(input2.tool_input.command, {
71885
+ cwd,
71886
+ ...budget.waitTimeoutSec === void 0 ? {} : { waitTimeoutSec: budget.waitTimeoutSec }
71887
+ });
71888
+ if (plan.action === "none") return "";
71889
+ const projectRoot = providerProjectDir(provider, io.env) ?? core2.heavyHookProjectRoot(cwd);
71890
+ const mode = core2.resolveHeavyHookMode(
71891
+ envMode,
71892
+ core2.isHeavyCommandHookMode(envMode) ? void 0 : await core2.configuredHeavyHookMode(projectRoot)
71893
+ );
71894
+ if (mode === "off") return "";
71895
+ if (mode === "warn") {
71896
+ plan = demote(
71897
+ plan,
71898
+ "the hook is in warn mode (CLEO_HEAVY_COMMAND_HOOK or resources.heavyCommandHook)"
71899
+ );
71900
+ }
71901
+ if (!core2.executableOnPath("cleo", io.env.PATH)) plan = demote(plan, "`cleo` is not on PATH");
71902
+ if (provider !== "kimi" && !REWRITE_MODES.has(input2.permission_mode ?? "")) {
71903
+ plan = demote(
71904
+ plan,
71905
+ `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"})`
71906
+ );
71907
+ }
71908
+ if (plan.action === "rewrite") {
71909
+ const hit = guardedHeavyCommand(provider, plan.segments, projectRoot, io.env);
71910
+ const where = provider === "codex" ? "Codex rules" : "Claude Code settings";
71911
+ if (hit?.kind === "word") {
71912
+ plan = demote(
71913
+ plan,
71914
+ `a deny or ask rule in your ${where} names \`${hit.word}\`, and a rewrite would hide the command from it`
71915
+ );
71916
+ } else if (hit?.kind === "all") {
71917
+ plan = demote(
71918
+ plan,
71919
+ `a deny or ask rule in your ${where} covers every Bash command, and a rewrite would hide the command from it`
71920
+ );
71921
+ } else if (hit?.kind === "unreadable") {
71922
+ plan = demote(
71923
+ plan,
71924
+ `${hit.file} could not be read or parsed, so the hook cannot tell whether a deny or ask rule names the command`
71925
+ );
71926
+ }
71927
+ }
71928
+ const context = heavyHookContext(plan, await core2.heavyPressureNotice(), provider);
71929
+ return renderHeavyHookAnswer(provider, input2.tool_input, plan, context, budget.timeoutMs);
71930
+ }
71931
+ async function runHookCli(argv, io = processHookIo()) {
71932
+ const [name, ...rest] = argv;
71933
+ if (name !== "heavy-command") {
71934
+ io.writeStderr(USAGE);
71935
+ return 1;
71936
+ }
71937
+ const flag = rest.findIndex((a) => a === "--provider" || a.startsWith("--provider="));
71938
+ const value = flag === -1 ? "claude-code" : rest[flag]?.split("=")[1] ?? rest[flag + 1];
71939
+ const provider = HEAVY_HOOK_PROVIDERS.find((p) => p === value);
71940
+ if (provider === void 0) {
71941
+ io.writeStderr(USAGE);
71942
+ return 1;
71943
+ }
71944
+ try {
71945
+ const answer = await heavyCommandHook(provider, await io.readStdin(), io);
71946
+ if (answer !== "") io.writeStdout(answer);
71947
+ } catch (err) {
71948
+ io.writeStderr(
71949
+ `[cleo hook] heavy-command skipped: ${err instanceof Error ? err.message : String(err)}
71950
+ `
71951
+ );
71952
+ }
71953
+ return 0;
71954
+ }
71955
+ 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;
71956
+ var init_hook_entry = __esm({
71957
+ "packages/cleo/src/cli/hook-entry.ts"() {
71958
+ "use strict";
71959
+ HEAVY_HOOK_PROVIDERS = [
71960
+ "claude-code",
71961
+ "codex",
71962
+ "kimi",
71963
+ "opencode"
71964
+ ];
71965
+ BASH_DEFAULT_MS = 12e4;
71966
+ BASH_MAX_MS = 6e5;
71967
+ MIN_WAIT_SEC = 30;
71968
+ MAX_WAIT_SEC = 300;
71969
+ DEFAULT_WAIT_SEC = 60;
71970
+ REWRITE_MODES = /* @__PURE__ */ new Set(["bypassPermissions", "auto"]);
71971
+ MAX_STDIN_BYTES = 1024 * 1024;
71972
+ USAGE = "usage: cleo hook heavy-command [--provider claude-code|codex|kimi|opencode] < hook-input.json\n";
71973
+ }
71974
+ });
71975
+
71976
+ // packages/cleo/src/cli/commands/hook.ts
71977
+ var hook_exports = {};
71978
+ __export(hook_exports, {
71979
+ hookCommand: () => hookCommand
71980
+ });
71981
+ var heavyCommandSubcommand, hookCommand;
71982
+ var init_hook = __esm({
71983
+ "packages/cleo/src/cli/commands/hook.ts"() {
71984
+ "use strict";
71985
+ init_define_cli_command();
71986
+ heavyCommandSubcommand = defineCommand({
71987
+ meta: {
71988
+ name: "heavy-command",
71989
+ description: "PreToolUse hook: route heavy shell commands (tests, builds, typechecks, installs) through cleo run. Reads the hook JSON on stdin; prints the harness answer."
71990
+ },
71991
+ args: {
71992
+ provider: {
71993
+ type: "string",
71994
+ description: "Harness protocol to answer in: claude-code (default), codex, kimi, opencode"
71995
+ }
71996
+ },
71997
+ async run({ args }) {
71998
+ const { runHookCli: runHookCli2 } = await Promise.resolve().then(() => (init_hook_entry(), hook_entry_exports));
71999
+ const provider = typeof args.provider === "string" ? args.provider : "claude-code";
72000
+ process.exitCode = await runHookCli2(["heavy-command", "--provider", provider]);
72001
+ }
72002
+ });
72003
+ hookCommand = defineCommand({
72004
+ meta: {
72005
+ name: "hook",
72006
+ 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"
72007
+ },
72008
+ subCommands: {
72009
+ "heavy-command": heavyCommandSubcommand
72010
+ },
72011
+ async run({ cmd, rawArgs }) {
72012
+ const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
72013
+ if (firstArg && cmd.subCommands && firstArg in cmd.subCommands) return;
72014
+ await showUsage(cmd);
72015
+ }
72016
+ });
72017
+ }
72018
+ });
72019
+
70786
72020
  // packages/cleo/src/cli/commands/hygiene.ts
70787
72021
  var hygiene_exports = {};
70788
72022
  __export(hygiene_exports, {
70789
72023
  hygieneCommand: () => hygieneCommand
70790
72024
  });
70791
- import { getProjectRoot as getProjectRoot61 } from "@cleocode/core";
72025
+ import { getProjectRoot as getProjectRoot62 } from "@cleocode/core";
70792
72026
  import { runSpawnReadinessHygieneCli } from "@cleocode/core/hygiene/validate-spawn-readiness.js";
70793
72027
  var hygieneCommand;
70794
72028
  var init_hygiene = __esm({
@@ -70817,7 +72051,7 @@ var init_hygiene = __esm({
70817
72051
  }
70818
72052
  },
70819
72053
  async run({ args }) {
70820
- const projectRoot = args["project-root"] || getProjectRoot61() || process.cwd();
72054
+ const projectRoot = args["project-root"] || getProjectRoot62() || process.cwd();
70821
72055
  const worktreePath = args["worktree-path"];
70822
72056
  await runSpawnReadinessHygieneCli(projectRoot, worktreePath);
70823
72057
  }
@@ -70992,8 +72226,8 @@ __export(init_exports, {
70992
72226
  isCredentialPoolEmpty: () => isCredentialPoolEmpty,
70993
72227
  maybeNudgeFirstRunLogin: () => maybeNudgeFirstRunLogin
70994
72228
  });
70995
- import { existsSync as existsSync16, readFileSync as readFileSync12 } from "node:fs";
70996
- import { join as join28 } from "node:path";
72229
+ import { existsSync as existsSync16, readFileSync as readFileSync13 } from "node:fs";
72230
+ import { join as join29 } from "node:path";
70997
72231
  import { fileURLToPath as fileURLToPath5 } from "node:url";
70998
72232
  import {
70999
72233
  CleoError as CleoError9,
@@ -71008,12 +72242,12 @@ import { getTemplatesByKind } from "@cleocode/core/templates/registry";
71008
72242
  function getGitignoreTemplate() {
71009
72243
  try {
71010
72244
  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");
72245
+ const packageRoot = join29(thisFile, "..", "..", "..", "..");
72246
+ const localTemplatePath = join29(packageRoot, "templates", "cleo-gitignore");
72247
+ const monorepoTemplatePath = join29(packageRoot, "..", "..", "templates", "cleo-gitignore");
71014
72248
  const templatePath = existsSync16(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
71015
72249
  if (existsSync16(templatePath)) {
71016
- return readFileSync12(templatePath, "utf-8");
72250
+ return readFileSync13(templatePath, "utf-8");
71017
72251
  }
71018
72252
  } catch {
71019
72253
  }
@@ -72160,7 +73394,7 @@ var llm_cost_exports = {};
72160
73394
  __export(llm_cost_exports, {
72161
73395
  costCommand: () => costCommand
72162
73396
  });
72163
- import { getProjectRoot as getProjectRoot62 } from "@cleocode/core/internal";
73397
+ import { getProjectRoot as getProjectRoot63 } from "@cleocode/core/internal";
72164
73398
  import { computeCost } from "@cleocode/core/llm/usage-pricing";
72165
73399
  function resolveSessionId(raw) {
72166
73400
  if (raw === "current") {
@@ -72233,7 +73467,7 @@ var init_llm_cost = __esm({
72233
73467
  process.exit(6);
72234
73468
  }
72235
73469
  const sessionId = resolveSessionId(rawSessionId);
72236
- const projectRoot = getProjectRoot62(process.cwd());
73470
+ const projectRoot = getProjectRoot63(process.cwd());
72237
73471
  let breakdown;
72238
73472
  try {
72239
73473
  breakdown = await loadSessionCostBreakdown(projectRoot, sessionId);
@@ -73610,7 +74844,7 @@ var memory_exports = {};
73610
74844
  __export(memory_exports, {
73611
74845
  memoryCommand: () => memoryCommand
73612
74846
  });
73613
- import { getProjectRoot as getProjectRoot63 } from "@cleocode/core";
74847
+ import { getProjectRoot as getProjectRoot64 } from "@cleocode/core";
73614
74848
  import {
73615
74849
  getBrainDb as getBrainDb2,
73616
74850
  getDreamStatus,
@@ -74568,7 +75802,7 @@ var init_memory3 = __esm({
74568
75802
  },
74569
75803
  args: {},
74570
75804
  async run() {
74571
- const root = getProjectRoot63();
75805
+ const root = getProjectRoot64();
74572
75806
  try {
74573
75807
  const result = await runConsolidation(root);
74574
75808
  cliOutput(result, { command: "memory-consolidate", operation: "memory.consolidate" });
@@ -74592,7 +75826,7 @@ var init_memory3 = __esm({
74592
75826
  }
74593
75827
  },
74594
75828
  async run({ args }) {
74595
- const root = getProjectRoot63();
75829
+ const root = getProjectRoot64();
74596
75830
  if (args.status) {
74597
75831
  try {
74598
75832
  const status = await getDreamStatus(root);
@@ -74629,7 +75863,7 @@ var init_memory3 = __esm({
74629
75863
  }
74630
75864
  },
74631
75865
  async run({ args }) {
74632
- const root = getProjectRoot63();
75866
+ const root = getProjectRoot64();
74633
75867
  try {
74634
75868
  const { runObserver, runReflector } = await import("@cleocode/core/memory");
74635
75869
  const observerResult = await runObserver(root, args.session, {
@@ -74669,7 +75903,7 @@ var init_memory3 = __esm({
74669
75903
  }
74670
75904
  },
74671
75905
  async run({ args }) {
74672
- const root = getProjectRoot63();
75906
+ const root = getProjectRoot64();
74673
75907
  await getBrainDb2(root);
74674
75908
  const { getBrainNativeDb: getBrainNativeDb3 } = await import("@cleocode/core/internal");
74675
75909
  const nativeDb = getBrainNativeDb3();
@@ -74707,7 +75941,7 @@ var init_memory3 = __esm({
74707
75941
  },
74708
75942
  async run({ args }) {
74709
75943
  const core2 = await import("@cleocode/core/internal");
74710
- const nexusDb = await core2.getNexusDb(getProjectRoot63());
75944
+ const nexusDb = await core2.getNexusDb(getProjectRoot64());
74711
75945
  const result = args.restore ? await core2.restorePrunedTraits(
74712
75946
  nexusDb,
74713
75947
  String(args.restore),
@@ -74737,7 +75971,7 @@ var init_memory3 = __esm({
74737
75971
  return;
74738
75972
  }
74739
75973
  const core2 = await import("@cleocode/core/internal");
74740
- const nexusDb = await core2.getNexusDb(getProjectRoot63());
75974
+ const nexusDb = await core2.getNexusDb(getProjectRoot64());
74741
75975
  const previous = await core2.setUserProfileTraitScope(nexusDb, String(args.key), scope);
74742
75976
  if (previous === null) {
74743
75977
  cliError(`No user-profile trait "${args.key}"`, "E_NOT_FOUND", { name: "E_NOT_FOUND" });
@@ -74761,7 +75995,7 @@ var init_memory3 = __esm({
74761
75995
  }
74762
75996
  },
74763
75997
  async run({ args }) {
74764
- const root = getProjectRoot63();
75998
+ const root = getProjectRoot64();
74765
75999
  try {
74766
76000
  await getBrainDb2(root);
74767
76001
  const { totalDuplicateRows, groups } = await scanDuplicateEntries();
@@ -74807,7 +76041,7 @@ var init_memory3 = __esm({
74807
76041
  async run({ args }) {
74808
76042
  const sourceDir = args.from;
74809
76043
  const isDryRun = !!args["dry-run"];
74810
- const projectRoot = getProjectRoot63();
76044
+ const projectRoot = getProjectRoot64();
74811
76045
  try {
74812
76046
  const result = await importMemoryFiles({
74813
76047
  sourceDir,
@@ -74958,7 +76192,7 @@ var init_memory3 = __esm({
74958
76192
  },
74959
76193
  args: {},
74960
76194
  async run() {
74961
- const root = getProjectRoot63();
76195
+ const root = getProjectRoot64();
74962
76196
  try {
74963
76197
  await getBrainDb2(root);
74964
76198
  const result = await getTierStats(root);
@@ -75001,7 +76235,7 @@ var init_memory3 = __esm({
75001
76235
  }
75002
76236
  },
75003
76237
  async run({ args }) {
75004
- const root = getProjectRoot63();
76238
+ const root = getProjectRoot64();
75005
76239
  const targetTier = args.to;
75006
76240
  const reason = args.reason;
75007
76241
  const validTiers = ["medium", "long"];
@@ -75067,7 +76301,7 @@ var init_memory3 = __esm({
75067
76301
  }
75068
76302
  },
75069
76303
  async run({ args }) {
75070
- const root = getProjectRoot63();
76304
+ const root = getProjectRoot64();
75071
76305
  const targetTier = args.to;
75072
76306
  const reason = args.reason;
75073
76307
  const validTiers = ["short", "medium"];
@@ -75540,7 +76774,7 @@ var migrate_claude_mem_exports = {};
75540
76774
  __export(migrate_claude_mem_exports, {
75541
76775
  migrateClaudeMemCommand: () => migrateClaudeMemCommand
75542
76776
  });
75543
- import { getProjectRoot as getProjectRoot64, migrateClaudeMem } from "@cleocode/core/internal";
76777
+ import { getProjectRoot as getProjectRoot65, migrateClaudeMem } from "@cleocode/core/internal";
75544
76778
  import { ingestLooseAgentOutputs, ingestRcasdDirectories } from "@cleocode/core/memory";
75545
76779
  import { getDb as getDb2 } from "@cleocode/core/store/sqlite";
75546
76780
  var storageCommand, claudeMemCommand, manifestIngestCommand, migrateClaudeMemCommand;
@@ -75603,7 +76837,7 @@ var init_migrate_claude_mem = __esm({
75603
76837
  }
75604
76838
  },
75605
76839
  async run({ args }) {
75606
- const root = getProjectRoot64();
76840
+ const root = getProjectRoot65();
75607
76841
  try {
75608
76842
  const result = await migrateClaudeMem(root, {
75609
76843
  sourcePath: args.source,
@@ -75652,7 +76886,7 @@ var init_migrate_claude_mem = __esm({
75652
76886
  }
75653
76887
  },
75654
76888
  async run({ args }) {
75655
- const projectRoot = getProjectRoot64();
76889
+ const projectRoot = getProjectRoot65();
75656
76890
  try {
75657
76891
  const db = await getDb2(projectRoot);
75658
76892
  const rcasdFlag = Boolean(args.rcasd);
@@ -75770,7 +77004,7 @@ __export(nexus_exports, {
75770
77004
  import { statSync as statSync2 } from "node:fs";
75771
77005
  import { appendFile as appendFile2, mkdir as mkdir5 } from "node:fs/promises";
75772
77006
  import path4 from "node:path";
75773
- import { getProjectRoot as getProjectRoot65 } from "@cleocode/core";
77007
+ import { getProjectRoot as getProjectRoot66 } from "@cleocode/core";
75774
77008
  import { getSymbolImpact } from "@cleocode/core/nexus";
75775
77009
  import { runNexusAnalysis } from "@cleocode/core/nexus/analyze-orchestrator.js";
75776
77010
  import {
@@ -75941,7 +77175,7 @@ var init_nexus3 = __esm({
75941
77175
  async run({ args }) {
75942
77176
  applyJsonFlag2(args.json);
75943
77177
  const projectIdOverride = args["project-id"];
75944
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
77178
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
75945
77179
  const startTime = Date.now();
75946
77180
  if (args.path) {
75947
77181
  let isDir = false;
@@ -76001,7 +77235,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648), so the coun
76001
77235
  process.exitCode = 2 /* INVALID_INPUT */;
76002
77236
  return;
76003
77237
  }
76004
- const currentRoot = getProjectRoot65();
77238
+ const currentRoot = getProjectRoot66();
76005
77239
  if (args.path && path4.resolve(repoPath) !== path4.resolve(currentRoot)) {
76006
77240
  cliError(
76007
77241
  `nexus status cannot report on '${repoPath}' from this project.
@@ -76179,9 +77413,9 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76179
77413
  args: {},
76180
77414
  async run() {
76181
77415
  try {
76182
- const { homedir: homedir4 } = await import("node:os");
77416
+ const { homedir: homedir5 } = await import("node:os");
76183
77417
  const { installNexusAugmentHook } = await import("@cleocode/core/internal");
76184
- const homeDir = homedir4();
77418
+ const homeDir = homedir5();
76185
77419
  installNexusAugmentHook(homeDir);
76186
77420
  cliOutput({ homeDir }, { command: "nexus-setup", operation: "nexus.setup" });
76187
77421
  } catch (err) {
@@ -76555,7 +77789,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76555
77789
  applyJsonFlag2(args.json);
76556
77790
  const startTime = Date.now();
76557
77791
  const projectIdOverride = args["project-id"];
76558
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
77792
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76559
77793
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
76560
77794
  const response = await dispatchRaw("query", "nexus", "clusters", { projectId, repoPath });
76561
77795
  const durationMs = Date.now() - startTime;
@@ -76599,7 +77833,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76599
77833
  applyJsonFlag2(args.json);
76600
77834
  const startTime = Date.now();
76601
77835
  const projectIdOverride = args["project-id"];
76602
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
77836
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76603
77837
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
76604
77838
  const response = await dispatchRaw("query", "nexus", "flows", { projectId, repoPath });
76605
77839
  const durationMs = Date.now() - startTime;
@@ -76642,7 +77876,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76642
77876
  void appendDeprecationTelemetry("nexus.context", "cleo graph context");
76643
77877
  const startTime = Date.now();
76644
77878
  const projectIdOverride = args["project-id"];
76645
- const repoPath = getProjectRoot65();
77879
+ const repoPath = getProjectRoot66();
76646
77880
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
76647
77881
  const limit = parseInt(args.limit, 10);
76648
77882
  const symbolName = args.symbol;
@@ -76705,7 +77939,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76705
77939
  const startTime = Date.now();
76706
77940
  const whyFlag = !!args.why;
76707
77941
  const projectIdOverride = args["project-id"];
76708
- const repoPath = getProjectRoot65();
77942
+ const repoPath = getProjectRoot66();
76709
77943
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
76710
77944
  const maxDepth = Math.min(parseInt(args.depth, 10), 5);
76711
77945
  const symbolName = args.symbol;
@@ -76809,7 +78043,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76809
78043
  const projectIdOverride = args["project-id"];
76810
78044
  const full = !!args.full;
76811
78045
  const ctx = getFormatContext();
76812
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78046
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76813
78047
  if (args.incremental)
76814
78048
  humanWarn(
76815
78049
  "[nexus] --incremental is deprecated and has no effect: incremental is the default."
@@ -76939,7 +78173,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76939
78173
  async run({ args }) {
76940
78174
  applyJsonFlag2(args.json);
76941
78175
  const startTime = Date.now();
76942
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78176
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76943
78177
  const name = args.name;
76944
78178
  const response = await dispatchRaw("mutate", "nexus", "projects.register", {
76945
78179
  path: repoPath,
@@ -77458,7 +78692,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77458
78692
  applyJsonFlag2(args.json);
77459
78693
  const startTime = Date.now();
77460
78694
  const projectIdOverride = args["project-id"];
77461
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78695
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77462
78696
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
77463
78697
  const response = await dispatchRaw("mutate", "nexus", "refresh-bridge", {
77464
78698
  repoPath,
@@ -77564,7 +78798,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77564
78798
  async run({ args }) {
77565
78799
  applyJsonFlag2(args.json);
77566
78800
  const startTime = Date.now();
77567
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78801
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77568
78802
  const projectIdOverride = args["project-id"];
77569
78803
  const beforeRef = args.before ?? "HEAD~1";
77570
78804
  const afterRef = args.after ?? "HEAD";
@@ -77682,7 +78916,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77682
78916
  applyJsonFlag2(args.json);
77683
78917
  const startTime = Date.now();
77684
78918
  const projectIdOverride = args["project-id"];
77685
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78919
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77686
78920
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
77687
78921
  const response = await dispatchRaw("query", "nexus", "route-map", { projectId });
77688
78922
  const durationMs = Date.now() - startTime;
@@ -77738,7 +78972,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77738
78972
  const startTime = Date.now();
77739
78973
  const routeSymbol = args.routeSymbol;
77740
78974
  const projectIdOverride = args["project-id"];
77741
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78975
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77742
78976
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
77743
78977
  const response = await dispatchRaw("query", "nexus", "shape-check", { routeSymbol, projectId });
77744
78978
  const durationMs = Date.now() - startTime;
@@ -78134,7 +79368,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
78134
79368
  async run({ args }) {
78135
79369
  applyJsonFlag2(args.json);
78136
79370
  const startTime = Date.now();
78137
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
79371
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
78138
79372
  const projectIdOverride = args["project-id"];
78139
79373
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
78140
79374
  const response = await dispatchRaw("mutate", "nexus", "contracts-sync", {
@@ -78244,7 +79478,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
78244
79478
  async run({ args }) {
78245
79479
  applyJsonFlag2(args.json);
78246
79480
  const startTime = Date.now();
78247
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
79481
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
78248
79482
  const projectId = Buffer.from(repoPath).toString("base64url").slice(0, 32);
78249
79483
  const response = await dispatchRaw("mutate", "nexus", "contracts-link-tasks", {
78250
79484
  projectId,
@@ -78328,7 +79562,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
78328
79562
  const isIncremental = !!args.incremental;
78329
79563
  try {
78330
79564
  const result = await runNexusWiki({
78331
- projectRoot: getProjectRoot65(),
79565
+ projectRoot: getProjectRoot66(),
78332
79566
  outputDir,
78333
79567
  communityFilter,
78334
79568
  incremental: isIncremental
@@ -78678,7 +79912,7 @@ __export(orchestrate_exports, {
78678
79912
  });
78679
79913
  import { execFileSync as execFileSync5 } from "node:child_process";
78680
79914
  import { orchestration } from "@cleocode/core";
78681
- import { BUILD_CONFIG as BUILD_CONFIG2, getProjectRoot as getProjectRoot66 } from "@cleocode/core/internal";
79915
+ import { BUILD_CONFIG as BUILD_CONFIG2, getProjectRoot as getProjectRoot67 } from "@cleocode/core/internal";
78682
79916
  function formatRollupTable(rollup) {
78683
79917
  const waves = "waves" in rollup ? rollup.waves : [rollup];
78684
79918
  const lines = [];
@@ -78821,7 +80055,7 @@ var init_orchestrate3 = __esm({
78821
80055
  },
78822
80056
  async run({ args }) {
78823
80057
  const rateWindowHours = args.window !== void 0 ? Number.parseFloat(String(args.window)) : void 0;
78824
- const metrics = await orchestration.collectOrchestrateDashboard(getProjectRoot66(), {
80058
+ const metrics = await orchestration.collectOrchestrateDashboard(getProjectRoot67(), {
78825
80059
  ...rateWindowHours !== void 0 && Number.isFinite(rateWindowHours) && rateWindowHours > 0 ? { rateWindowHours } : {}
78826
80060
  });
78827
80061
  cliOutput(metrics, {
@@ -80281,7 +81515,7 @@ __export(project_exports, {
80281
81515
  import { resolve as resolve9 } from "node:path";
80282
81516
  import {
80283
81517
  CleoError as CleoError11,
80284
- getProjectRoot as getProjectRoot67,
81518
+ getProjectRoot as getProjectRoot68,
80285
81519
  moveProject,
80286
81520
  projectLifecycle,
80287
81521
  renameProject,
@@ -80303,7 +81537,7 @@ function emitEngineFailure(error, operation) {
80303
81537
  }
80304
81538
  function resolveRootOrFail(operation) {
80305
81539
  try {
80306
- return getProjectRoot67();
81540
+ return getProjectRoot68();
80307
81541
  } catch (err) {
80308
81542
  const code = err instanceof CleoError11 && typeof err.details?.["code"] === "string" ? err.details["code"] : "E_NOT_CLEO_PROJECT";
80309
81543
  emitEngineFailure(
@@ -81138,7 +82372,7 @@ var refresh_memory_exports = {};
81138
82372
  __export(refresh_memory_exports, {
81139
82373
  refreshMemoryCommand: () => refreshMemoryCommand
81140
82374
  });
81141
- import { getProjectRoot as getProjectRoot68 } from "@cleocode/core";
82375
+ import { getProjectRoot as getProjectRoot69 } from "@cleocode/core";
81142
82376
  var refreshMemoryCommand;
81143
82377
  var init_refresh_memory = __esm({
81144
82378
  "packages/cleo/src/cli/commands/refresh-memory.ts"() {
@@ -81151,7 +82385,7 @@ var init_refresh_memory = __esm({
81151
82385
  description: "Regenerate .cleo/memory-bridge.md from brain.db"
81152
82386
  },
81153
82387
  async run() {
81154
- const projectDir = getProjectRoot68();
82388
+ const projectDir = getProjectRoot69();
81155
82389
  const { writeMemoryBridge } = await import("@cleocode/core/internal");
81156
82390
  const result = await writeMemoryBridge(projectDir);
81157
82391
  if (result.written) {
@@ -82737,7 +83971,7 @@ import fs3 from "node:fs";
82737
83971
  import path5 from "node:path";
82738
83972
  import {
82739
83973
  CleoError as CleoError13,
82740
- getProjectRoot as getProjectRoot69,
83974
+ getProjectRoot as getProjectRoot70,
82741
83975
  getTaskAccessor as getTaskAccessor3,
82742
83976
  parseConflictReport,
82743
83977
  setAtPath
@@ -82758,7 +83992,7 @@ var init_restore = __esm({
82758
83992
  description: "Apply manually-resolved conflicts from .cleo/restore-conflicts.md"
82759
83993
  },
82760
83994
  async run() {
82761
- const projectRoot = getProjectRoot69();
83995
+ const projectRoot = getProjectRoot70();
82762
83996
  const reportPath = path5.join(projectRoot, CLEO_DIR_NAME3, RESTORE_CONFLICTS_MD);
82763
83997
  if (!fs3.existsSync(reportPath)) {
82764
83998
  humanLine("No pending restore conflicts. Nothing to finalize.");
@@ -83130,7 +84364,7 @@ __export(revert_exports, {
83130
84364
  revertCommand: () => revertCommand2
83131
84365
  });
83132
84366
  import { readFile as readFile8 } from "node:fs/promises";
83133
- import { join as join29 } from "node:path";
84367
+ import { join as join30 } from "node:path";
83134
84368
  import { cwd as processCwd2 } from "node:process";
83135
84369
  import { E_RECEIPT_NOT_FOUND } from "@cleocode/core/sentient/chain-walker.js";
83136
84370
  import { SENTIENT_STATE_FILE } from "@cleocode/core/sentient/daemon.js";
@@ -83183,7 +84417,7 @@ async function loadOwnerAttestation(attestationFilePath) {
83183
84417
  return obj;
83184
84418
  }
83185
84419
  async function loadOwnerPubkeys(projectRoot) {
83186
- const path6 = join29(projectRoot, OWNER_PUBKEYS_FILE);
84420
+ const path6 = join30(projectRoot, OWNER_PUBKEYS_FILE);
83187
84421
  try {
83188
84422
  const raw = await readFile8(path6, "utf-8");
83189
84423
  const parsed = JSON.parse(raw);
@@ -83267,7 +84501,7 @@ var init_revert = __esm({
83267
84501
  if (attestation && allowedPubkeys.size > 0 && !allowedPubkeys.has(attestation.ownerPubkey)) {
83268
84502
  emitFailure2(
83269
84503
  E_OWNER_ATTESTATION_REQUIRED,
83270
- `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join29(projectRoot, OWNER_PUBKEYS_FILE)}`,
84504
+ `Attestation pubkey "${attestation.ownerPubkey}" is not in the owner allowlist at ${join30(projectRoot, OWNER_PUBKEYS_FILE)}`,
83271
84505
  jsonMode
83272
84506
  );
83273
84507
  }
@@ -83320,7 +84554,7 @@ ${lines}`
83320
84554
  identity,
83321
84555
  includeHuman
83322
84556
  });
83323
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE);
84557
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE);
83324
84558
  const state = await readSentientState(statePath);
83325
84559
  emitSuccess(
83326
84560
  {
@@ -83391,6 +84625,185 @@ var init_roadmap = __esm({
83391
84625
  }
83392
84626
  });
83393
84627
 
84628
+ // packages/cleo/src/cli/commands/run.ts
84629
+ var run_exports = {};
84630
+ __export(run_exports, {
84631
+ runCommand: () => runCommand6,
84632
+ runExitCode: () => runExitCode
84633
+ });
84634
+ import { constants } from "node:os";
84635
+ import {
84636
+ canonicalForClass,
84637
+ isWatchCommand,
84638
+ resolveRunClass
84639
+ } from "@cleocode/core/resources/run-admission.js";
84640
+ import { runGoverned } from "@cleocode/core/resources/run-governed.js";
84641
+ import { heavyToolEnv } from "@cleocode/core/tasks/heavy-tool-env.js";
84642
+ function commandAfterDashes(rawArgs) {
84643
+ const idx = rawArgs.indexOf("--");
84644
+ return idx === -1 ? [] : rawArgs.slice(idx + 1);
84645
+ }
84646
+ function invalid(message, fix, stderr2) {
84647
+ cliError(
84648
+ message,
84649
+ "E_VALIDATION",
84650
+ { name: "E_VALIDATION", fix },
84651
+ { operation: "resources.run" },
84652
+ { stderr: stderr2 }
84653
+ );
84654
+ process.exit(6);
84655
+ }
84656
+ function runExitCode(r) {
84657
+ if (r.spawnError !== null) return 127;
84658
+ if (r.signal !== null) return 128 + (constants.signals[r.signal] ?? 0);
84659
+ return r.exitCode ?? 1;
84660
+ }
84661
+ function exitFailed(result, code, passthrough) {
84662
+ const { kind: _kind, ...data } = result;
84663
+ const message = result.spawnError !== null ? `could not start command: ${result.spawnError}` : `command ${result.signal !== null ? `killed by ${result.signal}` : `exited with ${result.exitCode}`}`;
84664
+ if (passthrough && result.spawnError === null) {
84665
+ process.stderr.write(`[cleo run] ${RUN_COMMAND_FAILED_CODE}: ${message}
84666
+ `);
84667
+ } else {
84668
+ cliError(
84669
+ message,
84670
+ RUN_COMMAND_FAILED_CODE,
84671
+ { name: RUN_COMMAND_FAILED_CODE, details: data },
84672
+ { operation: "resources.run" },
84673
+ { stderr: passthrough }
84674
+ );
84675
+ }
84676
+ process.exit(code);
84677
+ }
84678
+ var runCommand6;
84679
+ var init_run = __esm({
84680
+ "packages/cleo/src/cli/commands/run.ts"() {
84681
+ "use strict";
84682
+ init_src2();
84683
+ init_define_cli_command();
84684
+ init_renderers();
84685
+ runCommand6 = defineCommand({
84686
+ meta: {
84687
+ name: "run",
84688
+ description: "Run a heavy command (tests, builds, installs) under the machine-wide resource budget: cleo run [--class test|build|full-build] [--wait] [--passthrough] -- <command...>"
84689
+ },
84690
+ args: {
84691
+ class: {
84692
+ type: "string",
84693
+ description: "Resource class: test, build, typecheck, install, scan, full-build, db (default: inferred from the command)"
84694
+ },
84695
+ wait: {
84696
+ type: "boolean",
84697
+ description: "Join the FIFO queue for the class instead of returning E_RESOURCE_DEFERRED",
84698
+ default: false
84699
+ },
84700
+ timeout: {
84701
+ type: "string",
84702
+ description: "With --wait: give up after this many seconds (default 1800)"
84703
+ },
84704
+ passthrough: {
84705
+ type: "boolean",
84706
+ 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",
84707
+ default: false
84708
+ }
84709
+ },
84710
+ async run({ args, rawArgs }) {
84711
+ const passthrough = args.passthrough === true;
84712
+ const argv = commandAfterDashes(rawArgs ?? []);
84713
+ if (argv.length === 0) {
84714
+ invalid(
84715
+ "cleo run needs a command after --",
84716
+ "cleo run --class test -- npx vitest run path/to/file.test.ts",
84717
+ passthrough
84718
+ );
84719
+ }
84720
+ if (args.class === void 0 && isWatchCommand(argv)) {
84721
+ invalid(
84722
+ `cleo run refuses watch/dev/serve commands, which never exit and would hold a resource slot forever: ${argv.join(" ")}`,
84723
+ "Run the watcher directly, without cleo run. If it is a bounded job, say so with --class (cleo run --class test -- <cmd>)",
84724
+ passthrough
84725
+ );
84726
+ }
84727
+ let timeoutMs = 18e5;
84728
+ if (args.timeout !== void 0) {
84729
+ if (!args.wait)
84730
+ invalid("--timeout requires --wait", "cleo run --wait --timeout 600 -- <cmd>", passthrough);
84731
+ const seconds = Number(args.timeout);
84732
+ if (!Number.isFinite(seconds) || seconds <= 0) {
84733
+ invalid(
84734
+ `--timeout must be a positive number of seconds (got '${args.timeout}')`,
84735
+ "--timeout 600",
84736
+ passthrough
84737
+ );
84738
+ }
84739
+ timeoutMs = seconds * 1e3;
84740
+ }
84741
+ let cls;
84742
+ try {
84743
+ cls = resolveRunClass(args.class, argv, process.cwd());
84744
+ } catch (err) {
84745
+ invalid(
84746
+ err instanceof Error ? err.message : String(err),
84747
+ "cleo run --class test -- <cmd>",
84748
+ passthrough
84749
+ );
84750
+ }
84751
+ let result;
84752
+ try {
84753
+ result = await runGoverned({
84754
+ argv,
84755
+ cls,
84756
+ cwd: process.cwd(),
84757
+ env: { ...process.env, ...heavyToolEnv(canonicalForClass(cls)) },
84758
+ sessionId: process.env.CLEO_SESSION_ID ?? process.env.CLAUDE_CODE_SESSION_ID ?? null,
84759
+ wait: Boolean(args.wait),
84760
+ timeoutMs,
84761
+ passthrough,
84762
+ // A terminal on stdin: keep the child in its foreground group.
84763
+ foreground: passthrough && process.stdin.isTTY === true,
84764
+ // Notices go to stderr; stdout carries only the final LAFS envelope, or
84765
+ // with --passthrough only the child's output (and then only warnings).
84766
+ notice: (line, level) => {
84767
+ if (passthrough && level === "info") return;
84768
+ process.stderr.write(`[cleo run] ${line}
84769
+ `);
84770
+ }
84771
+ });
84772
+ } catch (err) {
84773
+ cliError(
84774
+ `cleo run failed: ${err instanceof Error ? err.message : String(err)}`,
84775
+ 1,
84776
+ { name: "E_GENERAL" },
84777
+ { operation: "resources.run" },
84778
+ { stderr: passthrough }
84779
+ );
84780
+ process.exit(1);
84781
+ }
84782
+ if (result.kind === "deferred") {
84783
+ cliError(
84784
+ `not started: ${result.reason}`,
84785
+ RESOURCE_DEFERRED_CODE,
84786
+ {
84787
+ name: RESOURCE_DEFERRED_CODE,
84788
+ details: result.details,
84789
+ fix: result.fix,
84790
+ alternatives: result.alternatives
84791
+ },
84792
+ { operation: "resources.run" },
84793
+ { stderr: passthrough }
84794
+ );
84795
+ process.exit(RUN_DEFERRED_EXIT_CODE);
84796
+ }
84797
+ const code = runExitCode(result);
84798
+ if (code !== 0) exitFailed(result, code, passthrough);
84799
+ if (passthrough) return;
84800
+ const { kind: _kind, ...data } = result;
84801
+ cliOutput(data, { command: "run", operation: "resources.run" });
84802
+ }
84803
+ });
84804
+ }
84805
+ });
84806
+
83394
84807
  // packages/cleo/src/cli/commands/safestop.ts
83395
84808
  var safestop_exports = {};
83396
84809
  __export(safestop_exports, {
@@ -83687,8 +85100,8 @@ var init_saga = __esm({
83687
85100
  }
83688
85101
  },
83689
85102
  async run({ args }) {
83690
- const { sagas: sagas2, getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
83691
- const projectRoot = getProjectRoot75();
85103
+ const { sagas: sagas2, getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
85104
+ const projectRoot = getProjectRoot76();
83692
85105
  const sagaId = typeof args.sagaId === "string" && args.sagaId.length > 0 ? args.sagaId : void 0;
83693
85106
  const result = await sagas2.sagaNext(projectRoot, { sagaId });
83694
85107
  cliOutput(result.success ? result.data : result, { command: "saga", operation: "saga.next" });
@@ -83902,7 +85315,7 @@ __export(self_update_exports, {
83902
85315
  });
83903
85316
  import { execFile } from "node:child_process";
83904
85317
  import { readFile as readFile9 } from "node:fs/promises";
83905
- import { join as join30 } from "node:path";
85318
+ import { join as join31 } from "node:path";
83906
85319
  import * as readline3 from "node:readline";
83907
85320
  import { promisify } from "node:util";
83908
85321
  import {
@@ -83917,7 +85330,7 @@ import {
83917
85330
  async function getCurrentVersion() {
83918
85331
  const cleoHome = getCleoHome7();
83919
85332
  try {
83920
- const content = await readFile9(join30(cleoHome, "VERSION"), "utf-8");
85333
+ const content = await readFile9(join31(cleoHome, "VERSION"), "utf-8");
83921
85334
  return (content.split("\n")[0] ?? "unknown").trim();
83922
85335
  } catch {
83923
85336
  return "unknown";
@@ -83971,7 +85384,7 @@ async function writeRuntimeVersionMetadata(mode, source, version) {
83971
85384
  ];
83972
85385
  await import("node:fs/promises").then(
83973
85386
  ({ writeFile: writeFile4, mkdir: mkdir7 }) => mkdir7(cleoHome, { recursive: true }).then(
83974
- () => writeFile4(join30(cleoHome, "VERSION"), `${lines.join("\n")}
85387
+ () => writeFile4(join31(cleoHome, "VERSION"), `${lines.join("\n")}
83975
85388
  `, "utf-8")
83976
85389
  )
83977
85390
  );
@@ -84383,13 +85796,13 @@ var selfimprove_exports = {};
84383
85796
  __export(selfimprove_exports, {
84384
85797
  selfimproveCommand: () => selfimproveCommand
84385
85798
  });
84386
- var runCommand6, selfimproveCommand;
85799
+ var runCommand7, selfimproveCommand;
84387
85800
  var init_selfimprove2 = __esm({
84388
85801
  "packages/cleo/src/cli/commands/selfimprove.ts"() {
84389
85802
  "use strict";
84390
85803
  init_cli();
84391
85804
  init_define_cli_command();
84392
- runCommand6 = defineCommand({
85805
+ runCommand7 = defineCommand({
84393
85806
  meta: {
84394
85807
  name: "run",
84395
85808
  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 +85847,7 @@ var init_selfimprove2 = __esm({
84434
85847
  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
85848
  },
84436
85849
  subCommands: {
84437
- run: runCommand6
85850
+ run: runCommand7
84438
85851
  },
84439
85852
  async run({ cmd, rawArgs }) {
84440
85853
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
@@ -84452,7 +85865,7 @@ __export(sentient_exports, {
84452
85865
  promptAcceptExecution: () => promptAcceptExecution,
84453
85866
  sentientCommand: () => sentientCommand
84454
85867
  });
84455
- import { join as join31 } from "node:path";
85868
+ import { join as join32 } from "node:path";
84456
85869
  import { cwd as processCwd3, stdin, stdout } from "node:process";
84457
85870
  import { createInterface as createInterface4 } from "node:readline/promises";
84458
85871
  import {
@@ -84542,7 +85955,7 @@ var init_sentient3 = __esm({
84542
85955
  return;
84543
85956
  }
84544
85957
  if (dryRun) {
84545
- const statePath2 = join31(projectRoot, SENTIENT_STATE_FILE2);
85958
+ const statePath2 = join32(projectRoot, SENTIENT_STATE_FILE2);
84546
85959
  const outcome = await safeRunTick({ projectRoot, statePath: statePath2, dryRun: true });
84547
85960
  emitSuccess2(
84548
85961
  { dryRun: true, outcome },
@@ -84658,7 +86071,7 @@ Logs: ${logPath}`
84658
86071
  const jsonMode = args.json === true;
84659
86072
  const dryRun = args["dry-run"] === true;
84660
86073
  try {
84661
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86074
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84662
86075
  const outcome = await safeRunTick({ projectRoot, statePath, dryRun });
84663
86076
  emitSuccess2(
84664
86077
  { outcome, dryRun },
@@ -84750,7 +86163,7 @@ Logs: ${logPath}`
84750
86163
  return;
84751
86164
  }
84752
86165
  await db.update(tasks).set({ status: "pending", updatedAt: now }).where(eq2(tasks.id, id)).run();
84753
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86166
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84754
86167
  const state = await readSentientState2(statePath);
84755
86168
  await patchSentientState(statePath, {
84756
86169
  tier2Stats: {
@@ -84846,7 +86259,7 @@ Logs: ${logPath}`
84846
86259
  return;
84847
86260
  }
84848
86261
  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);
86262
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84850
86263
  const state = await readSentientState2(statePath);
84851
86264
  await patchSentientState(statePath, {
84852
86265
  tier2Stats: {
@@ -84891,7 +86304,7 @@ Logs: ${logPath}`
84891
86304
  const projectRoot = resolveProjectRoot5(args.project);
84892
86305
  const jsonMode = args.json === true;
84893
86306
  try {
84894
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86307
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84895
86308
  const outcome = await safeRunProposeTick({ projectRoot, statePath });
84896
86309
  emitSuccess2(
84897
86310
  { outcome },
@@ -84911,7 +86324,7 @@ Logs: ${logPath}`
84911
86324
  const projectRoot = resolveProjectRoot5(args.project);
84912
86325
  const jsonMode = args.json === true;
84913
86326
  try {
84914
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86327
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84915
86328
  const updated = await patchSentientState(statePath, { tier2Enabled: true });
84916
86329
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals enabled");
84917
86330
  } catch (err) {
@@ -84930,7 +86343,7 @@ Logs: ${logPath}`
84930
86343
  const projectRoot = resolveProjectRoot5(args.project);
84931
86344
  const jsonMode = args.json === true;
84932
86345
  try {
84933
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86346
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84934
86347
  const updated = await patchSentientState(statePath, { tier2Enabled: false });
84935
86348
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals disabled");
84936
86349
  } catch (err) {
@@ -84961,7 +86374,7 @@ Logs: ${logPath}`
84961
86374
  const projectRoot = resolveProjectRoot5(args.project);
84962
86375
  const jsonMode = args.json === true;
84963
86376
  try {
84964
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86377
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84965
86378
  const state = await readSentientState2(statePath);
84966
86379
  emitSuccess2(
84967
86380
  {
@@ -85519,7 +86932,7 @@ var sequence_exports = {};
85519
86932
  __export(sequence_exports, {
85520
86933
  sequenceCommand: () => sequenceCommand
85521
86934
  });
85522
- import { getProjectRoot as getProjectRoot70 } from "@cleocode/core/internal";
86935
+ import { getProjectRoot as getProjectRoot71 } from "@cleocode/core/internal";
85523
86936
  var showCommand12, checkCommand7, repairCommand3, sequenceCommand;
85524
86937
  var init_sequence = __esm({
85525
86938
  "packages/cleo/src/cli/commands/sequence.ts"() {
@@ -85555,7 +86968,7 @@ var init_sequence = __esm({
85555
86968
  meta: { name: "repair", description: "Reset counter to max + 1 if behind" },
85556
86969
  async run() {
85557
86970
  const { repairSequence } = await import("@cleocode/core/internal");
85558
- const projectRoot = getProjectRoot70();
86971
+ const projectRoot = getProjectRoot71();
85559
86972
  const repair = await repairSequence(projectRoot);
85560
86973
  const result = {
85561
86974
  repaired: repair.repaired,
@@ -86152,8 +87565,8 @@ var init_session4 = __esm({
86152
87565
  "audit-scope": { type: "string", description: "Audit log scope (global|local)" }
86153
87566
  },
86154
87567
  async run({ args }) {
86155
- const { detectSessionDrift, getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
86156
- const projectRoot = await getProjectRoot75();
87568
+ const { detectSessionDrift, getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
87569
+ const projectRoot = await getProjectRoot76();
86157
87570
  const scope = args["audit-scope"] === "local" ? "local" : "global";
86158
87571
  const report = await detectSessionDrift({ projectRoot, auditScope: scope });
86159
87572
  cliOutput(report, { command: "session drift", operation: "session.drift" });
@@ -88552,10 +89965,10 @@ var init_sync = __esm({
88552
89965
  }
88553
89966
  },
88554
89967
  async run({ args }) {
88555
- const { readFileSync: readFileSync22 } = await import("node:fs");
89968
+ const { readFileSync: readFileSync23 } = await import("node:fs");
88556
89969
  let externalTasks;
88557
89970
  try {
88558
- externalTasks = JSON.parse(readFileSync22(args.file, "utf8"));
89971
+ externalTasks = JSON.parse(readFileSync23(args.file, "utf8"));
88559
89972
  } catch (err) {
88560
89973
  const message = err instanceof Error ? err.message : String(err);
88561
89974
  cliError(`Failed to read or parse external tasks file: ${message}`, 2, {
@@ -88852,19 +90265,19 @@ var init_telemetry2 = __esm({
88852
90265
  });
88853
90266
 
88854
90267
  // packages/cleo/src/cli/commands/templates/lib.ts
88855
- import { readFileSync as readFileSync13 } from "node:fs";
90268
+ import { readFileSync as readFileSync14 } from "node:fs";
88856
90269
  import { isAbsolute as isAbsolute3, resolve as resolve10 } from "node:path";
88857
- import { getProjectRoot as getProjectRoot71 } from "@cleocode/core";
90270
+ import { getProjectRoot as getProjectRoot72 } from "@cleocode/core";
88858
90271
  import { resolveSourcePathAbsolute } from "@cleocode/core/templates/registry";
88859
90272
  function resolveProjectRoot6(raw) {
88860
90273
  if (typeof raw === "string" && raw.length > 0) {
88861
90274
  return isAbsolute3(raw) ? raw : resolve10(process.cwd(), raw);
88862
90275
  }
88863
- return getProjectRoot71();
90276
+ return getProjectRoot72();
88864
90277
  }
88865
90278
  function readTemplateSource(entry) {
88866
90279
  const sourceAbsolute = resolveSourcePathAbsolute(entry);
88867
- return readFileSync13(sourceAbsolute, "utf8");
90280
+ return readFileSync14(sourceAbsolute, "utf8");
88868
90281
  }
88869
90282
  function applySubstitution(entry, source) {
88870
90283
  if (entry.substitution === "static") {
@@ -88879,8 +90292,8 @@ var init_lib = __esm({
88879
90292
  });
88880
90293
 
88881
90294
  // 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";
90295
+ import { existsSync as existsSync17, readFileSync as readFileSync15 } from "node:fs";
90296
+ import { join as join33 } from "node:path";
88884
90297
  import { getTemplateById } from "@cleocode/core/templates/registry";
88885
90298
  function unifiedDiff(a, b) {
88886
90299
  const aLines = a.length === 0 ? [] : a.split("\n");
@@ -88950,7 +90363,7 @@ var init_diff = __esm({
88950
90363
  let rendered;
88951
90364
  try {
88952
90365
  projectRoot = resolveProjectRoot6(args["project"]);
88953
- installPath = join32(projectRoot, entry.installPath);
90366
+ installPath = join33(projectRoot, entry.installPath);
88954
90367
  const source = readTemplateSource(entry);
88955
90368
  rendered = applySubstitution(entry, source).rendered;
88956
90369
  } catch (err) {
@@ -88978,7 +90391,7 @@ ${unifiedDiff("", rendered)}`
88978
90391
  process.exit(1 /* GENERAL_ERROR */);
88979
90392
  return;
88980
90393
  }
88981
- const current = readFileSync14(installPath, "utf8");
90394
+ const current = readFileSync15(installPath, "utf8");
88982
90395
  const same = current === rendered;
88983
90396
  const result = {
88984
90397
  id,
@@ -89000,8 +90413,8 @@ ${unifiedDiff("", rendered)}`
89000
90413
  });
89001
90414
 
89002
90415
  // 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";
90416
+ import { existsSync as existsSync18, mkdirSync as mkdirSync5, readFileSync as readFileSync16, writeFileSync as writeFileSync6 } from "node:fs";
90417
+ import { dirname as dirname10, join as join34 } from "node:path";
89005
90418
  import { getTemplateById as getTemplateById2 } from "@cleocode/core/templates/registry";
89006
90419
  var templatesInstallCommand;
89007
90420
  var init_install = __esm({
@@ -89055,7 +90468,7 @@ var init_install = __esm({
89055
90468
  let substituted;
89056
90469
  try {
89057
90470
  projectRoot = resolveProjectRoot6(args["project"]);
89058
- installPath = join33(projectRoot, entry.installPath);
90471
+ installPath = join34(projectRoot, entry.installPath);
89059
90472
  const source = readTemplateSource(entry);
89060
90473
  const sub = applySubstitution(entry, source);
89061
90474
  rendered = sub.rendered;
@@ -89069,7 +90482,7 @@ var init_install = __esm({
89069
90482
  return;
89070
90483
  }
89071
90484
  if (existsSync18(installPath)) {
89072
- const current = readFileSync15(installPath, "utf8");
90485
+ const current = readFileSync16(installPath, "utf8");
89073
90486
  if (current === rendered) {
89074
90487
  const noopResult = {
89075
90488
  id,
@@ -89217,8 +90630,8 @@ var init_show3 = __esm({
89217
90630
  });
89218
90631
 
89219
90632
  // 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";
90633
+ import { existsSync as existsSync19, mkdirSync as mkdirSync6, readFileSync as readFileSync17, writeFileSync as writeFileSync7 } from "node:fs";
90634
+ import { dirname as dirname11, join as join35 } from "node:path";
89222
90635
  import { getTemplateById as getTemplateById4 } from "@cleocode/core/templates/registry";
89223
90636
  var templatesUpgradeCommand;
89224
90637
  var init_upgrade2 = __esm({
@@ -89280,7 +90693,7 @@ var init_upgrade2 = __esm({
89280
90693
  let rendered;
89281
90694
  try {
89282
90695
  projectRoot = resolveProjectRoot6(args["project"]);
89283
- installPath = join34(projectRoot, entry.installPath);
90696
+ installPath = join35(projectRoot, entry.installPath);
89284
90697
  const source = readTemplateSource(entry);
89285
90698
  rendered = applySubstitution(entry, source).rendered;
89286
90699
  } catch (err) {
@@ -89293,7 +90706,7 @@ var init_upgrade2 = __esm({
89293
90706
  }
89294
90707
  const previewOnly = args["diff"] === true;
89295
90708
  const accept = args["accept"] === true;
89296
- const current = existsSync19(installPath) ? readFileSync16(installPath, "utf8") : null;
90709
+ const current = existsSync19(installPath) ? readFileSync17(installPath, "utf8") : null;
89297
90710
  const diffBody = current === null ? "" : current === rendered ? "" : unifiedDiff(current, rendered);
89298
90711
  let outcome;
89299
90712
  let reason;
@@ -89517,7 +90930,7 @@ var testing_exports = {};
89517
90930
  __export(testing_exports, {
89518
90931
  testingCommand: () => testingCommand
89519
90932
  });
89520
- var validateCommand9, checkCommand8, statusCommand18, coverageCommand, runCommand7, testingCommand;
90933
+ var validateCommand9, checkCommand8, statusCommand18, coverageCommand, runCommand8, testingCommand;
89521
90934
  var init_testing = __esm({
89522
90935
  "packages/cleo/src/cli/commands/testing.ts"() {
89523
90936
  "use strict";
@@ -89602,7 +91015,7 @@ var init_testing = __esm({
89602
91015
  );
89603
91016
  }
89604
91017
  });
89605
- runCommand7 = defineCommand({
91018
+ runCommand8 = defineCommand({
89606
91019
  meta: { name: "run", description: "Run test suite" },
89607
91020
  args: {
89608
91021
  filter: {
@@ -89627,7 +91040,7 @@ var init_testing = __esm({
89627
91040
  check: checkCommand8,
89628
91041
  status: statusCommand18,
89629
91042
  coverage: coverageCommand,
89630
- run: runCommand7
91043
+ run: runCommand8
89631
91044
  },
89632
91045
  async run({ cmd, rawArgs }) {
89633
91046
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
@@ -89643,12 +91056,12 @@ var token_exports = {};
89643
91056
  __export(token_exports, {
89644
91057
  tokenCommand: () => tokenCommand
89645
91058
  });
89646
- import { readFileSync as readFileSync17 } from "node:fs";
89647
- import { getProjectRoot as getProjectRoot72, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
91059
+ import { readFileSync as readFileSync18 } from "node:fs";
91060
+ import { getProjectRoot as getProjectRoot73, measureTokenExchange, recordTokenExchange as recordTokenExchange2 } from "@cleocode/core/internal";
89648
91061
  function readPayload(args, textKey, fileKey) {
89649
91062
  const text = args[textKey];
89650
91063
  const file = args[fileKey];
89651
- if (file) return readFileSync17(file, "utf-8");
91064
+ if (file) return readFileSync18(file, "utf-8");
89652
91065
  return text;
89653
91066
  }
89654
91067
  var filterArgs, summaryCommand3, listCommand26, showCommand16, deleteCommand3, clearCommand2, estimateCommand, tokenCommand;
@@ -89808,7 +91221,7 @@ var init_token = __esm({
89808
91221
  domain: args.domain,
89809
91222
  operation: args.operation
89810
91223
  };
89811
- const result = args.record ? await recordTokenExchange2(getProjectRoot72(), input2) : await measureTokenExchange(input2);
91224
+ const result = args.record ? await recordTokenExchange2(getProjectRoot73(), input2) : await measureTokenExchange(input2);
89812
91225
  cliOutput(result, {
89813
91226
  command: "token",
89814
91227
  operation: args.record ? "admin.token.record" : "token.estimate"
@@ -89842,9 +91255,9 @@ var transcript_exports = {};
89842
91255
  __export(transcript_exports, {
89843
91256
  transcriptCommand: () => transcriptCommand
89844
91257
  });
89845
- import { homedir as homedir3 } from "node:os";
89846
- import { join as join35 } from "node:path";
89847
- import { getProjectRoot as getProjectRoot73 } from "@cleocode/core";
91258
+ import { homedir as homedir4 } from "node:os";
91259
+ import { join as join36 } from "node:path";
91260
+ import { getProjectRoot as getProjectRoot74 } from "@cleocode/core";
89848
91261
  import {
89849
91262
  parseDurationMs,
89850
91263
  pruneTranscripts,
@@ -89874,7 +91287,7 @@ var init_transcript = __esm({
89874
91287
  async run({ args }) {
89875
91288
  if (args.pending) {
89876
91289
  try {
89877
- const projectRoot = getProjectRoot73();
91290
+ const projectRoot = getProjectRoot74();
89878
91291
  const { scanPendingTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
89879
91292
  const pending = await scanPendingTranscripts(projectRoot);
89880
91293
  cliOutput(
@@ -89897,7 +91310,7 @@ var init_transcript = __esm({
89897
91310
  }
89898
91311
  return;
89899
91312
  }
89900
- const projectsDir = args["projects-dir"] ?? join35(homedir3(), ".claude", "projects");
91313
+ const projectsDir = args["projects-dir"] ?? join36(homedir4(), ".claude", "projects");
89901
91314
  try {
89902
91315
  const result = await scanTranscripts(projectsDir);
89903
91316
  cliOutput(
@@ -89971,7 +91384,7 @@ var init_transcript = __esm({
89971
91384
  async run({ args }) {
89972
91385
  const tier = args.tier ?? "warm";
89973
91386
  const dryRun = args["dry-run"] ?? false;
89974
- const projectRoot = getProjectRoot73();
91387
+ const projectRoot = getProjectRoot74();
89975
91388
  try {
89976
91389
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
89977
91390
  const { findSessionTranscriptPath, listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -90087,7 +91500,7 @@ var init_transcript = __esm({
90087
91500
  const dryRun = args["dry-run"] ?? false;
90088
91501
  const olderThanHours = args["older-than-hours"] ? Number.parseInt(args["older-than-hours"], 10) : 24;
90089
91502
  const limit = args.limit ? Number.parseInt(args.limit, 10) : void 0;
90090
- const projectRoot = getProjectRoot73();
91503
+ const projectRoot = getProjectRoot74();
90091
91504
  try {
90092
91505
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
90093
91506
  const { listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -90207,7 +91620,7 @@ var init_transcript = __esm({
90207
91620
  process.exit(2);
90208
91621
  return;
90209
91622
  }
90210
- const projectsDir = args["projects-dir"] ?? join35(homedir3(), ".claude", "projects");
91623
+ const projectsDir = args["projects-dir"] ?? join36(homedir4(), ".claude", "projects");
90211
91624
  try {
90212
91625
  const pruneResult = await pruneTranscripts({
90213
91626
  olderThanMs,
@@ -90274,10 +91687,10 @@ __export(gateway_auto_start_exports, {
90274
91687
  spawnGatewayIfDown: () => spawnGatewayIfDown
90275
91688
  });
90276
91689
  import { once } from "node:events";
90277
- import { createWriteStream, existsSync as existsSync20, readFileSync as readFileSync18, realpathSync } from "node:fs";
91690
+ import { createWriteStream, existsSync as existsSync20, readFileSync as readFileSync19, realpathSync } from "node:fs";
90278
91691
  import { mkdir as mkdir6 } from "node:fs/promises";
90279
91692
  import * as net from "node:net";
90280
- import { dirname as dirname12, join as join36 } from "node:path";
91693
+ import { dirname as dirname12, join as join37 } from "node:path";
90281
91694
  import { fileURLToPath as fileURLToPath6 } from "node:url";
90282
91695
  import { spawnWrapped } from "@cleocode/core/resources/spawn-wrapper.js";
90283
91696
  function shouldAutoStartGateway(config) {
@@ -90321,17 +91734,17 @@ function resolveCliEntryPath(startUrl = import.meta.url) {
90321
91734
  const startFile = realpathSync(fileURLToPath6(startUrl));
90322
91735
  let current = dirname12(startFile);
90323
91736
  for (let i = 0; i < 20; i++) {
90324
- const pkgJsonPath = join36(current, "package.json");
91737
+ const pkgJsonPath = join37(current, "package.json");
90325
91738
  if (existsSync20(pkgJsonPath)) {
90326
91739
  let pkgName;
90327
91740
  try {
90328
- const raw = readFileSync18(pkgJsonPath, "utf8");
91741
+ const raw = readFileSync19(pkgJsonPath, "utf8");
90329
91742
  const parsed = JSON.parse(raw);
90330
91743
  pkgName = typeof parsed["name"] === "string" ? parsed["name"] : void 0;
90331
91744
  } catch {
90332
91745
  }
90333
91746
  if (pkgName === CLEO_PACKAGE_NAME) {
90334
- const entry = join36(current, "dist", "cli", "index.js");
91747
+ const entry = join37(current, "dist", "cli", "index.js");
90335
91748
  if (!existsSync20(entry)) {
90336
91749
  throw new Error(
90337
91750
  `@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 +91781,8 @@ async function spawnGatewayIfDown(opts = {}) {
90368
91781
  const { getCleoLogDir } = await import("@cleocode/core");
90369
91782
  const logDir = getCleoLogDir();
90370
91783
  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" });
91784
+ const outStream = createWriteStream(join37(logDir, "gateway.log"), { flags: "a" });
91785
+ const errStream = createWriteStream(join37(logDir, "gateway.err"), { flags: "a" });
90373
91786
  await Promise.all([once(outStream, "open"), once(errStream, "open")]);
90374
91787
  outFd = outStream;
90375
91788
  errFd = errStream;
@@ -90828,8 +92241,8 @@ __export(cockpit_exports, {
90828
92241
  KanbanBoardComponent: () => KanbanBoardComponent,
90829
92242
  runCockpit: () => runCockpit
90830
92243
  });
90831
- import { readFileSync as readFileSync19 } from "node:fs";
90832
- import { join as join37 } from "node:path";
92244
+ import { readFileSync as readFileSync20 } from "node:fs";
92245
+ import { join as join38 } from "node:path";
90833
92246
  import { createCleoClient as createCleoClient2 } from "@cleocode/core/gateway-client";
90834
92247
  async function fetchTaskRows(baseUrl) {
90835
92248
  const client = createCleoClient2({ baseUrl });
@@ -90946,8 +92359,8 @@ async function runCockpit(options = {}, sink = (line) => process.stdout.write(`$
90946
92359
  }
90947
92360
  try {
90948
92361
  const { getCleoLogDir } = await import("@cleocode/core");
90949
- const errPath = join37(getCleoLogDir(), "gateway.err");
90950
- const errContent = readFileSync19(errPath, "utf8").trimEnd();
92362
+ const errPath = join38(getCleoLogDir(), "gateway.err");
92363
+ const errContent = readFileSync20(errPath, "utf8").trimEnd();
90951
92364
  if (errContent.length > 0) {
90952
92365
  const lastLine = errContent.split("\n").at(-1) ?? "";
90953
92366
  if (lastLine.length > 0) {
@@ -91975,7 +93388,7 @@ var init_verify = __esm({
91975
93388
  },
91976
93389
  evidence: {
91977
93390
  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)."
93391
+ 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
93392
  },
91980
93393
  explain: {
91981
93394
  type: "boolean",
@@ -91997,6 +93410,10 @@ var init_verify = __esm({
91997
93410
  type: "string",
91998
93411
  description: "With --auto: the merged PR that implements the task"
91999
93412
  },
93413
+ fresh: {
93414
+ type: "boolean",
93415
+ 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)."
93416
+ },
92000
93417
  "shared-evidence": {
92001
93418
  type: "boolean",
92002
93419
  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 +93425,85 @@ var init_verify = __esm({
92008
93425
  return;
92009
93426
  }
92010
93427
  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 */;
93428
+ const priorFresh = process.env["CLEO_EVIDENCE_FRESH"];
93429
+ if (args.fresh === true) process.env["CLEO_EVIDENCE_FRESH"] = "1";
93430
+ try {
93431
+ if (args.auto === true) {
93432
+ if (isWrite || args.evidence || args.run === true) {
93433
+ cliError(
93434
+ "--auto derives its own evidence; drop --gate/--all/--reset/--evidence/--run",
93435
+ "E_INVALID_INPUT"
93436
+ );
93437
+ process.exitCode = 6 /* VALIDATION_ERROR */;
93438
+ return;
93439
+ }
93440
+ const { parseDoneOptions } = await import("@cleocode/core/tasks/done-plan.js");
93441
+ const parsed = parseDoneOptions(args.satisfies, args.pr);
93442
+ if (!parsed.ok) {
93443
+ cliError(parsed.message, "E_INVALID_INPUT");
93444
+ process.exitCode = 6 /* VALIDATION_ERROR */;
93445
+ return;
93446
+ }
93447
+ const { recordTaskDone } = await import("@cleocode/core/tasks/done-record.js");
93448
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/paths.js");
93449
+ const r = await recordTaskDone(args.taskId, {
93450
+ projectRoot: getProjectRoot76(),
93451
+ ...parsed.options,
93452
+ ...args.agent ? { agent: args.agent } : {}
93453
+ });
93454
+ if (!r.success) {
93455
+ cliError(r.error.message, r.error.code, { fix: r.error.fix, details: r.error.details });
93456
+ process.exitCode = r.error.exitCode ?? 1;
93457
+ return;
93458
+ }
93459
+ const { plan: _plan, ...summary } = r.data;
93460
+ cliOutput(summary, { command: "verify", operation: "check.gate.auto" });
92018
93461
  return;
92019
93462
  }
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");
93463
+ if (args.satisfies !== void 0 || args.pr !== void 0) {
93464
+ cliError("--satisfies and --pr apply only with --auto (or cleo done)", "E_INVALID_INPUT");
92024
93465
  process.exitCode = 6 /* VALIDATION_ERROR */;
92025
93466
  return;
92026
93467
  }
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;
93468
+ if (args.run === true && isWrite) {
93469
+ cliError(
93470
+ "--run reports typed gate results and records nothing; it cannot be combined with --gate/--all/--reset.",
93471
+ 6 /* VALIDATION_ERROR */,
93472
+ {
93473
+ name: "E_VALIDATION",
93474
+ fix: "Run `cleo verify <id> --run` first, then attest with `cleo verify <id> --gate <name> --evidence <atoms>`"
93475
+ },
93476
+ { operation: "check.gate.run" }
93477
+ );
93478
+ process.exitCode = 6 /* VALIDATION_ERROR */;
92037
93479
  return;
92038
93480
  }
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 */,
93481
+ const useExplain = !isWrite && args.explain === true;
93482
+ const operation = isWrite ? "gate.set" : args.run === true ? "gate.run" : useExplain ? "verify.explain" : "gate.status";
93483
+ await dispatchFromCli(
93484
+ isWrite ? "mutate" : "query",
93485
+ "check",
93486
+ operation,
92052
93487
  {
92053
- name: "E_VALIDATION",
92054
- fix: "Run `cleo verify <id> --run` first, then attest with `cleo verify <id> --gate <name> --evidence <atoms>`"
93488
+ taskId: args.taskId,
93489
+ gate: args.gate,
93490
+ value: args.value === "false" ? false : args.gate ? true : void 0,
93491
+ agent: args.agent,
93492
+ all: args.all,
93493
+ reset: args.reset,
93494
+ evidence: args.evidence,
93495
+ sharedEvidence: args["shared-evidence"] ?? false,
93496
+ // T12621: citty turns `--no-run` into `run: false`; read it through the helper.
93497
+ ...isWrite && negatedFlag(args, "run") ? { noRun: true } : {}
92055
93498
  },
92056
- { operation: "check.gate.run" }
93499
+ { command: "verify" }
92057
93500
  );
92058
- process.exitCode = 6 /* VALIDATION_ERROR */;
92059
- return;
93501
+ } finally {
93502
+ if (args.fresh === true) {
93503
+ if (priorFresh === void 0) delete process.env["CLEO_EVIDENCE_FRESH"];
93504
+ else process.env["CLEO_EVIDENCE_FRESH"] = priorFresh;
93505
+ }
92060
93506
  }
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
93507
  }
92082
93508
  });
92083
93509
  }
@@ -92338,7 +93764,7 @@ var workgraph_exports = {};
92338
93764
  __export(workgraph_exports, {
92339
93765
  workgraphCommand: () => workgraphCommand
92340
93766
  });
92341
- import { readFileSync as readFileSync20 } from "node:fs";
93767
+ import { readFileSync as readFileSync21 } from "node:fs";
92342
93768
  import { resolve as resolve12 } from "node:path";
92343
93769
  var validateCommand10, applyCommand, planCommand4, structureCommand, statusCommand20, workgraphCommand;
92344
93770
  var init_workgraph2 = __esm({
@@ -92363,7 +93789,7 @@ var init_workgraph2 = __esm({
92363
93789
  const filePath = resolve12(String(args.file));
92364
93790
  let raw;
92365
93791
  try {
92366
- raw = readFileSync20(filePath, "utf-8");
93792
+ raw = readFileSync21(filePath, "utf-8");
92367
93793
  } catch {
92368
93794
  cliOutput2(
92369
93795
  { error: `Cannot read file: ${filePath}` },
@@ -92408,7 +93834,7 @@ var init_workgraph2 = __esm({
92408
93834
  const filePath = resolve12(String(args.file));
92409
93835
  let raw;
92410
93836
  try {
92411
- raw = readFileSync20(filePath, "utf-8");
93837
+ raw = readFileSync21(filePath, "utf-8");
92412
93838
  } catch {
92413
93839
  cliOutput2(
92414
93840
  { error: `Cannot read file: ${filePath}` },
@@ -92450,9 +93876,9 @@ var init_workgraph2 = __esm({
92450
93876
  },
92451
93877
  async run({ args }) {
92452
93878
  const { generatePlanningDoc } = await import("@cleocode/core/workgraph");
92453
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
93879
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
92454
93880
  const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
92455
- const projectRoot = getProjectRoot75();
93881
+ const projectRoot = getProjectRoot76();
92456
93882
  const audience = String(args.audience) === "agent" ? "agent" : "maintainer";
92457
93883
  const result = await generatePlanningDoc(projectRoot, {
92458
93884
  sagaId: String(args.sagaId),
@@ -92469,9 +93895,9 @@ var init_workgraph2 = __esm({
92469
93895
  async run() {
92470
93896
  const { validateWorkGraphStructure } = await import("@cleocode/core/workgraph");
92471
93897
  const { taskList: taskList2 } = await import("@cleocode/core/internal");
92472
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
93898
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
92473
93899
  const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
92474
- const projectRoot = getProjectRoot75();
93900
+ const projectRoot = getProjectRoot76();
92475
93901
  const listResult = await taskList2(projectRoot, { limit: 5e3 });
92476
93902
  const tasks = listResult.success ? listResult.data?.tasks ?? [] : [];
92477
93903
  const nodes = tasks.map((t) => ({
@@ -92490,9 +93916,9 @@ var init_workgraph2 = __esm({
92490
93916
  description: "One-shot saga-to-saga workgraph dashboard (tracking checklist)"
92491
93917
  },
92492
93918
  async run() {
92493
- const { sagas: sagas2, getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
93919
+ const { sagas: sagas2, getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
92494
93920
  const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
92495
- const projectRoot = getProjectRoot75();
93921
+ const projectRoot = getProjectRoot76();
92496
93922
  const listResult = await sagas2.sagaList(projectRoot);
92497
93923
  if (!listResult.success) {
92498
93924
  cliOutput2(listResult, { command: "workgraph", operation: "workgraph.status" });
@@ -92558,7 +93984,7 @@ __export(worktree_exports, {
92558
93984
  worktreeCommand: () => worktreeCommand
92559
93985
  });
92560
93986
  import readline4 from "node:readline";
92561
- import { getProjectRoot as getProjectRoot74, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
93987
+ import { getProjectRoot as getProjectRoot75, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
92562
93988
  async function promptYesNo2(question) {
92563
93989
  return new Promise((resolve13) => {
92564
93990
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
@@ -92663,7 +94089,7 @@ var init_worktree3 = __esm({
92663
94089
  const staleDays = staleDaysRaw !== void 0 ? Number.parseInt(staleDaysRaw, 10) : void 0;
92664
94090
  const idleDaysRaw = typeof args["idle-days"] === "string" ? args["idle-days"] : void 0;
92665
94091
  const idleDays = idleDaysRaw !== void 0 ? Number.parseInt(idleDaysRaw, 10) : void 0;
92666
- const projectRoot = getProjectRoot74();
94092
+ const projectRoot = getProjectRoot75();
92667
94093
  const listResult = await listWorktrees2({
92668
94094
  projectRoot,
92669
94095
  ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
@@ -92902,8 +94328,8 @@ var init_worktree3 = __esm({
92902
94328
 
92903
94329
  // packages/cleo/src/cli/index.ts
92904
94330
  init_dist();
92905
- import { readFileSync as readFileSync21 } from "node:fs";
92906
- import { dirname as dirname13, join as join39 } from "node:path";
94331
+ import { readFileSync as readFileSync22 } from "node:fs";
94332
+ import { dirname as dirname13, join as join40 } from "node:path";
92907
94333
  import { fileURLToPath as fileURLToPath7 } from "node:url";
92908
94334
  import { enforceNodeVersion } from "@cleocode/paths";
92909
94335
 
@@ -93116,7 +94542,7 @@ var COMMAND_MANIFEST = [
93116
94542
  {
93117
94543
  exportName: "cloudCommand",
93118
94544
  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].",
94545
+ 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
94546
  load: async () => (await Promise.resolve().then(() => (init_cloud(), cloud_exports))).cloudCommand
93121
94547
  },
93122
94548
  {
@@ -93347,6 +94773,12 @@ var COMMAND_MANIFEST = [
93347
94773
  description: "Audit the machine-wide memory guard that bounds test runs an agent starts OUTSIDE cleo ",
93348
94774
  load: async () => (await Promise.resolve().then(() => (init_doctor_memory_guard(), doctor_memory_guard_exports))).doctorMemoryGuardCommand
93349
94775
  },
94776
+ {
94777
+ exportName: "doctorMigrationsCommand",
94778
+ name: "migrations",
94779
+ description: "Report the migration journal of the project and global stores: row count, head, applied ",
94780
+ load: async () => (await Promise.resolve().then(() => (init_doctor_migrations(), doctor_migrations_exports))).doctorMigrationsCommand
94781
+ },
93350
94782
  {
93351
94783
  exportName: "doctorNexusResidencyCommand",
93352
94784
  name: "nexus-residency",
@@ -93539,6 +94971,12 @@ var COMMAND_MANIFEST = [
93539
94971
  description: "Completion timeline and productivity analytics",
93540
94972
  load: async () => (await Promise.resolve().then(() => (init_history(), history_exports))).historyCommand
93541
94973
  },
94974
+ {
94975
+ exportName: "hookCommand",
94976
+ name: "hook",
94977
+ 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",
94978
+ load: async () => (await Promise.resolve().then(() => (init_hook(), hook_exports))).hookCommand
94979
+ },
93542
94980
  {
93543
94981
  exportName: "hygieneCommand",
93544
94982
  name: "hygiene",
@@ -93845,6 +95283,12 @@ var COMMAND_MANIFEST = [
93845
95283
  description: "Generate project roadmap from task provenance \u2014 epics grouped by status with progress",
93846
95284
  load: async () => (await Promise.resolve().then(() => (init_roadmap(), roadmap_exports))).roadmapCommand
93847
95285
  },
95286
+ {
95287
+ exportName: "runCommand",
95288
+ name: "run",
95289
+ description: "Run a heavy command (tests, builds, installs) under the machine-wide resource budget: cleo run [--class test|build|full-build] [--wait] [--passthrough] -- <command...>",
95290
+ load: async () => (await Promise.resolve().then(() => (init_run(), run_exports))).runCommand
95291
+ },
93848
95292
  {
93849
95293
  exportName: "safestopCommand",
93850
95294
  name: "safestop",
@@ -94252,12 +95696,12 @@ init_did_you_mean();
94252
95696
 
94253
95697
  // packages/cleo/src/cli/lib/first-run-detection.ts
94254
95698
  import { existsSync as existsSync21 } from "node:fs";
94255
- import { join as join38 } from "node:path";
95699
+ import { join as join39 } from "node:path";
94256
95700
  async function detectFirstRun() {
94257
95701
  const envKey = process.env["ANTHROPIC_API_KEY"];
94258
95702
  if (typeof envKey === "string" && envKey.length > 0) return false;
94259
95703
  const { getCleoPlatformPaths } = await import("@cleocode/paths");
94260
- const configPath = join38(getCleoPlatformPaths().config, "config.json");
95704
+ const configPath = join39(getCleoPlatformPaths().config, "config.json");
94261
95705
  if (existsSync21(configPath)) return false;
94262
95706
  try {
94263
95707
  const { getCredentialPool: getCredentialPool2 } = await import("@cleocode/core/llm/credential-pool.js");
@@ -94389,8 +95833,8 @@ async function resolveSubCommandForHelp(cmd, rawArgs) {
94389
95833
  init_summary_context();
94390
95834
  enforceNodeVersion();
94391
95835
  function getPackageVersion() {
94392
- const pkgPath = join39(dirname13(fileURLToPath7(import.meta.url)), "../../package.json");
94393
- const pkg = JSON.parse(readFileSync21(pkgPath, "utf-8"));
95836
+ const pkgPath = join40(dirname13(fileURLToPath7(import.meta.url)), "../../package.json");
95837
+ const pkg = JSON.parse(readFileSync22(pkgPath, "utf-8"));
94394
95838
  return pkg.version;
94395
95839
  }
94396
95840
  var CLI_VERSION = getPackageVersion();
@@ -94431,6 +95875,7 @@ async function startCli() {
94431
95875
  let describeFlag = false;
94432
95876
  for (let i = 0; i < argv.length; i++) {
94433
95877
  const arg = argv[i];
95878
+ if (arg === "--") break;
94434
95879
  if (arg === "--json") rawOpts["json"] = true;
94435
95880
  else if (arg === "--human") rawOpts["human"] = true;
94436
95881
  else if (arg === "--quiet") rawOpts["quiet"] = true;
@@ -94641,7 +96086,7 @@ async function runStartupMaintenance() {
94641
96086
  detectAndRemoveStrayProjectNexus,
94642
96087
  getGlobalSalt,
94643
96088
  getLogger: getLogger22,
94644
- getProjectRoot: getProjectRoot75,
96089
+ getProjectRoot: getProjectRoot76,
94645
96090
  isCleanupMarkerSet,
94646
96091
  isMissingProjectError,
94647
96092
  migrateSignaldockToConduit,
@@ -94651,7 +96096,7 @@ async function runStartupMaintenance() {
94651
96096
  } = await import("@cleocode/core/internal");
94652
96097
  let projectRootForCleanup = "";
94653
96098
  try {
94654
- projectRootForCleanup = getProjectRoot75();
96099
+ projectRootForCleanup = getProjectRoot76();
94655
96100
  } catch {
94656
96101
  }
94657
96102
  if (!isCleanupMarkerSet(CLI_VERSION, projectRootForCleanup)) {
@@ -94671,7 +96116,7 @@ async function runStartupMaintenance() {
94671
96116
  const isInitInvocation = process.argv.slice(2).some((a) => a === "init");
94672
96117
  if (!isInitInvocation) {
94673
96118
  try {
94674
- const _projectRootForMigration = getProjectRoot75();
96119
+ const _projectRootForMigration = getProjectRoot76();
94675
96120
  if (needsSignaldockToConduitMigration(_projectRootForMigration)) {
94676
96121
  const migrationResult = await migrateSignaldockToConduit(_projectRootForMigration);
94677
96122
  if (migrationResult.status === "failed") {