@cleocode/cleo 2026.9.26 → 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 +2487 -369
  4. package/package.json +13 -13
  5. package/studio-dist/client/_app/immutable/chunks/{BhOwHRY9.js → BJp57kf2.js} +1 -1
  6. package/studio-dist/client/_app/immutable/chunks/{CobI0XAU.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.DaDdqQTe.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.CKHiZeuP.js → 0.Zy2IsLEl.js} +1 -1
  12. package/studio-dist/client/_app/immutable/nodes/{1.CmaYPYrk.js → 1.DJN1QI3l.js} +1 -1
  13. package/studio-dist/client/_app/immutable/nodes/{15.D23qtyoz.js → 15.B4rwqbHV.js} +1 -1
  14. package/studio-dist/client/_app/immutable/nodes/{16.Dtt6exbd.js → 16.jn-5BG_L.js} +1 -1
  15. package/studio-dist/client/_app/immutable/nodes/{17.CPZ22rBo.js → 17.DnWGC4t9.js} +1 -1
  16. package/studio-dist/client/_app/immutable/nodes/{18.Qm_fekS5.js → 18.0zddLZOY.js} +1 -1
  17. package/studio-dist/client/_app/immutable/nodes/{20.DjGgB4KD.js → 20.DEKHq9Tc.js} +1 -1
  18. package/studio-dist/client/_app/immutable/nodes/{24.CgMoobl_.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.C1oRqB1b.js → 26.BiE1i4iE.js} +1 -1
  21. package/studio-dist/client/_app/immutable/nodes/{3.Cy4T6zbv.js → 3.BObAOu_-.js} +1 -1
  22. package/studio-dist/client/_app/version.json +1 -1
  23. package/studio-dist/server/chunks/{0-G8NhADpo.js → 0-BmUoS2yd.js} +3 -3
  24. package/studio-dist/server/chunks/1-CTjj2MYz.js +9 -0
  25. package/studio-dist/server/chunks/{15-o63WM4MZ.js → 15-Dt4kqUxW.js} +3 -3
  26. package/studio-dist/server/chunks/{16-7h8G4VoG.js → 16-kgTLJvbO.js} +3 -3
  27. package/studio-dist/server/chunks/{17-DcShICKv.js → 17-mRYB5141.js} +3 -3
  28. package/studio-dist/server/chunks/{18-BER3ZYEh.js → 18-BjZ325q5.js} +3 -3
  29. package/studio-dist/server/chunks/{20-DErTM2qU.js → 20-DQ2Vrujq.js} +3 -3
  30. package/studio-dist/server/chunks/{24-BZh7ZC1u.js → 24-DAeuAfXN.js} +3 -3
  31. package/studio-dist/server/chunks/{25-qqsEYb5C.js → 25-DGCNmzAS.js} +4 -4
  32. package/studio-dist/server/chunks/{26-C424QBHc.js → 26-CiN6bbmR.js} +3 -3
  33. package/studio-dist/server/chunks/{3-DDisSHuV.js → 3-BS2FXYjP.js} +3 -3
  34. package/studio-dist/server/chunks/{_layout.svelte-DcfphVWO.js → _layout.svelte-DJ_UWmGp.js} +4 -4
  35. package/studio-dist/server/chunks/{_page.svelte-DuD1vdhl.js → _page.svelte-BUq8_eQH.js} +3 -3
  36. package/studio-dist/server/chunks/{_page.svelte-CPdHIklX.js → _page.svelte-CRnYa4cW.js} +5 -5
  37. package/studio-dist/server/chunks/{_page.svelte-B4hg1b3p.js → _page.svelte-Ca7x-ZvH.js} +4 -4
  38. package/studio-dist/server/chunks/{_page.svelte-DBbdqQsp.js → _page.svelte-CcP_KW3Y.js} +3 -3
  39. package/studio-dist/server/chunks/{_page.svelte-EPu-M4nY.js → _page.svelte-Cfv9tDBA.js} +3 -3
  40. package/studio-dist/server/chunks/{_page.svelte-C8Ybsn2v.js → _page.svelte-D8dLEr7O.js} +3 -3
  41. package/studio-dist/server/chunks/{_page.svelte-DdaHffLO.js → _page.svelte-Dk0znswQ.js} +3 -3
  42. package/studio-dist/server/chunks/{_page.svelte-CWNRWa2L.js → _page.svelte-J4HjPhfO.js} +3 -3
  43. package/studio-dist/server/chunks/{_page.svelte-BjX_VPfv.js → _page.svelte-WR6jUiQE.js} +3 -3
  44. package/studio-dist/server/chunks/{_server.ts-wZKCwtFH.js → _server.ts-2BazvYRP.js} +3 -3
  45. package/studio-dist/server/chunks/{_server.ts-BjIJy4O3.js → _server.ts-Bih2-_5O.js} +2 -2
  46. package/studio-dist/server/chunks/{_server.ts-CmiJfYD5.js → _server.ts-C0evMKCk.js} +3 -3
  47. package/studio-dist/server/chunks/{_server.ts-C4WHkBZ_.js → _server.ts-Cr57EKWf.js} +3 -3
  48. package/studio-dist/server/chunks/{_server.ts-BGuhOntH.js → _server.ts-P4wVVksg.js} +3 -3
  49. package/studio-dist/server/chunks/{client-ARinjJG0.js → client-Cl295FWH.js} +2 -2
  50. package/studio-dist/server/chunks/{dist-CLTFgJWk.js → dist-CdoCt9zT.js} +314 -4
  51. package/studio-dist/server/chunks/{error.svelte-m5N9iUFN.js → error.svelte-ajn1HNOb.js} +3 -3
  52. package/studio-dist/server/chunks/{http-DKP1pqq1.js → http-BiQjEmVU.js} +2 -2
  53. package/studio-dist/server/chunks/{internal-BF6KxfEH.js → internal-D9MtKHIF.js} +2 -2
  54. package/studio-dist/server/chunks/{stores-UvZbmzhQ.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/B2oT_qgu.js +0 -3
  58. package/studio-dist/client/_app/immutable/chunks/B7RPHy-R.js +0 -1
  59. package/studio-dist/client/_app/immutable/entry/start.BjuNqpl1.js +0 -1
  60. package/studio-dist/client/_app/immutable/nodes/25.DkFAoI4l.js +0 -39
  61. package/studio-dist/server/chunks/1-CfXNxnLm.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
  }
@@ -22759,8 +23086,37 @@ var init_nexus_account = __esm({
22759
23086
  "E_NEXUS_BUSY",
22760
23087
  /** Several accounts hold a device credential on one origin and none was named. */
22761
23088
  "E_NEXUS_ACCOUNT_AMBIGUOUS",
22762
- /** An option that needs device credentials (`--read-only`) without `CLEO_NEXUS_DEVICE=1`. */
22763
- "E_NEXUS_DEVICE_REQUIRED"
23089
+ /** An option that needs device credentials (`--read-only`) with `CLEO_NEXUS_DEVICE=0`. */
23090
+ "E_NEXUS_DEVICE_REQUIRED",
23091
+ /** `.cleo/nexus-link.json` is in a format this CLEO cannot update (written by a newer CLEO). */
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"
22764
23120
  ];
22765
23121
  nexusAccountUserSchema = z25.object({
22766
23122
  id: z25.string(),
@@ -22782,6 +23138,415 @@ var init_nexus_account = __esm({
22782
23138
  }
22783
23139
  });
22784
23140
 
23141
+ // packages/contracts/src/nexus-cloud.ts
23142
+ import { z as z26 } from "zod";
23143
+ var NEXUS_DEVICE_STATES, NEXUS_CLOUD_PROFILES, NEXUS_DEVICE_LIST_STATES, NEXUS_PAGE_LIMIT_MAX, NEXUS_CLOUD_MAX_PAGES, NEXUS_PRESENCE_FRESH_SECONDS, NEXUS_DEVICE_STATE_UNKNOWN, isoTime, profile, deviceState, nexusCloudCredentialSchema, nexusCloudDeviceSchema, nexusCloudOrganizationSchema, nexusCloudUserSchema, nexusCloudWhoamiSchema, nexusCloudDevicePageSchema, nexusCloudPresenceSchema, nexusCloudReplicaSchema, nexusCloudDeviceCountsSchema, projectFields, nexusCloudProjectListItemSchema, nexusCloudProjectPageSchema, nexusCloudProjectDetailSchema, nexusCloudReplicaPageSchema, NEXUS_STATUS_CHECK_IDS, NEXUS_STATUS_VERDICTS, CLOUD_STATUS_VERDICTS, knownCheckId, nexusCloudStatusCheckSchema, nexusCloudStatusSchema, NEXUS_UNAUTHENTICATED_REASONS, NEXUS_FORBIDDEN_REASONS, NEXUS_REVOKED_REASONS, LOGIN, COMPROMISED, DEVICE_REVOKED, SESSION_EXPIRED_LOGIN, SERVER_REFUSED, NEXUS_REVOKED_REASON_ERRORS, NEXUS_UNAUTHENTICATED_ERRORS, NEXUS_FORBIDDEN_ERRORS, NEXUS_CONFLICT_ERRORS, NEXUS_UNREACHABLE_ERROR;
23144
+ var init_nexus_cloud = __esm({
23145
+ "packages/contracts/src/nexus-cloud.ts"() {
23146
+ "use strict";
23147
+ NEXUS_DEVICE_STATES = ["active", "signed-out", "revoked"];
23148
+ NEXUS_CLOUD_PROFILES = ["device", "read-only"];
23149
+ NEXUS_DEVICE_LIST_STATES = ["active", "signed-out", "revoked", "all"];
23150
+ NEXUS_PAGE_LIMIT_MAX = 200;
23151
+ NEXUS_CLOUD_MAX_PAGES = 25;
23152
+ NEXUS_PRESENCE_FRESH_SECONDS = 86400;
23153
+ NEXUS_DEVICE_STATE_UNKNOWN = "unknown";
23154
+ isoTime = z26.iso.datetime({ offset: true });
23155
+ profile = z26.enum(NEXUS_CLOUD_PROFILES).nullable().catch(null);
23156
+ deviceState = z26.enum([...NEXUS_DEVICE_STATES, NEXUS_DEVICE_STATE_UNKNOWN]).catch(NEXUS_DEVICE_STATE_UNKNOWN);
23157
+ nexusCloudCredentialSchema = z26.object({
23158
+ kind: z26.enum(["device", "session"]),
23159
+ credentialId: z26.string().nullable().optional(),
23160
+ profile: profile.optional(),
23161
+ scopes: z26.array(z26.string()).default([]),
23162
+ createdAt: isoTime.nullable().optional(),
23163
+ lastUsedAt: isoTime.nullable().optional(),
23164
+ /** When the credential expires if it is not used again; null for sessions. */
23165
+ idleExpiresAt: isoTime.nullable().optional()
23166
+ });
23167
+ nexusCloudDeviceSchema = z26.object({
23168
+ deviceId: z26.string(),
23169
+ name: z26.string(),
23170
+ platform: z26.string().optional(),
23171
+ arch: z26.string().nullable().optional(),
23172
+ cliVersion: z26.string().nullable().optional(),
23173
+ createdAt: isoTime.optional(),
23174
+ lastSeenAt: isoTime.nullable().optional(),
23175
+ state: deviceState,
23176
+ signedOutAt: isoTime.nullable().optional(),
23177
+ /** Base64 device certificate; null until the device holds a key grant. */
23178
+ certificate: z26.string().nullable().optional(),
23179
+ /** The current credential's profile, or null with none (signed out or revoked). */
23180
+ profile: profile.optional(),
23181
+ /** True for the device whose credential made this request. */
23182
+ current: z26.boolean().default(false),
23183
+ projects: z26.number().int().nonnegative().optional(),
23184
+ replicas: z26.number().int().nonnegative().optional(),
23185
+ lastSyncAt: isoTime.nullable().optional(),
23186
+ lastPresenceAt: isoTime.nullable().optional()
23187
+ });
23188
+ nexusCloudOrganizationSchema = z26.object({
23189
+ id: z26.string(),
23190
+ name: z26.string(),
23191
+ slug: z26.string().nullable().optional(),
23192
+ role: z26.string().optional(),
23193
+ personal: z26.boolean().optional()
23194
+ });
23195
+ nexusCloudUserSchema = z26.object({
23196
+ id: z26.string(),
23197
+ email: z26.string(),
23198
+ name: z26.string().nullable().optional()
23199
+ });
23200
+ nexusCloudWhoamiSchema = z26.object({
23201
+ serverTime: isoTime.optional(),
23202
+ user: nexusCloudUserSchema,
23203
+ organizations: z26.array(nexusCloudOrganizationSchema).default([]),
23204
+ credential: nexusCloudCredentialSchema,
23205
+ /** The calling device; null for a session caller. */
23206
+ device: nexusCloudDeviceSchema.nullable()
23207
+ });
23208
+ nexusCloudDevicePageSchema = z26.object({
23209
+ devices: z26.array(nexusCloudDeviceSchema),
23210
+ nextCursor: z26.string().max(512).nullable().default(null),
23211
+ truncated: z26.boolean().default(false)
23212
+ });
23213
+ nexusCloudPresenceSchema = z26.looseObject({
23214
+ observedAt: isoTime.optional(),
23215
+ sync: z26.object({ enabled: z26.boolean() }).optional()
23216
+ });
23217
+ nexusCloudReplicaSchema = z26.object({
23218
+ projectId: z26.string(),
23219
+ replicaId: z26.string(),
23220
+ deviceId: z26.string(),
23221
+ deviceName: z26.string(),
23222
+ deviceState: deviceState.optional(),
23223
+ attachedAt: isoTime.optional(),
23224
+ lastSyncAt: isoTime.nullable(),
23225
+ presence: nexusCloudPresenceSchema.nullable(),
23226
+ presenceAt: isoTime.nullable()
23227
+ });
23228
+ nexusCloudDeviceCountsSchema = z26.object({
23229
+ active: z26.number().int().nonnegative(),
23230
+ total: z26.number().int().nonnegative()
23231
+ });
23232
+ projectFields = {
23233
+ projectId: z26.string(),
23234
+ label: z26.string().nullable(),
23235
+ organizationId: z26.string(),
23236
+ organizationName: z26.string().optional(),
23237
+ remoteUrl: z26.string().nullable().optional(),
23238
+ createdAt: isoTime.optional()
23239
+ };
23240
+ nexusCloudProjectListItemSchema = z26.object({
23241
+ ...projectFields,
23242
+ role: z26.string(),
23243
+ streamId: z26.string().optional(),
23244
+ headSeq: z26.number().int().nonnegative().nullable().optional(),
23245
+ openConflicts: z26.number().int().nonnegative().optional(),
23246
+ replicas: z26.array(nexusCloudReplicaSchema).default([]),
23247
+ devices: nexusCloudDeviceCountsSchema.optional(),
23248
+ replicaCount: z26.number().int().nonnegative().optional(),
23249
+ lastSyncAt: isoTime.nullable().optional(),
23250
+ lastPresenceAt: isoTime.nullable().optional(),
23251
+ /** This project's replica list was cut at 50 (T12858). */
23252
+ replicasTruncated: z26.boolean().default(false)
23253
+ });
23254
+ nexusCloudProjectPageSchema = z26.object({
23255
+ projects: z26.array(nexusCloudProjectListItemSchema),
23256
+ nextCursor: z26.string().max(512).nullable().default(null),
23257
+ /** Anything in the page was cut (the project list or a replica list). */
23258
+ truncated: z26.boolean().default(false),
23259
+ /** The project list itself was cut at 1000 (T12858). */
23260
+ projectsTruncated: z26.boolean().default(false)
23261
+ });
23262
+ nexusCloudProjectDetailSchema = z26.object({
23263
+ project: z26.object({ ...projectFields, deletedAt: isoTime.nullable().optional() }),
23264
+ role: z26.string(),
23265
+ canTrash: z26.boolean().optional(),
23266
+ openConflicts: z26.number().int().nonnegative(),
23267
+ /** At most 50, oldest attachment first. */
23268
+ replicas: z26.array(nexusCloudReplicaSchema),
23269
+ devices: nexusCloudDeviceCountsSchema,
23270
+ replicaCount: z26.number().int().nonnegative().optional(),
23271
+ lastSyncAt: isoTime.nullable().optional(),
23272
+ /** `replicas` was cut at 50. */
23273
+ truncated: z26.boolean().default(false),
23274
+ stream: z26.object({
23275
+ streamId: z26.string(),
23276
+ headSeq: z26.number().int().nonnegative(),
23277
+ headCheckpointId: z26.string().nullable()
23278
+ }).nullable()
23279
+ });
23280
+ nexusCloudReplicaPageSchema = z26.object({
23281
+ replicas: z26.array(nexusCloudReplicaSchema),
23282
+ devices: nexusCloudDeviceCountsSchema.optional(),
23283
+ nextCursor: z26.string().max(512).nullable().default(null),
23284
+ truncated: z26.boolean().default(false)
23285
+ });
23286
+ NEXUS_STATUS_CHECK_IDS = [
23287
+ "credential.valid",
23288
+ "device.registered",
23289
+ "device.active",
23290
+ "device.certified",
23291
+ "project.registered",
23292
+ "project.writable",
23293
+ "replica.attached",
23294
+ "presence.fresh",
23295
+ "replica.synced",
23296
+ "conflicts.none"
23297
+ ];
23298
+ NEXUS_STATUS_VERDICTS = ["ok", "attention", "not-linked", "not-registered"];
23299
+ CLOUD_STATUS_VERDICTS = [...NEXUS_STATUS_VERDICTS, "not-signed-in"];
23300
+ knownCheckId = z26.enum(NEXUS_STATUS_CHECK_IDS);
23301
+ nexusCloudStatusCheckSchema = z26.object({
23302
+ id: z26.enum(NEXUS_STATUS_CHECK_IDS),
23303
+ ok: z26.boolean(),
23304
+ required: z26.boolean(),
23305
+ detail: z26.string()
23306
+ });
23307
+ nexusCloudStatusSchema = z26.object({
23308
+ serverTime: isoTime.optional(),
23309
+ apiVersion: z26.string().optional(),
23310
+ user: nexusCloudUserSchema,
23311
+ credential: nexusCloudCredentialSchema,
23312
+ device: nexusCloudDeviceSchema.nullable(),
23313
+ project: z26.object({
23314
+ projectId: z26.string(),
23315
+ registered: z26.boolean(),
23316
+ organizationId: z26.string().nullable(),
23317
+ organizationName: z26.string().nullable(),
23318
+ role: z26.string().nullable()
23319
+ }).nullable(),
23320
+ replica: z26.object({
23321
+ replicaId: z26.string(),
23322
+ attached: z26.boolean(),
23323
+ attachedElsewhere: z26.boolean(),
23324
+ attachedAt: isoTime.nullable(),
23325
+ lastSyncAt: isoTime.nullable(),
23326
+ presenceAt: isoTime.nullable(),
23327
+ lastReplicaSeq: z26.number().int().nonnegative().nullable().optional()
23328
+ }).nullable(),
23329
+ stream: z26.object({
23330
+ streamId: z26.string(),
23331
+ headSeq: z26.number().int().nonnegative(),
23332
+ headCheckpointId: z26.string().nullable(),
23333
+ openConflicts: z26.number().int().nonnegative(),
23334
+ devices: nexusCloudDeviceCountsSchema
23335
+ }).nullable(),
23336
+ /** Check ids added by a newer server are dropped, never a parse failure. */
23337
+ checks: z26.array(nexusCloudStatusCheckSchema.extend({ id: z26.string() })).transform(
23338
+ (list) => list.flatMap((c) => {
23339
+ const id = knownCheckId.safeParse(c.id);
23340
+ return id.success ? [{ ...c, id: id.data }] : [];
23341
+ })
23342
+ ),
23343
+ /** A verdict added by a newer server reads as `attention`: never `ok` by accident. */
23344
+ verdict: z26.enum(NEXUS_STATUS_VERDICTS).catch("attention")
23345
+ });
23346
+ NEXUS_UNAUTHENTICATED_REASONS = [
23347
+ "missing",
23348
+ "invalid",
23349
+ "credential-revoked",
23350
+ "credential-expired",
23351
+ "device-signed-out",
23352
+ "device-revoked",
23353
+ "session-bearer-retired",
23354
+ "session-used"
23355
+ ];
23356
+ NEXUS_FORBIDDEN_REASONS = [
23357
+ "insufficient-scope",
23358
+ "session-required",
23359
+ "device-required",
23360
+ "device-mismatch",
23361
+ "not-self",
23362
+ "project-role",
23363
+ "route-undeclared",
23364
+ "bearer-session-required",
23365
+ "session-not-fresh",
23366
+ "device-limit",
23367
+ "device-flow-session-required",
23368
+ "device-not-enrolled"
23369
+ ];
23370
+ NEXUS_REVOKED_REASONS = ["signed-out", "revoked", "rotated", "reenrolled"];
23371
+ LOGIN = "run `cleo login nexus`";
23372
+ COMPROMISED = {
23373
+ code: "E_NEXUS_CREDENTIAL_COMPROMISED",
23374
+ message: "this device's credential was replaced or revoked elsewhere, possibly used from another machine",
23375
+ fix: "revoke this device on cleocode.dev and sign in again with `cleo login nexus`"
23376
+ };
23377
+ DEVICE_REVOKED = {
23378
+ code: "E_NEXUS_DEVICE_REVOKED",
23379
+ message: "this device was revoked",
23380
+ fix: "run `cleo login nexus` to enrol this machine as a new device"
23381
+ };
23382
+ SESSION_EXPIRED_LOGIN = {
23383
+ code: "E_NEXUS_SESSION_EXPIRED",
23384
+ message: "the session is too old for this request",
23385
+ fix: "run `cleo login nexus` (needs a browser: on a headless machine a human must complete the login)"
23386
+ };
23387
+ SERVER_REFUSED = {
23388
+ code: "E_NEXUS_REQUEST_FAILED",
23389
+ message: null,
23390
+ fix: null
23391
+ };
23392
+ NEXUS_REVOKED_REASON_ERRORS = {
23393
+ reenrolled: {
23394
+ code: "E_NEXUS_NOT_SIGNED_IN",
23395
+ message: "this device's credential was replaced by a newer login of the same device",
23396
+ fix: LOGIN
23397
+ },
23398
+ "signed-out": {
23399
+ code: "E_NEXUS_NOT_SIGNED_IN",
23400
+ message: "this device was signed out and later signed in again with another credential",
23401
+ fix: LOGIN
23402
+ },
23403
+ revoked: DEVICE_REVOKED,
23404
+ rotated: COMPROMISED
23405
+ };
23406
+ NEXUS_UNAUTHENTICATED_ERRORS = {
23407
+ missing: {
23408
+ code: "E_NEXUS_NOT_SIGNED_IN",
23409
+ message: "not signed in to Cleo Nexus (the credential is missing or invalid)",
23410
+ fix: LOGIN
23411
+ },
23412
+ invalid: {
23413
+ code: "E_NEXUS_NOT_SIGNED_IN",
23414
+ message: "not signed in to Cleo Nexus (the credential is missing or invalid)",
23415
+ fix: LOGIN
23416
+ },
23417
+ // Resolved by `details.revokedReason` through NEXUS_REVOKED_REASON_ERRORS.
23418
+ "credential-revoked": COMPROMISED,
23419
+ "credential-expired": {
23420
+ code: "E_NEXUS_SESSION_EXPIRED",
23421
+ message: "the device credential expired after 90 days without use",
23422
+ fix: LOGIN
23423
+ },
23424
+ "device-signed-out": {
23425
+ code: "E_NEXUS_DEVICE_SIGNED_OUT",
23426
+ message: "this device was signed out",
23427
+ fix: LOGIN
23428
+ },
23429
+ "device-revoked": DEVICE_REVOKED,
23430
+ "session-bearer-retired": {
23431
+ code: "E_NEXUS_SESSION_EXPIRED",
23432
+ message: "bearer sessions are no longer accepted",
23433
+ fix: "run `cleo login nexus` with the current CLI"
23434
+ },
23435
+ "session-used": {
23436
+ code: "E_NEXUS_SESSION_EXPIRED",
23437
+ message: "the 9.24 session was already used by another enrolment",
23438
+ fix: LOGIN
23439
+ }
23440
+ };
23441
+ NEXUS_FORBIDDEN_ERRORS = {
23442
+ "insufficient-scope": {
23443
+ code: "E_NEXUS_INSUFFICIENT_SCOPE",
23444
+ message: "this device's credential lacks the scope for that request",
23445
+ fix: "run `cleo login nexus` without --read-only to enrol with the full device profile"
23446
+ },
23447
+ "session-required": SERVER_REFUSED,
23448
+ "device-required": SERVER_REFUSED,
23449
+ "device-mismatch": SERVER_REFUSED,
23450
+ "not-self": SERVER_REFUSED,
23451
+ "project-role": SERVER_REFUSED,
23452
+ "route-undeclared": SERVER_REFUSED,
23453
+ "bearer-session-required": SESSION_EXPIRED_LOGIN,
23454
+ "session-not-fresh": SESSION_EXPIRED_LOGIN,
23455
+ "device-limit": {
23456
+ code: "E_NEXUS_REQUEST_FAILED",
23457
+ message: "the account has reached its device limit",
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
23469
+ }
23470
+ };
23471
+ NEXUS_CONFLICT_ERRORS = {
23472
+ "replica-copied": {
23473
+ code: "E_NEXUS_REPLICA_COPIED",
23474
+ message: "this project store is attached from another device (a copied store)",
23475
+ fix: null
23476
+ },
23477
+ "rotation-conflict": COMPROMISED
23478
+ };
23479
+ NEXUS_UNREACHABLE_ERROR = {
23480
+ code: "E_NEXUS_UNREACHABLE",
23481
+ message: null,
23482
+ fix: "check your network and retry"
23483
+ };
23484
+ }
23485
+ });
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
+
22785
23550
  // packages/contracts/src/task-id.ts
22786
23551
  function isTaskId(value) {
22787
23552
  return typeof value === "string" && TASK_ID_REGEX.test(value);
@@ -22849,6 +23614,7 @@ __export(src_exports, {
22849
23614
  CHANNEL_BOUNDARY_REGISTRY: () => CHANNEL_BOUNDARY_REGISTRY,
22850
23615
  CLEO_CONFIG_MANIFEST: () => CLEO_CONFIG_MANIFEST,
22851
23616
  CLI_CATEGORY_ORDER: () => CLI_CATEGORY_ORDER,
23617
+ CLOUD_STATUS_VERDICTS: () => CLOUD_STATUS_VERDICTS,
22852
23618
  COLLECTION_IDENTITY_FIELDS: () => COLLECTION_IDENTITY_FIELDS,
22853
23619
  COLLECTION_KEYS: () => COLLECTION_KEYS,
22854
23620
  CONFIG_MANIFEST_ENTRIES: () => CONFIG_MANIFEST_ENTRIES,
@@ -22963,10 +23729,28 @@ __export(src_exports, {
22963
23729
  MonitorResponseSchema: () => MonitorResponseSchema,
22964
23730
  NEXUS_ACCOUNT_ERROR_CODES: () => NEXUS_ACCOUNT_ERROR_CODES,
22965
23731
  NEXUS_CLI_CLIENT_ID: () => NEXUS_CLI_CLIENT_ID,
23732
+ NEXUS_CLOUD_MAX_PAGES: () => NEXUS_CLOUD_MAX_PAGES,
23733
+ NEXUS_CLOUD_PROFILES: () => NEXUS_CLOUD_PROFILES,
23734
+ NEXUS_CONFLICT_ERRORS: () => NEXUS_CONFLICT_ERRORS,
22966
23735
  NEXUS_DEFAULT_API_URL: () => NEXUS_DEFAULT_API_URL,
23736
+ NEXUS_DEVICE_LIST_STATES: () => NEXUS_DEVICE_LIST_STATES,
23737
+ NEXUS_DEVICE_STATES: () => NEXUS_DEVICE_STATES,
23738
+ NEXUS_DEVICE_STATE_UNKNOWN: () => NEXUS_DEVICE_STATE_UNKNOWN,
22967
23739
  NEXUS_FLEET_SCHEMA_VERSION: () => NEXUS_FLEET_SCHEMA_VERSION,
23740
+ NEXUS_FORBIDDEN_ERRORS: () => NEXUS_FORBIDDEN_ERRORS,
23741
+ NEXUS_FORBIDDEN_REASONS: () => NEXUS_FORBIDDEN_REASONS,
22968
23742
  NEXUS_LOGIN_TARGET: () => NEXUS_LOGIN_TARGET,
23743
+ NEXUS_PAGE_LIMIT_MAX: () => NEXUS_PAGE_LIMIT_MAX,
23744
+ NEXUS_PRESENCE_FRESH_SECONDS: () => NEXUS_PRESENCE_FRESH_SECONDS,
23745
+ NEXUS_REVOKED_REASONS: () => NEXUS_REVOKED_REASONS,
23746
+ NEXUS_REVOKED_REASON_ERRORS: () => NEXUS_REVOKED_REASON_ERRORS,
22969
23747
  NEXUS_SCOPE_MAP: () => NEXUS_SCOPE_MAP,
23748
+ NEXUS_STATUS_CHECK_IDS: () => NEXUS_STATUS_CHECK_IDS,
23749
+ NEXUS_STATUS_VERDICTS: () => NEXUS_STATUS_VERDICTS,
23750
+ NEXUS_UNAUTHENTICATED_ERRORS: () => NEXUS_UNAUTHENTICATED_ERRORS,
23751
+ NEXUS_UNAUTHENTICATED_REASONS: () => NEXUS_UNAUTHENTICATED_REASONS,
23752
+ NEXUS_UNREACHABLE_ERROR: () => NEXUS_UNREACHABLE_ERROR,
23753
+ NEXUS_VAULT_LEASE_ROLE: () => NEXUS_VAULT_LEASE_ROLE,
22970
23754
  OPEN_SYSTEM_KEY_PREFIXES: () => OPEN_SYSTEM_KEY_PREFIXES,
22971
23755
  OPERATIONS: () => OPERATIONS,
22972
23756
  OPERATION_RESULT_SCHEMAS: () => OPERATION_RESULT_SCHEMAS,
@@ -23012,6 +23796,8 @@ __export(src_exports, {
23012
23796
  RESOURCE_CLASSES: () => RESOURCE_CLASSES,
23013
23797
  RESOURCE_DEFERRED_CODE: () => RESOURCE_DEFERRED_CODE,
23014
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,
23015
23801
  RateCheckRequestSchema: () => RateCheckRequestSchema,
23016
23802
  RateResultResponseSchema: () => RateResultResponseSchema,
23017
23803
  ReleaseChannelSchema: () => ReleaseChannelSchema,
@@ -23047,6 +23833,8 @@ __export(src_exports, {
23047
23833
  SUPERVISOR_IPC_PROTOCOL_VERSION: () => SUPERVISOR_IPC_PROTOCOL_VERSION,
23048
23834
  SUPERVISOR_IPC_REQUEST_KINDS: () => SUPERVISOR_IPC_REQUEST_KINDS,
23049
23835
  SUPERVISOR_IPC_RESPONSE_KINDS: () => SUPERVISOR_IPC_RESPONSE_KINDS,
23836
+ SYNC_SCHEMA_VERSION: () => SYNC_SCHEMA_VERSION,
23837
+ SYNC_WRITE_INVARIANTS: () => SYNC_WRITE_INVARIANTS,
23050
23838
  SYSTEM_ROLE_MAP: () => SYSTEM_ROLE_MAP,
23051
23839
  SessionView: () => SessionView,
23052
23840
  SpawnRequestSchema: () => SpawnRequestSchema,
@@ -23246,6 +24034,28 @@ __export(src_exports, {
23246
24034
  nexusAccountMeSchema: () => nexusAccountMeSchema,
23247
24035
  nexusAccountOrganizationSchema: () => nexusAccountOrganizationSchema,
23248
24036
  nexusAccountUserSchema: () => nexusAccountUserSchema,
24037
+ nexusActivityEventSchema: () => nexusActivityEventSchema,
24038
+ nexusActivityPageSchema: () => nexusActivityPageSchema,
24039
+ nexusCloudCredentialSchema: () => nexusCloudCredentialSchema,
24040
+ nexusCloudDeviceCountsSchema: () => nexusCloudDeviceCountsSchema,
24041
+ nexusCloudDevicePageSchema: () => nexusCloudDevicePageSchema,
24042
+ nexusCloudDeviceSchema: () => nexusCloudDeviceSchema,
24043
+ nexusCloudOrganizationSchema: () => nexusCloudOrganizationSchema,
24044
+ nexusCloudPresenceSchema: () => nexusCloudPresenceSchema,
24045
+ nexusCloudProjectDetailSchema: () => nexusCloudProjectDetailSchema,
24046
+ nexusCloudProjectListItemSchema: () => nexusCloudProjectListItemSchema,
24047
+ nexusCloudProjectPageSchema: () => nexusCloudProjectPageSchema,
24048
+ nexusCloudReplicaPageSchema: () => nexusCloudReplicaPageSchema,
24049
+ nexusCloudReplicaSchema: () => nexusCloudReplicaSchema,
24050
+ nexusCloudStatusCheckSchema: () => nexusCloudStatusCheckSchema,
24051
+ nexusCloudStatusSchema: () => nexusCloudStatusSchema,
24052
+ nexusCloudUserSchema: () => nexusCloudUserSchema,
24053
+ nexusCloudWhoamiSchema: () => nexusCloudWhoamiSchema,
24054
+ nexusLeaseAcquireSchema: () => nexusLeaseAcquireSchema,
24055
+ nexusLeaseSchema: () => nexusLeaseSchema,
24056
+ nexusProjectKeysSchema: () => nexusProjectKeysSchema,
24057
+ nexusStreamHeadSchema: () => nexusStreamHeadSchema,
24058
+ nexusUserKeysSchema: () => nexusUserKeysSchema,
23249
24059
  normalizeError: () => normalizeError,
23250
24060
  noteAtomSchema: () => noteAtomSchema,
23251
24061
  noulDecisionAnswerSchema: () => noulDecisionAnswerSchema,
@@ -23426,6 +24236,9 @@ var init_src2 = __esm({
23426
24236
  init_decide();
23427
24237
  init_decide_sites();
23428
24238
  init_nexus_account();
24239
+ init_nexus_cloud();
24240
+ init_nexus_vault();
24241
+ init_sync_schema();
23429
24242
  init_task_id();
23430
24243
  }
23431
24244
  });
@@ -24281,7 +25094,7 @@ function humanProgress(text) {
24281
25094
  function isHumanOutput() {
24282
25095
  return humanEnabled();
24283
25096
  }
24284
- function cliError(message, code, details, meta) {
25097
+ function cliError(message, code, details, meta, options) {
24285
25098
  const ctx = getFormatContext();
24286
25099
  const outputMode = getOutputMode();
24287
25100
  if (outputMode === "silent") {
@@ -24323,6 +25136,11 @@ function cliError(message, code, details, meta) {
24323
25136
  error: errorObj,
24324
25137
  meta: errorMeta
24325
25138
  };
25139
+ if (options?.stderr === true) {
25140
+ process.stderr.write(`${JSON.stringify(envelope)}
25141
+ `);
25142
+ return;
25143
+ }
24326
25144
  process.stdout.write(JSON.stringify(envelope) + "\n");
24327
25145
  }
24328
25146
  var renderers;
@@ -36353,7 +37171,7 @@ function parseAgenticNode(raw, base, index) {
36353
37171
  inputs = acc;
36354
37172
  }
36355
37173
  const context_files = parseStringArray(raw.context_files, `nodes[${index}].context_files`);
36356
- const profile = parseOptionalNonEmptyString(raw.profile, `nodes[${index}].profile`);
37174
+ const profile2 = parseOptionalNonEmptyString(raw.profile, `nodes[${index}].profile`);
36357
37175
  const model = parseOptionalNonEmptyString(raw.model, `nodes[${index}].model`);
36358
37176
  const provider = parseOptionalNonEmptyString(raw.provider, `nodes[${index}].provider`);
36359
37177
  const allowed_skills = parseStringArray(raw.allowed_skills, `nodes[${index}].allowed_skills`);
@@ -36366,7 +37184,7 @@ function parseAgenticNode(raw, base, index) {
36366
37184
  role,
36367
37185
  inputs,
36368
37186
  ...context_files !== void 0 ? { context_files } : {},
36369
- ...profile !== void 0 ? { profile } : {},
37187
+ ...profile2 !== void 0 ? { profile: profile2 } : {},
36370
37188
  ...model !== void 0 ? { model } : {},
36371
37189
  ...provider !== void 0 ? { provider } : {},
36372
37190
  ...allowed_skills !== void 0 ? { allowed_skills } : {},
@@ -36915,21 +37733,21 @@ var init_migrate_e4 = __esm({
36915
37733
 
36916
37734
  // packages/playbooks/src/policy.ts
36917
37735
  function evaluatePolicy(command, rules = DEFAULT_POLICY_RULES) {
36918
- for (const rule of rules) {
36919
- 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)) {
36920
37738
  return {
36921
37739
  action: "require-human",
36922
- reason: rule.reason,
36923
- matchedPattern: rule.pattern.source
37740
+ reason: rule2.reason,
37741
+ matchedPattern: rule2.pattern.source
36924
37742
  };
36925
37743
  }
36926
37744
  }
36927
- for (const rule of rules) {
36928
- 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)) {
36929
37747
  return {
36930
37748
  action: "auto-approve",
36931
- reason: rule.reason,
36932
- matchedPattern: rule.pattern.source
37749
+ reason: rule2.reason,
37750
+ matchedPattern: rule2.pattern.source
36933
37751
  };
36934
37752
  }
36935
37753
  }
@@ -37504,9 +38322,9 @@ function auditContractViolation(projectRoot, runId, nodeId, field, key, playbook
37504
38322
  } catch {
37505
38323
  }
37506
38324
  }
37507
- function handleContractErrorHandler(playbook, trigger, _message) {
38325
+ function handleContractErrorHandler(playbook, trigger2, _message) {
37508
38326
  if (!playbook.error_handlers) return null;
37509
- const handler = playbook.error_handlers.find((h) => h.on === trigger);
38327
+ const handler = playbook.error_handlers.find((h) => h.on === trigger2);
37510
38328
  return handler?.action ?? null;
37511
38329
  }
37512
38330
  function iterationCapFor(node, runtimeDefault) {
@@ -38029,8 +38847,8 @@ async function loadPlaybookByName(name) {
38029
38847
  return null;
38030
38848
  }
38031
38849
  try {
38032
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/internal");
38033
- const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot75();
38850
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/internal");
38851
+ const projectRoot = __playbookRuntimeOverrides.projectRoot ?? getProjectRoot76();
38034
38852
  const resolved = resolvePlaybook(name, {
38035
38853
  projectRoot,
38036
38854
  globalPlaybooksDir: __playbookRuntimeOverrides.globalPlaybooksDir,
@@ -38075,7 +38893,7 @@ async function buildDefaultDispatcher() {
38075
38893
  if (__playbookRuntimeOverrides.dispatcher) return __playbookRuntimeOverrides.dispatcher;
38076
38894
  const { orchestrateSpawnExecute: orchestrateSpawnExecute2 } = await import("@cleocode/runtime/gateway");
38077
38895
  const {
38078
- getProjectRoot: getProjectRoot75,
38896
+ getProjectRoot: getProjectRoot76,
38079
38897
  createToolGuard,
38080
38898
  runSkillNodeOrSpawn,
38081
38899
  maybeCreatePiRunner,
@@ -38083,7 +38901,7 @@ async function buildDefaultDispatcher() {
38083
38901
  hasCantbookProfilePin,
38084
38902
  DEFAULT_DETERMINISTIC_DENIED_COMMANDS
38085
38903
  } = await import("@cleocode/core/internal");
38086
- const projectRoot = getProjectRoot75();
38904
+ const projectRoot = getProjectRoot76();
38087
38905
  const tools = createToolGuard({
38088
38906
  allowedRoots: [projectRoot],
38089
38907
  deniedCommands: DEFAULT_DETERMINISTIC_DENIED_COMMANDS,
@@ -38176,12 +38994,12 @@ async function buildDefaultDeterministicRunner() {
38176
38994
  return void 0;
38177
38995
  }
38178
38996
  const {
38179
- getProjectRoot: getProjectRoot75,
38997
+ getProjectRoot: getProjectRoot76,
38180
38998
  createToolGuard,
38181
38999
  createGuardedDeterministicRunner,
38182
39000
  DEFAULT_DETERMINISTIC_DENIED_COMMANDS
38183
39001
  } = await import("@cleocode/core/internal");
38184
- const projectRoot = getProjectRoot75();
39002
+ const projectRoot = getProjectRoot76();
38185
39003
  const tools = createToolGuard({
38186
39004
  allowedRoots: [projectRoot],
38187
39005
  deniedCommands: DEFAULT_DETERMINISTIC_DENIED_COMMANDS,
@@ -38339,8 +39157,8 @@ var init_playbook2 = __esm({
38339
39157
  projectRoot = __playbookRuntimeOverrides.projectRoot;
38340
39158
  } else {
38341
39159
  try {
38342
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/internal");
38343
- projectRoot = getProjectRoot75();
39160
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/internal");
39161
+ projectRoot = getProjectRoot76();
38344
39162
  } catch {
38345
39163
  projectRoot = void 0;
38346
39164
  }
@@ -38405,14 +39223,14 @@ var init_playbook2 = __esm({
38405
39223
  const deterministicRunner = await buildDefaultDeterministicRunner();
38406
39224
  let result;
38407
39225
  try {
38408
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/internal");
39226
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/internal");
38409
39227
  const opts = {
38410
39228
  db,
38411
39229
  playbook: parsed.definition,
38412
39230
  playbookHash: parsed.sourceHash,
38413
39231
  initialContext,
38414
39232
  dispatcher,
38415
- projectRoot: getProjectRoot75()
39233
+ projectRoot: getProjectRoot76()
38416
39234
  };
38417
39235
  if (deterministicRunner !== void 0) opts.deterministicRunner = deterministicRunner;
38418
39236
  if (__playbookRuntimeOverrides.approvalSecret !== void 0) {
@@ -38871,16 +39689,16 @@ async function orchestrateClassify(request, context, projectRoot, taskId) {
38871
39689
  }
38872
39690
  try {
38873
39691
  const { getCleoCantWorkflowsDir } = await import("@cleocode/core/internal");
38874
- const { readFileSync: readFileSync22, readdirSync: readdirSync3, existsSync: existsSync22 } = await import("node:fs");
38875
- 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");
38876
39694
  const workflowsDir = getCleoCantWorkflowsDir();
38877
39695
  const combined = `${request} ${context ?? ""}`.toLowerCase();
38878
39696
  const matches = [];
38879
39697
  if (existsSync22(workflowsDir)) {
38880
- const files = readdirSync3(workflowsDir).filter((f) => f.endsWith(".cant"));
39698
+ const files = readdirSync4(workflowsDir).filter((f) => f.endsWith(".cant"));
38881
39699
  for (const file of files) {
38882
39700
  try {
38883
- const src = readFileSync22(join40(workflowsDir, file), "utf-8");
39701
+ const src = readFileSync23(join41(workflowsDir, file), "utf-8");
38884
39702
  const teamMatch = /^team\s+(\S+):/m.exec(src);
38885
39703
  if (!teamMatch) continue;
38886
39704
  const teamName = teamMatch[1];
@@ -38895,12 +39713,12 @@ async function orchestrateClassify(request, context, projectRoot, taskId) {
38895
39713
  }
38896
39714
  }
38897
39715
  }
38898
- const localCantDir = join40(projectRoot, CLEO_DIR_NAME2, WORKFLOWS_SUBDIR);
39716
+ const localCantDir = join41(projectRoot, CLEO_DIR_NAME2, WORKFLOWS_SUBDIR);
38899
39717
  if (existsSync22(localCantDir)) {
38900
- const files = readdirSync3(localCantDir).filter((f) => f.endsWith(".cant"));
39718
+ const files = readdirSync4(localCantDir).filter((f) => f.endsWith(".cant"));
38901
39719
  for (const file of files) {
38902
39720
  try {
38903
- const src = readFileSync22(join40(localCantDir, file), "utf-8");
39721
+ const src = readFileSync23(join41(localCantDir, file), "utf-8");
38904
39722
  const teamMatch = /^team\s+(\S+):/m.exec(src);
38905
39723
  if (!teamMatch) continue;
38906
39724
  const teamName = teamMatch[1];
@@ -45751,11 +46569,11 @@ var init_security = __esm({
45751
46569
  });
45752
46570
 
45753
46571
  // packages/cleo/src/dispatch/middleware/sanitizer.ts
45754
- function createSanitizer(getProjectRoot75) {
46572
+ function createSanitizer(getProjectRoot76) {
45755
46573
  return async (req, next) => {
45756
46574
  if (req.params) {
45757
46575
  try {
45758
- const root = getProjectRoot75 ? getProjectRoot75() : void 0;
46576
+ const root = getProjectRoot76 ? getProjectRoot76() : void 0;
45759
46577
  req.params = sanitizeParams(req.params, root, {
45760
46578
  domain: req.domain,
45761
46579
  operation: req.operation
@@ -45857,14 +46675,14 @@ var init_session_resolver = __esm({
45857
46675
  });
45858
46676
 
45859
46677
  // packages/cleo/src/dispatch/middleware/store-write-guard.ts
45860
- function createStoreWriteGuard(getProjectRoot75) {
46678
+ function createStoreWriteGuard(getProjectRoot76) {
45861
46679
  return async (req, next) => {
45862
46680
  if (req.gateway !== "mutate" || ALLOWED_WHILE_READ_ONLY.has(`${req.domain}.${req.operation}`)) {
45863
46681
  return next();
45864
46682
  }
45865
46683
  let projectRoot;
45866
46684
  try {
45867
- projectRoot = getProjectRoot75();
46685
+ projectRoot = getProjectRoot76();
45868
46686
  } catch {
45869
46687
  return next();
45870
46688
  }
@@ -47610,8 +48428,8 @@ var init_agent_outputs = __esm({
47610
48428
  });
47611
48429
 
47612
48430
  // packages/cleo/src/cli/commands/agent-profile-status.ts
47613
- function computeProfileStatus(profile, validation) {
47614
- if (profile === null) return "none";
48431
+ function computeProfileStatus(profile2, validation) {
48432
+ if (profile2 === null) return "none";
47615
48433
  if (validation === null) return "loaded (unvalidated)";
47616
48434
  if (validation.valid) return "validated";
47617
48435
  return `invalid (${validation.errors.length} errors)`;
@@ -47714,9 +48532,9 @@ var init_agent = __esm({
47714
48532
  isActive: true
47715
48533
  });
47716
48534
  const { existsSync: existsSync22, mkdirSync: mkdirSync7, writeFileSync: writeFileSync8 } = await import("node:fs");
47717
- const { join: join40 } = await import("node:path");
47718
- const cantDir = join40(CLEO_DIR_NAME3, AGENTS_SUBDIR);
47719
- 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`);
47720
48538
  let cantScaffolded = false;
47721
48539
  if (!existsSync22(cantPath)) {
47722
48540
  mkdirSync7(cantDir, { recursive: true });
@@ -47897,8 +48715,8 @@ agent ${agentId}:
47897
48715
  try {
47898
48716
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
47899
48717
  const { createRuntime } = await import("@cleocode/runtime");
47900
- const { existsSync: existsSync22, readFileSync: readFileSync22 } = await import("node:fs");
47901
- 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");
47902
48720
  await openCleoDb("project");
47903
48721
  const registry = new AgentRegistryAccessor(getProjectRoot25());
47904
48722
  const credential = await registry.get(args.agentId);
@@ -47916,16 +48734,16 @@ agent ${agentId}:
47916
48734
  process.exitCode = 1;
47917
48735
  return;
47918
48736
  }
47919
- let profile = null;
48737
+ let profile2 = null;
47920
48738
  let cantValidation = null;
47921
- 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`);
47922
48740
  if (existsSync22(cantPath)) {
47923
- profile = readFileSync22(cantPath, "utf-8");
48741
+ profile2 = readFileSync23(cantPath, "utf-8");
47924
48742
  try {
47925
48743
  const cantModule = await import("@cleocode/cant");
47926
48744
  const validate = "validate" in cantModule ? cantModule.validate : null;
47927
48745
  if (validate) {
47928
- const result = validate(profile);
48746
+ const result = validate(profile2);
47929
48747
  cantValidation = {
47930
48748
  valid: result.valid,
47931
48749
  errors: result.diagnostics?.map((d) => d.message) ?? []
@@ -47968,7 +48786,7 @@ agent ${agentId}:
47968
48786
  transport: runtime.transport.name,
47969
48787
  // Surfaced for operator visibility only — see
47970
48788
  // computeProfileStatus tsdoc for the four possible values.
47971
- profile: computeProfileStatus(profile, cantValidation),
48789
+ profile: computeProfileStatus(profile2, cantValidation),
47972
48790
  services: {
47973
48791
  poller: "running",
47974
48792
  heartbeat: runtime.heartbeat ? "running" : "disabled",
@@ -48444,7 +49262,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
48444
49262
  const { AgentRegistryAccessor } = await import("@cleocode/core/agents");
48445
49263
  const { createRuntime } = await import("@cleocode/runtime");
48446
49264
  const { existsSync: existsSync22 } = await import("node:fs");
48447
- const { join: join40 } = await import("node:path");
49265
+ const { join: join41 } = await import("node:path");
48448
49266
  await openCleoDb("project");
48449
49267
  const registry = new AgentRegistryAccessor(getProjectRoot25());
48450
49268
  const credential = await registry.get(args.agentId);
@@ -48461,7 +49279,7 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
48461
49279
  }
48462
49280
  await registry.update(args.agentId, { isActive: true });
48463
49281
  await registry.markUsed(args.agentId);
48464
- const cantPath = join40(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
49282
+ const cantPath = join41(CLEO_DIR_NAME3, AGENTS_SUBDIR, `${args.agentId}.cant`);
48465
49283
  const hasProfile = existsSync22(cantPath);
48466
49284
  const runtime = await createRuntime(registry, {
48467
49285
  agentId: args.agentId,
@@ -49412,8 +50230,8 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
49412
50230
  process.exitCode = 4;
49413
50231
  return;
49414
50232
  }
49415
- const { join: join40 } = await import("node:path");
49416
- const personaPath = join40(resolvedDir, "persona.cant");
50233
+ const { join: join41 } = await import("node:path");
50234
+ const personaPath = join41(resolvedDir, "persona.cant");
49417
50235
  if (!existsSync22(personaPath)) {
49418
50236
  cliOutput(
49419
50237
  {
@@ -49453,15 +50271,15 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
49453
50271
  return;
49454
50272
  }
49455
50273
  const archiveStats = statSync3(archivePath);
49456
- const { readdirSync: readdirSync3 } = await import("node:fs");
50274
+ const { readdirSync: readdirSync4 } = await import("node:fs");
49457
50275
  let fileCount = 0;
49458
50276
  const countFiles = (dirPath) => {
49459
- const entries = readdirSync3(dirPath, { withFileTypes: true });
50277
+ const entries = readdirSync4(dirPath, { withFileTypes: true });
49460
50278
  for (const entry of entries) {
49461
50279
  if (entry.isFile()) {
49462
50280
  fileCount++;
49463
50281
  } else if (entry.isDirectory()) {
49464
- countFiles(join40(dirPath, entry.name));
50282
+ countFiles(join41(dirPath, entry.name));
49465
50283
  }
49466
50284
  }
49467
50285
  };
@@ -49709,17 +50527,17 @@ Task ${args.taskId} reassigned to you by ${active.agentId}. Run: cleo show ${arg
49709
50527
  },
49710
50528
  async run({ args }) {
49711
50529
  try {
49712
- const { existsSync: existsSync22, readFileSync: readFileSync22, mkdirSync: mkdirSync7 } = await import("node:fs");
49713
- 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");
49714
50532
  const specPath = resolve13(args.spec);
49715
50533
  if (!existsSync22(specPath)) {
49716
50534
  cliError(`spec file not found: ${specPath}`, 4, { name: "E_NOT_FOUND" });
49717
50535
  process.exitCode = 4;
49718
50536
  return;
49719
50537
  }
49720
- const specContent = readFileSync22(specPath, "utf-8");
50538
+ const specContent = readFileSync23(specPath, "utf-8");
49721
50539
  const projectRoot = getProjectRoot25();
49722
- 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");
49723
50541
  mkdirSync7(outputDir, { recursive: true });
49724
50542
  if (args["dry-run"]) {
49725
50543
  cliOutput(
@@ -50647,15 +51465,24 @@ function nexusApiUrlArg(args) {
50647
51465
  function failNexus(err, operation) {
50648
51466
  const code = err instanceof Error && "code" in err && typeof err.code === "string" ? err.code : void 0;
50649
51467
  const fix = err instanceof Error && "fix" in err && typeof err.fix === "string" ? err.fix : void 0;
50650
- const exitCode = code === "E_NEXUS_INVALID_API_URL" || code === "E_NEXUS_INVALID_LABEL" || code === "E_NEXUS_DEVICE_REQUIRED" ? 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;
51469
+ const details = err instanceof Error && "publicDetails" in err && typeof err.publicDetails === "object" && err.publicDetails ? err.publicDetails : void 0;
50651
51470
  cliError(
50652
51471
  err instanceof Error ? err.message : String(err),
50653
51472
  exitCode,
50654
- { name: code ?? "E_NEXUS_REQUEST_FAILED", ...fix ? { fix } : {} },
51473
+ {
51474
+ name: code ?? "E_NEXUS_REQUEST_FAILED",
51475
+ ...fix ? { fix } : {},
51476
+ ...details ? { details } : {}
51477
+ },
50655
51478
  { operation }
50656
51479
  );
50657
51480
  process.exit(exitCode);
50658
51481
  }
51482
+ function writeNexusWarnings(warnings) {
51483
+ for (const warning of warnings) process.stderr.write(`warning: ${warning}
51484
+ `);
51485
+ }
50659
51486
  function emitNexusResult(data, summary, command, operation) {
50660
51487
  if (isHumanOutput()) humanLine(summary);
50661
51488
  else cliOutput(data, { command, operation });
@@ -50670,9 +51497,11 @@ async function runNexusLogin(args, openBrowser2) {
50670
51497
  "@cleocode/core/cloud/nexus-device.js"
50671
51498
  );
50672
51499
  const noBrowser = negatedFlag(args, "browser");
51500
+ let codeShown = false;
50673
51501
  const hooks2 = {
50674
51502
  apiUrl: nexusApiUrlArg(args),
50675
51503
  onCode: (code) => {
51504
+ codeShown = true;
50676
51505
  writeDeviceCodePrompt(code, SERVICE_NAME);
50677
51506
  if (!noBrowser) openBrowser2(code.verificationUriComplete ?? code.verificationUri);
50678
51507
  },
@@ -50687,7 +51516,7 @@ async function runNexusLogin(args, openBrowser2) {
50687
51516
  ),
50688
51517
  {
50689
51518
  code: "E_NEXUS_DEVICE_REQUIRED",
50690
- fix: "set CLEO_NEXUS_DEVICE=1 to enrol a read-only device, or log in without --read-only"
51519
+ fix: "unset CLEO_NEXUS_DEVICE (=0 turns device credentials off) to enrol a read-only device, or log in without --read-only"
50691
51520
  }
50692
51521
  );
50693
51522
  }
@@ -50703,15 +51532,43 @@ async function runNexusLogin(args, openBrowser2) {
50703
51532
  readOnly,
50704
51533
  ...name !== void 0 ? { name } : {}
50705
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
+ }
50706
51553
  } else {
50707
51554
  if (name !== void 0) {
50708
51555
  process.stderr.write(
50709
- "warning: --name needs device credentials (CLEO_NEXUS_DEVICE=1); ignored\n"
51556
+ "warning: --name needs device credentials, which CLEO_NEXUS_DEVICE=0 turns off; ignored\n"
51557
+ );
51558
+ }
51559
+ const { NEXUS_TEST_BEARER_ENV, W_NEXUS_TEST_BEARER_IGNORED } = await import(
51560
+ /* webpackIgnore: true */
51561
+ "@cleocode/core/cloud/nexus-enrol.js"
51562
+ );
51563
+ if ((process.env[NEXUS_TEST_BEARER_ENV]?.trim() ?? "") !== "") {
51564
+ process.stderr.write(
51565
+ `warning: ${W_NEXUS_TEST_BEARER_IGNORED}: ${NEXUS_TEST_BEARER_ENV} needs device credentials, which CLEO_NEXUS_DEVICE turns off; ignored
51566
+ `
50710
51567
  );
50711
51568
  }
50712
51569
  result = await loginToNexus(hooks2);
50713
51570
  }
50714
- writeDeviceCodeApproved(SERVICE_NAME);
51571
+ if (codeShown) writeDeviceCodeApproved(SERVICE_NAME);
50715
51572
  for (const warning of result.warnings) process.stderr.write(`warning: ${warning}
50716
51573
  `);
50717
51574
  return result;
@@ -50721,15 +51578,51 @@ async function runNexusLogin(args, openBrowser2) {
50721
51578
  }
50722
51579
  }
50723
51580
  function nexusLoginSummary(r) {
50724
- const who = r.user?.email ?? "your account";
51581
+ const who2 = r.user?.email ?? "your account";
50725
51582
  const org = r.organization ? ` (${r.organization.name})` : "";
50726
51583
  const device = r.device ? ` This machine is device ${r.device.deviceId}${r.device.name ? ` (${r.device.name})` : ""}, profile ${r.device.profile ?? "unknown"}.` : "";
50727
- return `Signed in to ${r.apiUrl} as ${who}${org}.${device}`;
51584
+ return `Signed in to ${r.apiUrl} as ${who2}${org}.${device}`;
51585
+ }
51586
+ function nexusDeviceLogoutSummary(r) {
51587
+ const count = (o) => r.devices.filter((d) => d.outcome === o).length;
51588
+ const confirmed = count("confirmed");
51589
+ const open2 = r.devices.length - confirmed;
51590
+ const what = r.action === "revoke" ? "Revoke" : "Sign-out";
51591
+ if (r.devices.length === 0 && r.session === null) {
51592
+ return r.warnings.length > 0 ? `${what} on ${r.apiUrl}: nothing was sent (see warnings).` : `Not signed in to ${r.apiUrl}; nothing to do.`;
51593
+ }
51594
+ const parts = [];
51595
+ if (r.devices.length > 0)
51596
+ parts.push(`${confirmed} of ${r.devices.length} device request(s) confirmed`);
51597
+ if (open2 > 0) parts.push(`${open2} NOT confirmed (see warnings)`);
51598
+ if (r.session !== null) parts.push(`9.24 session ${r.session.revocation}`);
51599
+ const notConfirmed = open2 > 0 || r.devices.length > 0 && confirmed === 0 || r.session?.revocation === "failed";
51600
+ const lead = notConfirmed ? `${what} NOT fully confirmed on` : `${what} confirmed on`;
51601
+ return `${lead} ${r.apiUrl}: ${parts.join("; ")}.`;
51602
+ }
51603
+ async function runNexusDeviceLogout(args) {
51604
+ let result;
51605
+ try {
51606
+ const { logoutNexusDevice } = await import(
51607
+ /* webpackIgnore: true */
51608
+ "@cleocode/core/cloud/nexus-logout.js"
51609
+ );
51610
+ result = await logoutNexusDevice({
51611
+ apiUrl: nexusApiUrlArg(args),
51612
+ revoke: args["revoke"] === true
51613
+ });
51614
+ } catch (err) {
51615
+ failNexus(err, "logout.run");
51616
+ }
51617
+ for (const warning of result.warnings) process.stderr.write(`warning: ${warning}
51618
+ `);
51619
+ emitNexusResult(result, nexusDeviceLogoutSummary(result), "logout", "logout.run");
50728
51620
  }
50729
- var SERVICE_NAME, NEXUS_API_URL_ARG;
51621
+ var SERVICE_NAME, NEXUS_API_URL_ARG, VAULT_REFUSAL_EXIT_CODES;
50730
51622
  var init_nexus_account_cli = __esm({
50731
51623
  "packages/cleo/src/cli/lib/nexus-account-cli.ts"() {
50732
51624
  "use strict";
51625
+ init_src2();
50733
51626
  init_renderers();
50734
51627
  init_device_code_prompt();
50735
51628
  init_negated_flag();
@@ -50738,6 +51631,14 @@ var init_nexus_account_cli = __esm({
50738
51631
  type: "string",
50739
51632
  description: "Cleo Nexus API URL (default: $CLEO_NEXUS_API_URL, else https://api.cleocode.dev; staging: https://api.staging.cleocode.dev)."
50740
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
+ };
50741
51642
  }
50742
51643
  });
50743
51644
 
@@ -51071,13 +51972,13 @@ function _errorResult(code, message, meta) {
51071
51972
  }
51072
51973
  async function runLlmLogin(provider, opts) {
51073
51974
  const meta = { operation: "llm.login", timestamp: (/* @__PURE__ */ new Date()).toISOString() };
51074
- const profile = await getProviderProfile(provider);
51075
- const oauthMode = profile?.oauth?.mode;
51975
+ const profile2 = await getProviderProfile(provider);
51976
+ const oauthMode = profile2?.oauth?.mode;
51076
51977
  if (provider === "kimi-code" || oauthMode === "device-code") {
51077
51978
  return _runKimiCodeLogin(opts, meta);
51078
51979
  }
51079
51980
  if (oauthMode === "pkce") {
51080
- return _runPkceLogin(profile.name, profile.oauth, opts, meta);
51981
+ return _runPkceLogin(profile2.name, profile2.oauth, opts, meta);
51081
51982
  }
51082
51983
  return _errorResult(
51083
51984
  "E_NOT_IMPLEMENTED",
@@ -51615,11 +52516,11 @@ var init_login = __esm({
51615
52516
  },
51616
52517
  "read-only": {
51617
52518
  type: "boolean",
51618
- description: "nexus with CLEO_NEXUS_DEVICE=1: enrol this machine with the read-only device profile (account, devices and project reads only). Refused without CLEO_NEXUS_DEVICE=1."
52519
+ description: "nexus: enrol this machine with the read-only device profile (account, devices and project reads only). Refused with CLEO_NEXUS_DEVICE=0."
51619
52520
  },
51620
52521
  name: {
51621
52522
  type: "string",
51622
- description: "nexus with CLEO_NEXUS_DEVICE=1: device name shown on cleocode.dev (default: OS, arch and a short id; never the hostname)."
52523
+ description: "nexus: device name shown on cleocode.dev (default: OS, arch and a short id; never the hostname). Ignored with CLEO_NEXUS_DEVICE=0."
51623
52524
  },
51624
52525
  auth: {
51625
52526
  type: "string",
@@ -52925,14 +53826,14 @@ var init_backup = __esm({
52925
53826
  return;
52926
53827
  }
52927
53828
  const { exportPortableBundle, PortableBundleError } = await import("@cleocode/core/store/portable-bundle.js");
52928
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
53829
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
52929
53830
  const passphrase = args.encrypt === true ? await resolvePassphrase() : void 0;
52930
53831
  if (args.encrypt === true && passphrase === void 0) return;
52931
53832
  const encSuffix = args.encrypt === true ? "enc." : "";
52932
53833
  try {
52933
53834
  const result = await exportPortableBundle({
52934
53835
  scope,
52935
- projectRoot: scope === "project" || scope === "all" ? getProjectRoot75() : void 0,
53836
+ projectRoot: scope === "project" || scope === "all" ? getProjectRoot76() : void 0,
52936
53837
  outputPath: args.out ?? `./${args.name}.${encSuffix}cleobundle.tar.gz`,
52937
53838
  encrypt: args.encrypt === true,
52938
53839
  passphrase,
@@ -52989,12 +53890,12 @@ var init_backup = __esm({
52989
53890
  );
52990
53891
  return;
52991
53892
  }
52992
- const { getProjectRoot: getProjectRoot75, getCleoHome: getCleoHome8, getCleoVersion } = await import("@cleocode/core");
53893
+ const { getProjectRoot: getProjectRoot76, getCleoHome: getCleoHome8, getCleoVersion } = await import("@cleocode/core");
52993
53894
  const { BundleError, cleanupStaging, unpackBundle } = await import("@cleocode/core/store/backup-unpack.js");
52994
53895
  const { regenerateConfigJson, regenerateProjectContextJson, regenerateProjectInfoJson } = await import("@cleocode/core/store/regenerators.js");
52995
53896
  const { regenerateAndCompare } = await import("@cleocode/core/store/restore-json-merge.js");
52996
53897
  const { buildConflictReport, writeConflictReport } = await import("@cleocode/core/store/restore-conflict-report.js");
52997
- const projectRoot = getProjectRoot75();
53898
+ const projectRoot = getProjectRoot76();
52998
53899
  const { assertOwnerStoreRewriteConfirmed } = await import("@cleocode/core/store/worktree-isolation-guard.js");
52999
53900
  try {
53000
53901
  assertOwnerStoreRewriteConfirmed("backup import", path2.join(projectRoot, ".cleo"), {
@@ -54887,7 +55788,7 @@ var init_check3 = __esm({
54887
55788
  async run({ args }) {
54888
55789
  const { spawnSync: spawnSync2 } = await import("node:child_process");
54889
55790
  const { existsSync: existsSync22 } = await import("node:fs");
54890
- const { join: join40, resolve: resolve13 } = await import("node:path");
55791
+ const { join: join41, resolve: resolve13 } = await import("node:path");
54891
55792
  const strict = Boolean(args.strict);
54892
55793
  const jsonOnly = Boolean(args.json);
54893
55794
  const repoRoot = resolve13(process.cwd());
@@ -55195,13 +56096,48 @@ var init_check3 = __esm({
55195
56096
  task: "T12663",
55196
56097
  script: "scripts/lint-model-call-sites.mjs",
55197
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)"
55198
56134
  }
55199
56135
  ];
55200
56136
  const scriptArgs = strict ? ["--strict"] : ["--check"];
55201
56137
  const results = [];
55202
56138
  let anyFailed = false;
55203
56139
  for (const gate of gates) {
55204
- const scriptPath = join40(repoRoot, gate.script);
56140
+ const scriptPath = join41(repoRoot, gate.script);
55205
56141
  if (!existsSync22(scriptPath)) {
55206
56142
  results.push({
55207
56143
  id: gate.id,
@@ -55639,6 +56575,531 @@ var init_classify = __esm({
55639
56575
  }
55640
56576
  });
55641
56577
 
56578
+ // packages/cleo/src/cli/lib/nexus-cloud-cli.ts
56579
+ function stringArg(args, name) {
56580
+ const raw = args[name];
56581
+ return typeof raw === "string" && raw !== "" ? raw : void 0;
56582
+ }
56583
+ function writeWarnings(warnings) {
56584
+ for (const w of warnings) process.stderr.write(`warning: ${w.message} (${w.code})
56585
+ `);
56586
+ }
56587
+ function deviceStateArg(args) {
56588
+ const raw = stringArg(args, "state");
56589
+ if (raw === void 0) return void 0;
56590
+ const known = NEXUS_DEVICE_LIST_STATES.find((s) => s === raw);
56591
+ if (known !== void 0) return known;
56592
+ throw Object.assign(new Error(`unknown --state '${raw}'`), {
56593
+ code: "E_VALIDATION",
56594
+ fix: `use one of: ${NEXUS_DEVICE_LIST_STATES.join(", ")}`
56595
+ });
56596
+ }
56597
+ function cloudStatusSummary(r) {
56598
+ if (r.verdict === "not-signed-in") {
56599
+ return `Cloud status: not signed in to ${r.local.apiUrl}. Run \`cleo login nexus\`.`;
56600
+ }
56601
+ const s = r.summary;
56602
+ const parts = [`device ${r.local.nexusDeviceId ?? "unknown"} (${s.profile ?? "no profile"})`];
56603
+ if (r.local.projectId !== null) {
56604
+ parts.push(`project ${r.local.projectId} ${s.linked ? "linked" : "NOT linked"}`);
56605
+ parts.push(s.replicaAttached ? "replica attached" : "replica NOT attached");
56606
+ parts.push(`${s.devices} device(s)`);
56607
+ if (s.headSeq !== null) parts.push(`head ${s.headSeq}`);
56608
+ if (s.openConflicts !== null) parts.push(`${s.openConflicts} open conflict(s)`);
56609
+ }
56610
+ return `Cloud status: ${r.verdict}. ${parts.join("; ")}.`;
56611
+ }
56612
+ async function runCloudRead(operation, call, summary) {
56613
+ let result;
56614
+ try {
56615
+ result = await call();
56616
+ } catch (err) {
56617
+ const { NexusCloudOfflineError } = await import(
56618
+ /* webpackIgnore: true */
56619
+ "@cleocode/core/cloud/nexus-cloud-status.js"
56620
+ );
56621
+ if (err instanceof NexusCloudOfflineError) writeWarnings(err.publicDetails.warnings);
56622
+ failNexus(err, operation);
56623
+ }
56624
+ writeWarnings(result.warnings);
56625
+ emitNexusResult(result, summary(result), "cloud", operation);
56626
+ }
56627
+ async function runCloudStatus(args) {
56628
+ await runCloudRead(
56629
+ "cloud.status",
56630
+ async () => {
56631
+ const { getNexusCloudStatus } = await import(
56632
+ /* webpackIgnore: true */
56633
+ "@cleocode/core/cloud/nexus-cloud-status.js"
56634
+ );
56635
+ const projectId = stringArg(args, "project");
56636
+ return getNexusCloudStatus({
56637
+ apiUrl: nexusApiUrlArg(args),
56638
+ ...projectId !== void 0 ? { projectId } : {}
56639
+ });
56640
+ },
56641
+ cloudStatusSummary
56642
+ );
56643
+ }
56644
+ async function runCloudWhoami(args) {
56645
+ await runCloudRead(
56646
+ "cloud.whoami",
56647
+ async () => {
56648
+ const { nexusCloudWhoami } = await import(
56649
+ /* webpackIgnore: true */
56650
+ "@cleocode/core/cloud/nexus-cloud.js"
56651
+ );
56652
+ return nexusCloudWhoami({ apiUrl: nexusApiUrlArg(args) });
56653
+ },
56654
+ (r) => `Signed in to ${r.apiUrl} as ${r.user.email} with a ${r.credential.kind} credential${r.device ? ` (device ${r.device.deviceId}, profile ${r.credential.profile ?? "none"})` : ""}.`
56655
+ );
56656
+ }
56657
+ async function runCloudDevices(args) {
56658
+ await runCloudRead(
56659
+ "cloud.devices.list",
56660
+ async () => {
56661
+ const state = deviceStateArg(args);
56662
+ const { listNexusCloudDevices } = await import(
56663
+ /* webpackIgnore: true */
56664
+ "@cleocode/core/cloud/nexus-cloud.js"
56665
+ );
56666
+ return listNexusCloudDevices({
56667
+ apiUrl: nexusApiUrlArg(args),
56668
+ ...state !== void 0 ? { state } : {}
56669
+ });
56670
+ },
56671
+ (r) => `${r.count} device(s) on ${r.apiUrl}${r.state ? ` (state ${r.state})` : ""}: ${r.devices.map((d) => `${d.name} ${d.deviceId} ${d.state}${d.current ? " (this machine)" : ""}`).join("; ")}`
56672
+ );
56673
+ }
56674
+ async function runCloudProjects(args) {
56675
+ const action = stringArg(args, "action");
56676
+ if (action === "show") {
56677
+ await runCloudRead(
56678
+ "cloud.projects.show",
56679
+ async () => {
56680
+ const projectId = stringArg(args, "id");
56681
+ const { showNexusCloudProject } = await import(
56682
+ /* webpackIgnore: true */
56683
+ "@cleocode/core/cloud/nexus-cloud.js"
56684
+ );
56685
+ return showNexusCloudProject({
56686
+ apiUrl: nexusApiUrlArg(args),
56687
+ ...projectId !== void 0 ? { projectId } : {}
56688
+ });
56689
+ },
56690
+ (r) => `Project ${r.projectId} "${r.project.label ?? ""}" (${r.role}): ${r.devices.active} active device(s), ${r.replicas.length} replica(s), head ${r.stream?.headSeq ?? "none"}, ${r.openConflicts} open conflict(s).`
56691
+ );
56692
+ return;
56693
+ }
56694
+ if (action !== void 0 && action !== "list") {
56695
+ failNexus(
56696
+ Object.assign(new Error(`unknown action '${action}'`), {
56697
+ code: "E_VALIDATION",
56698
+ fix: "use `cleo cloud projects` or `cleo cloud projects show [<id>]`"
56699
+ }),
56700
+ "cloud.projects.list"
56701
+ );
56702
+ }
56703
+ await runCloudRead(
56704
+ "cloud.projects.list",
56705
+ async () => {
56706
+ const organizationId = stringArg(args, "org");
56707
+ const { listNexusCloudProjects } = await import(
56708
+ /* webpackIgnore: true */
56709
+ "@cleocode/core/cloud/nexus-cloud.js"
56710
+ );
56711
+ return listNexusCloudProjects({
56712
+ apiUrl: nexusApiUrlArg(args),
56713
+ ...organizationId !== void 0 ? { organizationId } : {}
56714
+ });
56715
+ },
56716
+ (r) => `${r.count} project(s) on ${r.apiUrl}: ${r.projects.map((p) => `${p.label ?? p.projectId} (${p.role})`).join("; ")}`
56717
+ );
56718
+ }
56719
+ var init_nexus_cloud_cli = __esm({
56720
+ "packages/cleo/src/cli/lib/nexus-cloud-cli.ts"() {
56721
+ "use strict";
56722
+ init_src2();
56723
+ init_nexus_account_cli();
56724
+ }
56725
+ });
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
+
56878
+ // packages/cleo/src/cli/commands/cloud.ts
56879
+ var cloud_exports = {};
56880
+ __export(cloud_exports, {
56881
+ cloudCommand: () => cloudCommand
56882
+ });
56883
+ var JSON_ARG, SCOPE_ARG, statusSubCommand, whoamiSubCommand, devicesSubCommand, projectsSubCommand, pushSubCommand, pullSubCommand, restoreSubCommand, verifyVaultSubCommand, vaultSubCommand, leaseSubCommand, activitySubCommand, cloudCommand;
56884
+ var init_cloud = __esm({
56885
+ "packages/cleo/src/cli/commands/cloud.ts"() {
56886
+ "use strict";
56887
+ init_src2();
56888
+ init_define_cli_command();
56889
+ init_nexus_account_cli();
56890
+ init_nexus_cloud_cli();
56891
+ init_nexus_vault_cli();
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
+ };
56897
+ statusSubCommand = defineCommand({
56898
+ meta: {
56899
+ name: "status",
56900
+ description: "Verify this machine against Cleo Nexus in one call: device, credential, project link, replica and stream. Returns { verdict, summary, local, remote, warnings }; verdict is ok, attention, not-linked, not-registered or not-signed-in. Reads only (GET; never binds a replica), except that getting the credential may upgrade a 9.24 session (E1) and retry unsettled logouts (E9/E10)."
56901
+ },
56902
+ args: {
56903
+ project: {
56904
+ type: "string",
56905
+ description: "Project id to check (default: the current project)."
56906
+ },
56907
+ "api-url": NEXUS_API_URL_ARG,
56908
+ json: JSON_ARG
56909
+ },
56910
+ async run({ args }) {
56911
+ await runCloudStatus(args);
56912
+ }
56913
+ });
56914
+ whoamiSubCommand = defineCommand({
56915
+ meta: {
56916
+ name: "whoami",
56917
+ description: "Show the Cleo Nexus user, organizations, credential and device for this machine."
56918
+ },
56919
+ args: { "api-url": NEXUS_API_URL_ARG, json: JSON_ARG },
56920
+ async run({ args }) {
56921
+ await runCloudWhoami(args);
56922
+ }
56923
+ });
56924
+ devicesSubCommand = defineCommand({
56925
+ meta: {
56926
+ name: "devices",
56927
+ description: "List the account's devices (newest first), following every page; reports truncation."
56928
+ },
56929
+ args: {
56930
+ state: {
56931
+ type: "string",
56932
+ description: `Filter: ${NEXUS_DEVICE_LIST_STATES.join(", ")} (default: active).`
56933
+ },
56934
+ "api-url": NEXUS_API_URL_ARG,
56935
+ json: JSON_ARG
56936
+ },
56937
+ async run({ args }) {
56938
+ await runCloudDevices(args);
56939
+ }
56940
+ });
56941
+ projectsSubCommand = defineCommand({
56942
+ meta: {
56943
+ name: "projects",
56944
+ description: "List visible Cleo Nexus projects, following every page (cleo cloud projects [--org <id>]), or show one with its replicas and device counts (cleo cloud projects show [<id>], default: the current project)."
56945
+ },
56946
+ args: {
56947
+ action: {
56948
+ type: "positional",
56949
+ description: "'list' (default) or 'show'.",
56950
+ required: false
56951
+ },
56952
+ id: {
56953
+ type: "positional",
56954
+ description: "Project id for show (default: the current project).",
56955
+ required: false
56956
+ },
56957
+ org: { type: "string", description: "Only this organization id (list)." },
56958
+ "api-url": NEXUS_API_URL_ARG,
56959
+ json: JSON_ARG
56960
+ },
56961
+ async run({ args }) {
56962
+ await runCloudProjects(args);
56963
+ }
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
+ });
57081
+ cloudCommand = defineCommand({
57082
+ meta: {
57083
+ name: "cloud",
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."
57085
+ },
57086
+ subCommands: {
57087
+ status: statusSubCommand,
57088
+ whoami: whoamiSubCommand,
57089
+ devices: devicesSubCommand,
57090
+ projects: projectsSubCommand,
57091
+ activity: activitySubCommand,
57092
+ push: pushSubCommand,
57093
+ pull: pullSubCommand,
57094
+ restore: restoreSubCommand,
57095
+ verify: verifyVaultSubCommand,
57096
+ vault: vaultSubCommand,
57097
+ lease: leaseSubCommand
57098
+ }
57099
+ });
57100
+ }
57101
+ });
57102
+
55642
57103
  // packages/cleo/src/cli/commands/code.ts
55643
57104
  var code_exports = {};
55644
57105
  __export(code_exports, {
@@ -55686,9 +57147,9 @@ var init_code = __esm({
55686
57147
  async run({ args }) {
55687
57148
  await requireTreeSitter();
55688
57149
  const { smartOutline } = await import("@cleocode/core/internal");
55689
- const { join: join40 } = await import("node:path");
57150
+ const { join: join41 } = await import("node:path");
55690
57151
  const root = process.cwd();
55691
- const absPath = args.file.startsWith("/") ? args.file : join40(root, args.file);
57152
+ const absPath = args.file.startsWith("/") ? args.file : join41(root, args.file);
55692
57153
  const result = smartOutline(absPath, root);
55693
57154
  if (result.errors.length > 0 && result.symbols.length === 0) {
55694
57155
  cliError(result.errors.join(", "), 1, { name: "E_OUTLINE_FAILED" });
@@ -55779,9 +57240,9 @@ var init_code = __esm({
55779
57240
  async run({ args }) {
55780
57241
  await requireTreeSitter();
55781
57242
  const { smartUnfold } = await import("@cleocode/core/internal");
55782
- const { join: join40 } = await import("node:path");
57243
+ const { join: join41 } = await import("node:path");
55783
57244
  const root = process.cwd();
55784
- const absPath = args.file.startsWith("/") ? args.file : join40(root, args.file);
57245
+ const absPath = args.file.startsWith("/") ? args.file : join41(root, args.file);
55785
57246
  const result = smartUnfold(absPath, args.symbol, root);
55786
57247
  if (!result.found) {
55787
57248
  const errs = result.errors.length > 0 ? `: ${result.errors.join(", ")}` : "";
@@ -63770,15 +65231,15 @@ var init_doctor_fk_check = __esm({
63770
65231
  }
63771
65232
  },
63772
65233
  async run({ args }) {
63773
- const scopeArg = args.scope;
63774
- if (scopeArg !== void 0 && scopeArg !== "project" && scopeArg !== "global") {
63775
- 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", {
63776
65237
  fix: "Run 'cleo doctor fk-check --scope project' or omit --scope to check both."
63777
65238
  });
63778
65239
  process.exitCode = 6;
63779
65240
  return;
63780
65241
  }
63781
- const scopeOpt = scopeArg ? { scopes: [scopeArg] } : {};
65242
+ const scopeOpt = scopeArg2 ? { scopes: [scopeArg2] } : {};
63782
65243
  if (args.fix === true) {
63783
65244
  const fixReport = await repairForeignKeyViolations({ cwd: process.cwd(), ...scopeOpt });
63784
65245
  humanInfo(
@@ -64195,12 +65656,44 @@ var init_doctor_memory_guard = __esm({
64195
65656
  }
64196
65657
  });
64197
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
+
64198
65691
  // packages/cleo/src/cli/commands/doctor-nexus-residency.ts
64199
65692
  var doctor_nexus_residency_exports = {};
64200
65693
  __export(doctor_nexus_residency_exports, {
64201
65694
  doctorNexusResidencyCommand: () => doctorNexusResidencyCommand
64202
65695
  });
64203
- import { getCleoHome as getCleoHome6, getProjectRoot as getProjectRoot49 } from "@cleocode/core";
65696
+ import { getCleoHome as getCleoHome6, getProjectRoot as getProjectRoot50 } from "@cleocode/core";
64204
65697
  import { scanNexusSchemaResidency } from "@cleocode/core/doctor/nexus-schema-residency.js";
64205
65698
  var doctorNexusResidencyCommand;
64206
65699
  var init_doctor_nexus_residency = __esm({
@@ -64219,7 +65712,7 @@ var init_doctor_nexus_residency = __esm({
64219
65712
  quiet: { type: "boolean", description: "Suppress non-essential output" }
64220
65713
  },
64221
65714
  async run() {
64222
- const result = scanNexusSchemaResidency(getProjectRoot49(), getCleoHome6());
65715
+ const result = scanNexusSchemaResidency(getProjectRoot50(), getCleoHome6());
64223
65716
  cliOutput(result, {
64224
65717
  command: "doctor",
64225
65718
  operation: "doctor.nexus-residency.run"
@@ -64237,7 +65730,7 @@ var doctor_project_identity_exports = {};
64237
65730
  __export(doctor_project_identity_exports, {
64238
65731
  doctorProjectIdentityCommand: () => doctorProjectIdentityCommand
64239
65732
  });
64240
- import { getProjectRoot as getProjectRoot50 } from "@cleocode/core";
65733
+ import { getProjectRoot as getProjectRoot51 } from "@cleocode/core";
64241
65734
  import {
64242
65735
  inspectProjectIdentity,
64243
65736
  inspectProjectNameDrift,
@@ -64262,7 +65755,7 @@ var init_doctor_project_identity = __esm({
64262
65755
  quiet: { type: "boolean", description: "Suppress non-essential output" }
64263
65756
  },
64264
65757
  async run({ args }) {
64265
- const projectRoot = getProjectRoot50();
65758
+ const projectRoot = getProjectRoot51();
64266
65759
  if (!args.resolve) {
64267
65760
  const report = inspectProjectIdentity(projectRoot);
64268
65761
  const nameDrift = await inspectProjectNameDrift(projectRoot);
@@ -64801,7 +66294,7 @@ var doctor_repair_exports = {};
64801
66294
  __export(doctor_repair_exports, {
64802
66295
  doctorRepairCommand: () => doctorRepairCommand
64803
66296
  });
64804
- import { getLogger as getLogger21, getProjectRoot as getProjectRoot51 } from "@cleocode/core";
66297
+ import { getLogger as getLogger21, getProjectRoot as getProjectRoot52 } from "@cleocode/core";
64805
66298
  import { repairMalformedDbs } from "@cleocode/core/store/repair-malformed-dbs.js";
64806
66299
  var doctorRepairCommand;
64807
66300
  var init_doctor_repair = __esm({
@@ -64850,7 +66343,7 @@ var init_doctor_repair = __esm({
64850
66343
  return;
64851
66344
  }
64852
66345
  const result = repairMalformedDbs({
64853
- projectRoot: getProjectRoot51(),
66346
+ projectRoot: getProjectRoot52(),
64854
66347
  roles: roleArg.length > 0 ? [roleArg] : void 0,
64855
66348
  dryRun,
64856
66349
  logger: getLogger21("doctor-repair"),
@@ -65052,7 +66545,7 @@ var doctor_superseded_store_exports = {};
65052
66545
  __export(doctor_superseded_store_exports, {
65053
66546
  doctorSupersededStoreCommand: () => doctorSupersededStoreCommand
65054
66547
  });
65055
- import { getProjectRoot as getProjectRoot52 } from "@cleocode/core";
66548
+ import { getProjectRoot as getProjectRoot53 } from "@cleocode/core";
65056
66549
  import { scanSupersededStores } from "@cleocode/core/doctor/superseded-store.js";
65057
66550
  import { reconcileSupersededStores } from "@cleocode/core/store/exodus/index.js";
65058
66551
  var doctorSupersededStoreCommand;
@@ -65085,7 +66578,7 @@ var init_doctor_superseded_store = __esm({
65085
66578
  },
65086
66579
  async run({ args }) {
65087
66580
  if (args.reconcile === true) {
65088
- const receipt = await reconcileSupersededStores(getProjectRoot52(), {
66581
+ const receipt = await reconcileSupersededStores(getProjectRoot53(), {
65089
66582
  dryRun: args["dry-run"] === true,
65090
66583
  additive: args.additive === true
65091
66584
  });
@@ -65107,7 +66600,7 @@ var init_doctor_superseded_store = __esm({
65107
66600
  );
65108
66601
  return;
65109
66602
  }
65110
- const result = scanSupersededStores(getProjectRoot52());
66603
+ const result = scanSupersededStores(getProjectRoot53());
65111
66604
  cliOutput(result, {
65112
66605
  command: "doctor",
65113
66606
  operation: "doctor.superseded-store.run"
@@ -65208,7 +66701,7 @@ import {
65208
66701
  rollbackTwinCollapse
65209
66702
  } from "@cleocode/core/doctor/twin-collapse.js";
65210
66703
  import { CleoError as CleoError8 } from "@cleocode/core/errors";
65211
- import { getProjectRoot as getProjectRoot53 } from "@cleocode/core/paths.js";
66704
+ import { getProjectRoot as getProjectRoot54 } from "@cleocode/core/paths.js";
65212
66705
  function reportTwinCollapseError(error, retry) {
65213
66706
  if (retry && !(error instanceof CleoError8)) throw error;
65214
66707
  const message = error instanceof Error ? error.message : String(error);
@@ -65279,7 +66772,7 @@ var init_doctor_twin_collapse = __esm({
65279
66772
  quiet: { type: "boolean", description: "Suppress non-essential output" }
65280
66773
  },
65281
66774
  async run({ args }) {
65282
- const projectRoot = getProjectRoot53();
66775
+ const projectRoot = getProjectRoot54();
65283
66776
  const guard = { cwd: process.cwd(), confirmOwnerStore: args["confirm-owner-store"] === true };
65284
66777
  const actions = twinCollapseActions(args);
65285
66778
  if (actions.length > 1) {
@@ -65357,7 +66850,7 @@ __export(doctor_worktree_stores_exports, {
65357
66850
  doctorWorktreeStoresCommand: () => doctorWorktreeStoresCommand
65358
66851
  });
65359
66852
  import { scanWorktreeStores } from "@cleocode/core/doctor/worktree-stores.js";
65360
- import { getProjectRoot as getProjectRoot54, resolveStoreOwnerRoot } from "@cleocode/core/paths.js";
66853
+ import { getProjectRoot as getProjectRoot55, resolveStoreOwnerRoot } from "@cleocode/core/paths.js";
65361
66854
  var doctorWorktreeStoresCommand;
65362
66855
  var init_doctor_worktree_stores = __esm({
65363
66856
  "packages/cleo/src/cli/commands/doctor-worktree-stores.ts"() {
@@ -65379,7 +66872,7 @@ var init_doctor_worktree_stores = __esm({
65379
66872
  quiet: { type: "boolean", description: "Suppress non-essential output" }
65380
66873
  },
65381
66874
  async run({ args }) {
65382
- const projectRoot = resolveStoreOwnerRoot(getProjectRoot54());
66875
+ const projectRoot = resolveStoreOwnerRoot(getProjectRoot55());
65383
66876
  const result = scanWorktreeStores(projectRoot, { skipCompare: args["skip-compare"] === true });
65384
66877
  cliOutput(result, {
65385
66878
  command: "doctor",
@@ -65531,7 +67024,7 @@ import {
65531
67024
  resumePreparedKnowledgeRepair,
65532
67025
  runKnowledgeDoctor as runKnowledgeDoctor2
65533
67026
  } from "@cleocode/core/doctor/knowledge.js";
65534
- import { getProjectRoot as getProjectRoot55 } from "@cleocode/core/paths.js";
67027
+ import { getProjectRoot as getProjectRoot56 } from "@cleocode/core/paths.js";
65535
67028
  var doctorKnowledgeSubcommand;
65536
67029
  var init_doctor_knowledge = __esm({
65537
67030
  "packages/cleo/src/cli/commands/doctor-knowledge.ts"() {
@@ -65606,7 +67099,7 @@ var init_doctor_knowledge = __esm({
65606
67099
  },
65607
67100
  async run({ args }) {
65608
67101
  const startedAt = Date.now();
65609
- const root = getProjectRoot55();
67102
+ const root = getProjectRoot56();
65610
67103
  let context;
65611
67104
  let pending;
65612
67105
  try {
@@ -65774,7 +67267,7 @@ import { join as join24 } from "node:path";
65774
67267
  import {
65775
67268
  ensureGlobalAgentRegistryDb,
65776
67269
  getGlobalAgentRegistryNativeDb,
65777
- getProjectRoot as getProjectRoot56,
67270
+ getProjectRoot as getProjectRoot57,
65778
67271
  installAgentFromCant
65779
67272
  } from "@cleocode/core/internal";
65780
67273
  function sha256Hex(bytes) {
@@ -65962,7 +67455,7 @@ var init_migrate_agents_v2 = __esm({
65962
67455
  }
65963
67456
  },
65964
67457
  async run({ args }) {
65965
- const projectRoot = getProjectRoot56();
67458
+ const projectRoot = getProjectRoot57();
65966
67459
  const verbose = args.quiet !== true;
65967
67460
  if (verbose) {
65968
67461
  humanInfo("Scanning .cleo/cant/agents/ and .cleo/agents/ for unregistered agents...");
@@ -66006,7 +67499,7 @@ __export(doctor_exports, {
66006
67499
  });
66007
67500
  import { mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "node:fs";
66008
67501
  import { join as join25 } from "node:path";
66009
- import { getProjectRoot as getProjectRoot57, pushWarning as pushWarning5 } from "@cleocode/core";
67502
+ import { getProjectRoot as getProjectRoot58, pushWarning as pushWarning5 } from "@cleocode/core";
66010
67503
  import { renderInvariantAuditLines } from "@cleocode/core/doctor/invariant-audit-render.js";
66011
67504
  import {
66012
67505
  quarantineRogueCleoDir,
@@ -66137,6 +67630,7 @@ var init_doctor = __esm({
66137
67630
  init_doctor_malformed_ids();
66138
67631
  init_doctor_manifest_rows();
66139
67632
  init_doctor_memory_guard();
67633
+ init_doctor_migrations();
66140
67634
  init_doctor_nexus_residency();
66141
67635
  init_doctor_project_identity();
66142
67636
  init_doctor_projects();
@@ -66169,6 +67663,8 @@ var init_doctor = __esm({
66169
67663
  "legacy-reaper": doctorLegacyReaperCommand,
66170
67664
  // T12128 — task ids that fail the write-path validator
66171
67665
  "malformed-ids": doctorMalformedIdsCommand,
67666
+ // T12796 — the migration journal of each store (read-only; the live journal count)
67667
+ migrations: doctorMigrationsCommand,
66172
67668
  // T12686 — manifest rows whose metadata violates the stored field contract (+ --repair/--rollback)
66173
67669
  "manifest-rows": doctorManifestRowsCommand,
66174
67670
  // T12095 — pre-dual-scope store files still on disk under their old LIVE names
@@ -66413,7 +67909,7 @@ var init_doctor = __esm({
66413
67909
  const { join: pathJoin } = await import("node:path");
66414
67910
  const { existsSync: existsSync22 } = await import("node:fs");
66415
67911
  const { detectAndHealCoreWorktreeLeak } = await import("@cleocode/worktree");
66416
- const projectRoot = getProjectRoot57();
67912
+ const projectRoot = getProjectRoot58();
66417
67913
  let gitRoot = projectRoot;
66418
67914
  try {
66419
67915
  gitRoot = execFile2("git", ["rev-parse", "--show-toplevel"], {
@@ -66465,7 +67961,7 @@ var init_doctor = __esm({
66465
67961
  }
66466
67962
  if (args.brain) {
66467
67963
  const { computeBrainHealthDashboard } = await import("@cleocode/core/memory/brain-health-dashboard.js");
66468
- const projectRoot = getProjectRoot57();
67964
+ const projectRoot = getProjectRoot58();
66469
67965
  const dashboard = await computeBrainHealthDashboard(projectRoot);
66470
67966
  cliOutput(dashboard, { command: "doctor", operation: "doctor.brain" });
66471
67967
  if (dashboard.hasP0Failure) {
@@ -66474,7 +67970,7 @@ var init_doctor = __esm({
66474
67970
  return;
66475
67971
  }
66476
67972
  if (args["scan-test-fixtures-in-prod"]) {
66477
- const projectRoot = getProjectRoot57();
67973
+ const projectRoot = getProjectRoot58();
66478
67974
  const matches = await scanTestFixturesInProd(projectRoot);
66479
67975
  const dryRun = args["dry-run"] !== false && args.quarantine !== true;
66480
67976
  const quarantined = !dryRun && matches.length > 0 ? await quarantineTestFixtures(projectRoot, matches) : void 0;
@@ -66562,7 +68058,7 @@ var init_doctor = __esm({
66562
68058
  progress.complete("Comprehensive diagnostics complete");
66563
68059
  } else if (args["scan-rogue-cleo-dirs"]) {
66564
68060
  progress.step(0, "Scanning for rogue .cleo/ directories");
66565
- const projectRoot = getProjectRoot57();
68061
+ const projectRoot = getProjectRoot58();
66566
68062
  const reports = scanRogueCleoDirs(projectRoot);
66567
68063
  progress.complete(
66568
68064
  `Found ${reports.length} rogue .cleo/ director${reports.length === 1 ? "y" : "ies"}`
@@ -66571,7 +68067,7 @@ var init_doctor = __esm({
66571
68067
  } else if (args["quarantine-rogue-cleo-dirs"]) {
66572
68068
  const isDryRun = args["dry-run"] === true;
66573
68069
  progress.step(0, `${isDryRun ? "[DRY RUN] " : ""}Scanning for rogue .cleo/ directories`);
66574
- const projectRoot = getProjectRoot57();
68070
+ const projectRoot = getProjectRoot58();
66575
68071
  const reports = scanRogueCleoDirs(projectRoot);
66576
68072
  if (reports.length === 0) {
66577
68073
  progress.complete("No rogue .cleo/ directories found \u2014 nothing to quarantine");
@@ -66625,7 +68121,7 @@ var init_doctor = __esm({
66625
68121
  const { detectAndRemoveLegacyGlobalFiles, detectAndRemoveStrayProjectNexus } = await import("@cleocode/core/store/cleanup-legacy.js");
66626
68122
  const { getCleoHome: getCleoHome8 } = await import("@cleocode/core");
66627
68123
  const cleoHome = getCleoHome8();
66628
- const projectRoot = getProjectRoot57();
68124
+ const projectRoot = getProjectRoot58();
66629
68125
  const legacyResult = detectAndRemoveLegacyGlobalFiles(cleoHome);
66630
68126
  const strayResult = detectAndRemoveStrayProjectNexus(projectRoot);
66631
68127
  const isDryRun = args["dry-run"] === true;
@@ -66658,7 +68154,7 @@ var init_doctor = __esm({
66658
68154
  } else if (args["audit-worktree-orphans"]) {
66659
68155
  progress.step(0, "Comprehensive worktree anomaly audit (T9808 / council D009)");
66660
68156
  const { auditWorktreeOrphansComprehensive, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
66661
- const projectRoot = getProjectRoot57();
68157
+ const projectRoot = getProjectRoot58();
66662
68158
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
66663
68159
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
66664
68160
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -66715,7 +68211,7 @@ var init_doctor = __esm({
66715
68211
  `${isDryRun ? "[DRY RUN] " : ""}Scanning + pruning worktree-orphan .cleo/ directories`
66716
68212
  );
66717
68213
  const { pruneWorktreeOrphans, scanWorktreeOrphansBudgeted } = await import("@cleocode/core/doctor/worktree-orphans.js");
66718
- const projectRoot = getProjectRoot57();
68214
+ const projectRoot = getProjectRoot58();
66719
68215
  const timeoutSecs = args["timeout"] !== void 0 ? Number.parseInt(String(args["timeout"]), 10) : 30;
66720
68216
  const timeoutMs = Number.isFinite(timeoutSecs) && timeoutSecs > 0 ? timeoutSecs * 1e3 : 3e4;
66721
68217
  const maxEntriesPerLevel = args["max-entries-per-level"] !== void 0 ? Number.parseInt(String(args["max-entries-per-level"]), 10) : 500;
@@ -66794,7 +68290,7 @@ var init_doctor = __esm({
66794
68290
  `${isDryRun ? "[DRY RUN] " : ""}Migrating .cleo/worktree-include \u2192 .worktreeinclude`
66795
68291
  );
66796
68292
  const { migrateWorktreeIncludeFile } = await import("@cleocode/core");
66797
- const projectRoot = getProjectRoot57();
68293
+ const projectRoot = getProjectRoot58();
66798
68294
  const result = await migrateWorktreeIncludeFile(projectRoot, { dryRun: isDryRun });
66799
68295
  progress.complete(`Migration ${result.action}`);
66800
68296
  cliOutput(result, { command: "doctor", operation: "doctor.migrate-worktree-include" });
@@ -66813,7 +68309,7 @@ var init_doctor = __esm({
66813
68309
  const stepLabel = isFocusedAlias ? "Auditing Saga hierarchy for ADR-073 invariants" : "Walking central INVARIANTS_REGISTRY";
66814
68310
  progress.step(0, stepLabel);
66815
68311
  const { auditInvariantRegistry } = await import("@cleocode/core/doctor/invariant-audit.js");
66816
- const projectRoot = getProjectRoot57();
68312
+ const projectRoot = getProjectRoot58();
66817
68313
  const result = await auditInvariantRegistry(projectRoot, { adrFilter });
66818
68314
  const operation = isFocusedAlias ? "doctor.audit-sagas" : "doctor.audit-invariants";
66819
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`;
@@ -66835,7 +68331,7 @@ var init_doctor = __esm({
66835
68331
  { command: "doctor", operation: "admin.health" }
66836
68332
  );
66837
68333
  try {
66838
- const projectRoot = getProjectRoot57();
68334
+ const projectRoot = getProjectRoot58();
66839
68335
  const conflicts = readMigrationConflicts(projectRoot);
66840
68336
  if (conflicts.length > 0) {
66841
68337
  progress.complete(
@@ -66866,7 +68362,7 @@ var init_doctor = __esm({
66866
68362
  progress.complete("Health check complete");
66867
68363
  }
66868
68364
  try {
66869
- const projectRoot = getProjectRoot57();
68365
+ const projectRoot = getProjectRoot58();
66870
68366
  const { auditSagaHierarchy } = await import("@cleocode/core/doctor/saga-audit.js");
66871
68367
  const sagaAudit = await auditSagaHierarchy(projectRoot);
66872
68368
  if (sagaAudit.sagas.length === 0) {
@@ -66895,7 +68391,7 @@ Saga Hierarchy: audit skipped (${msg})`);
66895
68391
  }
66896
68392
  try {
66897
68393
  const { scanDependencyCycles: scanDependencyCycles2 } = await import("@cleocode/core/doctor/dependency-cycles.js");
66898
- const cycles = await scanDependencyCycles2(getProjectRoot57());
68394
+ const cycles = await scanDependencyCycles2(getProjectRoot58());
66899
68395
  humanLine(
66900
68396
  `
66901
68397
  Dependency cycles: ${cycles.cycleCount} (${cycles.edgeCount} edge(s) checked)`
@@ -67006,14 +68502,14 @@ var init_done = __esm({
67006
68502
  process.exitCode = 2;
67007
68503
  return;
67008
68504
  }
67009
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/paths.js");
67010
- const options = { projectRoot: getProjectRoot75(), ...parsed.options };
68505
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core/paths.js");
68506
+ const options = { projectRoot: getProjectRoot76(), ...parsed.options };
67011
68507
  const requested = [
67012
68508
  ...new Set([args.taskId, ...args._ ?? []].map(String))
67013
68509
  ];
67014
- const invalid = requested.filter((id) => !/^T\d+$/.test(id));
67015
- if (invalid.length > 0) {
67016
- 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");
67017
68513
  process.exitCode = 2;
67018
68514
  return;
67019
68515
  }
@@ -67277,8 +68773,8 @@ var init_event = __esm({
67277
68773
  }
67278
68774
  for (const file of filesToTail) {
67279
68775
  const agentId = file.replace(".jsonl", "");
67280
- const { readFileSync: readFileSync22 } = await import("node:fs");
67281
- 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");
67282
68778
  const eventLines = content.trim().split("\n").filter(Boolean);
67283
68779
  const tail = eventLines.slice(-lines);
67284
68780
  if (jsonMode) {
@@ -67373,8 +68869,8 @@ var init_event = __esm({
67373
68869
  const printAgentLog = async (file) => {
67374
68870
  const agentId = file.replace(".jsonl", "");
67375
68871
  try {
67376
- const { readFileSync: readFileSync22 } = await import("node:fs");
67377
- 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");
67378
68874
  const eventLines = content.trim().split("\n").filter(Boolean);
67379
68875
  const tail = eventLines.slice(-lines);
67380
68876
  if (jsonMode) {
@@ -67559,7 +69055,7 @@ function showStatus() {
67559
69055
  }
67560
69056
  cliOutput(result, { command: "exodus status" });
67561
69057
  }
67562
- var migrateSubCommand, verifySubCommand, sealSubCommand, statusSubCommand, exodusCommand;
69058
+ var migrateSubCommand, verifySubCommand, sealSubCommand, statusSubCommand2, exodusCommand;
67563
69059
  var init_exodus = __esm({
67564
69060
  "packages/cleo/src/cli/commands/exodus.ts"() {
67565
69061
  "use strict";
@@ -67869,7 +69365,7 @@ Passing tables (${passing.length}):`);
67869
69365
  );
67870
69366
  }
67871
69367
  });
67872
- statusSubCommand = defineCommand({
69368
+ statusSubCommand2 = defineCommand({
67873
69369
  meta: {
67874
69370
  name: "status",
67875
69371
  description: "Show exodus migration status (staging, source DBs, target DBs)"
@@ -67887,7 +69383,7 @@ Passing tables (${passing.length}):`);
67887
69383
  migrate: migrateSubCommand,
67888
69384
  verify: verifySubCommand,
67889
69385
  seal: sealSubCommand,
67890
- status: statusSubCommand
69386
+ status: statusSubCommand2
67891
69387
  },
67892
69388
  async run({ cmd, rawArgs }) {
67893
69389
  if (isSubCommandDispatch(rawArgs, cmd.subCommands)) return;
@@ -68369,7 +69865,7 @@ __export(gateway_exports, {
68369
69865
  gatewayOpenapiSubCommand: () => gatewayOpenapiSubCommand
68370
69866
  });
68371
69867
  import { resolve as resolve8 } from "node:path";
68372
- import { generateOpenApi, getProjectRoot as getProjectRoot58 } from "@cleocode/core";
69868
+ import { generateOpenApi, getProjectRoot as getProjectRoot59 } from "@cleocode/core";
68373
69869
  var gatewayOpenapiSubCommand, gatewayCommand;
68374
69870
  var init_gateway = __esm({
68375
69871
  "packages/cleo/src/cli/commands/gateway.ts"() {
@@ -68401,7 +69897,7 @@ var init_gateway = __esm({
68401
69897
  const pathCount = Object.keys(doc.paths).length;
68402
69898
  if (typeof args.out === "string" && args.out.length > 0) {
68403
69899
  const { writeFileSync: writeFileSync8 } = await import("node:fs");
68404
- const target = resolve8(getProjectRoot58(), args.out);
69900
+ const target = resolve8(getProjectRoot59(), args.out);
68405
69901
  writeFileSync8(target, json2, "utf8");
68406
69902
  cliOutput(
68407
69903
  { out: target, pathCount, version: doc.info.version, openapi: doc.openapi },
@@ -68862,7 +70358,7 @@ var go_exports = {};
68862
70358
  __export(go_exports, {
68863
70359
  goCommand: () => goCommand
68864
70360
  });
68865
- import { getProjectRoot as getProjectRoot59, go } from "@cleocode/core";
70361
+ import { getProjectRoot as getProjectRoot60, go } from "@cleocode/core";
68866
70362
  var goCommand;
68867
70363
  var init_go = __esm({
68868
70364
  "packages/cleo/src/cli/commands/go.ts"() {
@@ -68888,7 +70384,7 @@ var init_go = __esm({
68888
70384
  }
68889
70385
  },
68890
70386
  async run({ args }) {
68891
- const projectRoot = getProjectRoot59();
70387
+ const projectRoot = getProjectRoot60();
68892
70388
  const { getCurrentSessionId, resolveBoundSessionId } = await import("@cleocode/core/internal");
68893
70389
  let sessionId = getCurrentSessionId(projectRoot) ?? void 0;
68894
70390
  if (sessionId === void 0) {
@@ -68916,7 +70412,7 @@ var goal_exports = {};
68916
70412
  __export(goal_exports, {
68917
70413
  goalCommand: () => goalCommand
68918
70414
  });
68919
- import { getProjectRoot as getProjectRoot60, goal } from "@cleocode/core";
70415
+ import { getProjectRoot as getProjectRoot61, goal } from "@cleocode/core";
68920
70416
  function resolveGoalKind(task) {
68921
70417
  if (typeof task === "string" && task.length > 0) {
68922
70418
  if (!isValidGoalTargetTaskId(task)) {
@@ -68963,7 +70459,7 @@ var init_goal2 = __esm({
68963
70459
  }
68964
70460
  const record = await goal.createGoal(
68965
70461
  { goalKind: kindResult.kind, intent, turnBudget: resolveTurnBudget(args.turns) },
68966
- getProjectRoot60()
70462
+ getProjectRoot61()
68967
70463
  );
68968
70464
  cliOutput(record, { command: "goal set", operation: "goal.set" });
68969
70465
  }
@@ -68974,7 +70470,7 @@ var init_goal2 = __esm({
68974
70470
  description: "Show the current agent's active goal (per-agent scoped)."
68975
70471
  },
68976
70472
  async run() {
68977
- const record = await goal.getActiveGoal(getProjectRoot60());
70473
+ const record = await goal.getActiveGoal(getProjectRoot61());
68978
70474
  cliOutput(record ?? { active: null }, { command: "goal status", operation: "goal.status" });
68979
70475
  }
68980
70476
  });
@@ -68996,7 +70492,7 @@ var init_goal2 = __esm({
68996
70492
  });
68997
70493
  return;
68998
70494
  }
68999
- const cwd = getProjectRoot60();
70495
+ const cwd = getProjectRoot61();
69000
70496
  const parent = await goal.getActiveGoal(cwd);
69001
70497
  if (!parent) {
69002
70498
  cliError(
@@ -69044,7 +70540,7 @@ var init_goal2 = __esm({
69044
70540
  });
69045
70541
  return;
69046
70542
  }
69047
- const cwd = getProjectRoot60();
70543
+ const cwd = getProjectRoot61();
69048
70544
  const result = await goal.advanceGoalWithPersist(goalId, { cwd });
69049
70545
  if (!result) {
69050
70546
  cliError(`Goal '${goalId}' not found.`, 4 /* NOT_FOUND */, { name: "E_NOT_FOUND" });
@@ -69069,7 +70565,7 @@ var init_goal2 = __esm({
69069
70565
  });
69070
70566
  return;
69071
70567
  }
69072
- const cwd = getProjectRoot60();
70568
+ const cwd = getProjectRoot61();
69073
70569
  const active = await goal.getActiveGoal(cwd);
69074
70570
  if (!active) {
69075
70571
  cliError(
@@ -70111,12 +71607,422 @@ var init_history = __esm({
70111
71607
  }
70112
71608
  });
70113
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
+
70114
72020
  // packages/cleo/src/cli/commands/hygiene.ts
70115
72021
  var hygiene_exports = {};
70116
72022
  __export(hygiene_exports, {
70117
72023
  hygieneCommand: () => hygieneCommand
70118
72024
  });
70119
- import { getProjectRoot as getProjectRoot61 } from "@cleocode/core";
72025
+ import { getProjectRoot as getProjectRoot62 } from "@cleocode/core";
70120
72026
  import { runSpawnReadinessHygieneCli } from "@cleocode/core/hygiene/validate-spawn-readiness.js";
70121
72027
  var hygieneCommand;
70122
72028
  var init_hygiene = __esm({
@@ -70145,7 +72051,7 @@ var init_hygiene = __esm({
70145
72051
  }
70146
72052
  },
70147
72053
  async run({ args }) {
70148
- const projectRoot = args["project-root"] || getProjectRoot61() || process.cwd();
72054
+ const projectRoot = args["project-root"] || getProjectRoot62() || process.cwd();
70149
72055
  const worktreePath = args["worktree-path"];
70150
72056
  await runSpawnReadinessHygieneCli(projectRoot, worktreePath);
70151
72057
  }
@@ -70320,8 +72226,8 @@ __export(init_exports, {
70320
72226
  isCredentialPoolEmpty: () => isCredentialPoolEmpty,
70321
72227
  maybeNudgeFirstRunLogin: () => maybeNudgeFirstRunLogin
70322
72228
  });
70323
- import { existsSync as existsSync16, readFileSync as readFileSync12 } from "node:fs";
70324
- 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";
70325
72231
  import { fileURLToPath as fileURLToPath5 } from "node:url";
70326
72232
  import {
70327
72233
  CleoError as CleoError9,
@@ -70336,12 +72242,12 @@ import { getTemplatesByKind } from "@cleocode/core/templates/registry";
70336
72242
  function getGitignoreTemplate() {
70337
72243
  try {
70338
72244
  const thisFile = fileURLToPath5(import.meta.url);
70339
- const packageRoot = join28(thisFile, "..", "..", "..", "..");
70340
- const localTemplatePath = join28(packageRoot, "templates", "cleo-gitignore");
70341
- 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");
70342
72248
  const templatePath = existsSync16(localTemplatePath) ? localTemplatePath : monorepoTemplatePath;
70343
72249
  if (existsSync16(templatePath)) {
70344
- return readFileSync12(templatePath, "utf-8");
72250
+ return readFileSync13(templatePath, "utf-8");
70345
72251
  }
70346
72252
  } catch {
70347
72253
  }
@@ -71488,7 +73394,7 @@ var llm_cost_exports = {};
71488
73394
  __export(llm_cost_exports, {
71489
73395
  costCommand: () => costCommand
71490
73396
  });
71491
- import { getProjectRoot as getProjectRoot62 } from "@cleocode/core/internal";
73397
+ import { getProjectRoot as getProjectRoot63 } from "@cleocode/core/internal";
71492
73398
  import { computeCost } from "@cleocode/core/llm/usage-pricing";
71493
73399
  function resolveSessionId(raw) {
71494
73400
  if (raw === "current") {
@@ -71561,7 +73467,7 @@ var init_llm_cost = __esm({
71561
73467
  process.exit(6);
71562
73468
  }
71563
73469
  const sessionId = resolveSessionId(rawSessionId);
71564
- const projectRoot = getProjectRoot62(process.cwd());
73470
+ const projectRoot = getProjectRoot63(process.cwd());
71565
73471
  let breakdown;
71566
73472
  try {
71567
73473
  breakdown = await loadSessionCostBreakdown(projectRoot, sessionId);
@@ -71660,8 +73566,8 @@ async function resolveDefaultModel(provider) {
71660
73566
  "@cleocode/core/llm/role-resolver.js"
71661
73567
  )
71662
73568
  ]);
71663
- const profile = await getProviderProfile2(provider);
71664
- return profile?.defaultModel ?? IMPLICIT_FALLBACK_MODEL;
73569
+ const profile2 = await getProviderProfile2(provider);
73570
+ return profile2?.defaultModel ?? IMPLICIT_FALLBACK_MODEL;
71665
73571
  }
71666
73572
  async function runLlmStream(opts) {
71667
73573
  const stdout2 = opts.stdout ?? process.stdout;
@@ -72519,14 +74425,8 @@ var init_log = __esm({
72519
74425
  // packages/cleo/src/cli/commands/logout.ts
72520
74426
  var logout_exports = {};
72521
74427
  __export(logout_exports, {
72522
- logoutCommand: () => logoutCommand,
72523
- nexusLogoutSummary: () => nexusLogoutSummary
74428
+ logoutCommand: () => logoutCommand
72524
74429
  });
72525
- function nexusLogoutSummary(r) {
72526
- if (!r.removedLocally) return `Not signed in to ${r.apiUrl}; nothing to do.`;
72527
- const server = r.revocation === "revoked" ? "session revoked" : r.revocation === "already-invalid" ? "session was already invalid" : "server-side revocation FAILED (the session ends when it expires)";
72528
- return `Signed out of ${r.apiUrl}: ${server}; local token deleted.`;
72529
- }
72530
74430
  var logoutCommand;
72531
74431
  var init_logout = __esm({
72532
74432
  "packages/cleo/src/cli/commands/logout.ts"() {
@@ -72538,7 +74438,7 @@ var init_logout = __esm({
72538
74438
  logoutCommand = defineCommand({
72539
74439
  meta: {
72540
74440
  name: "logout",
72541
- description: "Sign out. cleo logout [nexus] revokes the Cleo Nexus session server-side and deletes the stored token; cleo logout <provider> [label] removes an LLM credential exactly like cleo auth remove (the label may be omitted when the provider has one credential)."
74441
+ description: "Sign out. cleo logout [nexus] signs this machine out of Cleo Nexus (the device keeps its id for the next login; --revoke burns it), confirmed by the server; cleo logout <provider> [label] removes an LLM credential exactly like cleo auth remove (the label may be omitted when the provider has one credential)."
72542
74442
  },
72543
74443
  args: {
72544
74444
  target: {
@@ -72552,6 +74452,10 @@ var init_logout = __esm({
72552
74452
  required: false
72553
74453
  },
72554
74454
  "api-url": NEXUS_API_URL_ARG,
74455
+ revoke: {
74456
+ type: "boolean",
74457
+ description: "Hard-revoke this device: destroys its key grant and burns the device id; the next login enrols a new device. Without it, logout signs the device out and keeps it for the next login."
74458
+ },
72555
74459
  json: { type: "boolean", description: "Output as JSON envelope" }
72556
74460
  },
72557
74461
  async run({ args }) {
@@ -72566,17 +74470,7 @@ var init_logout = __esm({
72566
74470
  emitLlmCredentialRemoval(await removeLlmCredential(target, label), "logout", "logout.run");
72567
74471
  return;
72568
74472
  }
72569
- const { logoutFromNexus } = await import(
72570
- /* webpackIgnore: true */
72571
- "@cleocode/core/cloud/nexus-auth.js"
72572
- );
72573
- let result;
72574
- try {
72575
- result = await logoutFromNexus({ apiUrl: nexusApiUrlArg(a) });
72576
- } catch (err) {
72577
- failNexus(err, "logout.run");
72578
- }
72579
- emitNexusResult(result, nexusLogoutSummary(result), "logout", "logout.run");
74473
+ await runNexusDeviceLogout(a);
72580
74474
  }
72581
74475
  });
72582
74476
  }
@@ -72950,7 +74844,7 @@ var memory_exports = {};
72950
74844
  __export(memory_exports, {
72951
74845
  memoryCommand: () => memoryCommand
72952
74846
  });
72953
- import { getProjectRoot as getProjectRoot63 } from "@cleocode/core";
74847
+ import { getProjectRoot as getProjectRoot64 } from "@cleocode/core";
72954
74848
  import {
72955
74849
  getBrainDb as getBrainDb2,
72956
74850
  getDreamStatus,
@@ -73908,7 +75802,7 @@ var init_memory3 = __esm({
73908
75802
  },
73909
75803
  args: {},
73910
75804
  async run() {
73911
- const root = getProjectRoot63();
75805
+ const root = getProjectRoot64();
73912
75806
  try {
73913
75807
  const result = await runConsolidation(root);
73914
75808
  cliOutput(result, { command: "memory-consolidate", operation: "memory.consolidate" });
@@ -73932,7 +75826,7 @@ var init_memory3 = __esm({
73932
75826
  }
73933
75827
  },
73934
75828
  async run({ args }) {
73935
- const root = getProjectRoot63();
75829
+ const root = getProjectRoot64();
73936
75830
  if (args.status) {
73937
75831
  try {
73938
75832
  const status = await getDreamStatus(root);
@@ -73969,7 +75863,7 @@ var init_memory3 = __esm({
73969
75863
  }
73970
75864
  },
73971
75865
  async run({ args }) {
73972
- const root = getProjectRoot63();
75866
+ const root = getProjectRoot64();
73973
75867
  try {
73974
75868
  const { runObserver, runReflector } = await import("@cleocode/core/memory");
73975
75869
  const observerResult = await runObserver(root, args.session, {
@@ -74009,7 +75903,7 @@ var init_memory3 = __esm({
74009
75903
  }
74010
75904
  },
74011
75905
  async run({ args }) {
74012
- const root = getProjectRoot63();
75906
+ const root = getProjectRoot64();
74013
75907
  await getBrainDb2(root);
74014
75908
  const { getBrainNativeDb: getBrainNativeDb3 } = await import("@cleocode/core/internal");
74015
75909
  const nativeDb = getBrainNativeDb3();
@@ -74047,7 +75941,7 @@ var init_memory3 = __esm({
74047
75941
  },
74048
75942
  async run({ args }) {
74049
75943
  const core2 = await import("@cleocode/core/internal");
74050
- const nexusDb = await core2.getNexusDb(getProjectRoot63());
75944
+ const nexusDb = await core2.getNexusDb(getProjectRoot64());
74051
75945
  const result = args.restore ? await core2.restorePrunedTraits(
74052
75946
  nexusDb,
74053
75947
  String(args.restore),
@@ -74077,7 +75971,7 @@ var init_memory3 = __esm({
74077
75971
  return;
74078
75972
  }
74079
75973
  const core2 = await import("@cleocode/core/internal");
74080
- const nexusDb = await core2.getNexusDb(getProjectRoot63());
75974
+ const nexusDb = await core2.getNexusDb(getProjectRoot64());
74081
75975
  const previous = await core2.setUserProfileTraitScope(nexusDb, String(args.key), scope);
74082
75976
  if (previous === null) {
74083
75977
  cliError(`No user-profile trait "${args.key}"`, "E_NOT_FOUND", { name: "E_NOT_FOUND" });
@@ -74101,7 +75995,7 @@ var init_memory3 = __esm({
74101
75995
  }
74102
75996
  },
74103
75997
  async run({ args }) {
74104
- const root = getProjectRoot63();
75998
+ const root = getProjectRoot64();
74105
75999
  try {
74106
76000
  await getBrainDb2(root);
74107
76001
  const { totalDuplicateRows, groups } = await scanDuplicateEntries();
@@ -74147,7 +76041,7 @@ var init_memory3 = __esm({
74147
76041
  async run({ args }) {
74148
76042
  const sourceDir = args.from;
74149
76043
  const isDryRun = !!args["dry-run"];
74150
- const projectRoot = getProjectRoot63();
76044
+ const projectRoot = getProjectRoot64();
74151
76045
  try {
74152
76046
  const result = await importMemoryFiles({
74153
76047
  sourceDir,
@@ -74298,7 +76192,7 @@ var init_memory3 = __esm({
74298
76192
  },
74299
76193
  args: {},
74300
76194
  async run() {
74301
- const root = getProjectRoot63();
76195
+ const root = getProjectRoot64();
74302
76196
  try {
74303
76197
  await getBrainDb2(root);
74304
76198
  const result = await getTierStats(root);
@@ -74341,7 +76235,7 @@ var init_memory3 = __esm({
74341
76235
  }
74342
76236
  },
74343
76237
  async run({ args }) {
74344
- const root = getProjectRoot63();
76238
+ const root = getProjectRoot64();
74345
76239
  const targetTier = args.to;
74346
76240
  const reason = args.reason;
74347
76241
  const validTiers = ["medium", "long"];
@@ -74407,7 +76301,7 @@ var init_memory3 = __esm({
74407
76301
  }
74408
76302
  },
74409
76303
  async run({ args }) {
74410
- const root = getProjectRoot63();
76304
+ const root = getProjectRoot64();
74411
76305
  const targetTier = args.to;
74412
76306
  const reason = args.reason;
74413
76307
  const validTiers = ["short", "medium"];
@@ -74880,7 +76774,7 @@ var migrate_claude_mem_exports = {};
74880
76774
  __export(migrate_claude_mem_exports, {
74881
76775
  migrateClaudeMemCommand: () => migrateClaudeMemCommand
74882
76776
  });
74883
- import { getProjectRoot as getProjectRoot64, migrateClaudeMem } from "@cleocode/core/internal";
76777
+ import { getProjectRoot as getProjectRoot65, migrateClaudeMem } from "@cleocode/core/internal";
74884
76778
  import { ingestLooseAgentOutputs, ingestRcasdDirectories } from "@cleocode/core/memory";
74885
76779
  import { getDb as getDb2 } from "@cleocode/core/store/sqlite";
74886
76780
  var storageCommand, claudeMemCommand, manifestIngestCommand, migrateClaudeMemCommand;
@@ -74943,7 +76837,7 @@ var init_migrate_claude_mem = __esm({
74943
76837
  }
74944
76838
  },
74945
76839
  async run({ args }) {
74946
- const root = getProjectRoot64();
76840
+ const root = getProjectRoot65();
74947
76841
  try {
74948
76842
  const result = await migrateClaudeMem(root, {
74949
76843
  sourcePath: args.source,
@@ -74992,7 +76886,7 @@ var init_migrate_claude_mem = __esm({
74992
76886
  }
74993
76887
  },
74994
76888
  async run({ args }) {
74995
- const projectRoot = getProjectRoot64();
76889
+ const projectRoot = getProjectRoot65();
74996
76890
  try {
74997
76891
  const db = await getDb2(projectRoot);
74998
76892
  const rcasdFlag = Boolean(args.rcasd);
@@ -75110,7 +77004,7 @@ __export(nexus_exports, {
75110
77004
  import { statSync as statSync2 } from "node:fs";
75111
77005
  import { appendFile as appendFile2, mkdir as mkdir5 } from "node:fs/promises";
75112
77006
  import path4 from "node:path";
75113
- import { getProjectRoot as getProjectRoot65 } from "@cleocode/core";
77007
+ import { getProjectRoot as getProjectRoot66 } from "@cleocode/core";
75114
77008
  import { getSymbolImpact } from "@cleocode/core/nexus";
75115
77009
  import { runNexusAnalysis } from "@cleocode/core/nexus/analyze-orchestrator.js";
75116
77010
  import {
@@ -75281,7 +77175,7 @@ var init_nexus3 = __esm({
75281
77175
  async run({ args }) {
75282
77176
  applyJsonFlag2(args.json);
75283
77177
  const projectIdOverride = args["project-id"];
75284
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
77178
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
75285
77179
  const startTime = Date.now();
75286
77180
  if (args.path) {
75287
77181
  let isDir = false;
@@ -75341,7 +77235,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648), so the coun
75341
77235
  process.exitCode = 2 /* INVALID_INPUT */;
75342
77236
  return;
75343
77237
  }
75344
- const currentRoot = getProjectRoot65();
77238
+ const currentRoot = getProjectRoot66();
75345
77239
  if (args.path && path4.resolve(repoPath) !== path4.resolve(currentRoot)) {
75346
77240
  cliError(
75347
77241
  `nexus status cannot report on '${repoPath}' from this project.
@@ -75519,9 +77413,9 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
75519
77413
  args: {},
75520
77414
  async run() {
75521
77415
  try {
75522
- const { homedir: homedir4 } = await import("node:os");
77416
+ const { homedir: homedir5 } = await import("node:os");
75523
77417
  const { installNexusAugmentHook } = await import("@cleocode/core/internal");
75524
- const homeDir = homedir4();
77418
+ const homeDir = homedir5();
75525
77419
  installNexusAugmentHook(homeDir);
75526
77420
  cliOutput({ homeDir }, { command: "nexus-setup", operation: "nexus.setup" });
75527
77421
  } catch (err) {
@@ -75895,7 +77789,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
75895
77789
  applyJsonFlag2(args.json);
75896
77790
  const startTime = Date.now();
75897
77791
  const projectIdOverride = args["project-id"];
75898
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
77792
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
75899
77793
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
75900
77794
  const response = await dispatchRaw("query", "nexus", "clusters", { projectId, repoPath });
75901
77795
  const durationMs = Date.now() - startTime;
@@ -75939,7 +77833,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
75939
77833
  applyJsonFlag2(args.json);
75940
77834
  const startTime = Date.now();
75941
77835
  const projectIdOverride = args["project-id"];
75942
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
77836
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
75943
77837
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
75944
77838
  const response = await dispatchRaw("query", "nexus", "flows", { projectId, repoPath });
75945
77839
  const durationMs = Date.now() - startTime;
@@ -75982,7 +77876,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
75982
77876
  void appendDeprecationTelemetry("nexus.context", "cleo graph context");
75983
77877
  const startTime = Date.now();
75984
77878
  const projectIdOverride = args["project-id"];
75985
- const repoPath = getProjectRoot65();
77879
+ const repoPath = getProjectRoot66();
75986
77880
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
75987
77881
  const limit = parseInt(args.limit, 10);
75988
77882
  const symbolName = args.symbol;
@@ -76045,7 +77939,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76045
77939
  const startTime = Date.now();
76046
77940
  const whyFlag = !!args.why;
76047
77941
  const projectIdOverride = args["project-id"];
76048
- const repoPath = getProjectRoot65();
77942
+ const repoPath = getProjectRoot66();
76049
77943
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
76050
77944
  const maxDepth = Math.min(parseInt(args.depth, 10), 5);
76051
77945
  const symbolName = args.symbol;
@@ -76149,7 +78043,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76149
78043
  const projectIdOverride = args["project-id"];
76150
78044
  const full = !!args.full;
76151
78045
  const ctx = getFormatContext();
76152
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78046
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76153
78047
  if (args.incremental)
76154
78048
  humanWarn(
76155
78049
  "[nexus] --incremental is deprecated and has no effect: incremental is the default."
@@ -76279,7 +78173,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76279
78173
  async run({ args }) {
76280
78174
  applyJsonFlag2(args.json);
76281
78175
  const startTime = Date.now();
76282
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78176
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76283
78177
  const name = args.name;
76284
78178
  const response = await dispatchRaw("mutate", "nexus", "projects.register", {
76285
78179
  path: repoPath,
@@ -76798,7 +78692,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76798
78692
  applyJsonFlag2(args.json);
76799
78693
  const startTime = Date.now();
76800
78694
  const projectIdOverride = args["project-id"];
76801
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78695
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76802
78696
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
76803
78697
  const response = await dispatchRaw("mutate", "nexus", "refresh-bridge", {
76804
78698
  repoPath,
@@ -76904,7 +78798,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
76904
78798
  async run({ args }) {
76905
78799
  applyJsonFlag2(args.json);
76906
78800
  const startTime = Date.now();
76907
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78801
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
76908
78802
  const projectIdOverride = args["project-id"];
76909
78803
  const beforeRef = args.before ?? "HEAD~1";
76910
78804
  const afterRef = args.after ?? "HEAD";
@@ -77022,7 +78916,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77022
78916
  applyJsonFlag2(args.json);
77023
78917
  const startTime = Date.now();
77024
78918
  const projectIdOverride = args["project-id"];
77025
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78919
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77026
78920
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
77027
78921
  const response = await dispatchRaw("query", "nexus", "route-map", { projectId });
77028
78922
  const durationMs = Date.now() - startTime;
@@ -77078,7 +78972,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77078
78972
  const startTime = Date.now();
77079
78973
  const routeSymbol = args.routeSymbol;
77080
78974
  const projectIdOverride = args["project-id"];
77081
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
78975
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77082
78976
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
77083
78977
  const response = await dispatchRaw("query", "nexus", "shape-check", { routeSymbol, projectId });
77084
78978
  const durationMs = Date.now() - startTime;
@@ -77474,7 +79368,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77474
79368
  async run({ args }) {
77475
79369
  applyJsonFlag2(args.json);
77476
79370
  const startTime = Date.now();
77477
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
79371
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77478
79372
  const projectIdOverride = args["project-id"];
77479
79373
  const projectId = projectIdOverride ?? Buffer.from(repoPath).toString("base64url").slice(0, 32);
77480
79374
  const response = await dispatchRaw("mutate", "nexus", "contracts-sync", {
@@ -77584,7 +79478,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77584
79478
  async run({ args }) {
77585
79479
  applyJsonFlag2(args.json);
77586
79480
  const startTime = Date.now();
77587
- const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot65();
79481
+ const repoPath = args.path ? path4.resolve(args.path) : getProjectRoot66();
77588
79482
  const projectId = Buffer.from(repoPath).toString("base64url").slice(0, 32);
77589
79483
  const response = await dispatchRaw("mutate", "nexus", "contracts-link-tasks", {
77590
79484
  projectId,
@@ -77668,7 +79562,7 @@ The code-intelligence graph is project-scoped (ADR-090 \xB7 T11648): one store p
77668
79562
  const isIncremental = !!args.incremental;
77669
79563
  try {
77670
79564
  const result = await runNexusWiki({
77671
- projectRoot: getProjectRoot65(),
79565
+ projectRoot: getProjectRoot66(),
77672
79566
  outputDir,
77673
79567
  communityFilter,
77674
79568
  incremental: isIncremental
@@ -78018,7 +79912,7 @@ __export(orchestrate_exports, {
78018
79912
  });
78019
79913
  import { execFileSync as execFileSync5 } from "node:child_process";
78020
79914
  import { orchestration } from "@cleocode/core";
78021
- 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";
78022
79916
  function formatRollupTable(rollup) {
78023
79917
  const waves = "waves" in rollup ? rollup.waves : [rollup];
78024
79918
  const lines = [];
@@ -78161,7 +80055,7 @@ var init_orchestrate3 = __esm({
78161
80055
  },
78162
80056
  async run({ args }) {
78163
80057
  const rateWindowHours = args.window !== void 0 ? Number.parseFloat(String(args.window)) : void 0;
78164
- const metrics = await orchestration.collectOrchestrateDashboard(getProjectRoot66(), {
80058
+ const metrics = await orchestration.collectOrchestrateDashboard(getProjectRoot67(), {
78165
80059
  ...rateWindowHours !== void 0 && Number.isFinite(rateWindowHours) && rateWindowHours > 0 ? { rateWindowHours } : {}
78166
80060
  });
78167
80061
  cliOutput(metrics, {
@@ -79621,7 +81515,7 @@ __export(project_exports, {
79621
81515
  import { resolve as resolve9 } from "node:path";
79622
81516
  import {
79623
81517
  CleoError as CleoError11,
79624
- getProjectRoot as getProjectRoot67,
81518
+ getProjectRoot as getProjectRoot68,
79625
81519
  moveProject,
79626
81520
  projectLifecycle,
79627
81521
  renameProject,
@@ -79643,7 +81537,7 @@ function emitEngineFailure(error, operation) {
79643
81537
  }
79644
81538
  function resolveRootOrFail(operation) {
79645
81539
  try {
79646
- return getProjectRoot67();
81540
+ return getProjectRoot68();
79647
81541
  } catch (err) {
79648
81542
  const code = err instanceof CleoError11 && typeof err.details?.["code"] === "string" ? err.details["code"] : "E_NOT_CLEO_PROJECT";
79649
81543
  emitEngineFailure(
@@ -79874,6 +81768,10 @@ var init_project = __esm({
79874
81768
  type: "string",
79875
81769
  description: "Name shown in Nexus, sent in plaintext (default: the project name). A name, never a path."
79876
81770
  },
81771
+ rebind: {
81772
+ type: "boolean",
81773
+ description: "Use only after E_NEXUS_REPLICA_COPIED: give this copy of the project a new replica id before attaching it (this machine was re-enrolled, or the store was copied). Each run mints a new id and leaves the old one on the server as stale history."
81774
+ },
79877
81775
  "api-url": NEXUS_API_URL_ARG,
79878
81776
  json: { type: "boolean", description: "Output raw JSON envelope.", default: false }
79879
81777
  },
@@ -79886,14 +81784,17 @@ var init_project = __esm({
79886
81784
  try {
79887
81785
  result = await linkProjectToNexus({
79888
81786
  apiUrl: nexusApiUrlArg(args),
79889
- ...typeof args["label"] === "string" && args["label"] ? { label: args["label"] } : {}
81787
+ ...typeof args["label"] === "string" && args["label"] ? { label: args["label"] } : {},
81788
+ ...args["rebind"] === true ? { rebind: true } : {}
79890
81789
  });
79891
81790
  } catch (err) {
79892
81791
  failNexus(err, "project.link");
79893
81792
  }
79894
- const { link } = result;
81793
+ const { link, replica } = result;
79895
81794
  const verb = result.alreadyLinked ? "Already linked" : "Linked";
79896
- const summary = `${verb}: project ${link.localProjectId} as "${link.label ?? ""}" on ${link.apiUrl}.`;
81795
+ const attached = replica ? ` This machine (device ${replica.deviceId}) holds it as replica ${replica.replicaId}${replica.reboundFrom ? ` (rebound from ${replica.reboundFrom})` : ""}${replica.presenceAt ? "; presence reported" : ""}.` : "";
81796
+ const summary = `${verb}: project ${link.localProjectId} as "${link.label ?? ""}" on ${link.apiUrl}.${attached}`;
81797
+ writeNexusWarnings(result.warnings);
79897
81798
  emitNexusResult(result, summary, "project", "project.link");
79898
81799
  }
79899
81800
  });
@@ -80471,7 +82372,7 @@ var refresh_memory_exports = {};
80471
82372
  __export(refresh_memory_exports, {
80472
82373
  refreshMemoryCommand: () => refreshMemoryCommand
80473
82374
  });
80474
- import { getProjectRoot as getProjectRoot68 } from "@cleocode/core";
82375
+ import { getProjectRoot as getProjectRoot69 } from "@cleocode/core";
80475
82376
  var refreshMemoryCommand;
80476
82377
  var init_refresh_memory = __esm({
80477
82378
  "packages/cleo/src/cli/commands/refresh-memory.ts"() {
@@ -80484,7 +82385,7 @@ var init_refresh_memory = __esm({
80484
82385
  description: "Regenerate .cleo/memory-bridge.md from brain.db"
80485
82386
  },
80486
82387
  async run() {
80487
- const projectDir = getProjectRoot68();
82388
+ const projectDir = getProjectRoot69();
80488
82389
  const { writeMemoryBridge } = await import("@cleocode/core/internal");
80489
82390
  const result = await writeMemoryBridge(projectDir);
80490
82391
  if (result.written) {
@@ -82070,7 +83971,7 @@ import fs3 from "node:fs";
82070
83971
  import path5 from "node:path";
82071
83972
  import {
82072
83973
  CleoError as CleoError13,
82073
- getProjectRoot as getProjectRoot69,
83974
+ getProjectRoot as getProjectRoot70,
82074
83975
  getTaskAccessor as getTaskAccessor3,
82075
83976
  parseConflictReport,
82076
83977
  setAtPath
@@ -82091,7 +83992,7 @@ var init_restore = __esm({
82091
83992
  description: "Apply manually-resolved conflicts from .cleo/restore-conflicts.md"
82092
83993
  },
82093
83994
  async run() {
82094
- const projectRoot = getProjectRoot69();
83995
+ const projectRoot = getProjectRoot70();
82095
83996
  const reportPath = path5.join(projectRoot, CLEO_DIR_NAME3, RESTORE_CONFLICTS_MD);
82096
83997
  if (!fs3.existsSync(reportPath)) {
82097
83998
  humanLine("No pending restore conflicts. Nothing to finalize.");
@@ -82463,7 +84364,7 @@ __export(revert_exports, {
82463
84364
  revertCommand: () => revertCommand2
82464
84365
  });
82465
84366
  import { readFile as readFile8 } from "node:fs/promises";
82466
- import { join as join29 } from "node:path";
84367
+ import { join as join30 } from "node:path";
82467
84368
  import { cwd as processCwd2 } from "node:process";
82468
84369
  import { E_RECEIPT_NOT_FOUND } from "@cleocode/core/sentient/chain-walker.js";
82469
84370
  import { SENTIENT_STATE_FILE } from "@cleocode/core/sentient/daemon.js";
@@ -82516,7 +84417,7 @@ async function loadOwnerAttestation(attestationFilePath) {
82516
84417
  return obj;
82517
84418
  }
82518
84419
  async function loadOwnerPubkeys(projectRoot) {
82519
- const path6 = join29(projectRoot, OWNER_PUBKEYS_FILE);
84420
+ const path6 = join30(projectRoot, OWNER_PUBKEYS_FILE);
82520
84421
  try {
82521
84422
  const raw = await readFile8(path6, "utf-8");
82522
84423
  const parsed = JSON.parse(raw);
@@ -82600,7 +84501,7 @@ var init_revert = __esm({
82600
84501
  if (attestation && allowedPubkeys.size > 0 && !allowedPubkeys.has(attestation.ownerPubkey)) {
82601
84502
  emitFailure2(
82602
84503
  E_OWNER_ATTESTATION_REQUIRED,
82603
- `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)}`,
82604
84505
  jsonMode
82605
84506
  );
82606
84507
  }
@@ -82653,7 +84554,7 @@ ${lines}`
82653
84554
  identity,
82654
84555
  includeHuman
82655
84556
  });
82656
- const statePath = join29(projectRoot, SENTIENT_STATE_FILE);
84557
+ const statePath = join30(projectRoot, SENTIENT_STATE_FILE);
82657
84558
  const state = await readSentientState(statePath);
82658
84559
  emitSuccess(
82659
84560
  {
@@ -82724,6 +84625,185 @@ var init_roadmap = __esm({
82724
84625
  }
82725
84626
  });
82726
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
+
82727
84807
  // packages/cleo/src/cli/commands/safestop.ts
82728
84808
  var safestop_exports = {};
82729
84809
  __export(safestop_exports, {
@@ -83020,8 +85100,8 @@ var init_saga = __esm({
83020
85100
  }
83021
85101
  },
83022
85102
  async run({ args }) {
83023
- const { sagas: sagas2, getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
83024
- const projectRoot = getProjectRoot75();
85103
+ const { sagas: sagas2, getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
85104
+ const projectRoot = getProjectRoot76();
83025
85105
  const sagaId = typeof args.sagaId === "string" && args.sagaId.length > 0 ? args.sagaId : void 0;
83026
85106
  const result = await sagas2.sagaNext(projectRoot, { sagaId });
83027
85107
  cliOutput(result.success ? result.data : result, { command: "saga", operation: "saga.next" });
@@ -83235,7 +85315,7 @@ __export(self_update_exports, {
83235
85315
  });
83236
85316
  import { execFile } from "node:child_process";
83237
85317
  import { readFile as readFile9 } from "node:fs/promises";
83238
- import { join as join30 } from "node:path";
85318
+ import { join as join31 } from "node:path";
83239
85319
  import * as readline3 from "node:readline";
83240
85320
  import { promisify } from "node:util";
83241
85321
  import {
@@ -83250,7 +85330,7 @@ import {
83250
85330
  async function getCurrentVersion() {
83251
85331
  const cleoHome = getCleoHome7();
83252
85332
  try {
83253
- const content = await readFile9(join30(cleoHome, "VERSION"), "utf-8");
85333
+ const content = await readFile9(join31(cleoHome, "VERSION"), "utf-8");
83254
85334
  return (content.split("\n")[0] ?? "unknown").trim();
83255
85335
  } catch {
83256
85336
  return "unknown";
@@ -83304,7 +85384,7 @@ async function writeRuntimeVersionMetadata(mode, source, version) {
83304
85384
  ];
83305
85385
  await import("node:fs/promises").then(
83306
85386
  ({ writeFile: writeFile4, mkdir: mkdir7 }) => mkdir7(cleoHome, { recursive: true }).then(
83307
- () => writeFile4(join30(cleoHome, "VERSION"), `${lines.join("\n")}
85387
+ () => writeFile4(join31(cleoHome, "VERSION"), `${lines.join("\n")}
83308
85388
  `, "utf-8")
83309
85389
  )
83310
85390
  );
@@ -83716,13 +85796,13 @@ var selfimprove_exports = {};
83716
85796
  __export(selfimprove_exports, {
83717
85797
  selfimproveCommand: () => selfimproveCommand
83718
85798
  });
83719
- var runCommand6, selfimproveCommand;
85799
+ var runCommand7, selfimproveCommand;
83720
85800
  var init_selfimprove2 = __esm({
83721
85801
  "packages/cleo/src/cli/commands/selfimprove.ts"() {
83722
85802
  "use strict";
83723
85803
  init_cli();
83724
85804
  init_define_cli_command();
83725
- runCommand6 = defineCommand({
85805
+ runCommand7 = defineCommand({
83726
85806
  meta: {
83727
85807
  name: "run",
83728
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)."
@@ -83767,7 +85847,7 @@ var init_selfimprove2 = __esm({
83767
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)."
83768
85848
  },
83769
85849
  subCommands: {
83770
- run: runCommand6
85850
+ run: runCommand7
83771
85851
  },
83772
85852
  async run({ cmd, rawArgs }) {
83773
85853
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
@@ -83785,7 +85865,7 @@ __export(sentient_exports, {
83785
85865
  promptAcceptExecution: () => promptAcceptExecution,
83786
85866
  sentientCommand: () => sentientCommand
83787
85867
  });
83788
- import { join as join31 } from "node:path";
85868
+ import { join as join32 } from "node:path";
83789
85869
  import { cwd as processCwd3, stdin, stdout } from "node:process";
83790
85870
  import { createInterface as createInterface4 } from "node:readline/promises";
83791
85871
  import {
@@ -83875,7 +85955,7 @@ var init_sentient3 = __esm({
83875
85955
  return;
83876
85956
  }
83877
85957
  if (dryRun) {
83878
- const statePath2 = join31(projectRoot, SENTIENT_STATE_FILE2);
85958
+ const statePath2 = join32(projectRoot, SENTIENT_STATE_FILE2);
83879
85959
  const outcome = await safeRunTick({ projectRoot, statePath: statePath2, dryRun: true });
83880
85960
  emitSuccess2(
83881
85961
  { dryRun: true, outcome },
@@ -83991,7 +86071,7 @@ Logs: ${logPath}`
83991
86071
  const jsonMode = args.json === true;
83992
86072
  const dryRun = args["dry-run"] === true;
83993
86073
  try {
83994
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86074
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
83995
86075
  const outcome = await safeRunTick({ projectRoot, statePath, dryRun });
83996
86076
  emitSuccess2(
83997
86077
  { outcome, dryRun },
@@ -84083,7 +86163,7 @@ Logs: ${logPath}`
84083
86163
  return;
84084
86164
  }
84085
86165
  await db.update(tasks).set({ status: "pending", updatedAt: now }).where(eq2(tasks.id, id)).run();
84086
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86166
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84087
86167
  const state = await readSentientState2(statePath);
84088
86168
  await patchSentientState(statePath, {
84089
86169
  tier2Stats: {
@@ -84179,7 +86259,7 @@ Logs: ${logPath}`
84179
86259
  return;
84180
86260
  }
84181
86261
  await db.update(tasks).set({ status: "cancelled", cancellationReason: reason, cancelledAt: now, updatedAt: now }).where(eq2(tasks.id, id)).run();
84182
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86262
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84183
86263
  const state = await readSentientState2(statePath);
84184
86264
  await patchSentientState(statePath, {
84185
86265
  tier2Stats: {
@@ -84224,7 +86304,7 @@ Logs: ${logPath}`
84224
86304
  const projectRoot = resolveProjectRoot5(args.project);
84225
86305
  const jsonMode = args.json === true;
84226
86306
  try {
84227
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86307
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84228
86308
  const outcome = await safeRunProposeTick({ projectRoot, statePath });
84229
86309
  emitSuccess2(
84230
86310
  { outcome },
@@ -84244,7 +86324,7 @@ Logs: ${logPath}`
84244
86324
  const projectRoot = resolveProjectRoot5(args.project);
84245
86325
  const jsonMode = args.json === true;
84246
86326
  try {
84247
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86327
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84248
86328
  const updated = await patchSentientState(statePath, { tier2Enabled: true });
84249
86329
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals enabled");
84250
86330
  } catch (err) {
@@ -84263,7 +86343,7 @@ Logs: ${logPath}`
84263
86343
  const projectRoot = resolveProjectRoot5(args.project);
84264
86344
  const jsonMode = args.json === true;
84265
86345
  try {
84266
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86346
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84267
86347
  const updated = await patchSentientState(statePath, { tier2Enabled: false });
84268
86348
  emitSuccess2({ tier2Enabled: updated.tier2Enabled }, jsonMode, "Tier-2 proposals disabled");
84269
86349
  } catch (err) {
@@ -84294,7 +86374,7 @@ Logs: ${logPath}`
84294
86374
  const projectRoot = resolveProjectRoot5(args.project);
84295
86375
  const jsonMode = args.json === true;
84296
86376
  try {
84297
- const statePath = join31(projectRoot, SENTIENT_STATE_FILE2);
86377
+ const statePath = join32(projectRoot, SENTIENT_STATE_FILE2);
84298
86378
  const state = await readSentientState2(statePath);
84299
86379
  emitSuccess2(
84300
86380
  {
@@ -84852,7 +86932,7 @@ var sequence_exports = {};
84852
86932
  __export(sequence_exports, {
84853
86933
  sequenceCommand: () => sequenceCommand
84854
86934
  });
84855
- import { getProjectRoot as getProjectRoot70 } from "@cleocode/core/internal";
86935
+ import { getProjectRoot as getProjectRoot71 } from "@cleocode/core/internal";
84856
86936
  var showCommand12, checkCommand7, repairCommand3, sequenceCommand;
84857
86937
  var init_sequence = __esm({
84858
86938
  "packages/cleo/src/cli/commands/sequence.ts"() {
@@ -84888,7 +86968,7 @@ var init_sequence = __esm({
84888
86968
  meta: { name: "repair", description: "Reset counter to max + 1 if behind" },
84889
86969
  async run() {
84890
86970
  const { repairSequence } = await import("@cleocode/core/internal");
84891
- const projectRoot = getProjectRoot70();
86971
+ const projectRoot = getProjectRoot71();
84892
86972
  const repair = await repairSequence(projectRoot);
84893
86973
  const result = {
84894
86974
  repaired: repair.repaired,
@@ -85485,8 +87565,8 @@ var init_session4 = __esm({
85485
87565
  "audit-scope": { type: "string", description: "Audit log scope (global|local)" }
85486
87566
  },
85487
87567
  async run({ args }) {
85488
- const { detectSessionDrift, getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
85489
- const projectRoot = await getProjectRoot75();
87568
+ const { detectSessionDrift, getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
87569
+ const projectRoot = await getProjectRoot76();
85490
87570
  const scope = args["audit-scope"] === "local" ? "local" : "global";
85491
87571
  const report = await detectSessionDrift({ projectRoot, auditScope: scope });
85492
87572
  cliOutput(report, { command: "session drift", operation: "session.drift" });
@@ -87885,10 +89965,10 @@ var init_sync = __esm({
87885
89965
  }
87886
89966
  },
87887
89967
  async run({ args }) {
87888
- const { readFileSync: readFileSync22 } = await import("node:fs");
89968
+ const { readFileSync: readFileSync23 } = await import("node:fs");
87889
89969
  let externalTasks;
87890
89970
  try {
87891
- externalTasks = JSON.parse(readFileSync22(args.file, "utf8"));
89971
+ externalTasks = JSON.parse(readFileSync23(args.file, "utf8"));
87892
89972
  } catch (err) {
87893
89973
  const message = err instanceof Error ? err.message : String(err);
87894
89974
  cliError(`Failed to read or parse external tasks file: ${message}`, 2, {
@@ -88185,19 +90265,19 @@ var init_telemetry2 = __esm({
88185
90265
  });
88186
90266
 
88187
90267
  // packages/cleo/src/cli/commands/templates/lib.ts
88188
- import { readFileSync as readFileSync13 } from "node:fs";
90268
+ import { readFileSync as readFileSync14 } from "node:fs";
88189
90269
  import { isAbsolute as isAbsolute3, resolve as resolve10 } from "node:path";
88190
- import { getProjectRoot as getProjectRoot71 } from "@cleocode/core";
90270
+ import { getProjectRoot as getProjectRoot72 } from "@cleocode/core";
88191
90271
  import { resolveSourcePathAbsolute } from "@cleocode/core/templates/registry";
88192
90272
  function resolveProjectRoot6(raw) {
88193
90273
  if (typeof raw === "string" && raw.length > 0) {
88194
90274
  return isAbsolute3(raw) ? raw : resolve10(process.cwd(), raw);
88195
90275
  }
88196
- return getProjectRoot71();
90276
+ return getProjectRoot72();
88197
90277
  }
88198
90278
  function readTemplateSource(entry) {
88199
90279
  const sourceAbsolute = resolveSourcePathAbsolute(entry);
88200
- return readFileSync13(sourceAbsolute, "utf8");
90280
+ return readFileSync14(sourceAbsolute, "utf8");
88201
90281
  }
88202
90282
  function applySubstitution(entry, source) {
88203
90283
  if (entry.substitution === "static") {
@@ -88212,8 +90292,8 @@ var init_lib = __esm({
88212
90292
  });
88213
90293
 
88214
90294
  // packages/cleo/src/cli/commands/templates/diff.ts
88215
- import { existsSync as existsSync17, readFileSync as readFileSync14 } from "node:fs";
88216
- 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";
88217
90297
  import { getTemplateById } from "@cleocode/core/templates/registry";
88218
90298
  function unifiedDiff(a, b) {
88219
90299
  const aLines = a.length === 0 ? [] : a.split("\n");
@@ -88283,7 +90363,7 @@ var init_diff = __esm({
88283
90363
  let rendered;
88284
90364
  try {
88285
90365
  projectRoot = resolveProjectRoot6(args["project"]);
88286
- installPath = join32(projectRoot, entry.installPath);
90366
+ installPath = join33(projectRoot, entry.installPath);
88287
90367
  const source = readTemplateSource(entry);
88288
90368
  rendered = applySubstitution(entry, source).rendered;
88289
90369
  } catch (err) {
@@ -88311,7 +90391,7 @@ ${unifiedDiff("", rendered)}`
88311
90391
  process.exit(1 /* GENERAL_ERROR */);
88312
90392
  return;
88313
90393
  }
88314
- const current = readFileSync14(installPath, "utf8");
90394
+ const current = readFileSync15(installPath, "utf8");
88315
90395
  const same = current === rendered;
88316
90396
  const result = {
88317
90397
  id,
@@ -88333,8 +90413,8 @@ ${unifiedDiff("", rendered)}`
88333
90413
  });
88334
90414
 
88335
90415
  // packages/cleo/src/cli/commands/templates/install.ts
88336
- import { existsSync as existsSync18, mkdirSync as mkdirSync5, readFileSync as readFileSync15, writeFileSync as writeFileSync6 } from "node:fs";
88337
- 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";
88338
90418
  import { getTemplateById as getTemplateById2 } from "@cleocode/core/templates/registry";
88339
90419
  var templatesInstallCommand;
88340
90420
  var init_install = __esm({
@@ -88388,7 +90468,7 @@ var init_install = __esm({
88388
90468
  let substituted;
88389
90469
  try {
88390
90470
  projectRoot = resolveProjectRoot6(args["project"]);
88391
- installPath = join33(projectRoot, entry.installPath);
90471
+ installPath = join34(projectRoot, entry.installPath);
88392
90472
  const source = readTemplateSource(entry);
88393
90473
  const sub = applySubstitution(entry, source);
88394
90474
  rendered = sub.rendered;
@@ -88402,7 +90482,7 @@ var init_install = __esm({
88402
90482
  return;
88403
90483
  }
88404
90484
  if (existsSync18(installPath)) {
88405
- const current = readFileSync15(installPath, "utf8");
90485
+ const current = readFileSync16(installPath, "utf8");
88406
90486
  if (current === rendered) {
88407
90487
  const noopResult = {
88408
90488
  id,
@@ -88550,8 +90630,8 @@ var init_show3 = __esm({
88550
90630
  });
88551
90631
 
88552
90632
  // packages/cleo/src/cli/commands/templates/upgrade.ts
88553
- import { existsSync as existsSync19, mkdirSync as mkdirSync6, readFileSync as readFileSync16, writeFileSync as writeFileSync7 } from "node:fs";
88554
- 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";
88555
90635
  import { getTemplateById as getTemplateById4 } from "@cleocode/core/templates/registry";
88556
90636
  var templatesUpgradeCommand;
88557
90637
  var init_upgrade2 = __esm({
@@ -88613,7 +90693,7 @@ var init_upgrade2 = __esm({
88613
90693
  let rendered;
88614
90694
  try {
88615
90695
  projectRoot = resolveProjectRoot6(args["project"]);
88616
- installPath = join34(projectRoot, entry.installPath);
90696
+ installPath = join35(projectRoot, entry.installPath);
88617
90697
  const source = readTemplateSource(entry);
88618
90698
  rendered = applySubstitution(entry, source).rendered;
88619
90699
  } catch (err) {
@@ -88626,7 +90706,7 @@ var init_upgrade2 = __esm({
88626
90706
  }
88627
90707
  const previewOnly = args["diff"] === true;
88628
90708
  const accept = args["accept"] === true;
88629
- const current = existsSync19(installPath) ? readFileSync16(installPath, "utf8") : null;
90709
+ const current = existsSync19(installPath) ? readFileSync17(installPath, "utf8") : null;
88630
90710
  const diffBody = current === null ? "" : current === rendered ? "" : unifiedDiff(current, rendered);
88631
90711
  let outcome;
88632
90712
  let reason;
@@ -88850,7 +90930,7 @@ var testing_exports = {};
88850
90930
  __export(testing_exports, {
88851
90931
  testingCommand: () => testingCommand
88852
90932
  });
88853
- var validateCommand9, checkCommand8, statusCommand18, coverageCommand, runCommand7, testingCommand;
90933
+ var validateCommand9, checkCommand8, statusCommand18, coverageCommand, runCommand8, testingCommand;
88854
90934
  var init_testing = __esm({
88855
90935
  "packages/cleo/src/cli/commands/testing.ts"() {
88856
90936
  "use strict";
@@ -88935,7 +91015,7 @@ var init_testing = __esm({
88935
91015
  );
88936
91016
  }
88937
91017
  });
88938
- runCommand7 = defineCommand({
91018
+ runCommand8 = defineCommand({
88939
91019
  meta: { name: "run", description: "Run test suite" },
88940
91020
  args: {
88941
91021
  filter: {
@@ -88960,7 +91040,7 @@ var init_testing = __esm({
88960
91040
  check: checkCommand8,
88961
91041
  status: statusCommand18,
88962
91042
  coverage: coverageCommand,
88963
- run: runCommand7
91043
+ run: runCommand8
88964
91044
  },
88965
91045
  async run({ cmd, rawArgs }) {
88966
91046
  const firstArg = rawArgs?.find((a) => !a.startsWith("-"));
@@ -88976,12 +91056,12 @@ var token_exports = {};
88976
91056
  __export(token_exports, {
88977
91057
  tokenCommand: () => tokenCommand
88978
91058
  });
88979
- import { readFileSync as readFileSync17 } from "node:fs";
88980
- 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";
88981
91061
  function readPayload(args, textKey, fileKey) {
88982
91062
  const text = args[textKey];
88983
91063
  const file = args[fileKey];
88984
- if (file) return readFileSync17(file, "utf-8");
91064
+ if (file) return readFileSync18(file, "utf-8");
88985
91065
  return text;
88986
91066
  }
88987
91067
  var filterArgs, summaryCommand3, listCommand26, showCommand16, deleteCommand3, clearCommand2, estimateCommand, tokenCommand;
@@ -89141,7 +91221,7 @@ var init_token = __esm({
89141
91221
  domain: args.domain,
89142
91222
  operation: args.operation
89143
91223
  };
89144
- const result = args.record ? await recordTokenExchange2(getProjectRoot72(), input2) : await measureTokenExchange(input2);
91224
+ const result = args.record ? await recordTokenExchange2(getProjectRoot73(), input2) : await measureTokenExchange(input2);
89145
91225
  cliOutput(result, {
89146
91226
  command: "token",
89147
91227
  operation: args.record ? "admin.token.record" : "token.estimate"
@@ -89175,9 +91255,9 @@ var transcript_exports = {};
89175
91255
  __export(transcript_exports, {
89176
91256
  transcriptCommand: () => transcriptCommand
89177
91257
  });
89178
- import { homedir as homedir3 } from "node:os";
89179
- import { join as join35 } from "node:path";
89180
- 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";
89181
91261
  import {
89182
91262
  parseDurationMs,
89183
91263
  pruneTranscripts,
@@ -89207,7 +91287,7 @@ var init_transcript = __esm({
89207
91287
  async run({ args }) {
89208
91288
  if (args.pending) {
89209
91289
  try {
89210
- const projectRoot = getProjectRoot73();
91290
+ const projectRoot = getProjectRoot74();
89211
91291
  const { scanPendingTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
89212
91292
  const pending = await scanPendingTranscripts(projectRoot);
89213
91293
  cliOutput(
@@ -89230,7 +91310,7 @@ var init_transcript = __esm({
89230
91310
  }
89231
91311
  return;
89232
91312
  }
89233
- const projectsDir = args["projects-dir"] ?? join35(homedir3(), ".claude", "projects");
91313
+ const projectsDir = args["projects-dir"] ?? join36(homedir4(), ".claude", "projects");
89234
91314
  try {
89235
91315
  const result = await scanTranscripts(projectsDir);
89236
91316
  cliOutput(
@@ -89304,7 +91384,7 @@ var init_transcript = __esm({
89304
91384
  async run({ args }) {
89305
91385
  const tier = args.tier ?? "warm";
89306
91386
  const dryRun = args["dry-run"] ?? false;
89307
- const projectRoot = getProjectRoot73();
91387
+ const projectRoot = getProjectRoot74();
89308
91388
  try {
89309
91389
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
89310
91390
  const { findSessionTranscriptPath, listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -89420,7 +91500,7 @@ var init_transcript = __esm({
89420
91500
  const dryRun = args["dry-run"] ?? false;
89421
91501
  const olderThanHours = args["older-than-hours"] ? Number.parseInt(args["older-than-hours"], 10) : 24;
89422
91502
  const limit = args.limit ? Number.parseInt(args.limit, 10) : void 0;
89423
- const projectRoot = getProjectRoot73();
91503
+ const projectRoot = getProjectRoot74();
89424
91504
  try {
89425
91505
  const { extractTranscript } = await import("@cleocode/core/memory/transcript-extractor.js");
89426
91506
  const { listAllTranscripts } = await import("@cleocode/core/memory/transcript-scanner.js");
@@ -89540,7 +91620,7 @@ var init_transcript = __esm({
89540
91620
  process.exit(2);
89541
91621
  return;
89542
91622
  }
89543
- const projectsDir = args["projects-dir"] ?? join35(homedir3(), ".claude", "projects");
91623
+ const projectsDir = args["projects-dir"] ?? join36(homedir4(), ".claude", "projects");
89544
91624
  try {
89545
91625
  const pruneResult = await pruneTranscripts({
89546
91626
  olderThanMs,
@@ -89607,10 +91687,10 @@ __export(gateway_auto_start_exports, {
89607
91687
  spawnGatewayIfDown: () => spawnGatewayIfDown
89608
91688
  });
89609
91689
  import { once } from "node:events";
89610
- 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";
89611
91691
  import { mkdir as mkdir6 } from "node:fs/promises";
89612
91692
  import * as net from "node:net";
89613
- import { dirname as dirname12, join as join36 } from "node:path";
91693
+ import { dirname as dirname12, join as join37 } from "node:path";
89614
91694
  import { fileURLToPath as fileURLToPath6 } from "node:url";
89615
91695
  import { spawnWrapped } from "@cleocode/core/resources/spawn-wrapper.js";
89616
91696
  function shouldAutoStartGateway(config) {
@@ -89654,17 +91734,17 @@ function resolveCliEntryPath(startUrl = import.meta.url) {
89654
91734
  const startFile = realpathSync(fileURLToPath6(startUrl));
89655
91735
  let current = dirname12(startFile);
89656
91736
  for (let i = 0; i < 20; i++) {
89657
- const pkgJsonPath = join36(current, "package.json");
91737
+ const pkgJsonPath = join37(current, "package.json");
89658
91738
  if (existsSync20(pkgJsonPath)) {
89659
91739
  let pkgName;
89660
91740
  try {
89661
- const raw = readFileSync18(pkgJsonPath, "utf8");
91741
+ const raw = readFileSync19(pkgJsonPath, "utf8");
89662
91742
  const parsed = JSON.parse(raw);
89663
91743
  pkgName = typeof parsed["name"] === "string" ? parsed["name"] : void 0;
89664
91744
  } catch {
89665
91745
  }
89666
91746
  if (pkgName === CLEO_PACKAGE_NAME) {
89667
- const entry = join36(current, "dist", "cli", "index.js");
91747
+ const entry = join37(current, "dist", "cli", "index.js");
89668
91748
  if (!existsSync20(entry)) {
89669
91749
  throw new Error(
89670
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`
@@ -89701,8 +91781,8 @@ async function spawnGatewayIfDown(opts = {}) {
89701
91781
  const { getCleoLogDir } = await import("@cleocode/core");
89702
91782
  const logDir = getCleoLogDir();
89703
91783
  await mkdir6(logDir, { recursive: true });
89704
- const outStream = createWriteStream(join36(logDir, "gateway.log"), { flags: "a" });
89705
- 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" });
89706
91786
  await Promise.all([once(outStream, "open"), once(errStream, "open")]);
89707
91787
  outFd = outStream;
89708
91788
  errFd = errStream;
@@ -90161,8 +92241,8 @@ __export(cockpit_exports, {
90161
92241
  KanbanBoardComponent: () => KanbanBoardComponent,
90162
92242
  runCockpit: () => runCockpit
90163
92243
  });
90164
- import { readFileSync as readFileSync19 } from "node:fs";
90165
- import { join as join37 } from "node:path";
92244
+ import { readFileSync as readFileSync20 } from "node:fs";
92245
+ import { join as join38 } from "node:path";
90166
92246
  import { createCleoClient as createCleoClient2 } from "@cleocode/core/gateway-client";
90167
92247
  async function fetchTaskRows(baseUrl) {
90168
92248
  const client = createCleoClient2({ baseUrl });
@@ -90279,8 +92359,8 @@ async function runCockpit(options = {}, sink = (line) => process.stdout.write(`$
90279
92359
  }
90280
92360
  try {
90281
92361
  const { getCleoLogDir } = await import("@cleocode/core");
90282
- const errPath = join37(getCleoLogDir(), "gateway.err");
90283
- const errContent = readFileSync19(errPath, "utf8").trimEnd();
92362
+ const errPath = join38(getCleoLogDir(), "gateway.err");
92363
+ const errContent = readFileSync20(errPath, "utf8").trimEnd();
90284
92364
  if (errContent.length > 0) {
90285
92365
  const lastLine = errContent.split("\n").at(-1) ?? "";
90286
92366
  if (lastLine.length > 0) {
@@ -91308,7 +93388,7 @@ var init_verify = __esm({
91308
93388
  },
91309
93389
  evidence: {
91310
93390
  type: "string",
91311
- 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)."
91312
93392
  },
91313
93393
  explain: {
91314
93394
  type: "boolean",
@@ -91330,6 +93410,10 @@ var init_verify = __esm({
91330
93410
  type: "string",
91331
93411
  description: "With --auto: the merged PR that implements the task"
91332
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
+ },
91333
93417
  "shared-evidence": {
91334
93418
  type: "boolean",
91335
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."
@@ -91341,76 +93425,85 @@ var init_verify = __esm({
91341
93425
  return;
91342
93426
  }
91343
93427
  const isWrite = !!(args.gate || args.all || args.reset);
91344
- if (args.auto === true) {
91345
- if (isWrite || args.evidence || args.run === true) {
91346
- cliError(
91347
- "--auto derives its own evidence; drop --gate/--all/--reset/--evidence/--run",
91348
- "E_INVALID_INPUT"
91349
- );
91350
- 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" });
91351
93461
  return;
91352
93462
  }
91353
- const { parseDoneOptions } = await import("@cleocode/core/tasks/done-plan.js");
91354
- const parsed = parseDoneOptions(args.satisfies, args.pr);
91355
- if (!parsed.ok) {
91356
- 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");
91357
93465
  process.exitCode = 6 /* VALIDATION_ERROR */;
91358
93466
  return;
91359
93467
  }
91360
- const { recordTaskDone } = await import("@cleocode/core/tasks/done-record.js");
91361
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core/paths.js");
91362
- const r = await recordTaskDone(args.taskId, {
91363
- projectRoot: getProjectRoot75(),
91364
- ...parsed.options,
91365
- ...args.agent ? { agent: args.agent } : {}
91366
- });
91367
- if (!r.success) {
91368
- cliError(r.error.message, r.error.code, { fix: r.error.fix, details: r.error.details });
91369
- 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 */;
91370
93479
  return;
91371
93480
  }
91372
- const { plan: _plan, ...summary } = r.data;
91373
- cliOutput(summary, { command: "verify", operation: "check.gate.auto" });
91374
- return;
91375
- }
91376
- if (args.satisfies !== void 0 || args.pr !== void 0) {
91377
- cliError("--satisfies and --pr apply only with --auto (or cleo done)", "E_INVALID_INPUT");
91378
- process.exitCode = 6 /* VALIDATION_ERROR */;
91379
- return;
91380
- }
91381
- if (args.run === true && isWrite) {
91382
- cliError(
91383
- "--run reports typed gate results and records nothing; it cannot be combined with --gate/--all/--reset.",
91384
- 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,
91385
93487
  {
91386
- name: "E_VALIDATION",
91387
- 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 } : {}
91388
93498
  },
91389
- { operation: "check.gate.run" }
93499
+ { command: "verify" }
91390
93500
  );
91391
- process.exitCode = 6 /* VALIDATION_ERROR */;
91392
- 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
+ }
91393
93506
  }
91394
- const useExplain = !isWrite && args.explain === true;
91395
- const operation = isWrite ? "gate.set" : args.run === true ? "gate.run" : useExplain ? "verify.explain" : "gate.status";
91396
- await dispatchFromCli(
91397
- isWrite ? "mutate" : "query",
91398
- "check",
91399
- operation,
91400
- {
91401
- taskId: args.taskId,
91402
- gate: args.gate,
91403
- value: args.value === "false" ? false : args.gate ? true : void 0,
91404
- agent: args.agent,
91405
- all: args.all,
91406
- reset: args.reset,
91407
- evidence: args.evidence,
91408
- sharedEvidence: args["shared-evidence"] ?? false,
91409
- // T12621: citty turns `--no-run` into `run: false`; read it through the helper.
91410
- ...isWrite && negatedFlag(args, "run") ? { noRun: true } : {}
91411
- },
91412
- { command: "verify" }
91413
- );
91414
93507
  }
91415
93508
  });
91416
93509
  }
@@ -91671,7 +93764,7 @@ var workgraph_exports = {};
91671
93764
  __export(workgraph_exports, {
91672
93765
  workgraphCommand: () => workgraphCommand
91673
93766
  });
91674
- import { readFileSync as readFileSync20 } from "node:fs";
93767
+ import { readFileSync as readFileSync21 } from "node:fs";
91675
93768
  import { resolve as resolve12 } from "node:path";
91676
93769
  var validateCommand10, applyCommand, planCommand4, structureCommand, statusCommand20, workgraphCommand;
91677
93770
  var init_workgraph2 = __esm({
@@ -91696,7 +93789,7 @@ var init_workgraph2 = __esm({
91696
93789
  const filePath = resolve12(String(args.file));
91697
93790
  let raw;
91698
93791
  try {
91699
- raw = readFileSync20(filePath, "utf-8");
93792
+ raw = readFileSync21(filePath, "utf-8");
91700
93793
  } catch {
91701
93794
  cliOutput2(
91702
93795
  { error: `Cannot read file: ${filePath}` },
@@ -91741,7 +93834,7 @@ var init_workgraph2 = __esm({
91741
93834
  const filePath = resolve12(String(args.file));
91742
93835
  let raw;
91743
93836
  try {
91744
- raw = readFileSync20(filePath, "utf-8");
93837
+ raw = readFileSync21(filePath, "utf-8");
91745
93838
  } catch {
91746
93839
  cliOutput2(
91747
93840
  { error: `Cannot read file: ${filePath}` },
@@ -91783,9 +93876,9 @@ var init_workgraph2 = __esm({
91783
93876
  },
91784
93877
  async run({ args }) {
91785
93878
  const { generatePlanningDoc } = await import("@cleocode/core/workgraph");
91786
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
93879
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
91787
93880
  const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
91788
- const projectRoot = getProjectRoot75();
93881
+ const projectRoot = getProjectRoot76();
91789
93882
  const audience = String(args.audience) === "agent" ? "agent" : "maintainer";
91790
93883
  const result = await generatePlanningDoc(projectRoot, {
91791
93884
  sagaId: String(args.sagaId),
@@ -91802,9 +93895,9 @@ var init_workgraph2 = __esm({
91802
93895
  async run() {
91803
93896
  const { validateWorkGraphStructure } = await import("@cleocode/core/workgraph");
91804
93897
  const { taskList: taskList2 } = await import("@cleocode/core/internal");
91805
- const { getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
93898
+ const { getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
91806
93899
  const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
91807
- const projectRoot = getProjectRoot75();
93900
+ const projectRoot = getProjectRoot76();
91808
93901
  const listResult = await taskList2(projectRoot, { limit: 5e3 });
91809
93902
  const tasks = listResult.success ? listResult.data?.tasks ?? [] : [];
91810
93903
  const nodes = tasks.map((t) => ({
@@ -91823,9 +93916,9 @@ var init_workgraph2 = __esm({
91823
93916
  description: "One-shot saga-to-saga workgraph dashboard (tracking checklist)"
91824
93917
  },
91825
93918
  async run() {
91826
- const { sagas: sagas2, getProjectRoot: getProjectRoot75 } = await import("@cleocode/core");
93919
+ const { sagas: sagas2, getProjectRoot: getProjectRoot76 } = await import("@cleocode/core");
91827
93920
  const { cliOutput: cliOutput2 } = await Promise.resolve().then(() => (init_renderers(), renderers_exports));
91828
- const projectRoot = getProjectRoot75();
93921
+ const projectRoot = getProjectRoot76();
91829
93922
  const listResult = await sagas2.sagaList(projectRoot);
91830
93923
  if (!listResult.success) {
91831
93924
  cliOutput2(listResult, { command: "workgraph", operation: "workgraph.status" });
@@ -91891,7 +93984,7 @@ __export(worktree_exports, {
91891
93984
  worktreeCommand: () => worktreeCommand
91892
93985
  });
91893
93986
  import readline4 from "node:readline";
91894
- import { getProjectRoot as getProjectRoot74, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
93987
+ import { getProjectRoot as getProjectRoot75, listWorktrees as listWorktrees2 } from "@cleocode/core/internal";
91895
93988
  async function promptYesNo2(question) {
91896
93989
  return new Promise((resolve13) => {
91897
93990
  const rl = readline4.createInterface({ input: process.stdin, output: process.stdout });
@@ -91996,7 +94089,7 @@ var init_worktree3 = __esm({
91996
94089
  const staleDays = staleDaysRaw !== void 0 ? Number.parseInt(staleDaysRaw, 10) : void 0;
91997
94090
  const idleDaysRaw = typeof args["idle-days"] === "string" ? args["idle-days"] : void 0;
91998
94091
  const idleDays = idleDaysRaw !== void 0 ? Number.parseInt(idleDaysRaw, 10) : void 0;
91999
- const projectRoot = getProjectRoot74();
94092
+ const projectRoot = getProjectRoot75();
92000
94093
  const listResult = await listWorktrees2({
92001
94094
  projectRoot,
92002
94095
  ...staleDays !== void 0 && !Number.isNaN(staleDays) ? { staleDays } : {}
@@ -92235,8 +94328,8 @@ var init_worktree3 = __esm({
92235
94328
 
92236
94329
  // packages/cleo/src/cli/index.ts
92237
94330
  init_dist();
92238
- import { readFileSync as readFileSync21 } from "node:fs";
92239
- 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";
92240
94333
  import { fileURLToPath as fileURLToPath7 } from "node:url";
92241
94334
  import { enforceNodeVersion } from "@cleocode/paths";
92242
94335
 
@@ -92446,6 +94539,12 @@ var COMMAND_MANIFEST = [
92446
94539
  description: "Classify a task: readiness verdict (proceed|grill) + persona routing (agent, confidence)",
92447
94540
  load: async () => (await Promise.resolve().then(() => (init_classify(), classify_exports))).classifyCommand
92448
94541
  },
94542
+ {
94543
+ exportName: "cloudCommand",
94544
+ name: "cloud",
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.",
94546
+ load: async () => (await Promise.resolve().then(() => (init_cloud(), cloud_exports))).cloudCommand
94547
+ },
92449
94548
  {
92450
94549
  exportName: "codeCommand",
92451
94550
  name: "code",
@@ -92674,6 +94773,12 @@ var COMMAND_MANIFEST = [
92674
94773
  description: "Audit the machine-wide memory guard that bounds test runs an agent starts OUTSIDE cleo ",
92675
94774
  load: async () => (await Promise.resolve().then(() => (init_doctor_memory_guard(), doctor_memory_guard_exports))).doctorMemoryGuardCommand
92676
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
+ },
92677
94782
  {
92678
94783
  exportName: "doctorNexusResidencyCommand",
92679
94784
  name: "nexus-residency",
@@ -92866,6 +94971,12 @@ var COMMAND_MANIFEST = [
92866
94971
  description: "Completion timeline and productivity analytics",
92867
94972
  load: async () => (await Promise.resolve().then(() => (init_history(), history_exports))).historyCommand
92868
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
+ },
92869
94980
  {
92870
94981
  exportName: "hygieneCommand",
92871
94982
  name: "hygiene",
@@ -92971,7 +95082,7 @@ var COMMAND_MANIFEST = [
92971
95082
  {
92972
95083
  exportName: "logoutCommand",
92973
95084
  name: "logout",
92974
- description: "Sign out. cleo logout [nexus] revokes the Cleo Nexus session server-side and deletes the stored token; cleo logout <provider> [label] removes an LLM credential exactly like cleo auth remove (the label may be omitted when the provider has one credential).",
95085
+ description: "Sign out. cleo logout [nexus] signs this machine out of Cleo Nexus (the device keeps its id for the next login; --revoke burns it), confirmed by the server; cleo logout <provider> [label] removes an LLM credential exactly like cleo auth remove (the label may be omitted when the provider has one credential).",
92975
95086
  load: async () => (await Promise.resolve().then(() => (init_logout(), logout_exports))).logoutCommand
92976
95087
  },
92977
95088
  {
@@ -93172,6 +95283,12 @@ var COMMAND_MANIFEST = [
93172
95283
  description: "Generate project roadmap from task provenance \u2014 epics grouped by status with progress",
93173
95284
  load: async () => (await Promise.resolve().then(() => (init_roadmap(), roadmap_exports))).roadmapCommand
93174
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
+ },
93175
95292
  {
93176
95293
  exportName: "safestopCommand",
93177
95294
  name: "safestop",
@@ -93579,12 +95696,12 @@ init_did_you_mean();
93579
95696
 
93580
95697
  // packages/cleo/src/cli/lib/first-run-detection.ts
93581
95698
  import { existsSync as existsSync21 } from "node:fs";
93582
- import { join as join38 } from "node:path";
95699
+ import { join as join39 } from "node:path";
93583
95700
  async function detectFirstRun() {
93584
95701
  const envKey = process.env["ANTHROPIC_API_KEY"];
93585
95702
  if (typeof envKey === "string" && envKey.length > 0) return false;
93586
95703
  const { getCleoPlatformPaths } = await import("@cleocode/paths");
93587
- const configPath = join38(getCleoPlatformPaths().config, "config.json");
95704
+ const configPath = join39(getCleoPlatformPaths().config, "config.json");
93588
95705
  if (existsSync21(configPath)) return false;
93589
95706
  try {
93590
95707
  const { getCredentialPool: getCredentialPool2 } = await import("@cleocode/core/llm/credential-pool.js");
@@ -93716,8 +95833,8 @@ async function resolveSubCommandForHelp(cmd, rawArgs) {
93716
95833
  init_summary_context();
93717
95834
  enforceNodeVersion();
93718
95835
  function getPackageVersion() {
93719
- const pkgPath = join39(dirname13(fileURLToPath7(import.meta.url)), "../../package.json");
93720
- 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"));
93721
95838
  return pkg.version;
93722
95839
  }
93723
95840
  var CLI_VERSION = getPackageVersion();
@@ -93758,6 +95875,7 @@ async function startCli() {
93758
95875
  let describeFlag = false;
93759
95876
  for (let i = 0; i < argv.length; i++) {
93760
95877
  const arg = argv[i];
95878
+ if (arg === "--") break;
93761
95879
  if (arg === "--json") rawOpts["json"] = true;
93762
95880
  else if (arg === "--human") rawOpts["human"] = true;
93763
95881
  else if (arg === "--quiet") rawOpts["quiet"] = true;
@@ -93968,7 +96086,7 @@ async function runStartupMaintenance() {
93968
96086
  detectAndRemoveStrayProjectNexus,
93969
96087
  getGlobalSalt,
93970
96088
  getLogger: getLogger22,
93971
- getProjectRoot: getProjectRoot75,
96089
+ getProjectRoot: getProjectRoot76,
93972
96090
  isCleanupMarkerSet,
93973
96091
  isMissingProjectError,
93974
96092
  migrateSignaldockToConduit,
@@ -93978,7 +96096,7 @@ async function runStartupMaintenance() {
93978
96096
  } = await import("@cleocode/core/internal");
93979
96097
  let projectRootForCleanup = "";
93980
96098
  try {
93981
- projectRootForCleanup = getProjectRoot75();
96099
+ projectRootForCleanup = getProjectRoot76();
93982
96100
  } catch {
93983
96101
  }
93984
96102
  if (!isCleanupMarkerSet(CLI_VERSION, projectRootForCleanup)) {
@@ -93998,7 +96116,7 @@ async function runStartupMaintenance() {
93998
96116
  const isInitInvocation = process.argv.slice(2).some((a) => a === "init");
93999
96117
  if (!isInitInvocation) {
94000
96118
  try {
94001
- const _projectRootForMigration = getProjectRoot75();
96119
+ const _projectRootForMigration = getProjectRoot76();
94002
96120
  if (needsSignaldockToConduitMigration(_projectRootForMigration)) {
94003
96121
  const migrationResult = await migrateSignaldockToConduit(_projectRootForMigration);
94004
96122
  if (migrationResult.status === "failed") {