dreamcontext 0.8.1 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (127) hide show
  1. package/README.md +97 -3
  2. package/agents/sleep-product.md +22 -0
  3. package/agents/sleep-state.md +3 -1
  4. package/agents/sleep-tasks.md +3 -1
  5. package/dist/agents/sleep-product.md +22 -0
  6. package/dist/agents/sleep-state.md +3 -1
  7. package/dist/agents/sleep-tasks.md +3 -1
  8. package/dist/dashboard/assets/{BrainCanvas3D-CNDjMlun.js → BrainCanvas3D-CoTzHqzT.js} +1 -1
  9. package/dist/dashboard/assets/{_baseUniq-DtoPVYjz.js → _baseUniq-BlQ6XWxs.js} +1 -1
  10. package/dist/dashboard/assets/{ar-SA-G6X2FPQ2-D_dXe_8i.js → ar-SA-G6X2FPQ2-C4qyHe9L.js} +1 -1
  11. package/dist/dashboard/assets/{arc-8LFYH4lG.js → arc-uGukQNxI.js} +1 -1
  12. package/dist/dashboard/assets/{architectureDiagram-Q4EWVU46-BIgEpM4v.js → architectureDiagram-Q4EWVU46-BhtWTFvf.js} +1 -1
  13. package/dist/dashboard/assets/{az-AZ-76LH7QW2-C30ZBwgT.js → az-AZ-76LH7QW2-HfK2pIVQ.js} +1 -1
  14. package/dist/dashboard/assets/{bg-BG-XCXSNQG7-D0R9pSdG.js → bg-BG-XCXSNQG7-L7TlhXli.js} +1 -1
  15. package/dist/dashboard/assets/{blockDiagram-DXYQGD6D-DRTa0DpJ.js → blockDiagram-DXYQGD6D-BmPhQEp6.js} +1 -1
  16. package/dist/dashboard/assets/{bn-BD-2XOGV67Q-vkWxteG3.js → bn-BD-2XOGV67Q-DE0uNoU6.js} +1 -1
  17. package/dist/dashboard/assets/{c4Diagram-AHTNJAMY-Do_gB8Cs.js → c4Diagram-AHTNJAMY-DtQKYrmP.js} +1 -1
  18. package/dist/dashboard/assets/{ca-ES-6MX7JW3Y-CTyxGdzW.js → ca-ES-6MX7JW3Y-7JHCTA6b.js} +1 -1
  19. package/dist/dashboard/assets/channel-3OfE-PZ3.js +1 -0
  20. package/dist/dashboard/assets/{chunk-4BX2VUAB-DJlttKoY.js → chunk-4BX2VUAB-BvnLY9qE.js} +1 -1
  21. package/dist/dashboard/assets/{chunk-4TB4RGXK-BdixZX4J.js → chunk-4TB4RGXK--piiFXgS.js} +1 -1
  22. package/dist/dashboard/assets/{chunk-55IACEB6-CPhKaTLr.js → chunk-55IACEB6-C7uvmawY.js} +1 -1
  23. package/dist/dashboard/assets/{chunk-EDXVE4YY-Bv0bQVvi.js → chunk-EDXVE4YY-BuWBKOPY.js} +1 -1
  24. package/dist/dashboard/assets/{chunk-FMBD7UC4-DGjRdLDd.js → chunk-FMBD7UC4-C1Le6hxh.js} +1 -1
  25. package/dist/dashboard/assets/{chunk-OYMX7WX6-B-wzkRri.js → chunk-OYMX7WX6-B8JE8Wz4.js} +1 -1
  26. package/dist/dashboard/assets/{chunk-QZHKN3VN-BwK1NqpV.js → chunk-QZHKN3VN-U9FJi59p.js} +1 -1
  27. package/dist/dashboard/assets/{chunk-YZCP3GAM-DjEwJGlh.js → chunk-YZCP3GAM-BNc94uy1.js} +1 -1
  28. package/dist/dashboard/assets/classDiagram-6PBFFD2Q-Dpt9qwZI.js +1 -0
  29. package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-Dpt9qwZI.js +1 -0
  30. package/dist/dashboard/assets/clone-CZ-InUnR.js +1 -0
  31. package/dist/dashboard/assets/{cose-bilkent-S5V4N54A-BJXUn11L.js → cose-bilkent-S5V4N54A-D0hUzBCj.js} +1 -1
  32. package/dist/dashboard/assets/{cs-CZ-2BRQDIVT-BjRikaNe.js → cs-CZ-2BRQDIVT-B0rWHDIi.js} +1 -1
  33. package/dist/dashboard/assets/{da-DK-5WZEPLOC-Cn3GTxbV.js → da-DK-5WZEPLOC-D_PQO_T0.js} +1 -1
  34. package/dist/dashboard/assets/{dagre-KV5264BT-BHn2c24z.js → dagre-KV5264BT-B_bjkEDQ.js} +1 -1
  35. package/dist/dashboard/assets/{de-DE-XR44H4JA-IvGsdpTt.js → de-DE-XR44H4JA-D1G4J6Mz.js} +1 -1
  36. package/dist/dashboard/assets/{diagram-5BDNPKRD-YrlF3B5a.js → diagram-5BDNPKRD-B63uEoiS.js} +1 -1
  37. package/dist/dashboard/assets/{diagram-G4DWMVQ6-DHONF1OD.js → diagram-G4DWMVQ6-DShdwm3D.js} +1 -1
  38. package/dist/dashboard/assets/{diagram-MMDJMWI5-B1vJLt5b.js → diagram-MMDJMWI5-DdVsHQ-l.js} +1 -1
  39. package/dist/dashboard/assets/{diagram-TYMM5635-C8P5-4A3.js → diagram-TYMM5635-BdHifyqU.js} +1 -1
  40. package/dist/dashboard/assets/{el-GR-BZB4AONW-B9GA8_lO.js → el-GR-BZB4AONW-a0CO4RfB.js} +1 -1
  41. package/dist/dashboard/assets/{erDiagram-SMLLAGMA-CjWWTCWe.js → erDiagram-SMLLAGMA-CYxdxNcb.js} +1 -1
  42. package/dist/dashboard/assets/{es-ES-U4NZUMDT-Ct1wP_9r.js → es-ES-U4NZUMDT-ejRYVYRf.js} +1 -1
  43. package/dist/dashboard/assets/{eu-ES-A7QVB2H4-C-49gWlR.js → eu-ES-A7QVB2H4-B-4OXJLd.js} +1 -1
  44. package/dist/dashboard/assets/{fa-IR-HGAKTJCU-DUo8t-xv.js → fa-IR-HGAKTJCU-DhOcLy7v.js} +1 -1
  45. package/dist/dashboard/assets/{fi-FI-Z5N7JZ37-DCObnr3i.js → fi-FI-Z5N7JZ37-CKQF9xKf.js} +1 -1
  46. package/dist/dashboard/assets/{flowDiagram-DWJPFMVM-OQ_IRMqG.js → flowDiagram-DWJPFMVM-azQUtREP.js} +1 -1
  47. package/dist/dashboard/assets/{fr-FR-RHASNOE6-0EGg3zhN.js → fr-FR-RHASNOE6-CsGekBXq.js} +1 -1
  48. package/dist/dashboard/assets/{ganttDiagram-T4ZO3ILL-DPTSBcnu.js → ganttDiagram-T4ZO3ILL-DjXmGcb4.js} +2 -2
  49. package/dist/dashboard/assets/{gitGraphDiagram-UUTBAWPF-BxfeiCqm.js → gitGraphDiagram-UUTBAWPF-Dz87wo6e.js} +1 -1
  50. package/dist/dashboard/assets/{gl-ES-HMX3MZ6V-WtVwXY6x.js → gl-ES-HMX3MZ6V-NRfsjlmW.js} +1 -1
  51. package/dist/dashboard/assets/{graph-Du_3_o8q.js → graph-BMW3t-Jz.js} +1 -1
  52. package/dist/dashboard/assets/{he-IL-6SHJWFNN-CfgspIku.js → he-IL-6SHJWFNN-CK4gfEss.js} +1 -1
  53. package/dist/dashboard/assets/{hi-IN-IWLTKZ5I-CS9l2g3B.js → hi-IN-IWLTKZ5I-CqyBl1jA.js} +1 -1
  54. package/dist/dashboard/assets/{hu-HU-A5ZG7DT2-BQ46AerM.js → hu-HU-A5ZG7DT2-BO0SthvO.js} +1 -1
  55. package/dist/dashboard/assets/{id-ID-SAP4L64H-BeShJyKQ.js → id-ID-SAP4L64H-CrHxJe1s.js} +1 -1
  56. package/dist/dashboard/assets/{index-D7dWmypK.js → index-B0pCDfL8.js} +1 -1
  57. package/dist/dashboard/assets/index-rIZLhbl7.js +480 -0
  58. package/dist/dashboard/assets/index-sax--nf3.css +1 -0
  59. package/dist/dashboard/assets/{infoDiagram-42DDH7IO-CcFhyaQp.js → infoDiagram-42DDH7IO-zG-8q9HR.js} +1 -1
  60. package/dist/dashboard/assets/{ishikawaDiagram-UXIWVN3A-9QJeD00p.js → ishikawaDiagram-UXIWVN3A-5OzPmL1c.js} +1 -1
  61. package/dist/dashboard/assets/{it-IT-JPQ66NNP-csyvfk0t.js → it-IT-JPQ66NNP-CW6fpZrT.js} +1 -1
  62. package/dist/dashboard/assets/{ja-JP-DBVTYXUO-DctpJ2yz.js → ja-JP-DBVTYXUO-DMJRiMhd.js} +1 -1
  63. package/dist/dashboard/assets/{journeyDiagram-VCZTEJTY-CU4EYedt.js → journeyDiagram-VCZTEJTY-f8lbDQ22.js} +1 -1
  64. package/dist/dashboard/assets/{kaa-6HZHGXH3-D0tWzHt3.js → kaa-6HZHGXH3-C4yr2X6j.js} +1 -1
  65. package/dist/dashboard/assets/{kab-KAB-ZGHBKWFO-BC-g4xJU.js → kab-KAB-ZGHBKWFO-BtwhZ5Ak.js} +1 -1
  66. package/dist/dashboard/assets/{kanban-definition-6JOO6SKY-BxXqVmz1.js → kanban-definition-6JOO6SKY-BJtF1llZ.js} +1 -1
  67. package/dist/dashboard/assets/{kk-KZ-P5N5QNE5-TLB3Lxri.js → kk-KZ-P5N5QNE5-BiS5ISFw.js} +1 -1
  68. package/dist/dashboard/assets/{km-KH-HSX4SM5Z-DCh7cRAS.js → km-KH-HSX4SM5Z-CJcAjj0D.js} +1 -1
  69. package/dist/dashboard/assets/{ko-KR-MTYHY66A-BPIl5ido.js → ko-KR-MTYHY66A-yw6XRj7m.js} +1 -1
  70. package/dist/dashboard/assets/{ku-TR-6OUDTVRD-TUpeN1Tm.js → ku-TR-6OUDTVRD-nAwdHGyN.js} +1 -1
  71. package/dist/dashboard/assets/{layout-CyrgfqIp.js → layout-guqP2e-e.js} +1 -1
  72. package/dist/dashboard/assets/linear-W2_Ct9N6.js +1 -0
  73. package/dist/dashboard/assets/{lt-LT-XHIRWOB4-BRKyR_Xw.js → lt-LT-XHIRWOB4-D7h1NJrv.js} +1 -1
  74. package/dist/dashboard/assets/{lv-LV-5QDEKY6T-BANbTe4s.js → lv-LV-5QDEKY6T-DJfUJgRc.js} +1 -1
  75. package/dist/dashboard/assets/{min-lcwVZhZ7.js → min-BlLHklQU.js} +1 -1
  76. package/dist/dashboard/assets/{mindmap-definition-QFDTVHPH-fVIbdlXp.js → mindmap-definition-QFDTVHPH-Ch2AO4mc.js} +1 -1
  77. package/dist/dashboard/assets/{mr-IN-CRQNXWMA-DLFutdXk.js → mr-IN-CRQNXWMA-BV3znx0p.js} +1 -1
  78. package/dist/dashboard/assets/{my-MM-5M5IBNSE-CGWrcNBC.js → my-MM-5M5IBNSE-IjUN-e5U.js} +1 -1
  79. package/dist/dashboard/assets/{nb-NO-T6EIAALU-CGRDupuc.js → nb-NO-T6EIAALU-MMsvbc2a.js} +1 -1
  80. package/dist/dashboard/assets/{nl-NL-IS3SIHDZ-BKwBfrzp.js → nl-NL-IS3SIHDZ-ByYTJGOK.js} +1 -1
  81. package/dist/dashboard/assets/{nn-NO-6E72VCQL-DDQkGe44.js → nn-NO-6E72VCQL-Bgbgzvhm.js} +1 -1
  82. package/dist/dashboard/assets/{oc-FR-POXYY2M6-DufeHCWh.js → oc-FR-POXYY2M6-BMBbvfQp.js} +1 -1
  83. package/dist/dashboard/assets/{pa-IN-N4M65BXN-BUzelJDX.js → pa-IN-N4M65BXN-CgcUC9Zd.js} +1 -1
  84. package/dist/dashboard/assets/{percentages-BXMCSKIN-FxAvjywS.js → percentages-BXMCSKIN-AuedyVVS.js} +7 -7
  85. package/dist/dashboard/assets/{pica-Cek5bFnr.js → pica-DxO5y0j_.js} +1 -1
  86. package/dist/dashboard/assets/{pieDiagram-DEJITSTG-PgIrKPnB.js → pieDiagram-DEJITSTG-q-J8tI3B.js} +1 -1
  87. package/dist/dashboard/assets/{pl-PL-T2D74RX3-Bd-rxZs3.js → pl-PL-T2D74RX3-BaZSYTKJ.js} +1 -1
  88. package/dist/dashboard/assets/{pt-BR-5N22H2LF-D0QJGoo5.js → pt-BR-5N22H2LF-DSPF7aLm.js} +1 -1
  89. package/dist/dashboard/assets/{pt-PT-UZXXM6DQ-DjumltMq.js → pt-PT-UZXXM6DQ-aoPTHC3m.js} +1 -1
  90. package/dist/dashboard/assets/{quadrantDiagram-34T5L4WZ-C30tZOBh.js → quadrantDiagram-34T5L4WZ-CGbfFson.js} +1 -1
  91. package/dist/dashboard/assets/{requirementDiagram-MS252O5E-D3vhi-ZB.js → requirementDiagram-MS252O5E-ThxVmoCe.js} +1 -1
  92. package/dist/dashboard/assets/{ro-RO-JPDTUUEW-DmEo8cEd.js → ro-RO-JPDTUUEW-YfCwiIS2.js} +1 -1
  93. package/dist/dashboard/assets/{ru-RU-B4JR7IUQ-ZHCu1nBu.js → ru-RU-B4JR7IUQ-zIVsVhsz.js} +1 -1
  94. package/dist/dashboard/assets/{sankeyDiagram-XADWPNL6-Cmbs-PxO.js → sankeyDiagram-XADWPNL6-BvEv917s.js} +1 -1
  95. package/dist/dashboard/assets/{sequenceDiagram-FGHM5R23-DlBqk4uQ.js → sequenceDiagram-FGHM5R23-JrhjN3MG.js} +1 -1
  96. package/dist/dashboard/assets/{si-LK-N5RQ5JYF-iuqtpRqI.js → si-LK-N5RQ5JYF-CegSAwip.js} +1 -1
  97. package/dist/dashboard/assets/{sk-SK-C5VTKIMK-BWFUWdaQ.js → sk-SK-C5VTKIMK-C_K-Uoai.js} +1 -1
  98. package/dist/dashboard/assets/{sl-SI-NN7IZMDC-irYTfiq_.js → sl-SI-NN7IZMDC-DHGXOoZl.js} +1 -1
  99. package/dist/dashboard/assets/{stateDiagram-FHFEXIEX-B6T9ib8G.js → stateDiagram-FHFEXIEX-BzOtZESp.js} +1 -1
  100. package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-CjcHIbj7.js +1 -0
  101. package/dist/dashboard/assets/{subset-shared.chunk-LTgWgeng.js → subset-shared.chunk-BWfXaC19.js} +1 -1
  102. package/dist/dashboard/assets/{subset-worker.chunk-CT_2iDuG.js → subset-worker.chunk-DHcqLDUZ.js} +1 -1
  103. package/dist/dashboard/assets/{sv-SE-XGPEYMSR-BvDzjArd.js → sv-SE-XGPEYMSR-BoNob2y3.js} +1 -1
  104. package/dist/dashboard/assets/{ta-IN-2NMHFXQM-DdsS_3Yq.js → ta-IN-2NMHFXQM-C8UHJYct.js} +1 -1
  105. package/dist/dashboard/assets/{th-TH-HPSO5L25-Duadkok3.js → th-TH-HPSO5L25-D7wP1iSi.js} +1 -1
  106. package/dist/dashboard/assets/{timeline-definition-GMOUNBTQ-CHTQqVpC.js → timeline-definition-GMOUNBTQ-Gwb0w7bX.js} +1 -1
  107. package/dist/dashboard/assets/{tr-TR-DEFEU3FU-CTnPpl_3.js → tr-TR-DEFEU3FU-He51QB-L.js} +1 -1
  108. package/dist/dashboard/assets/{uk-UA-QMV73CPH-CAqmQ01_.js → uk-UA-QMV73CPH-Blg5n9CR.js} +1 -1
  109. package/dist/dashboard/assets/{vennDiagram-DHZGUBPP-tWl34rwo.js → vennDiagram-DHZGUBPP-y2S0dZjp.js} +1 -1
  110. package/dist/dashboard/assets/{vi-VN-M7AON7JQ-Cz7FDG8R.js → vi-VN-M7AON7JQ-2z-4xcM3.js} +1 -1
  111. package/dist/dashboard/assets/{wardley-RL74JXVD-UjdnBcpJ.js → wardley-RL74JXVD-BNThyuCt.js} +1 -1
  112. package/dist/dashboard/assets/{wardleyDiagram-NUSXRM2D-KhVWSzPf.js → wardleyDiagram-NUSXRM2D-Sljri5hz.js} +1 -1
  113. package/dist/dashboard/assets/{xychartDiagram-5P7HB3ND-SwtVQYTW.js → xychartDiagram-5P7HB3ND-BIFYd4_d.js} +1 -1
  114. package/dist/dashboard/assets/{zh-CN-LNUGB5OW-B7cbFS35.js → zh-CN-LNUGB5OW-DZ8sfmlq.js} +1 -1
  115. package/dist/dashboard/assets/{zh-HK-E62DVLB3-CLi9BFmp.js → zh-HK-E62DVLB3-Zvqwoloz.js} +1 -1
  116. package/dist/dashboard/assets/{zh-TW-RAJ6MFWO-XAcgJHay.js → zh-TW-RAJ6MFWO-Ck_uDtMQ.js} +1 -1
  117. package/dist/dashboard/index.html +2 -2
  118. package/dist/index.js +931 -483
  119. package/package.json +1 -1
  120. package/dist/dashboard/assets/channel-C5p1t-nJ.js +0 -1
  121. package/dist/dashboard/assets/classDiagram-6PBFFD2Q-sTJpbWV4.js +0 -1
  122. package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-sTJpbWV4.js +0 -1
  123. package/dist/dashboard/assets/clone-DTslXBzp.js +0 -1
  124. package/dist/dashboard/assets/index-C9VT2u9E.js +0 -480
  125. package/dist/dashboard/assets/index-DoFaQKCx.css +0 -1
  126. package/dist/dashboard/assets/linear-B6cMUkoc.js +0 -1
  127. package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-CN0hAOp7.js +0 -1
package/dist/index.js CHANGED
@@ -18458,11 +18458,11 @@ var init_install_claude_md = __esm({
18458
18458
  import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
18459
18459
  import { dirname as dirname4, join as join6 } from "path";
18460
18460
  function applyClaudeAutoMemory(projectRoot, disable) {
18461
- const settingsPath = join6(projectRoot, ".claude", "settings.json");
18461
+ const settingsPath2 = join6(projectRoot, ".claude", "settings.json");
18462
18462
  let settings = {};
18463
- if (existsSync6(settingsPath)) {
18463
+ if (existsSync6(settingsPath2)) {
18464
18464
  try {
18465
- const parsed = JSON.parse(readFileSync7(settingsPath, "utf-8"));
18465
+ const parsed = JSON.parse(readFileSync7(settingsPath2, "utf-8"));
18466
18466
  if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
18467
18467
  settings = parsed;
18468
18468
  }
@@ -18473,8 +18473,8 @@ function applyClaudeAutoMemory(projectRoot, disable) {
18473
18473
  const desired = !disable;
18474
18474
  if (settings.autoMemoryEnabled === desired) return false;
18475
18475
  settings.autoMemoryEnabled = desired;
18476
- mkdirSync4(dirname4(settingsPath), { recursive: true });
18477
- writeFileSync7(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
18476
+ mkdirSync4(dirname4(settingsPath2), { recursive: true });
18477
+ writeFileSync7(settingsPath2, JSON.stringify(settings, null, 2) + "\n", "utf-8");
18478
18478
  return true;
18479
18479
  }
18480
18480
  var init_claude_settings = __esm({
@@ -22458,12 +22458,12 @@ async function resolvePlatforms(projectRoot, raw) {
22458
22458
  return platforms;
22459
22459
  }
22460
22460
  function ensureClaudeHooks(projectRoot) {
22461
- const settingsPath = join9(projectRoot, ".claude", "settings.json");
22461
+ const settingsPath2 = join9(projectRoot, ".claude", "settings.json");
22462
22462
  const result = { added: [], migrated: false };
22463
22463
  let settings = {};
22464
- if (existsSync9(settingsPath)) {
22464
+ if (existsSync9(settingsPath2)) {
22465
22465
  try {
22466
- settings = JSON.parse(readFileSync10(settingsPath, "utf-8"));
22466
+ settings = JSON.parse(readFileSync10(settingsPath2, "utf-8"));
22467
22467
  } catch {
22468
22468
  settings = {};
22469
22469
  }
@@ -22497,7 +22497,7 @@ function ensureClaudeHooks(projectRoot) {
22497
22497
  }
22498
22498
  }
22499
22499
  mkdirSync6(join9(projectRoot, ".claude"), { recursive: true });
22500
- writeFileSync9(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
22500
+ writeFileSync9(settingsPath2, JSON.stringify(settings, null, 2) + "\n", "utf-8");
22501
22501
  return result;
22502
22502
  }
22503
22503
  function findPackageFile(subdir, filename) {
@@ -34672,6 +34672,170 @@ var init_migration_runner = __esm({
34672
34672
  }
34673
34673
  });
34674
34674
 
34675
+ // src/lib/sleep-consolidation.ts
34676
+ function sleepinessLevel(debt) {
34677
+ if (debt <= 3) return "Alert";
34678
+ if (debt <= 6) return "Drowsy";
34679
+ if (debt <= 9) return "Sleepy";
34680
+ return "Must Sleep";
34681
+ }
34682
+ function sleepinessRange(debt) {
34683
+ if (debt <= 3) return "0-3";
34684
+ if (debt <= 6) return "4-6";
34685
+ if (debt <= 9) return "7-9";
34686
+ return "10+";
34687
+ }
34688
+ function recomputeDebt(sessions) {
34689
+ return sessions.reduce((sum, s) => sum + (s.score ?? 0), 0);
34690
+ }
34691
+ function depthFromDebt(debt) {
34692
+ if (debt <= 3) return "light";
34693
+ if (debt <= 9) return "standard";
34694
+ return "deep";
34695
+ }
34696
+ function consolidationDepth(debt, opts = {}) {
34697
+ const base = depthFromDebt(debt);
34698
+ if (opts.userRequestedDeep) {
34699
+ return { depth: "deep", reason: "user requested deep consolidation", source: "user" };
34700
+ }
34701
+ const bump = Math.max(0, Math.min(2, opts.agentBump ?? 0));
34702
+ if (bump > 0) {
34703
+ const baseIdx = DEPTH_ORDER.indexOf(base);
34704
+ const idx = Math.min(DEPTH_ORDER.length - 1, baseIdx + bump);
34705
+ return {
34706
+ depth: DEPTH_ORDER[idx],
34707
+ reason: `agent bumped depth by ${bump} tier(s) from ${base}`,
34708
+ source: "agent"
34709
+ };
34710
+ }
34711
+ return { depth: base, reason: `debt ${debt} \u2192 ${base}`, source: "debt" };
34712
+ }
34713
+ function isDestructiveAllowed(depth) {
34714
+ return depth === "deep";
34715
+ }
34716
+ function applyConsolidation(state, epoch) {
34717
+ const next = cloneState(state);
34718
+ let sessionsProcessed = 0;
34719
+ let bookmarksProcessed = 0;
34720
+ let processedSessionIds = [];
34721
+ if (epoch) {
34722
+ const processedSessions = next.sessions.filter((s) => !s.stopped_at || s.stopped_at <= epoch);
34723
+ sessionsProcessed = processedSessions.length;
34724
+ processedSessionIds = processedSessions.map((s) => s.session_id);
34725
+ bookmarksProcessed = next.bookmarks.filter((b) => b.created_at <= epoch).length;
34726
+ next.sessions = next.sessions.filter((s) => {
34727
+ if (!s.stopped_at) return false;
34728
+ return s.stopped_at > epoch;
34729
+ });
34730
+ next.bookmarks = next.bookmarks.filter((b) => b.created_at > epoch);
34731
+ next.dashboard_changes = next.dashboard_changes.filter((c) => c.timestamp > epoch);
34732
+ next.debt = recomputeDebt(next.sessions);
34733
+ } else {
34734
+ sessionsProcessed = next.sessions.length;
34735
+ processedSessionIds = next.sessions.map((s) => s.session_id);
34736
+ bookmarksProcessed = next.bookmarks.length;
34737
+ next.sessions = [];
34738
+ next.bookmarks = [];
34739
+ next.dashboard_changes = [];
34740
+ next.debt = 0;
34741
+ }
34742
+ next.triggers = next.triggers.filter((t) => t.fired_count < t.max_fires);
34743
+ return { state: next, sessionsProcessed, bookmarksProcessed, processedSessionIds };
34744
+ }
34745
+ function upsertSessionOnStop(state, input2) {
34746
+ const next = cloneState(state);
34747
+ const existing = next.sessions.findIndex((s) => s.session_id === input2.session_id);
34748
+ if (existing >= 0) {
34749
+ const oldScore = next.sessions[existing].score ?? 0;
34750
+ next.debt = Math.max(0, next.debt - oldScore);
34751
+ const existingSlugs = next.sessions[existing].task_slugs ?? [];
34752
+ next.sessions[existing] = {
34753
+ ...next.sessions[existing],
34754
+ transcript_path: input2.transcript_path,
34755
+ stopped_at: input2.stopped_at,
34756
+ last_assistant_message: input2.last_assistant_message,
34757
+ change_count: input2.change_count,
34758
+ tool_count: input2.tool_count,
34759
+ score: input2.score,
34760
+ task_slugs: [.../* @__PURE__ */ new Set([...existingSlugs, ...input2.task_slugs])]
34761
+ };
34762
+ next.debt += input2.score;
34763
+ } else {
34764
+ next.sessions.unshift({
34765
+ session_id: input2.session_id,
34766
+ transcript_path: input2.transcript_path,
34767
+ stopped_at: input2.stopped_at,
34768
+ last_assistant_message: input2.last_assistant_message,
34769
+ change_count: input2.change_count,
34770
+ tool_count: input2.tool_count,
34771
+ score: input2.score,
34772
+ task_slugs: input2.task_slugs
34773
+ });
34774
+ next.debt += input2.score;
34775
+ next.sessions_since_last_sleep = (next.sessions_since_last_sleep || 0) + 1;
34776
+ }
34777
+ return next;
34778
+ }
34779
+ function appendCompactionRecord(state, record) {
34780
+ const next = cloneState(state);
34781
+ next.compaction_log.unshift(record);
34782
+ if (next.compaction_log.length > COMPACTION_LOG_CAP) {
34783
+ next.compaction_log = next.compaction_log.slice(0, COMPACTION_LOG_CAP);
34784
+ }
34785
+ return next;
34786
+ }
34787
+ function validateSleepAdd(scoreStr, desc) {
34788
+ const score = parseInt(scoreStr, 10);
34789
+ if (isNaN(score) || score < 1 || score > 3) {
34790
+ return { ok: false, error: "Score must be 1, 2, or 3." };
34791
+ }
34792
+ if (!desc.trim()) {
34793
+ return { ok: false, error: "Description is required." };
34794
+ }
34795
+ return { ok: true };
34796
+ }
34797
+ function buildHistoryEntry(prevDebt, result, summary, today2) {
34798
+ return {
34799
+ date: today2,
34800
+ consolidated_at: (/* @__PURE__ */ new Date()).toISOString(),
34801
+ summary: summary.trim(),
34802
+ debt_before: prevDebt,
34803
+ debt_after: result.state.debt,
34804
+ sessions_processed: result.sessionsProcessed,
34805
+ bookmarks_processed: result.bookmarksProcessed,
34806
+ session_ids: result.processedSessionIds
34807
+ };
34808
+ }
34809
+ function finalizeSleepState(state, summary, today2) {
34810
+ const next = cloneState(state);
34811
+ next.last_sleep = today2;
34812
+ next.last_sleep_summary = summary.trim();
34813
+ next.sleep_started_at = null;
34814
+ next.sessions_since_last_sleep = 0;
34815
+ next.consolidation_depth = null;
34816
+ return next;
34817
+ }
34818
+ function cloneState(state) {
34819
+ return {
34820
+ ...state,
34821
+ sessions: state.sessions.map((s) => ({ ...s, task_slugs: [...s.task_slugs ?? []] })),
34822
+ bookmarks: state.bookmarks.map((b) => ({ ...b })),
34823
+ triggers: state.triggers.map((t) => ({ ...t })),
34824
+ knowledge_access: { ...state.knowledge_access },
34825
+ dashboard_changes: state.dashboard_changes.map((c) => ({ ...c })),
34826
+ compaction_log: state.compaction_log.map((c) => ({ ...c })),
34827
+ pendingMigrationNotices: [...state.pendingMigrationNotices]
34828
+ };
34829
+ }
34830
+ var DEPTH_ORDER, COMPACTION_LOG_CAP;
34831
+ var init_sleep_consolidation = __esm({
34832
+ "src/lib/sleep-consolidation.ts"() {
34833
+ "use strict";
34834
+ DEPTH_ORDER = ["light", "standard", "deep"];
34835
+ COMPACTION_LOG_CAP = 20;
34836
+ }
34837
+ });
34838
+
34675
34839
  // src/cli/commands/sleep.ts
34676
34840
  import { existsSync as existsSync37 } from "fs";
34677
34841
  import { join as join37, dirname as dirname18 } from "path";
@@ -34695,6 +34859,7 @@ function freshDefaults() {
34695
34859
  dashboard_changes: [],
34696
34860
  compaction_log: [],
34697
34861
  recall_mode: "haiku",
34862
+ consolidation_depth: null,
34698
34863
  pendingMigrationNotices: []
34699
34864
  };
34700
34865
  }
@@ -34757,25 +34922,13 @@ function bumpKnowledgeAccess(state, slug) {
34757
34922
  state.knowledge_access[slug].last_accessed = today();
34758
34923
  state.knowledge_access[slug].count++;
34759
34924
  }
34760
- function getSleepinessLevel(debt) {
34761
- if (debt <= 3) return "Alert";
34762
- if (debt <= 6) return "Drowsy";
34763
- if (debt <= 9) return "Sleepy";
34764
- return "Must Sleep";
34765
- }
34766
- function getSleepinessRange(debt) {
34767
- if (debt <= 3) return "0-3";
34768
- if (debt <= 6) return "4-6";
34769
- if (debt <= 9) return "7-9";
34770
- return "10+";
34771
- }
34772
34925
  function registerSleepCommand(program2) {
34773
34926
  const sleep2 = program2.command("sleep").description("Track sleep debt and consolidation state");
34774
34927
  sleep2.command("status").description("Show current sleep debt level and history").action(() => {
34775
34928
  const root = ensureContextRoot();
34776
34929
  const state = readSleepState(root);
34777
- const level = getSleepinessLevel(state.debt);
34778
- const range = getSleepinessRange(state.debt);
34930
+ const level = sleepinessLevel(state.debt);
34931
+ const range = sleepinessRange(state.debt);
34779
34932
  console.log(header("Sleep State"));
34780
34933
  console.log(` Debt: ${source_default.bold(String(state.debt))} ${source_default.dim(`(${range})`)} ${source_default.magentaBright(level)}`);
34781
34934
  console.log(` Last sleep: ${state.last_sleep ? source_default.white(state.last_sleep) : source_default.dim("never")}`);
@@ -34803,16 +34956,13 @@ function registerSleepCommand(program2) {
34803
34956
  }
34804
34957
  });
34805
34958
  sleep2.command("add").argument("<score>", "Debt score to add (1-3)").argument("<description...>", "Description of what happened").description("Record a debt-accumulating action").action((scoreStr, descParts) => {
34806
- const score = parseInt(scoreStr, 10);
34807
- if (isNaN(score) || score < 1 || score > 3) {
34808
- error("Score must be 1, 2, or 3.");
34809
- return;
34810
- }
34811
34959
  const description = descParts.join(" ");
34812
- if (!description.trim()) {
34813
- error("Description is required.");
34960
+ const valid = validateSleepAdd(scoreStr, description);
34961
+ if (!valid.ok) {
34962
+ error(valid.error);
34814
34963
  return;
34815
34964
  }
34965
+ const score = parseInt(scoreStr, 10);
34816
34966
  const root = ensureContextRoot();
34817
34967
  const state = readSleepState(root);
34818
34968
  state.sessions.unshift({
@@ -34827,7 +34977,7 @@ function registerSleepCommand(program2) {
34827
34977
  });
34828
34978
  state.debt += score;
34829
34979
  writeSleepState(root, state);
34830
- const level = getSleepinessLevel(state.debt);
34980
+ const level = sleepinessLevel(state.debt);
34831
34981
  success(`Sleep debt: ${state.debt} (${level})`);
34832
34982
  if (state.debt >= 10) {
34833
34983
  warn("Must sleep! Debt is 10+. Consolidation needed.");
@@ -34835,12 +34985,14 @@ function registerSleepCommand(program2) {
34835
34985
  info("Getting sleepy. Consider consolidating soon.");
34836
34986
  }
34837
34987
  });
34838
- sleep2.command("start").description("Mark beginning of consolidation (sets epoch for safe clearing)").action(() => {
34988
+ sleep2.command("start").description("Mark beginning of consolidation (sets epoch for safe clearing)").option("--deep", "Force a deep consolidation (authorizes destructive knowledge ops)").action((opts) => {
34839
34989
  const root = ensureContextRoot();
34840
34990
  const state = readSleepState(root);
34841
34991
  if (state.sleep_started_at) {
34842
34992
  warn(`Consolidation already in progress (started ${state.sleep_started_at}). Overwriting epoch.`);
34843
34993
  }
34994
+ const decision = consolidationDepth(state.debt, { userRequestedDeep: !!opts.deep });
34995
+ state.consolidation_depth = decision.depth;
34844
34996
  state.pendingMigrationNotices = [];
34845
34997
  const projectRoot = dirname18(root);
34846
34998
  const config = readSetupConfig(projectRoot);
@@ -34864,6 +35016,10 @@ function registerSleepCommand(program2) {
34864
35016
  state.sleep_started_at = (/* @__PURE__ */ new Date()).toISOString();
34865
35017
  writeSleepState(root, state);
34866
35018
  success(`Consolidation epoch set: ${state.sleep_started_at}`);
35019
+ info(`Consolidation depth: ${decision.depth} (source: ${decision.source}) \u2014 ${decision.reason}`);
35020
+ if (decision.depth !== "deep") {
35021
+ info("Light/standard consolidation: do NOT merge/summarize-replace/delete knowledge \u2014 flag candidates in the report instead.");
35022
+ }
34867
35023
  });
34868
35024
  sleep2.command("done").argument("<summary...>", "Summary of what was consolidated").description("Mark consolidation complete, reset debt").action(async (summaryParts) => {
34869
35025
  const summary = summaryParts.join(" ");
@@ -34875,52 +35031,17 @@ function registerSleepCommand(program2) {
34875
35031
  const state = readSleepState(root);
34876
35032
  const previousDebt = state.debt;
34877
35033
  const epoch = state.sleep_started_at;
34878
- let sessionsProcessed = 0;
34879
- let bookmarksProcessed = 0;
34880
- let processedSessionIds = [];
34881
- if (epoch) {
34882
- const processedSessions = state.sessions.filter((s) => !s.stopped_at || s.stopped_at <= epoch);
34883
- sessionsProcessed = processedSessions.length;
34884
- processedSessionIds = processedSessions.map((s) => s.session_id);
34885
- bookmarksProcessed = state.bookmarks.filter((b) => b.created_at <= epoch).length;
34886
- state.sessions = state.sessions.filter((s) => {
34887
- if (!s.stopped_at) return false;
34888
- return s.stopped_at > epoch;
34889
- });
34890
- state.bookmarks = state.bookmarks.filter((b) => b.created_at > epoch);
34891
- state.dashboard_changes = state.dashboard_changes.filter((c) => c.timestamp > epoch);
34892
- state.debt = state.sessions.reduce((sum, s) => sum + (s.score ?? 0), 0);
34893
- } else {
34894
- sessionsProcessed = state.sessions.length;
34895
- processedSessionIds = state.sessions.map((s) => s.session_id);
34896
- bookmarksProcessed = state.bookmarks.length;
34897
- state.sessions = [];
34898
- state.bookmarks = [];
34899
- state.dashboard_changes = [];
34900
- state.debt = 0;
34901
- }
34902
- state.triggers = state.triggers.filter((t) => t.fired_count < t.max_fires);
35034
+ const result = applyConsolidation(state, epoch);
35035
+ const today_ = today();
34903
35036
  const history = readSleepHistory(root);
34904
- history.unshift({
34905
- date: today(),
34906
- consolidated_at: (/* @__PURE__ */ new Date()).toISOString(),
34907
- summary: summary.trim(),
34908
- debt_before: previousDebt,
34909
- debt_after: state.debt,
34910
- sessions_processed: sessionsProcessed,
34911
- bookmarks_processed: bookmarksProcessed,
34912
- session_ids: processedSessionIds
34913
- });
35037
+ history.unshift(buildHistoryEntry(previousDebt, result, summary, today_));
34914
35038
  writeSleepHistory(root, history);
34915
- state.last_sleep = today();
34916
- state.last_sleep_summary = summary.trim();
34917
- state.sleep_started_at = null;
34918
- state.sessions_since_last_sleep = 0;
34919
- writeSleepState(root, state);
34920
- if (epoch && state.sessions.length > 0) {
34921
- success(`Consolidation complete. Debt reduced from ${previousDebt} to ${state.debt}. ${state.sessions.length} post-epoch session(s) preserved.`);
35039
+ const finalState = finalizeSleepState(result.state, summary, today_);
35040
+ writeSleepState(root, finalState);
35041
+ if (epoch && finalState.sessions.length > 0) {
35042
+ success(`Consolidation complete. Debt reduced from ${previousDebt} to ${finalState.debt}. ${finalState.sessions.length} post-epoch session(s) preserved.`);
34922
35043
  } else {
34923
- success(`Consolidation complete. Debt reset from ${previousDebt} to ${state.debt}.`);
35044
+ success(`Consolidation complete. Debt reset from ${previousDebt} to ${finalState.debt}.`);
34924
35045
  }
34925
35046
  try {
34926
35047
  const backend = getTaskBackend(root);
@@ -35012,6 +35133,7 @@ var init_sleep = __esm({
35012
35133
  init_migration_runner();
35013
35134
  init_setup_config();
35014
35135
  init_manifest();
35136
+ init_sleep_consolidation();
35015
35137
  }
35016
35138
  });
35017
35139
 
@@ -37695,6 +37817,53 @@ var init_snapshot2 = __esm({
37695
37817
  }
37696
37818
  });
37697
37819
 
37820
+ // src/lib/salience.ts
37821
+ function clamp(text) {
37822
+ const oneLine = text.replace(/\s+/g, " ").trim();
37823
+ return oneLine.length <= MAX_MESSAGE_CHARS ? oneLine : oneLine.slice(0, MAX_MESSAGE_CHARS - 1) + "\u2026";
37824
+ }
37825
+ function detectSalience(distilled) {
37826
+ const moments = [];
37827
+ const seen = /* @__PURE__ */ new Set();
37828
+ const push = (message, salience) => {
37829
+ const clamped = clamp(message);
37830
+ if (!clamped) return;
37831
+ const key = `${salience}::${clamped.toLowerCase()}`;
37832
+ if (seen.has(key)) return;
37833
+ seen.add(key);
37834
+ moments.push({ message: clamped, salience });
37835
+ };
37836
+ for (const msg of distilled.userMessages) {
37837
+ if (CORRECTION_RE.test(msg)) {
37838
+ push(`User correction: ${msg}`, 2);
37839
+ }
37840
+ }
37841
+ if (distilled.errors.length > 0 && distilled.codeChanges.length > 0) {
37842
+ const firstError = distilled.errors[0];
37843
+ push(`Error resolved by code change: ${firstError}`, 1);
37844
+ }
37845
+ const decisionSources = [
37846
+ ...distilled.agentDecisions.filter((d) => !d.startsWith("[thinking]")),
37847
+ ...distilled.userMessages
37848
+ ];
37849
+ for (const src of decisionSources) {
37850
+ if (DECISION_RE.test(src)) {
37851
+ push(`Decision: ${src}`, 2);
37852
+ }
37853
+ }
37854
+ return moments.slice(0, MAX_MOMENTS);
37855
+ }
37856
+ var CORRECTION_RE, DECISION_RE, MAX_MOMENTS, MAX_MESSAGE_CHARS;
37857
+ var init_salience = __esm({
37858
+ "src/lib/salience.ts"() {
37859
+ "use strict";
37860
+ CORRECTION_RE = /\b(no|actually|wrong|instead|hayır|yanlış|değil)\b/i;
37861
+ DECISION_RE = /\b(decided|chose|switched to|will use|karar|seçtik)\b/i;
37862
+ MAX_MOMENTS = 5;
37863
+ MAX_MESSAGE_CHARS = 200;
37864
+ }
37865
+ });
37866
+
37698
37867
  // src/cli/commands/transcript.ts
37699
37868
  import { readFileSync as readFileSync35, existsSync as existsSync46, statSync as statSync6 } from "fs";
37700
37869
  function distillTranscript(transcriptPath, sinceTimestamp) {
@@ -38889,53 +39058,6 @@ var init_session_digest = __esm({
38889
39058
  }
38890
39059
  });
38891
39060
 
38892
- // src/lib/salience.ts
38893
- function clamp(text) {
38894
- const oneLine = text.replace(/\s+/g, " ").trim();
38895
- return oneLine.length <= MAX_MESSAGE_CHARS ? oneLine : oneLine.slice(0, MAX_MESSAGE_CHARS - 1) + "\u2026";
38896
- }
38897
- function detectSalience(distilled) {
38898
- const moments = [];
38899
- const seen = /* @__PURE__ */ new Set();
38900
- const push = (message, salience) => {
38901
- const clamped = clamp(message);
38902
- if (!clamped) return;
38903
- const key = `${salience}::${clamped.toLowerCase()}`;
38904
- if (seen.has(key)) return;
38905
- seen.add(key);
38906
- moments.push({ message: clamped, salience });
38907
- };
38908
- for (const msg of distilled.userMessages) {
38909
- if (CORRECTION_RE.test(msg)) {
38910
- push(`User correction: ${msg}`, 2);
38911
- }
38912
- }
38913
- if (distilled.errors.length > 0 && distilled.codeChanges.length > 0) {
38914
- const firstError = distilled.errors[0];
38915
- push(`Error resolved by code change: ${firstError}`, 1);
38916
- }
38917
- const decisionSources = [
38918
- ...distilled.agentDecisions.filter((d) => !d.startsWith("[thinking]")),
38919
- ...distilled.userMessages
38920
- ];
38921
- for (const src of decisionSources) {
38922
- if (DECISION_RE.test(src)) {
38923
- push(`Decision: ${src}`, 2);
38924
- }
38925
- }
38926
- return moments.slice(0, MAX_MOMENTS);
38927
- }
38928
- var CORRECTION_RE, DECISION_RE, MAX_MOMENTS, MAX_MESSAGE_CHARS;
38929
- var init_salience = __esm({
38930
- "src/lib/salience.ts"() {
38931
- "use strict";
38932
- CORRECTION_RE = /\b(no|actually|wrong|instead|hayır|yanlış|değil)\b/i;
38933
- DECISION_RE = /\b(decided|chose|switched to|will use|karar|seçtik)\b/i;
38934
- MAX_MOMENTS = 5;
38935
- MAX_MESSAGE_CHARS = 200;
38936
- }
38937
- });
38938
-
38939
39061
  // src/lib/marketing/path-guards.ts
38940
39062
  import { existsSync as existsSync49, realpathSync } from "fs";
38941
39063
  import { basename as basename14, dirname as dirname24, resolve as resolve8, sep as sep5 } from "path";
@@ -39498,15 +39620,76 @@ function analyzeTranscript(transcriptPath) {
39498
39620
  for (const m of content.matchAll(/"file_path"\s*:\s*"[^"]*_dream_context\/state\/([a-z0-9][a-z0-9-]*)\.md"/g)) {
39499
39621
  slugs.add(m[1]);
39500
39622
  }
39623
+ let userTurns = 0;
39624
+ let assistantChars = 0;
39625
+ let decisionMarkers = 0;
39626
+ for (const line of content.split("\n")) {
39627
+ const trimmed = line.trim();
39628
+ if (!trimmed) continue;
39629
+ if (DECISION_RE.test(trimmed) || CORRECTION_RE.test(trimmed)) {
39630
+ decisionMarkers++;
39631
+ }
39632
+ let rec;
39633
+ try {
39634
+ rec = JSON.parse(trimmed);
39635
+ } catch {
39636
+ continue;
39637
+ }
39638
+ if (!rec || typeof rec !== "object") continue;
39639
+ const role = recordRole(rec);
39640
+ if (role === "user") {
39641
+ userTurns++;
39642
+ } else if (role === "assistant") {
39643
+ assistantChars += sumAssistantTextChars(rec);
39644
+ }
39645
+ }
39501
39646
  return {
39502
39647
  changeCount: changeMatches ? changeMatches.length : 0,
39503
39648
  toolCount: toolMatches ? toolMatches.length : 0,
39504
- taskSlugs: [...slugs]
39649
+ taskSlugs: [...slugs],
39650
+ userTurns,
39651
+ assistantChars,
39652
+ decisionMarkers
39505
39653
  };
39506
39654
  } catch {
39507
39655
  return ZERO_ANALYSIS;
39508
39656
  }
39509
39657
  }
39658
+ function recordRole(rec) {
39659
+ const r = rec;
39660
+ if (typeof r.role === "string") return r.role;
39661
+ if (r.message && typeof r.message === "object" && typeof r.message.role === "string") {
39662
+ return r.message.role;
39663
+ }
39664
+ return null;
39665
+ }
39666
+ function sumAssistantTextChars(rec) {
39667
+ const r = rec;
39668
+ const content = (r.message && typeof r.message === "object" ? r.message.content : void 0) ?? r.content;
39669
+ let total = 0;
39670
+ if (typeof content === "string") {
39671
+ return Math.min(MAX_TEXT_BLOCK_CHARS, content.length);
39672
+ }
39673
+ if (Array.isArray(content)) {
39674
+ for (const block of content) {
39675
+ if (block && typeof block === "object") {
39676
+ const b = block;
39677
+ if (b.type === "text" && typeof b.text === "string") {
39678
+ total += Math.min(MAX_TEXT_BLOCK_CHARS, b.text.length);
39679
+ }
39680
+ }
39681
+ }
39682
+ }
39683
+ return total;
39684
+ }
39685
+ function scoreFromSubstance(signals2) {
39686
+ let pts = 0;
39687
+ if (signals2.userTurns >= 6) pts++;
39688
+ if (signals2.assistantChars >= 6e3) pts++;
39689
+ if (signals2.decisionMarkers >= 1) pts++;
39690
+ if (signals2.taskSlugs.length >= 2) pts++;
39691
+ return Math.min(3, pts);
39692
+ }
39510
39693
  function scoreFromChangeCount(count) {
39511
39694
  if (count <= 0) return 0;
39512
39695
  if (count <= 3) return 1;
@@ -39698,6 +39881,29 @@ function getConsolidationDirective(state) {
39698
39881
  }
39699
39882
  return null;
39700
39883
  }
39884
+ function userPromptReminder(state) {
39885
+ const { debt, bookmarks, sleep_started_at } = state;
39886
+ if (sleep_started_at) {
39887
+ if (debt >= 4) {
39888
+ return `Consolidation already in progress (started: ${sleep_started_at}). Do NOT dispatch another sleep agent.`;
39889
+ }
39890
+ return null;
39891
+ }
39892
+ const criticalBookmarks = bookmarks.filter((b) => b.salience === 3);
39893
+ if (debt >= 10) {
39894
+ return `Sleep debt is ${debt}. CONSOLIDATION REQUIRED. Run sleep flow per SKILL.md (parallel specialist fan-out) NOW.`;
39895
+ }
39896
+ if (criticalBookmarks.length > 0) {
39897
+ return `${criticalBookmarks.length} critical bookmark(s) need consolidation. Run sleep flow per SKILL.md.`;
39898
+ }
39899
+ if (debt >= 7) {
39900
+ return `Sleep debt is ${debt}. Consolidation recommended before starting new work.`;
39901
+ }
39902
+ if (debt >= 4) {
39903
+ return `Sleep debt is ${debt}. After completing the current task, offer to consolidate.`;
39904
+ }
39905
+ return null;
39906
+ }
39701
39907
  function resolveDashboardPort() {
39702
39908
  const raw = process.env.DREAMCONTEXT_DASHBOARD_PORT;
39703
39909
  if (raw) {
@@ -39760,7 +39966,11 @@ function registerHookCommand(program2) {
39760
39966
  const stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
39761
39967
  const analysis = transcriptPath ? analyzeTranscript(transcriptPath) : ZERO_ANALYSIS;
39762
39968
  const { changeCount, toolCount } = analysis;
39763
- const score = Math.max(scoreFromChangeCount(changeCount), scoreFromToolCount(toolCount));
39969
+ const score = Math.max(
39970
+ scoreFromChangeCount(changeCount),
39971
+ scoreFromToolCount(toolCount),
39972
+ scoreFromSubstance(analysis)
39973
+ );
39764
39974
  for (const bookmark of state.bookmarks) {
39765
39975
  if (!bookmark.session_id) {
39766
39976
  bookmark.session_id = sessionId;
@@ -39769,35 +39979,18 @@ function registerHookCommand(program2) {
39769
39979
  const bookmarkTaskSlugs = state.bookmarks.filter((b) => b.session_id === sessionId && b.task_slug).map((b) => b.task_slug);
39770
39980
  const transcriptTaskSlugs = analysis.taskSlugs;
39771
39981
  const taskSlugs = [.../* @__PURE__ */ new Set([...transcriptTaskSlugs, ...bookmarkTaskSlugs])];
39772
- const existing = state.sessions.findIndex((s) => s.session_id === sessionId);
39773
- if (existing >= 0) {
39774
- const oldScore = state.sessions[existing].score ?? 0;
39775
- state.debt = Math.max(0, state.debt - oldScore);
39776
- state.sessions[existing].transcript_path = transcriptPath;
39777
- state.sessions[existing].stopped_at = stoppedAt;
39778
- state.sessions[existing].last_assistant_message = lastAssistantMessage;
39779
- state.sessions[existing].change_count = changeCount;
39780
- state.sessions[existing].tool_count = toolCount;
39781
- state.sessions[existing].score = score;
39782
- const existingSlugs = state.sessions[existing].task_slugs ?? [];
39783
- state.sessions[existing].task_slugs = [.../* @__PURE__ */ new Set([...existingSlugs, ...taskSlugs])];
39784
- } else {
39785
- state.sessions.unshift({
39786
- session_id: sessionId,
39787
- transcript_path: transcriptPath,
39788
- stopped_at: stoppedAt,
39789
- last_assistant_message: lastAssistantMessage,
39790
- change_count: changeCount,
39791
- tool_count: toolCount,
39792
- score,
39793
- task_slugs: taskSlugs
39794
- });
39795
- }
39796
- state.debt += score;
39797
- if (existing < 0) {
39798
- state.sessions_since_last_sleep = (state.sessions_since_last_sleep || 0) + 1;
39799
- }
39800
- writeSleepState(root, state);
39982
+ const upsertInput = {
39983
+ session_id: sessionId,
39984
+ transcript_path: transcriptPath,
39985
+ stopped_at: stoppedAt,
39986
+ last_assistant_message: lastAssistantMessage,
39987
+ change_count: changeCount,
39988
+ tool_count: toolCount,
39989
+ score,
39990
+ task_slugs: taskSlugs
39991
+ };
39992
+ const nextState = upsertSessionOnStop(state, upsertInput);
39993
+ writeSleepState(root, nextState);
39801
39994
  });
39802
39995
  hook.command("session-start").description("Analyze previous session + output context snapshot (called by Claude Code SessionStart hook)").action(() => {
39803
39996
  const input2 = readStdin();
@@ -39819,7 +40012,11 @@ function registerHookCommand(program2) {
39819
40012
  continue;
39820
40013
  }
39821
40014
  const analysis = analyzeTranscript(session.transcript_path);
39822
- const score = Math.max(scoreFromChangeCount(analysis.changeCount), scoreFromToolCount(analysis.toolCount));
40015
+ const score = Math.max(
40016
+ scoreFromChangeCount(analysis.changeCount),
40017
+ scoreFromToolCount(analysis.toolCount),
40018
+ scoreFromSubstance(analysis)
40019
+ );
39823
40020
  session.change_count = analysis.changeCount;
39824
40021
  session.tool_count = analysis.toolCount;
39825
40022
  session.score = score;
@@ -39924,23 +40121,12 @@ function registerHookCommand(program2) {
39924
40121
  const root = resolveContextRoot();
39925
40122
  if (!root) process.exit(0);
39926
40123
  const state = readSleepState(root);
39927
- const { debt, bookmarks, sleep_started_at } = state;
39928
- if (sleep_started_at) {
39929
- if (debt >= 4) {
39930
- console.log(`Consolidation already in progress (started: ${sleep_started_at}). Do NOT dispatch another sleep agent.`);
39931
- }
40124
+ const reminder = userPromptReminder(state);
40125
+ if (state.sleep_started_at) {
40126
+ if (reminder) console.log(reminder);
39932
40127
  return;
39933
40128
  }
39934
- const criticalBookmarks = bookmarks.filter((b) => b.salience === 3);
39935
- if (debt >= 10) {
39936
- console.log(`Sleep debt is ${debt}. CONSOLIDATION REQUIRED. Run sleep flow per SKILL.md (parallel specialist fan-out) NOW.`);
39937
- } else if (criticalBookmarks.length > 0) {
39938
- console.log(`${criticalBookmarks.length} critical bookmark(s) need consolidation. Run sleep flow per SKILL.md.`);
39939
- } else if (debt >= 7) {
39940
- console.log(`Sleep debt is ${debt}. Consolidation recommended before starting new work.`);
39941
- } else if (debt >= 4) {
39942
- console.log(`Sleep debt is ${debt}. After completing the current task, offer to consolidate.`);
39943
- }
40129
+ if (reminder) console.log(reminder);
39944
40130
  try {
39945
40131
  const stale = listStaleRecs(24);
39946
40132
  if (stale.length > 0) {
@@ -40090,17 +40276,14 @@ function registerHookCommand(program2) {
40090
40276
  if (!root) process.exit(0);
40091
40277
  const state = readSleepState(root);
40092
40278
  const trigger = input2 && typeof input2.trigger === "string" ? input2.trigger : "unknown";
40093
- state.compaction_log.unshift({
40279
+ const nextState = appendCompactionRecord(state, {
40094
40280
  timestamp: (/* @__PURE__ */ new Date()).toISOString(),
40095
40281
  trigger,
40096
40282
  debt_at_compaction: state.debt,
40097
40283
  sessions_count: state.sessions.length,
40098
40284
  bookmarks_count: state.bookmarks.length
40099
40285
  });
40100
- if (state.compaction_log.length > 20) {
40101
- state.compaction_log = state.compaction_log.slice(0, 20);
40102
- }
40103
- writeSleepState(root, state);
40286
+ writeSleepState(root, nextState);
40104
40287
  try {
40105
40288
  const sessionId = input2 && typeof input2.session_id === "string" ? input2.session_id : "";
40106
40289
  const transcriptPath = input2 && typeof input2.transcript_path === "string" ? input2.transcript_path : "";
@@ -40129,12 +40312,14 @@ function registerHookCommand(program2) {
40129
40312
  process.exit(0);
40130
40313
  });
40131
40314
  }
40132
- var MAX_TRANSCRIPT_BYTES2, SKILL_SCORE_THRESHOLD, ZERO_ANALYSIS, JS_TS_EXTENSIONS, MAX_WALK_LEVELS, BIOME_CONFIGS, PRETTIER_CONFIGS, DEFAULT_DASHBOARD_PORT;
40315
+ var MAX_TRANSCRIPT_BYTES2, SKILL_SCORE_THRESHOLD, ZERO_ANALYSIS, MAX_TEXT_BLOCK_CHARS, JS_TS_EXTENSIONS, MAX_WALK_LEVELS, BIOME_CONFIGS, PRETTIER_CONFIGS, DEFAULT_DASHBOARD_PORT;
40133
40316
  var init_hook = __esm({
40134
40317
  "src/cli/commands/hook.ts"() {
40135
40318
  "use strict";
40136
40319
  init_context_path();
40137
40320
  init_sleep();
40321
+ init_sleep_consolidation();
40322
+ init_salience();
40138
40323
  init_transcript();
40139
40324
  init_session_digest();
40140
40325
  init_salience();
@@ -40151,7 +40336,15 @@ var init_hook = __esm({
40151
40336
  init_install_skill();
40152
40337
  MAX_TRANSCRIPT_BYTES2 = 50 * 1024 * 1024;
40153
40338
  SKILL_SCORE_THRESHOLD = 1;
40154
- ZERO_ANALYSIS = { changeCount: 0, toolCount: 0, taskSlugs: [] };
40339
+ ZERO_ANALYSIS = {
40340
+ changeCount: 0,
40341
+ toolCount: 0,
40342
+ taskSlugs: [],
40343
+ userTurns: 0,
40344
+ assistantChars: 0,
40345
+ decisionMarkers: 0
40346
+ };
40347
+ MAX_TEXT_BLOCK_CHARS = 2e4;
40155
40348
  JS_TS_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".mts", ".cts"]);
40156
40349
  MAX_WALK_LEVELS = 10;
40157
40350
  BIOME_CONFIGS = ["biome.json", "biome.jsonc"];
@@ -41091,8 +41284,8 @@ async function handleCoreGet(_req, res, params, contextRoot) {
41091
41284
  return;
41092
41285
  }
41093
41286
  if (filename.endsWith(".json")) {
41094
- const { readFileSync: readFileSync66 } = await import("fs");
41095
- const raw2 = readFileSync66(filePath, "utf-8");
41287
+ const { readFileSync: readFileSync67 } = await import("fs");
41288
+ const raw2 = readFileSync67(filePath, "utf-8");
41096
41289
  try {
41097
41290
  const data = JSON.parse(raw2);
41098
41291
  sendJson(res, 200, { filename, type: "json", data });
@@ -41126,8 +41319,8 @@ async function handleCoreGet(_req, res, params, contextRoot) {
41126
41319
  });
41127
41320
  return;
41128
41321
  }
41129
- const { readFileSync: readFileSync65 } = await import("fs");
41130
- const raw = readFileSync65(filePath, "utf-8");
41322
+ const { readFileSync: readFileSync66 } = await import("fs");
41323
+ const raw = readFileSync66(filePath, "utf-8");
41131
41324
  sendJson(res, 200, { filename, type: "text", content: raw });
41132
41325
  }
41133
41326
  async function handleCoreUpdate(req, res, params, contextRoot) {
@@ -41177,8 +41370,8 @@ async function handleCoreUpdate(req, res, params, contextRoot) {
41177
41370
  return;
41178
41371
  }
41179
41372
  changedParts.push("content");
41180
- const { writeFileSync: writeFileSync44 } = await import("fs");
41181
- writeFileSync44(filePath, body.content, "utf-8");
41373
+ const { writeFileSync: writeFileSync45 } = await import("fs");
41374
+ writeFileSync45(filePath, body.content, "utf-8");
41182
41375
  }
41183
41376
  const what = changedParts.length > 0 ? changedParts.join(" and ") : "file";
41184
41377
  recordDashboardChange(contextRoot, {
@@ -42793,8 +42986,9 @@ function buildAskPrompt(question) {
42793
42986
 
42794
42987
  Question: "${question}"`;
42795
42988
  }
42796
- function buildSleepPrompt() {
42797
- return `Think hard. Run a dreamcontext memory consolidation ("sleep") for THIS project now, fully autonomously \u2014 do NOT ask any questions. Follow the project's dreamcontext sleep/consolidation flow: pin the epoch with \`dreamcontext sleep start\`, reconcile the task/changelog/knowledge/feature files to current truth as warranted (prefer updating existing entities over creating new ones), then close the cycle with \`dreamcontext sleep done "<one-paragraph summary>"\` to reset the debt. When finished, reply with a SHORT GitHub-flavored Markdown summary (a few bullets) of what was consolidated. Keep it concise.`;
42989
+ function buildSleepPrompt(depth) {
42990
+ const depthLine = isDestructiveAllowed(depth) ? `This is a DEEP consolidation: you ARE authorized to perform destructive/expensive knowledge ops (merge-with-delete, summarize-and-replace still-valid detail, archive/delete stale files) \u2014 but first copy any file you will merge/replace/delete to \`_dream_context/knowledge/.archive/<slug>-<YYYYMMDD>.md\` (create the dir if absent).` : `This is a ${depth.toUpperCase()} consolidation: do NOT merge, summarize-and-replace, or delete any knowledge. Only create/extend/retag/tick. If you spot merge or deletion candidates, FLAG them in your report instead of acting on them.`;
42991
+ return `Think hard. Run a dreamcontext memory consolidation ("sleep") for THIS project now, fully autonomously \u2014 do NOT ask any questions. Follow the project's dreamcontext sleep/consolidation flow: pin the epoch with \`dreamcontext sleep start\`, reconcile the task/changelog/knowledge/feature files to current truth as warranted (prefer updating existing entities over creating new ones), then close the cycle with \`dreamcontext sleep done "<one-paragraph summary>"\` to reset the debt. ${depthLine} When finished, reply with a SHORT GitHub-flavored Markdown summary (a few bullets) of what was consolidated. Keep it concise.`;
42798
42992
  }
42799
42993
  async function handleLauncherCapture(req, res, _params, _contextRoot) {
42800
42994
  const body = await parseJsonBody(req);
@@ -42852,7 +43046,18 @@ async function handleLauncherCapture(req, res, _params, _contextRoot) {
42852
43046
  captureRuns.set(captureId, run2);
42853
43047
  try {
42854
43048
  const shell = process.env.SHELL || "/bin/zsh";
42855
- const prompt = mode === "sleep" ? buildSleepPrompt() : mode === "ask" ? buildAskPrompt(text) : buildCapturePrompt(text);
43049
+ let sleepDepth = "deep";
43050
+ if (mode === "sleep") {
43051
+ try {
43052
+ sleepDepth = consolidationDepth(readSleepState(cwd).debt, {
43053
+ userRequestedDeep: true
43054
+ }).depth;
43055
+ } catch (err) {
43056
+ console.error("[launcher] could not read sleep state for depth:", err);
43057
+ sleepDepth = "deep";
43058
+ }
43059
+ }
43060
+ const prompt = mode === "sleep" ? buildSleepPrompt(sleepDepth) : mode === "ask" ? buildAskPrompt(text) : buildCapturePrompt(text);
42856
43061
  const child = spawn4(shell, ["-ilc", 'exec claude --model sonnet -p "$0"', prompt], {
42857
43062
  cwd,
42858
43063
  stdio: ["ignore", "pipe", "pipe"]
@@ -42899,6 +43104,177 @@ async function handleLauncherDefaults(_req, res, _params, _contextRoot) {
42899
43104
  const home = homedir3();
42900
43105
  sendJson(res, 200, { home, defaultParent: join59(home, "projects") });
42901
43106
  }
43107
+ function computeVaultStatus(v, latest) {
43108
+ const exists = existsSync63(resolve15(v.path));
43109
+ let setupVersion = "0.0.0";
43110
+ let shareable = false;
43111
+ if (exists) {
43112
+ try {
43113
+ const cfg = readSetupConfig(resolve15(v.path));
43114
+ if (cfg) {
43115
+ setupVersion = cfg.setupVersion || "0.0.0";
43116
+ shareable = cfg.shareable === true;
43117
+ }
43118
+ } catch {
43119
+ }
43120
+ }
43121
+ const needsUpdate = exists && compareVersions(setupVersion, latest) < 0;
43122
+ return { name: v.name, path: v.path, exists, setupVersion, latestVersion: latest, needsUpdate, shareable };
43123
+ }
43124
+ async function handleLauncherStatus(_req, res, _params, _contextRoot) {
43125
+ const latest = dreamcontextVersion();
43126
+ const vaults = listVaults().map((v) => computeVaultStatus(v, latest));
43127
+ sendJson(res, 200, { vaults, latestVersion: latest });
43128
+ }
43129
+ async function handleLauncherUnregister(req, res, _params, _contextRoot) {
43130
+ const body = await parseJsonBody(req);
43131
+ if (!body) {
43132
+ sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
43133
+ return;
43134
+ }
43135
+ const name = typeof body.name === "string" ? body.name.trim() : "";
43136
+ if (!name) {
43137
+ sendError(res, 400, "invalid_name", "name must be a non-empty string.");
43138
+ return;
43139
+ }
43140
+ const removed = removeVault(name);
43141
+ sendJson(res, 200, { removed, vaults: listVaults() });
43142
+ }
43143
+ async function handleLauncherUpdate(req, res, _params, _contextRoot) {
43144
+ const body = await parseJsonBody(req);
43145
+ if (!body) {
43146
+ sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
43147
+ return;
43148
+ }
43149
+ const name = typeof body.name === "string" ? body.name.trim() : "";
43150
+ if (!name) {
43151
+ sendError(res, 400, "invalid_name", "name must be a non-empty string.");
43152
+ return;
43153
+ }
43154
+ const vault = listVaults().find((v) => v.name === name);
43155
+ if (!vault) {
43156
+ sendError(res, 400, "unknown_vault", `No registered vault named "${name}".`);
43157
+ return;
43158
+ }
43159
+ const target = resolve15(vault.path);
43160
+ if (!existsSync63(target)) {
43161
+ sendError(res, 400, "missing_vault", `Vault path no longer exists: ${target}`);
43162
+ return;
43163
+ }
43164
+ try {
43165
+ await defaultCliRunner(["update"], target);
43166
+ const latest = dreamcontextVersion();
43167
+ sendJson(res, 200, { ok: true, status: computeVaultStatus(vault, latest) });
43168
+ } catch (err) {
43169
+ console.error("[launcher] update failed:", err);
43170
+ const detail = err instanceof Error ? err.message : "unknown error";
43171
+ sendError(res, 500, "update_failed", `Update failed: ${detail}`);
43172
+ }
43173
+ }
43174
+ async function handleLauncherFederationGraph(_req, res, _params, _contextRoot) {
43175
+ const latest = dreamcontextVersion();
43176
+ const vaults = listVaults();
43177
+ const nodes = vaults.map((v) => computeVaultStatus(v, latest));
43178
+ const shareableByName = new Map(nodes.map((n) => [n.name, n.shareable]));
43179
+ const known = new Set(vaults.map((v) => v.name));
43180
+ const edges = [];
43181
+ const seen = /* @__PURE__ */ new Set();
43182
+ for (const v of vaults) {
43183
+ if (!existsSync63(resolve15(v.path))) continue;
43184
+ const conns = listConnections(join59(resolve15(v.path), "_dream_context"));
43185
+ for (const c of conns) {
43186
+ if (c.direction !== "out" && c.direction !== "both") continue;
43187
+ if (!known.has(c.vault)) continue;
43188
+ if (c.status === "stale") continue;
43189
+ const key = `${v.name}\0${c.vault}`;
43190
+ if (seen.has(key)) continue;
43191
+ seen.add(key);
43192
+ edges.push({ source: v.name, target: c.vault, active: shareableByName.get(c.vault) === true });
43193
+ }
43194
+ }
43195
+ sendJson(res, 200, { nodes, edges, latestVersion: latest });
43196
+ }
43197
+ async function handleLauncherConnectionCreate(req, res, _params, _contextRoot) {
43198
+ const body = await parseJsonBody(req);
43199
+ if (!body) {
43200
+ sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
43201
+ return;
43202
+ }
43203
+ const from = typeof body.from === "string" ? body.from.trim() : "";
43204
+ const to = typeof body.to === "string" ? body.to.trim() : "";
43205
+ if (!from || !to) {
43206
+ sendError(res, 400, "invalid_body", "from and to must be non-empty strings.");
43207
+ return;
43208
+ }
43209
+ const fromVault = listVaults().find((v) => v.name === from);
43210
+ if (!fromVault) {
43211
+ sendError(res, 400, "unknown_vault", `No registered vault named "${from}".`);
43212
+ return;
43213
+ }
43214
+ const fromRoot = join59(resolve15(fromVault.path), "_dream_context");
43215
+ try {
43216
+ addConnection(fromRoot, from, to, "out", null);
43217
+ sendJson(res, 200, { ok: true });
43218
+ } catch (err) {
43219
+ if (err instanceof VaultError) {
43220
+ sendError(res, 400, "invalid_connection", err.message);
43221
+ return;
43222
+ }
43223
+ console.error("[launcher] connection create failed:", err);
43224
+ sendError(res, 500, "connection_failed", "Failed to create connection.");
43225
+ }
43226
+ }
43227
+ async function handleLauncherConnectionRemove(req, res, _params, _contextRoot) {
43228
+ const body = await parseJsonBody(req);
43229
+ if (!body) {
43230
+ sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
43231
+ return;
43232
+ }
43233
+ const from = typeof body.from === "string" ? body.from.trim() : "";
43234
+ const to = typeof body.to === "string" ? body.to.trim() : "";
43235
+ if (!from || !to) {
43236
+ sendError(res, 400, "invalid_body", "from and to must be non-empty strings.");
43237
+ return;
43238
+ }
43239
+ const fromVault = listVaults().find((v) => v.name === from);
43240
+ if (!fromVault) {
43241
+ sendError(res, 400, "unknown_vault", `No registered vault named "${from}".`);
43242
+ return;
43243
+ }
43244
+ const fromRoot = join59(resolve15(fromVault.path), "_dream_context");
43245
+ const removed = removeConnection(fromRoot, to);
43246
+ sendJson(res, 200, { ok: true, removed });
43247
+ }
43248
+ async function handleLauncherShareable(req, res, _params, _contextRoot) {
43249
+ const body = await parseJsonBody(req);
43250
+ if (!body) {
43251
+ sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
43252
+ return;
43253
+ }
43254
+ const name = typeof body.name === "string" ? body.name.trim() : "";
43255
+ const shareable = body.shareable === true;
43256
+ if (!name) {
43257
+ sendError(res, 400, "invalid_name", "name must be a non-empty string.");
43258
+ return;
43259
+ }
43260
+ const vault = listVaults().find((v) => v.name === name);
43261
+ if (!vault) {
43262
+ sendError(res, 400, "unknown_vault", `No registered vault named "${name}".`);
43263
+ return;
43264
+ }
43265
+ const root = resolve15(vault.path);
43266
+ if (!existsSync63(root)) {
43267
+ sendError(res, 400, "missing_vault", `Vault path no longer exists: ${root}`);
43268
+ return;
43269
+ }
43270
+ try {
43271
+ updateSetupConfig(root, { shareable });
43272
+ sendJson(res, 200, { ok: true, name, shareable });
43273
+ } catch (err) {
43274
+ console.error("[launcher] shareable toggle failed:", err);
43275
+ sendError(res, 500, "shareable_failed", "Failed to update sharing.");
43276
+ }
43277
+ }
42902
43278
  var execFileAsync2, captureRuns, CAPTURE_RUN_TTL_MS, CAPTURE_RUNS_MAX, ScaffoldError, defaultCliRunner, SAFE_NAME_RE, SLEEPY_MODES;
42903
43279
  var init_launcher = __esm({
42904
43280
  "src/server/routes/launcher.ts"() {
@@ -42906,12 +43282,18 @@ var init_launcher = __esm({
42906
43282
  init_middleware();
42907
43283
  init_vault_discovery();
42908
43284
  init_vaults();
43285
+ init_connections();
43286
+ init_setup_config();
43287
+ init_manifest();
43288
+ init_version_check();
42909
43289
  init_tech_stack();
42910
43290
  init_ensure_cli();
42911
43291
  init_platforms();
42912
43292
  init_catalog();
42913
43293
  init_json_file();
42914
43294
  init_id();
43295
+ init_sleep();
43296
+ init_sleep_consolidation();
42915
43297
  execFileAsync2 = promisify2(execFile2);
42916
43298
  captureRuns = /* @__PURE__ */ new Map();
42917
43299
  CAPTURE_RUN_TTL_MS = 10 * 60 * 1e3;
@@ -42940,6 +43322,62 @@ var init_launcher = __esm({
42940
43322
  }
42941
43323
  });
42942
43324
 
43325
+ // src/server/routes/ui-settings.ts
43326
+ import { dirname as dirname30, join as join60 } from "path";
43327
+ import { existsSync as existsSync64, mkdirSync as mkdirSync26, readFileSync as readFileSync46, writeFileSync as writeFileSync33 } from "fs";
43328
+ function settingsPath(contextRoot) {
43329
+ return join60(contextRoot, BRAIN_SETTINGS_REL_PATH);
43330
+ }
43331
+ async function handleBrainSettingsGet(_req, res, _params, contextRoot) {
43332
+ const path2 = settingsPath(contextRoot);
43333
+ if (!existsSync64(path2)) {
43334
+ sendJson(res, 200, { settings: {} });
43335
+ return;
43336
+ }
43337
+ try {
43338
+ const raw = JSON.parse(readFileSync46(path2, "utf-8"));
43339
+ const settings = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
43340
+ sendJson(res, 200, { settings });
43341
+ } catch {
43342
+ sendJson(res, 200, { settings: {} });
43343
+ }
43344
+ }
43345
+ async function handleBrainSettingsPut(req, res, _params, contextRoot) {
43346
+ const body = await parseJsonBody(req);
43347
+ if (!body) {
43348
+ sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
43349
+ return;
43350
+ }
43351
+ const settings = body.settings;
43352
+ if (settings === null || typeof settings !== "object" || Array.isArray(settings)) {
43353
+ sendError(res, 400, "invalid_settings", "settings must be a JSON object.");
43354
+ return;
43355
+ }
43356
+ const serialized = JSON.stringify(settings, null, 2);
43357
+ if (Buffer.byteLength(serialized, "utf-8") > MAX_BYTES) {
43358
+ sendError(res, 400, "too_large", "settings payload is too large.");
43359
+ return;
43360
+ }
43361
+ try {
43362
+ const path2 = settingsPath(contextRoot);
43363
+ mkdirSync26(dirname30(path2), { recursive: true });
43364
+ writeFileSync33(path2, serialized + "\n", "utf-8");
43365
+ sendJson(res, 200, { ok: true });
43366
+ } catch (err) {
43367
+ console.error("[ui-settings] brain-settings write failed:", err);
43368
+ sendError(res, 500, "write_failed", "Failed to persist brain settings.");
43369
+ }
43370
+ }
43371
+ var BRAIN_SETTINGS_REL_PATH, MAX_BYTES;
43372
+ var init_ui_settings = __esm({
43373
+ "src/server/routes/ui-settings.ts"() {
43374
+ "use strict";
43375
+ init_middleware();
43376
+ BRAIN_SETTINGS_REL_PATH = "state/.brain-settings.json";
43377
+ MAX_BYTES = 256 * 1024;
43378
+ }
43379
+ });
43380
+
42943
43381
  // src/lib/federation-config.ts
42944
43382
  function isShareable(projectRoot) {
42945
43383
  const cfg = readSetupConfig(projectRoot);
@@ -42953,7 +43391,7 @@ var init_federation_config = __esm({
42953
43391
  });
42954
43392
 
42955
43393
  // src/lib/federation-recall.ts
42956
- import { basename as basename19, dirname as dirname30 } from "path";
43394
+ import { basename as basename19, dirname as dirname31 } from "path";
42957
43395
  function namespacedKey(vault, type, slug) {
42958
43396
  return `${vault}::${type}/${slug}`;
42959
43397
  }
@@ -42978,7 +43416,7 @@ function crossVaultRecall(query, opts) {
42978
43416
  }
42979
43417
  const isCurrent = target.current === true;
42980
43418
  if (!isCurrent) {
42981
- const projectRoot = dirname30(contextRoot);
43419
+ const projectRoot = dirname31(contextRoot);
42982
43420
  if (!isShareable(projectRoot)) continue;
42983
43421
  }
42984
43422
  const corpus = buildCorpus(contextRoot, opts.types ? { types: opts.types } : {}).filter((doc) => !isFederated(doc));
@@ -43051,9 +43489,9 @@ var init_federation_recall = __esm({
43051
43489
  });
43052
43490
 
43053
43491
  // src/server/routes/connections.ts
43054
- import { dirname as dirname31 } from "path";
43492
+ import { dirname as dirname32 } from "path";
43055
43493
  function currentVaultName(contextRoot) {
43056
- return currentVaultTarget(dirname31(contextRoot)).name;
43494
+ return currentVaultTarget(dirname32(contextRoot)).name;
43057
43495
  }
43058
43496
  async function handleConnectionsList(_req, res, _params, contextRoot) {
43059
43497
  sendJson(res, 200, { connections: listConnections(contextRoot) });
@@ -43128,8 +43566,8 @@ var init_connections2 = __esm({
43128
43566
  });
43129
43567
 
43130
43568
  // src/lib/federation-digest.ts
43131
- import { existsSync as existsSync64 } from "fs";
43132
- import { join as join60 } from "path";
43569
+ import { existsSync as existsSync65 } from "fs";
43570
+ import { join as join61 } from "path";
43133
43571
  function buildInterestProfile(peerRoot, topics) {
43134
43572
  if (topics && topics.length > 0) {
43135
43573
  const terms2 = Array.from(new Set(tokenize(topics.join(" "))));
@@ -43148,8 +43586,8 @@ function buildInterestProfile(peerRoot, topics) {
43148
43586
  return { terms, query: terms.join(" ") };
43149
43587
  }
43150
43588
  function activeTaskTerms(peerRoot) {
43151
- const stateDir = join60(peerRoot, "state");
43152
- if (!existsSync64(stateDir)) return [];
43589
+ const stateDir = join61(peerRoot, "state");
43590
+ if (!existsSync65(stateDir)) return [];
43153
43591
  let files;
43154
43592
  try {
43155
43593
  files = import_fast_glob17.default.sync("*.md", { cwd: stateDir, absolute: true });
@@ -43250,7 +43688,7 @@ var init_federation_digest = __esm({
43250
43688
  });
43251
43689
 
43252
43690
  // src/server/routes/federation.ts
43253
- import { dirname as dirname32 } from "path";
43691
+ import { dirname as dirname33 } from "path";
43254
43692
  async function handleFederationInboxGet(_req, res, _params, contextRoot) {
43255
43693
  const { entries, quarantined } = drainInbox(contextRoot);
43256
43694
  const pending = entries.map((e) => e.entry);
@@ -43262,7 +43700,7 @@ async function handleFederationInboxGet(_req, res, _params, contextRoot) {
43262
43700
  });
43263
43701
  }
43264
43702
  async function handleFederationSyncPost(_req, res, _params, contextRoot) {
43265
- const senderName = currentVaultTarget(dirname32(contextRoot)).name;
43703
+ const senderName = currentVaultTarget(dirname33(contextRoot)).name;
43266
43704
  const outbound = listConnections(contextRoot).filter(
43267
43705
  (c) => (c.direction === "out" || c.direction === "both") && c.status !== "stale"
43268
43706
  );
@@ -43310,14 +43748,14 @@ var init_federation = __esm({
43310
43748
  });
43311
43749
 
43312
43750
  // src/server/routes/packs.ts
43313
- import { dirname as dirname33 } from "path";
43751
+ import { dirname as dirname34 } from "path";
43314
43752
  async function handlePacksGet(_req, res, _params, contextRoot) {
43315
43753
  const loaded = loadCatalog();
43316
43754
  if (!loaded) {
43317
43755
  sendJson(res, 200, { packs: [], standalone: [] });
43318
43756
  return;
43319
43757
  }
43320
- const projectRoot = dirname33(contextRoot);
43758
+ const projectRoot = dirname34(contextRoot);
43321
43759
  const packs = loaded.catalog.packs.map((p) => ({ ...p, installed: isSkillInstalled(projectRoot, p.name) }));
43322
43760
  const standalone = loaded.catalog.standalone.map((s) => ({ ...s, installed: isSkillInstalled(projectRoot, s.name) }));
43323
43761
  sendJson(res, 200, { packs, standalone });
@@ -43331,7 +43769,7 @@ var init_packs = __esm({
43331
43769
  });
43332
43770
 
43333
43771
  // src/server/routes/packs-install.ts
43334
- import { dirname as dirname34 } from "path";
43772
+ import { dirname as dirname35 } from "path";
43335
43773
  function validatePackName(name, contextRoot) {
43336
43774
  if (name.includes("/") || name.includes("\0") || safeChildPath2("/x", name) === null) {
43337
43775
  return { ok: false, status: 400, code: "invalid_name", message: "Invalid pack name." };
@@ -43344,7 +43782,7 @@ function validatePackName(name, contextRoot) {
43344
43782
  if (!known) {
43345
43783
  return { ok: false, status: 404, code: "unknown_pack", message: `Pack "${name}" not found.` };
43346
43784
  }
43347
- const projectRoot = dirname34(contextRoot);
43785
+ const projectRoot = dirname35(contextRoot);
43348
43786
  const config = readSetupConfig(projectRoot);
43349
43787
  const platforms = normalizePlatforms(config?.platforms ?? []);
43350
43788
  const resolved = platforms.length > 0 ? platforms : [...DEFAULT_PLATFORMS];
@@ -43417,10 +43855,10 @@ var init_packs_install = __esm({
43417
43855
  });
43418
43856
 
43419
43857
  // src/server/routes/version-check.ts
43420
- import { dirname as dirname35 } from "path";
43858
+ import { dirname as dirname36 } from "path";
43421
43859
  async function handleVersionCheckGet(_req, res, _params, contextRoot) {
43422
43860
  try {
43423
- const projectRoot = dirname35(contextRoot);
43861
+ const projectRoot = dirname36(contextRoot);
43424
43862
  const cache = readVersionCache(projectRoot);
43425
43863
  const fresh = isCacheFresh(cache);
43426
43864
  const installedCli = dreamcontextVersion();
@@ -43475,7 +43913,7 @@ var init_taxonomy2 = __esm({
43475
43913
 
43476
43914
  // src/server/index.ts
43477
43915
  import { createServer } from "http";
43478
- import { join as join61, resolve as resolve16 } from "path";
43916
+ import { join as join62, resolve as resolve16 } from "path";
43479
43917
  import { fileURLToPath as fileURLToPath7 } from "url";
43480
43918
  import { exec } from "child_process";
43481
43919
  function buildRouter() {
@@ -43521,6 +43959,13 @@ function buildRouter() {
43521
43959
  router.get("/api/launcher/capture/status", handleLauncherCaptureStatus);
43522
43960
  router.get("/api/launcher/sleepy-config", handleSleepyConfigGet);
43523
43961
  router.post("/api/launcher/sleepy-config", handleSleepyConfigSet);
43962
+ router.get("/api/launcher/status", handleLauncherStatus);
43963
+ router.post("/api/launcher/unregister", handleLauncherUnregister);
43964
+ router.post("/api/launcher/update", handleLauncherUpdate);
43965
+ router.get("/api/launcher/federation-graph", handleLauncherFederationGraph);
43966
+ router.post("/api/launcher/connection", handleLauncherConnectionCreate);
43967
+ router.post("/api/launcher/connection/remove", handleLauncherConnectionRemove);
43968
+ router.post("/api/launcher/shareable", handleLauncherShareable);
43524
43969
  router.get("/api/sleepy/video", handleSleepyVideo);
43525
43970
  router.get("/api/sleepy/anim", handleSleepyAnim);
43526
43971
  router.get("/api/vaults", handleVaultsGet);
@@ -43532,6 +43977,8 @@ function buildRouter() {
43532
43977
  router.get("/api/packs", handlePacksGet);
43533
43978
  router.post("/api/packs/:name/install", handlePackInstall);
43534
43979
  router.delete("/api/packs/:name", handlePackUninstall);
43980
+ router.get("/api/brain-settings", handleBrainSettingsGet);
43981
+ router.put("/api/brain-settings", handleBrainSettingsPut);
43535
43982
  router.get("/api/version-check", handleVersionCheckGet);
43536
43983
  router.get("/api/taxonomy", handleTaxonomyGet);
43537
43984
  router.get("/api/changelog", handleChangelogGet);
@@ -43553,7 +44000,7 @@ function resolveRequestVault(req) {
43553
44000
  if (/[/\\:.\x00]/.test(h)) return "INVALID";
43554
44001
  const v = listVaults().find((x) => x.name === h);
43555
44002
  if (!v) return "INVALID";
43556
- return join61(v.path, "_dream_context");
44003
+ return join62(v.path, "_dream_context");
43557
44004
  }
43558
44005
  function getDashboardDir() {
43559
44006
  const __dirname8 = fileURLToPath7(new URL(".", import.meta.url));
@@ -43653,6 +44100,7 @@ var init_server = __esm({
43653
44100
  init_config();
43654
44101
  init_vaults2();
43655
44102
  init_launcher();
44103
+ init_ui_settings();
43656
44104
  init_connections2();
43657
44105
  init_federation();
43658
44106
  init_packs();
@@ -43844,8 +44292,8 @@ var init_trigger = __esm({
43844
44292
  });
43845
44293
 
43846
44294
  // src/lib/reflection.ts
43847
- import { existsSync as existsSync65, mkdirSync as mkdirSync26, writeFileSync as writeFileSync33 } from "fs";
43848
- import { join as join62, dirname as dirname36 } from "path";
44295
+ import { existsSync as existsSync66, mkdirSync as mkdirSync27, writeFileSync as writeFileSync34 } from "fs";
44296
+ import { join as join63, dirname as dirname37 } from "path";
43849
44297
  function buildExclusionSet(corpus, excludedExtra) {
43850
44298
  const excluded = new Set(excludedExtra);
43851
44299
  for (const doc of corpus) {
@@ -44021,13 +44469,13 @@ function formatReflection(result) {
44021
44469
  return capToBytes(lines, MAX_REFLECTION_BYTES);
44022
44470
  }
44023
44471
  function reflectionPath(root) {
44024
- return join62(root, "state", ".reflection.md");
44472
+ return join63(root, "state", ".reflection.md");
44025
44473
  }
44026
44474
  function writeReflection(root, md) {
44027
44475
  const outPath = reflectionPath(root);
44028
- const dir = dirname36(outPath);
44029
- if (!existsSync65(dir)) {
44030
- mkdirSync26(dir, { recursive: true });
44476
+ const dir = dirname37(outPath);
44477
+ if (!existsSync66(dir)) {
44478
+ mkdirSync27(dir, { recursive: true });
44031
44479
  }
44032
44480
  const tsMatch = md.match(/Generated: ([^\n]+)/);
44033
44481
  const generatedAt = tsMatch ? tsMatch[1].trim() : (/* @__PURE__ */ new Date()).toISOString();
@@ -44038,7 +44486,7 @@ function writeReflection(root, md) {
44038
44486
  "---",
44039
44487
  ""
44040
44488
  ].join("\n");
44041
- writeFileSync33(outPath, frontmatter + md, "utf-8");
44489
+ writeFileSync34(outPath, frontmatter + md, "utf-8");
44042
44490
  return outPath;
44043
44491
  }
44044
44492
  var MAX_REFLECTION_BYTES, DEFAULT_MIN_SESSIONS, DEFAULT_MAX_CANDIDATES, REFLECTION_NOISE;
@@ -44202,14 +44650,14 @@ var init_reflection = __esm({
44202
44650
  });
44203
44651
 
44204
44652
  // src/cli/commands/reflect.ts
44205
- import { existsSync as existsSync66, readFileSync as readFileSync48 } from "fs";
44206
- import { join as join63 } from "path";
44653
+ import { existsSync as existsSync67, readFileSync as readFileSync49 } from "fs";
44654
+ import { join as join64 } from "path";
44207
44655
  function buildBookmarkSessions(root) {
44208
- const sleepPath = join63(root, "state", ".sleep.json");
44656
+ const sleepPath = join64(root, "state", ".sleep.json");
44209
44657
  const result = /* @__PURE__ */ new Map();
44210
- if (!existsSync66(sleepPath)) return result;
44658
+ if (!existsSync67(sleepPath)) return result;
44211
44659
  try {
44212
- const parsed = JSON.parse(readFileSync48(sleepPath, "utf-8"));
44660
+ const parsed = JSON.parse(readFileSync49(sleepPath, "utf-8"));
44213
44661
  const bookmarks = parsed.bookmarks ?? [];
44214
44662
  for (const b of bookmarks) {
44215
44663
  if (b.id && b.session_id) {
@@ -44223,13 +44671,13 @@ function buildBookmarkSessions(root) {
44223
44671
  function buildExcludedExtra(root) {
44224
44672
  const excluded = /* @__PURE__ */ new Set();
44225
44673
  const coreFiles = [
44226
- join63(root, "core", "0.soul.md"),
44227
- join63(root, "core", "1.user.md")
44674
+ join64(root, "core", "0.soul.md"),
44675
+ join64(root, "core", "1.user.md")
44228
44676
  ];
44229
44677
  for (const filePath of coreFiles) {
44230
- if (!existsSync66(filePath)) continue;
44678
+ if (!existsSync67(filePath)) continue;
44231
44679
  try {
44232
- const content = readFileSync48(filePath, "utf-8");
44680
+ const content = readFileSync49(filePath, "utf-8");
44233
44681
  for (const tok of tokenize(content)) {
44234
44682
  excluded.add(tok);
44235
44683
  }
@@ -44280,8 +44728,8 @@ var init_reflect = __esm({
44280
44728
  });
44281
44729
 
44282
44730
  // src/cli/commands/council.ts
44283
- import { existsSync as existsSync67, mkdirSync as mkdirSync27, readFileSync as readFileSync49, writeFileSync as writeFileSync34 } from "fs";
44284
- import { join as join64 } from "path";
44731
+ import { existsSync as existsSync68, mkdirSync as mkdirSync28, readFileSync as readFileSync50, writeFileSync as writeFileSync35 } from "fs";
44732
+ import { join as join65 } from "path";
44285
44733
  function roundRunningStatus(n) {
44286
44734
  return `round_${n}_running`;
44287
44735
  }
@@ -44323,12 +44771,12 @@ function registerCreate(council) {
44323
44771
  }
44324
44772
  const id = generateId("council");
44325
44773
  const dir = getDebateDir(id);
44326
- mkdirSync27(dir, { recursive: true });
44774
+ mkdirSync28(dir, { recursive: true });
44327
44775
  const template = loadTemplate("council-debate.md");
44328
44776
  const content = template.replaceAll("{{ID}}", id).replaceAll("{{TOPIC}}", topic.replace(/"/g, '\\"')).replaceAll("{{ROUNDS}}", String(rounds)).replaceAll("{{INTERRUPT}}", opts.interrupt ? "true" : "false").replaceAll("{{DATE}}", today());
44329
- writeFileSync34(join64(dir, "debate.md"), content, "utf-8");
44330
- writeFileSync34(
44331
- join64(dir, "round-log.md"),
44777
+ writeFileSync35(join65(dir, "debate.md"), content, "utf-8");
44778
+ writeFileSync35(
44779
+ join65(dir, "round-log.md"),
44332
44780
  `# Round log \u2014 ${id}
44333
44781
 
44334
44782
  (Main agent appends timeline entries here.)
@@ -44370,8 +44818,8 @@ function registerAgent(council) {
44370
44818
  process.exit(1);
44371
44819
  }
44372
44820
  const personaDir = getPersonaDir(debateId, slug);
44373
- const personaFile = join64(personaDir, "context-and-persona.md");
44374
- if (existsSync67(personaFile) && !opts.force) {
44821
+ const personaFile = join65(personaDir, "context-and-persona.md");
44822
+ if (existsSync68(personaFile) && !opts.force) {
44375
44823
  error(`Persona already exists: ${slug}`, "Use --force to overwrite.");
44376
44824
  process.exit(1);
44377
44825
  }
@@ -44381,14 +44829,14 @@ function registerAgent(council) {
44381
44829
  process.exit(1);
44382
44830
  }
44383
44831
  const aspects = opts.aspects ? opts.aspects.split(",").map((a) => a.trim()).filter(Boolean) : [];
44384
- mkdirSync27(personaDir, { recursive: true });
44832
+ mkdirSync28(personaDir, { recursive: true });
44385
44833
  const template = loadTemplate("council-persona.md");
44386
44834
  const personaContent = template.replaceAll("{{SLUG}}", slug).replaceAll("{{MODEL}}", opts.model).replaceAll("{{ASPECTS}}", JSON.stringify(aspects)).replaceAll("{{PERSONA_BODY}}", body.trim());
44387
- writeFileSync34(personaFile, personaContent, "utf-8");
44835
+ writeFileSync35(personaFile, personaContent, "utf-8");
44388
44836
  const reportTemplate = loadTemplate("council-report.md");
44389
44837
  const reportContent = reportTemplate.replaceAll("{{SLUG}}", slug);
44390
- writeFileSync34(join64(personaDir, "report.md"), reportContent, "utf-8");
44391
- const debateFile = join64(getDebateDir(debateId), "debate.md");
44838
+ writeFileSync35(join65(personaDir, "report.md"), reportContent, "utf-8");
44839
+ const debateFile = join65(getDebateDir(debateId), "debate.md");
44392
44840
  const { data } = readFrontmatter(debateFile);
44393
44841
  const personas = Array.isArray(data.personas) ? data.personas.slice() : [];
44394
44842
  if (!personas.includes(slug)) personas.push(slug);
@@ -44417,7 +44865,7 @@ function registerRound(council) {
44417
44865
  error(`Round ${n} exceeds planned rounds (${data.rounds_planned}).`);
44418
44866
  process.exit(1);
44419
44867
  }
44420
- const debateFile = join64(getDebateDir(debateId), "debate.md");
44868
+ const debateFile = join65(getDebateDir(debateId), "debate.md");
44421
44869
  const personas = data.personas ?? [];
44422
44870
  if (personas.length === 0) {
44423
44871
  error("No personas registered. Run `council agent create` first.");
@@ -44426,9 +44874,9 @@ function registerRound(council) {
44426
44874
  const crossContextHeader = `## Round ${n} \u2014 Cross-context loaded`;
44427
44875
  if (n >= 2) {
44428
44876
  for (const persona of personas) {
44429
- const personaFile = join64(getPersonaDir(debateId, persona), "context-and-persona.md");
44430
- if (!existsSync67(personaFile)) continue;
44431
- const existing = readFileSync49(personaFile, "utf-8");
44877
+ const personaFile = join65(getPersonaDir(debateId, persona), "context-and-persona.md");
44878
+ if (!existsSync68(personaFile)) continue;
44879
+ const existing = readFileSync50(personaFile, "utf-8");
44432
44880
  if (existing.includes(crossContextHeader)) {
44433
44881
  continue;
44434
44882
  }
@@ -44450,7 +44898,7 @@ _(no round ${n - 1} report submitted)_`);
44450
44898
 
44451
44899
  ${peerLines.join("\n\n")}`;
44452
44900
  const updated = existing.trimEnd() + "\n\n" + newSection + "\n";
44453
- writeFileSync34(personaFile, updated, "utf-8");
44901
+ writeFileSync35(personaFile, updated, "utf-8");
44454
44902
  }
44455
44903
  }
44456
44904
  updateFrontmatterFields(debateFile, {
@@ -44458,13 +44906,13 @@ ${peerLines.join("\n\n")}`;
44458
44906
  current_round: n,
44459
44907
  updated_at: today()
44460
44908
  });
44461
- const logFile = join64(getDebateDir(debateId), "round-log.md");
44462
- const logExisting = existsSync67(logFile) ? readFileSync49(logFile, "utf-8") : "";
44909
+ const logFile = join65(getDebateDir(debateId), "round-log.md");
44910
+ const logExisting = existsSync68(logFile) ? readFileSync50(logFile, "utf-8") : "";
44463
44911
  const logEntry = `
44464
44912
  ## Round ${n} started \u2014 ${today()}
44465
44913
  - Personas: ${formatPersonaList(personas)}
44466
44914
  `;
44467
- writeFileSync34(logFile, logExisting.trimEnd() + "\n" + logEntry + "\n", "utf-8");
44915
+ writeFileSync35(logFile, logExisting.trimEnd() + "\n" + logEntry + "\n", "utf-8");
44468
44916
  upsertCouncilIndex({
44469
44917
  id: debateId,
44470
44918
  topic: data.topic,
@@ -44498,18 +44946,18 @@ ${peerLines.join("\n\n")}`;
44498
44946
  error(`Round ${n} incomplete. Missing reports from: ${missing.join(", ")}`);
44499
44947
  process.exit(1);
44500
44948
  }
44501
- const debateFile = join64(getDebateDir(debateId), "debate.md");
44949
+ const debateFile = join65(getDebateDir(debateId), "debate.md");
44502
44950
  updateFrontmatterFields(debateFile, {
44503
44951
  status: roundCompleteStatus(n),
44504
44952
  updated_at: today()
44505
44953
  });
44506
- const logFile = join64(getDebateDir(debateId), "round-log.md");
44507
- const logExisting = existsSync67(logFile) ? readFileSync49(logFile, "utf-8") : "";
44954
+ const logFile = join65(getDebateDir(debateId), "round-log.md");
44955
+ const logExisting = existsSync68(logFile) ? readFileSync50(logFile, "utf-8") : "";
44508
44956
  const logEntry = `
44509
44957
  ## Round ${n} complete \u2014 ${today()}
44510
44958
  - All ${personas.length} personas submitted reports.
44511
44959
  `;
44512
- writeFileSync34(logFile, logExisting.trimEnd() + "\n" + logEntry + "\n", "utf-8");
44960
+ writeFileSync35(logFile, logExisting.trimEnd() + "\n" + logEntry + "\n", "utf-8");
44513
44961
  upsertCouncilIndex({
44514
44962
  id: debateId,
44515
44963
  topic: data.topic,
@@ -44532,8 +44980,8 @@ function registerRoundContext(council) {
44532
44980
  try {
44533
44981
  const data = readDebateFrontmatter(debateId);
44534
44982
  ensurePersonaExists(debateId, personaSlug);
44535
- const personaFile = join64(getPersonaDir(debateId, personaSlug), "context-and-persona.md");
44536
- const personaContent = readFileSync49(personaFile, "utf-8");
44983
+ const personaFile = join65(getPersonaDir(debateId, personaSlug), "context-and-persona.md");
44984
+ const personaContent = readFileSync50(personaFile, "utf-8");
44537
44985
  console.log(`# Council debate: ${data.topic}`);
44538
44986
  console.log(`Debate ID: ${debateId}`);
44539
44987
  console.log(`Current round: ${data.current_round}/${data.rounds_planned}`);
@@ -44542,8 +44990,8 @@ function registerRoundContext(council) {
44542
44990
  console.log("---");
44543
44991
  console.log("");
44544
44992
  console.log(personaContent);
44545
- const debateFile = join64(getDebateDir(debateId), "debate.md");
44546
- const debateRaw = readFileSync49(debateFile, "utf-8");
44993
+ const debateFile = join65(getDebateDir(debateId), "debate.md");
44994
+ const debateRaw = readFileSync50(debateFile, "utf-8");
44547
44995
  const questionMatch = debateRaw.match(/##\s+Question\s*\n([\s\S]*?)(?=\n##\s|\Z)/);
44548
44996
  const constraintsMatch = debateRaw.match(/##\s+Constraints & Known Facts\s*\n([\s\S]*?)(?=\n##\s|\Z)/);
44549
44997
  if (questionMatch) {
@@ -44586,7 +45034,7 @@ function registerReport(council) {
44586
45034
  process.exit(1);
44587
45035
  }
44588
45036
  for (const w of validation.warnings) warn(w);
44589
- const reportFile = join64(getPersonaDir(debateId, personaSlug), "report.md");
45037
+ const reportFile = join65(getPersonaDir(debateId, personaSlug), "report.md");
44590
45038
  const { data: reportData, content } = readFrontmatter(reportFile);
44591
45039
  const existingRounds = parseReportRounds(content);
44592
45040
  if (existingRounds.find((r) => r.round === round)) {
@@ -44608,7 +45056,7 @@ ${otherSerialized}
44608
45056
  persona: personaSlug,
44609
45057
  rounds_completed: Math.max(reportData.rounds_completed ?? 0, round)
44610
45058
  }, "\n" + merged);
44611
- const personaFile = join64(getPersonaDir(debateId, personaSlug), "context-and-persona.md");
45059
+ const personaFile = join65(getPersonaDir(debateId, personaSlug), "context-and-persona.md");
44612
45060
  const { data: pData } = readFrontmatter(personaFile);
44613
45061
  updateFrontmatterFields(personaFile, {
44614
45062
  round_entries: Math.max(pData.round_entries ?? 0, round)
@@ -44651,13 +45099,13 @@ function registerResearch(council) {
44651
45099
  error("Research topic is required.");
44652
45100
  process.exit(1);
44653
45101
  }
44654
- const researchesDir = join64(getPersonaDir(debateId, personaSlug), "researches");
44655
- mkdirSync27(researchesDir, { recursive: true });
44656
- const indexPath2 = join64(researchesDir, "index.json");
44657
- if (!existsSync67(indexPath2)) writeJsonArray(indexPath2, []);
45102
+ const researchesDir = join65(getPersonaDir(debateId, personaSlug), "researches");
45103
+ mkdirSync28(researchesDir, { recursive: true });
45104
+ const indexPath2 = join65(researchesDir, "index.json");
45105
+ if (!existsSync68(indexPath2)) writeJsonArray(indexPath2, []);
44658
45106
  const slug = slugify(topic);
44659
- const file = join64(researchesDir, `${slug}.md`);
44660
- if (existsSync67(file)) {
45107
+ const file = join65(researchesDir, `${slug}.md`);
45108
+ if (existsSync68(file)) {
44661
45109
  error(`Research note already exists: ${slug}.md`);
44662
45110
  process.exit(1);
44663
45111
  }
@@ -44672,7 +45120,7 @@ _Added ${today()} by ${personaSlug}_
44672
45120
 
44673
45121
  ${body.trim()}
44674
45122
  `;
44675
- writeFileSync34(file, noteContent, "utf-8");
45123
+ writeFileSync35(file, noteContent, "utf-8");
44676
45124
  insertToJsonArray(indexPath2, {
44677
45125
  slug,
44678
45126
  topic,
@@ -44687,9 +45135,9 @@ ${body.trim()}
44687
45135
  research.command("list").argument("<debate_id>").argument("<persona_slug>").description("List this persona's prior research notes.").action((debateId, personaSlug) => {
44688
45136
  try {
44689
45137
  ensurePersonaExists(debateId, personaSlug);
44690
- const researchesDir = join64(getPersonaDir(debateId, personaSlug), "researches");
44691
- const indexPath2 = join64(researchesDir, "index.json");
44692
- if (!existsSync67(indexPath2)) {
45138
+ const researchesDir = join65(getPersonaDir(debateId, personaSlug), "researches");
45139
+ const indexPath2 = join65(researchesDir, "index.json");
45140
+ if (!existsSync68(indexPath2)) {
44693
45141
  console.log(source_default.dim("(no researches)"));
44694
45142
  return;
44695
45143
  }
@@ -44711,7 +45159,7 @@ function registerSynthesize(council) {
44711
45159
  council.command("synthesize").argument("<debate_id>").description("Mark status=synthesizing; print manifest of files synthesizer should read.").action((debateId) => {
44712
45160
  try {
44713
45161
  const data = readDebateFrontmatter(debateId);
44714
- const debateFile = join64(getDebateDir(debateId), "debate.md");
45162
+ const debateFile = join65(getDebateDir(debateId), "debate.md");
44715
45163
  updateFrontmatterFields(debateFile, {
44716
45164
  status: "synthesizing",
44717
45165
  updated_at: today()
@@ -44733,8 +45181,8 @@ function registerSynthesize(council) {
44733
45181
  const personaDir = getPersonaDir(debateId, persona);
44734
45182
  manifest.push(`_dream_context/council/${debateId}/${persona}/context-and-persona.md`);
44735
45183
  manifest.push(`_dream_context/council/${debateId}/${persona}/report.md`);
44736
- const researchesIndex = join64(personaDir, "researches", "index.json");
44737
- if (existsSync67(researchesIndex)) {
45184
+ const researchesIndex = join65(personaDir, "researches", "index.json");
45185
+ if (existsSync68(researchesIndex)) {
44738
45186
  manifest.push(`_dream_context/council/${debateId}/${persona}/researches/`);
44739
45187
  }
44740
45188
  }
@@ -44752,12 +45200,12 @@ function registerComplete(council) {
44752
45200
  council.command("complete").argument("<debate_id>").description("Mark status=complete after final-report.md is written.").action((debateId) => {
44753
45201
  try {
44754
45202
  const data = readDebateFrontmatter(debateId);
44755
- const finalReport = join64(getDebateDir(debateId), "final-report.md");
44756
- if (!existsSync67(finalReport)) {
45203
+ const finalReport = join65(getDebateDir(debateId), "final-report.md");
45204
+ if (!existsSync68(finalReport)) {
44757
45205
  error("final-report.md not found.", "Synthesizer must write it before calling `council complete`.");
44758
45206
  process.exit(1);
44759
45207
  }
44760
- const debateFile = join64(getDebateDir(debateId), "debate.md");
45208
+ const debateFile = join65(getDebateDir(debateId), "debate.md");
44761
45209
  updateFrontmatterFields(debateFile, {
44762
45210
  status: "complete",
44763
45211
  updated_at: today()
@@ -44789,8 +45237,8 @@ function registerPromote(council) {
44789
45237
  error(`Cannot promote: debate status is "${data.status}", expected "complete".`);
44790
45238
  process.exit(1);
44791
45239
  }
44792
- const finalReport = join64(getDebateDir(debateId), "final-report.md");
44793
- if (!existsSync67(finalReport)) {
45240
+ const finalReport = join65(getDebateDir(debateId), "final-report.md");
45241
+ if (!existsSync68(finalReport)) {
44794
45242
  error("final-report.md not found.");
44795
45243
  process.exit(1);
44796
45244
  }
@@ -44803,12 +45251,12 @@ function registerPromote(council) {
44803
45251
 
44804
45252
  ${sec.body.trim()}` : null;
44805
45253
  }).filter(Boolean).join("\n\n");
44806
- const knowledgeDir = join64(root, "knowledge");
44807
- mkdirSync27(knowledgeDir, { recursive: true });
45254
+ const knowledgeDir = join65(root, "knowledge");
45255
+ mkdirSync28(knowledgeDir, { recursive: true });
44808
45256
  const slug = slugify(data.topic).slice(0, 80) || debateId;
44809
45257
  const filename = `decision-${slug}.md`;
44810
- const target = join64(knowledgeDir, filename);
44811
- if (existsSync67(target) && !opts.force) {
45258
+ const target = join65(knowledgeDir, filename);
45259
+ if (existsSync68(target) && !opts.force) {
44812
45260
  error(`Knowledge file exists: ${filename}`, "Use --force to overwrite.");
44813
45261
  process.exit(1);
44814
45262
  }
@@ -44832,7 +45280,7 @@ ${kept}
44832
45280
  _Promoted from council debate \`${debateId}\` on ${today()}. See \`_dream_context/council/${debateId}/final-report.md\` for the full record._
44833
45281
  `;
44834
45282
  writeFrontmatter(target, knowledgeFrontmatter, body);
44835
- updateFrontmatterFields(join64(getDebateDir(debateId), "debate.md"), {
45283
+ updateFrontmatterFields(join65(getDebateDir(debateId), "debate.md"), {
44836
45284
  promoted_to_knowledge: `knowledge/${filename}`,
44837
45285
  updated_at: today()
44838
45286
  });
@@ -44894,10 +45342,10 @@ function registerShow(council) {
44894
45342
  console.log(` promoted: ${data.promoted_to_knowledge ?? source_default.dim("(no)")}`);
44895
45343
  console.log(` created: ${data.created_at}`);
44896
45344
  console.log(` updated: ${data.updated_at}`);
44897
- const logFile = join64(getDebateDir(debateId), "round-log.md");
44898
- if (existsSync67(logFile)) {
45345
+ const logFile = join65(getDebateDir(debateId), "round-log.md");
45346
+ if (existsSync68(logFile)) {
44899
45347
  console.log("\n" + source_default.dim("\u2500\u2500\u2500 Round log \u2500\u2500\u2500"));
44900
- console.log(readFileSync49(logFile, "utf-8"));
45348
+ console.log(readFileSync50(logFile, "utf-8"));
44901
45349
  }
44902
45350
  } catch (err) {
44903
45351
  error(err.message);
@@ -45089,12 +45537,12 @@ var init_env_loader = __esm({
45089
45537
  });
45090
45538
 
45091
45539
  // src/lib/marketing/config.ts
45092
- import { existsSync as existsSync68, readFileSync as readFileSync50, writeFileSync as writeFileSync35, mkdirSync as mkdirSync28 } from "fs";
45093
- import { dirname as dirname37 } from "path";
45540
+ import { existsSync as existsSync69, readFileSync as readFileSync51, writeFileSync as writeFileSync36, mkdirSync as mkdirSync29 } from "fs";
45541
+ import { dirname as dirname38 } from "path";
45094
45542
  function readEnvFile() {
45095
45543
  const path2 = MARKETING_PATHS.envFile();
45096
- if (!existsSync68(path2)) return {};
45097
- const raw = readFileSync50(path2, "utf8");
45544
+ if (!existsSync69(path2)) return {};
45545
+ const raw = readFileSync51(path2, "utf8");
45098
45546
  const parsed = parseEnv(raw);
45099
45547
  if (parsed.errors.length > 0) {
45100
45548
  for (const e of parsed.errors) {
@@ -45138,9 +45586,9 @@ function requireEnv(keys = REQUIRED_KEYS) {
45138
45586
  }
45139
45587
  function loadConfig() {
45140
45588
  const path2 = MARKETING_PATHS.configFile();
45141
- if (!existsSync68(path2)) return { ...EMPTY_CONFIG, feature_flags: { ...EMPTY_CONFIG.feature_flags } };
45589
+ if (!existsSync69(path2)) return { ...EMPTY_CONFIG, feature_flags: { ...EMPTY_CONFIG.feature_flags } };
45142
45590
  try {
45143
- const raw = readFileSync50(path2, "utf8");
45591
+ const raw = readFileSync51(path2, "utf8");
45144
45592
  const parsed = JSON.parse(raw);
45145
45593
  return {
45146
45594
  default_profile: parsed.default_profile ?? null,
@@ -45155,21 +45603,21 @@ function loadConfig() {
45155
45603
  }
45156
45604
  function writeConfig(cfg) {
45157
45605
  const path2 = MARKETING_PATHS.configFile();
45158
- mkdirSync28(dirname37(path2), { recursive: true });
45159
- writeFileSync35(path2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
45606
+ mkdirSync29(dirname38(path2), { recursive: true });
45607
+ writeFileSync36(path2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
45160
45608
  }
45161
45609
  function ensureConfigFile() {
45162
45610
  const path2 = MARKETING_PATHS.configFile();
45163
- if (existsSync68(path2)) return loadConfig();
45611
+ if (existsSync69(path2)) return loadConfig();
45164
45612
  const cfg = { ...EMPTY_CONFIG, feature_flags: { ...EMPTY_CONFIG.feature_flags } };
45165
45613
  writeConfig(cfg);
45166
45614
  return cfg;
45167
45615
  }
45168
45616
  function ensureEnvFile() {
45169
45617
  const path2 = MARKETING_PATHS.envFile();
45170
- if (existsSync68(path2)) return;
45171
- mkdirSync28(marketingRoot(), { recursive: true });
45172
- writeFileSync35(path2, ENV_TEMPLATE, { encoding: "utf8", mode: 384 });
45618
+ if (existsSync69(path2)) return;
45619
+ mkdirSync29(marketingRoot(), { recursive: true });
45620
+ writeFileSync36(path2, ENV_TEMPLATE, { encoding: "utf8", mode: 384 });
45173
45621
  }
45174
45622
  var DEFAULT_API_VERSION, EMPTY_CONFIG, REQUIRED_KEYS, OPTIONAL_KEYS, ENV_TEMPLATE;
45175
45623
  var init_config2 = __esm({
@@ -45210,9 +45658,9 @@ REINFLUENCE_BIN= # optional override; default uses .venv
45210
45658
 
45211
45659
  // src/lib/marketing/bootstrap.ts
45212
45660
  import { spawn as spawn5, spawnSync as spawnSync2 } from "child_process";
45213
- import { existsSync as existsSync69, mkdirSync as mkdirSync29, cpSync as cpSync3 } from "fs";
45661
+ import { existsSync as existsSync70, mkdirSync as mkdirSync30, cpSync as cpSync3 } from "fs";
45214
45662
  import { fileURLToPath as fileURLToPath8 } from "url";
45215
- import { dirname as dirname38, resolve as resolve17, join as join65 } from "path";
45663
+ import { dirname as dirname39, resolve as resolve17, join as join66 } from "path";
45216
45664
  function findBundledReinfluence() {
45217
45665
  const candidates = [
45218
45666
  // Installed npm package: dist/<chunk>.js -> ../tools/reinfluence
@@ -45222,7 +45670,7 @@ function findBundledReinfluence() {
45222
45670
  resolve17(__dirname7, "..", "..", "..", "tools", "reinfluence")
45223
45671
  ];
45224
45672
  for (const c of candidates) {
45225
- if (existsSync69(join65(c, "__main__.py"))) return c;
45673
+ if (existsSync70(join66(c, "__main__.py"))) return c;
45226
45674
  }
45227
45675
  throw new Error(
45228
45676
  "Bundled reinfluence not found. Reinstall dreamcontext or set REINFLUENCE_BIN."
@@ -45253,18 +45701,18 @@ async function bootstrapMarketing(opts = {}) {
45253
45701
  if (verbose) process.stderr.write(`[mk init] ${msg}
45254
45702
  `);
45255
45703
  };
45256
- mkdirSync29(marketingRoot(), { recursive: true });
45704
+ mkdirSync30(marketingRoot(), { recursive: true });
45257
45705
  const bundled = findBundledReinfluence();
45258
45706
  const target = MARKETING_PATHS.reinfluenceDir();
45259
45707
  log(`copying tools \u2192 ${target}`);
45260
- mkdirSync29(MARKETING_PATHS.toolsDir(), { recursive: true });
45708
+ mkdirSync30(MARKETING_PATHS.toolsDir(), { recursive: true });
45261
45709
  cpSync3(bundled, target, { recursive: true });
45262
45710
  const py = findPython3();
45263
45711
  if (!py) {
45264
45712
  throw new Error("python3 not found on PATH. Install Python 3.10+ and retry.");
45265
45713
  }
45266
45714
  const venv = MARKETING_PATHS.venvDir();
45267
- if (!existsSync69(MARKETING_PATHS.venvPython())) {
45715
+ if (!existsSync70(MARKETING_PATHS.venvPython())) {
45268
45716
  log(`creating venv \u2192 ${venv}`);
45269
45717
  const r2 = runBlocking(py, ["-m", "venv", venv]);
45270
45718
  if (r2.code !== 0) {
@@ -45277,7 +45725,7 @@ async function bootstrapMarketing(opts = {}) {
45277
45725
  log("upgrading pip");
45278
45726
  let r = runBlocking(venvPy, ["-m", "pip", "install", "--upgrade", "pip", "--quiet"]);
45279
45727
  if (r.code !== 0) log(`pip upgrade warning: ${r.stderr.trim().slice(0, 200)}`);
45280
- const reqs = join65(target, "requirements.txt");
45728
+ const reqs = join66(target, "requirements.txt");
45281
45729
  log("installing python deps (whisper / yt-dlp / instaloader) \u2014 first run can take several minutes");
45282
45730
  r = runBlocking(venvPy, ["-m", "pip", "install", "-r", reqs, "--quiet"]);
45283
45731
  if (r.code !== 0) {
@@ -45287,7 +45735,7 @@ ${r.stderr.trim() || r.stdout.trim()}`);
45287
45735
  let whisperPrimed = false;
45288
45736
  if (whisperModel) {
45289
45737
  log(`pre-pulling whisper model "${whisperModel}" into ${MARKETING_PATHS.whisperCacheDir()}`);
45290
- mkdirSync29(MARKETING_PATHS.whisperCacheDir(), { recursive: true });
45738
+ mkdirSync30(MARKETING_PATHS.whisperCacheDir(), { recursive: true });
45291
45739
  whisperPrimed = await primeWhisper(whisperModel);
45292
45740
  if (!whisperPrimed) log("whisper pre-pull failed (will retry on first ingest)");
45293
45741
  }
@@ -45327,15 +45775,15 @@ function subprocessEnv() {
45327
45775
  return {
45328
45776
  ...process.env,
45329
45777
  XDG_CACHE_HOME: cache,
45330
- HF_HOME: join65(cache, "hf"),
45331
- TRANSFORMERS_CACHE: join65(cache, "hf", "transformers"),
45778
+ HF_HOME: join66(cache, "hf"),
45779
+ TRANSFORMERS_CACHE: join66(cache, "hf", "transformers"),
45332
45780
  WHISPER_CACHE_DIR: MARKETING_PATHS.whisperCacheDir(),
45333
45781
  PYTHONUNBUFFERED: "1",
45334
45782
  PYTHONPATH: MARKETING_PATHS.toolsDir()
45335
45783
  };
45336
45784
  }
45337
45785
  function isBootstrapped() {
45338
- return existsSync69(MARKETING_PATHS.venvPython()) && existsSync69(join65(MARKETING_PATHS.reinfluenceDir(), "__main__.py"));
45786
+ return existsSync70(MARKETING_PATHS.venvPython()) && existsSync70(join66(MARKETING_PATHS.reinfluenceDir(), "__main__.py"));
45339
45787
  }
45340
45788
  var __filename, __dirname7;
45341
45789
  var init_bootstrap = __esm({
@@ -45343,12 +45791,12 @@ var init_bootstrap = __esm({
45343
45791
  "use strict";
45344
45792
  init_paths2();
45345
45793
  __filename = fileURLToPath8(import.meta.url);
45346
- __dirname7 = dirname38(__filename);
45794
+ __dirname7 = dirname39(__filename);
45347
45795
  }
45348
45796
  });
45349
45797
 
45350
45798
  // src/cli/commands/marketing/init.ts
45351
- import { mkdirSync as mkdirSync30 } from "fs";
45799
+ import { mkdirSync as mkdirSync31 } from "fs";
45352
45800
  function registerMarketingInit(parent) {
45353
45801
  parent.command("init").description("Bootstrap _dream_context/marketing/ (folders, .env, venv, reinfluence tools, whisper cache)").option("--skip-bootstrap", "Only create folders + .env template; skip venv + pip install", false).option("--whisper-model <model>", "Whisper model to pre-pull (default: medium)", "medium").option("--no-whisper", "Skip Whisper model pre-pull").action(async (opts) => {
45354
45802
  try {
@@ -45359,7 +45807,7 @@ function registerMarketingInit(parent) {
45359
45807
  }
45360
45808
  console.log(header("Marketing init"));
45361
45809
  const root = marketingRoot();
45362
- mkdirSync30(root, { recursive: true });
45810
+ mkdirSync31(root, { recursive: true });
45363
45811
  for (const dir of [
45364
45812
  MARKETING_PATHS.cohortsDir(),
45365
45813
  MARKETING_PATHS.campaignsDir(),
@@ -45372,7 +45820,7 @@ function registerMarketingInit(parent) {
45372
45820
  MARKETING_PATHS.byIdemDir(),
45373
45821
  MARKETING_PATHS.cacheDir()
45374
45822
  ]) {
45375
- mkdirSync30(dir, { recursive: true });
45823
+ mkdirSync31(dir, { recursive: true });
45376
45824
  }
45377
45825
  info(`folders ready under ${source_default.dim(root)}`);
45378
45826
  ensureEnvFile();
@@ -45412,8 +45860,8 @@ var init_init2 = __esm({
45412
45860
  });
45413
45861
 
45414
45862
  // src/lib/marketing/vision.ts
45415
- import { existsSync as existsSync70, readFileSync as readFileSync51, writeFileSync as writeFileSync36 } from "fs";
45416
- import { dirname as dirname39, join as join66 } from "path";
45863
+ import { existsSync as existsSync71, readFileSync as readFileSync52, writeFileSync as writeFileSync37 } from "fs";
45864
+ import { dirname as dirname40, join as join67 } from "path";
45417
45865
  function pickVisionProvider(env2 = process.env) {
45418
45866
  const oai = env2.OPENAI_VISION_API_KEY;
45419
45867
  if (oai && oai.trim().length > 0) return { provider: "openai", apiKey: oai.trim() };
@@ -45452,11 +45900,11 @@ function parseLabelsFromText(text, allowlist = LABEL_ALLOWLIST) {
45452
45900
  return out;
45453
45901
  }
45454
45902
  async function readImageAsBase64(framePath) {
45455
- const buf = readFileSync51(framePath);
45903
+ const buf = readFileSync52(framePath);
45456
45904
  return buf.toString("base64");
45457
45905
  }
45458
45906
  async function labelHookFrame(framePath, opts) {
45459
- if (!existsSync70(framePath)) return [];
45907
+ if (!existsSync71(framePath)) return [];
45460
45908
  const fetcher = opts.fetcher ?? defaultFetcher;
45461
45909
  const prompt = opts.promptOverride ?? PROMPT;
45462
45910
  const b64 = await readImageAsBase64(framePath);
@@ -45506,7 +45954,7 @@ async function labelHookFrame(framePath, opts) {
45506
45954
  return parseLabelsFromText(text);
45507
45955
  }
45508
45956
  async function runVisionPassOnPost(postJsonPath, opts = {}) {
45509
- const raw = readFileSync51(postJsonPath, "utf-8");
45957
+ const raw = readFileSync52(postJsonPath, "utf-8");
45510
45958
  const post = JSON.parse(raw);
45511
45959
  const shortcode = post.shortcode ?? "?";
45512
45960
  const provider = opts.provider && opts.apiKey ? { provider: opts.provider, apiKey: opts.apiKey } : pickVisionProvider();
@@ -45545,15 +45993,15 @@ async function runVisionPassOnPost(postJsonPath, opts = {}) {
45545
45993
  post.pattern_tags = [...aggregated].sort();
45546
45994
  post.vision_summary = post.pattern_tags.length > 0 ? `Vision-tagged ${framesLabeled}/${hookFrames.length} hook frames; patterns: ${post.pattern_tags.join(", ")}.` : `Vision pass found no allowlisted patterns across ${hookFrames.length} hook frames.`;
45547
45995
  const tmp = postJsonPath + ".tmp";
45548
- writeFileSync36(tmp, JSON.stringify(post, null, 2) + "\n", "utf-8");
45996
+ writeFileSync37(tmp, JSON.stringify(post, null, 2) + "\n", "utf-8");
45549
45997
  const fs = await import("fs");
45550
45998
  fs.renameSync(tmp, postJsonPath);
45551
- const mdPath = join66(dirname39(postJsonPath), `${shortcode}.md`);
45552
- if (existsSync70(mdPath)) {
45999
+ const mdPath = join67(dirname40(postJsonPath), `${shortcode}.md`);
46000
+ if (existsSync71(mdPath)) {
45553
46001
  try {
45554
- const md = readFileSync51(mdPath, "utf-8");
46002
+ const md = readFileSync52(mdPath, "utf-8");
45555
46003
  const refreshed = updatePatternTagsInBridge(md, post.pattern_tags);
45556
- writeFileSync36(mdPath, refreshed, "utf-8");
46004
+ writeFileSync37(mdPath, refreshed, "utf-8");
45557
46005
  } catch {
45558
46006
  }
45559
46007
  }
@@ -45628,8 +46076,8 @@ Example output: ["talking-head","prop-driven"]`;
45628
46076
  // src/lib/marketing/competitors.ts
45629
46077
  import { spawn as spawn6 } from "child_process";
45630
46078
  import { spawnSync as spawnSync3 } from "child_process";
45631
- import { existsSync as existsSync71, mkdirSync as mkdirSync31, statfsSync } from "fs";
45632
- import { dirname as dirname40, join as join67, basename as basename20, extname as extname4 } from "path";
46079
+ import { existsSync as existsSync72, mkdirSync as mkdirSync32, statfsSync } from "fs";
46080
+ import { dirname as dirname41, join as join68, basename as basename20, extname as extname4 } from "path";
45633
46081
  function which(cmd) {
45634
46082
  const r = spawnSync3(process.platform === "win32" ? "where" : "which", [cmd], { encoding: "utf8" });
45635
46083
  if (r.status === 0) return (r.stdout || "").trim().split("\n")[0] || null;
@@ -45706,8 +46154,8 @@ ${h.installHints.join("\n")}`);
45706
46154
  skip_transcripts: !!opts.skipTranscripts,
45707
46155
  skip_frames: !!opts.skipFrames
45708
46156
  });
45709
- const outDir = join67(MARKETING_PATHS.competitorsDir(), "_ingest-tmp", run2.id);
45710
- mkdirSync31(outDir, { recursive: true });
46157
+ const outDir = join68(MARKETING_PATHS.competitorsDir(), "_ingest-tmp", run2.id);
46158
+ mkdirSync32(outDir, { recursive: true });
45711
46159
  const args = [
45712
46160
  "-m",
45713
46161
  "reinfluence",
@@ -45807,15 +46255,15 @@ stderr: ${stderrBuf.slice(0, 1e3)}`));
45807
46255
  return { runId: run2.id, postsIngested, warnings, errors };
45808
46256
  }
45809
46257
  function persistPost(evt) {
45810
- const handleDir = join67(MARKETING_PATHS.competitorsDir(), evt.handle);
45811
- const postsDir = join67(handleDir, "posts");
45812
- const mediaDir = join67(handleDir, "_media", evt.shortcode);
45813
- mkdirSync31(postsDir, { recursive: true });
45814
- mkdirSync31(mediaDir, { recursive: true });
45815
- const finalVideoPath = evt.video_path ? moveAsset(evt.video_path, join67(mediaDir, basename20(evt.video_path))) : null;
46258
+ const handleDir = join68(MARKETING_PATHS.competitorsDir(), evt.handle);
46259
+ const postsDir = join68(handleDir, "posts");
46260
+ const mediaDir = join68(handleDir, "_media", evt.shortcode);
46261
+ mkdirSync32(postsDir, { recursive: true });
46262
+ mkdirSync32(mediaDir, { recursive: true });
46263
+ const finalVideoPath = evt.video_path ? moveAsset(evt.video_path, join68(mediaDir, basename20(evt.video_path))) : null;
45816
46264
  const finalFramePaths = [];
45817
46265
  for (const fr of evt.frames) {
45818
- const finalP = moveAsset(fr.path, join67(mediaDir, "frames", basename20(fr.path)));
46266
+ const finalP = moveAsset(fr.path, join68(mediaDir, "frames", basename20(fr.path)));
45819
46267
  finalFramePaths.push(finalP);
45820
46268
  }
45821
46269
  const id = `${evt.handle}__${evt.shortcode}`;
@@ -45835,14 +46283,14 @@ function persistPost(evt) {
45835
46283
  ingested_at: (/* @__PURE__ */ new Date()).toISOString(),
45836
46284
  asset_paths: { video: finalVideoPath, frames: finalFramePaths }
45837
46285
  };
45838
- const jsonPath = join67(postsDir, `${evt.shortcode}.json`);
45839
- const bridgePath = join67(postsDir, `${evt.shortcode}.md`);
46286
+ const jsonPath = join68(postsDir, `${evt.shortcode}.json`);
46287
+ const bridgePath = join68(postsDir, `${evt.shortcode}.md`);
45840
46288
  writeJsonWithBridge(jsonPath, bridgePath, json, renderPostBridge(json));
45841
- const metaPath = join67(handleDir, "meta.json");
45842
- if (!existsSync71(metaPath)) {
46289
+ const metaPath = join68(handleDir, "meta.json");
46290
+ if (!existsSync72(metaPath)) {
45843
46291
  writeJsonWithBridge(
45844
46292
  metaPath,
45845
- join67(handleDir, "meta.md"),
46293
+ join68(handleDir, "meta.md"),
45846
46294
  { handle: evt.handle, first_seen_at: (/* @__PURE__ */ new Date()).toISOString() },
45847
46295
  `---
45848
46296
  id: competitor_${evt.handle}
@@ -45859,8 +46307,8 @@ First seen: ${(/* @__PURE__ */ new Date()).toISOString()}
45859
46307
  return jsonPath;
45860
46308
  }
45861
46309
  function moveAsset(src, dest) {
45862
- if (!existsSync71(src)) return dest;
45863
- mkdirSync31(dirname40(dest), { recursive: true });
46310
+ if (!existsSync72(src)) return dest;
46311
+ mkdirSync32(dirname41(dest), { recursive: true });
45864
46312
  const fs = __require("fs");
45865
46313
  try {
45866
46314
  fs.renameSync(src, dest);
@@ -45921,8 +46369,8 @@ var init_competitors = __esm({
45921
46369
  });
45922
46370
 
45923
46371
  // src/cli/commands/marketing/competitor.ts
45924
- import { existsSync as existsSync72, readdirSync as readdirSync16, statSync as statSync11 } from "fs";
45925
- import { join as join68 } from "path";
46372
+ import { existsSync as existsSync73, readdirSync as readdirSync16, statSync as statSync11 } from "fs";
46373
+ import { join as join69 } from "path";
45926
46374
  function registerMarketingCompetitor(parent) {
45927
46375
  const cmd = parent.command("competitor").description("Ingest competitor IG / YouTube content (Reinfluence pipeline).");
45928
46376
  cmd.command("ingest <target>").description("Ingest a single URL or an IG handle. Outputs land under _dream_context/marketing/competitors/<handle>/.").option("--model <name>", "Whisper model size (tiny|base|small|medium|large)", "medium").option("--max <n>", "Max reels for IG handle ingest (0 = all)", "0").option("--skip-transcripts", "Skip Whisper transcription", false).option("--skip-frames", "Skip frame extraction", false).option("--timeout <seconds>", "Wall-clock kill", "600").action(async (target, opts) => {
@@ -45972,13 +46420,13 @@ function registerMarketingCompetitor(parent) {
45972
46420
  });
45973
46421
  cmd.command("list").description("List ingested competitor handles.").action(() => {
45974
46422
  const dir = MARKETING_PATHS.competitorsDir();
45975
- if (!existsSync72(dir)) {
46423
+ if (!existsSync73(dir)) {
45976
46424
  info("No competitors ingested yet.");
45977
46425
  return;
45978
46426
  }
45979
46427
  const handles = readdirSync16(dir).filter((name) => {
45980
46428
  if (name.startsWith("_") || name.startsWith(".")) return false;
45981
- const full = join68(dir, name);
46429
+ const full = join69(dir, name);
45982
46430
  try {
45983
46431
  return statSync11(full).isDirectory();
45984
46432
  } catch {
@@ -45991,8 +46439,8 @@ function registerMarketingCompetitor(parent) {
45991
46439
  }
45992
46440
  console.log(header("Competitors"));
45993
46441
  for (const handle of handles) {
45994
- const postsDir = join68(dir, handle, "posts");
45995
- const postCount = existsSync72(postsDir) ? readdirSync16(postsDir).filter((f) => f.endsWith(".json")).length : 0;
46442
+ const postsDir = join69(dir, handle, "posts");
46443
+ const postCount = existsSync73(postsDir) ? readdirSync16(postsDir).filter((f) => f.endsWith(".json")).length : 0;
45996
46444
  console.log(` ${source_default.cyan("@" + handle)} ${source_default.dim(`${postCount} post(s)`)}`);
45997
46445
  }
45998
46446
  });
@@ -46005,11 +46453,11 @@ function registerMarketingCompetitor(parent) {
46005
46453
  }
46006
46454
  info(`Provider: ${provider.provider}`);
46007
46455
  const competitorsDir = MARKETING_PATHS.competitorsDir();
46008
- const handles = opts.handle ? [opts.handle] : existsSync72(competitorsDir) ? readdirSync16(competitorsDir).filter((h) => !h.startsWith("_") && statSync11(join68(competitorsDir, h)).isDirectory()) : [];
46456
+ const handles = opts.handle ? [opts.handle] : existsSync73(competitorsDir) ? readdirSync16(competitorsDir).filter((h) => !h.startsWith("_") && statSync11(join69(competitorsDir, h)).isDirectory()) : [];
46009
46457
  const matches = [];
46010
46458
  for (const h of handles) {
46011
- const candidate = join68(competitorsDir, h, "posts", `${shortcode}.json`);
46012
- if (existsSync72(candidate)) matches.push(candidate);
46459
+ const candidate = join69(competitorsDir, h, "posts", `${shortcode}.json`);
46460
+ if (existsSync73(candidate)) matches.push(candidate);
46013
46461
  }
46014
46462
  if (matches.length === 0) {
46015
46463
  error(`No post JSON found for shortcode "${shortcode}".`);
@@ -46044,18 +46492,18 @@ function registerMarketingCompetitor(parent) {
46044
46492
  process.exit(1);
46045
46493
  }
46046
46494
  const competitorsDir = MARKETING_PATHS.competitorsDir();
46047
- if (!existsSync72(competitorsDir)) {
46495
+ if (!existsSync73(competitorsDir)) {
46048
46496
  warn("No competitors directory yet \u2014 nothing to relabel.");
46049
46497
  return;
46050
46498
  }
46051
- const handles = readdirSync16(competitorsDir).filter((h) => !h.startsWith("_") && statSync11(join68(competitorsDir, h)).isDirectory());
46499
+ const handles = readdirSync16(competitorsDir).filter((h) => !h.startsWith("_") && statSync11(join69(competitorsDir, h)).isDirectory());
46052
46500
  let labeled = 0;
46053
46501
  let skipped = 0;
46054
46502
  for (const h of handles) {
46055
- const postsDir = join68(competitorsDir, h, "posts");
46056
- if (!existsSync72(postsDir)) continue;
46503
+ const postsDir = join69(competitorsDir, h, "posts");
46504
+ if (!existsSync73(postsDir)) continue;
46057
46505
  for (const f of readdirSync16(postsDir).filter((n) => n.endsWith(".json"))) {
46058
- const path2 = join68(postsDir, f);
46506
+ const path2 = join69(postsDir, f);
46059
46507
  if (opts.dryRun) {
46060
46508
  info(`would relabel: ${path2}`);
46061
46509
  continue;
@@ -46102,8 +46550,8 @@ var init_competitor = __esm({
46102
46550
  });
46103
46551
 
46104
46552
  // src/lib/marketing/meta-fetch.ts
46105
- import { existsSync as existsSync73, mkdirSync as mkdirSync32, readFileSync as readFileSync52, writeFileSync as writeFileSync37, statSync as statSync12, openSync as openSync2, readSync, closeSync as closeSync2 } from "fs";
46106
- import { dirname as dirname41, basename as basename21 } from "path";
46553
+ import { existsSync as existsSync74, mkdirSync as mkdirSync33, readFileSync as readFileSync53, writeFileSync as writeFileSync38, statSync as statSync12, openSync as openSync2, readSync, closeSync as closeSync2 } from "fs";
46554
+ import { dirname as dirname42, basename as basename21 } from "path";
46107
46555
  import { randomUUID as randomUUID3 } from "crypto";
46108
46556
  function getQueue(accountId) {
46109
46557
  let q = writeQueues.get(accountId);
@@ -46153,17 +46601,17 @@ function idemCachePath(key) {
46153
46601
  }
46154
46602
  function readIdem(key) {
46155
46603
  const p = idemCachePath(key);
46156
- if (!existsSync73(p)) return null;
46604
+ if (!existsSync74(p)) return null;
46157
46605
  try {
46158
- return JSON.parse(readFileSync52(p, "utf8"));
46606
+ return JSON.parse(readFileSync53(p, "utf8"));
46159
46607
  } catch {
46160
46608
  return null;
46161
46609
  }
46162
46610
  }
46163
46611
  function writeIdem(rec) {
46164
46612
  const p = idemCachePath(rec.key);
46165
- mkdirSync32(dirname41(p), { recursive: true });
46166
- writeFileSync37(p, JSON.stringify(rec, null, 2) + "\n", "utf8");
46613
+ mkdirSync33(dirname42(p), { recursive: true });
46614
+ writeFileSync38(p, JSON.stringify(rec, null, 2) + "\n", "utf8");
46167
46615
  }
46168
46616
  function backoffMs(attempt, hintSec) {
46169
46617
  if (hintSec != null && Number.isFinite(hintSec) && hintSec > 0) {
@@ -46431,7 +46879,7 @@ async function singleShotVideoUpload(ctx, filepath, fields) {
46431
46879
  if (fields.name) form.set("name", fields.name);
46432
46880
  if (fields.title) form.set("title", fields.title);
46433
46881
  if (fields.description) form.set("description", fields.description);
46434
- const buffer = readFileSync52(filepath);
46882
+ const buffer = readFileSync53(filepath);
46435
46883
  const blob = new Blob([new Uint8Array(buffer)], { type: "video/mp4" });
46436
46884
  form.set("source", blob, basename21(filepath));
46437
46885
  const resp = await fetch(url, {
@@ -46480,7 +46928,7 @@ async function uploadImageFile(ctx, filepath) {
46480
46928
  return withWriteSlot(ctx.adAccountId, async () => {
46481
46929
  const url = buildUrl(ctx, { method: "POST", path: `${ctx.adAccountId}/adimages` });
46482
46930
  const form = new FormData();
46483
- const buffer = readFileSync52(filepath);
46931
+ const buffer = readFileSync53(filepath);
46484
46932
  const blob = new Blob([new Uint8Array(buffer)], { type: "image/png" });
46485
46933
  form.set("filename", blob, basename21(filepath));
46486
46934
  const resp = await fetch(url, {
@@ -46899,7 +47347,7 @@ var init_account = __esm({
46899
47347
  });
46900
47348
 
46901
47349
  // src/lib/marketing/hypothesis.ts
46902
- import { existsSync as existsSync74, readFileSync as readFileSync53 } from "fs";
47350
+ import { existsSync as existsSync75, readFileSync as readFileSync54 } from "fs";
46903
47351
  function validateHypothesis(raw, options2 = {}) {
46904
47352
  const errors = [];
46905
47353
  const fieldErrors = {};
@@ -46966,12 +47414,12 @@ function validateHypothesis(raw, options2 = {}) {
46966
47414
  };
46967
47415
  }
46968
47416
  function loadHypothesisFile(path2, options2 = {}) {
46969
- if (!existsSync74(path2)) {
47417
+ if (!existsSync75(path2)) {
46970
47418
  return { ok: false, errors: [`Hypothesis file not found: ${path2}`] };
46971
47419
  }
46972
47420
  let parsed;
46973
47421
  try {
46974
- parsed = JSON.parse(readFileSync53(path2, "utf8"));
47422
+ parsed = JSON.parse(readFileSync54(path2, "utf8"));
46975
47423
  } catch (e) {
46976
47424
  return { ok: false, errors: [`Failed to parse JSON at ${path2}: ${e.message}`] };
46977
47425
  }
@@ -47159,8 +47607,8 @@ var init_cohort2 = __esm({
47159
47607
  });
47160
47608
 
47161
47609
  // src/lib/marketing/insights-cache.ts
47162
- import { existsSync as existsSync75, readFileSync as readFileSync54, mkdirSync as mkdirSync33, writeFileSync as writeFileSync38, readdirSync as readdirSync17, statSync as statSync13 } from "fs";
47163
- import { join as join69 } from "path";
47610
+ import { existsSync as existsSync76, readFileSync as readFileSync55, mkdirSync as mkdirSync34, writeFileSync as writeFileSync39, readdirSync as readdirSync17, statSync as statSync13 } from "fs";
47611
+ import { join as join70 } from "path";
47164
47612
  import { randomBytes as randomBytes3 } from "crypto";
47165
47613
  function snapshotFilename(entityId, pulledAt) {
47166
47614
  const yyyy = pulledAt.getUTCFullYear();
@@ -47171,30 +47619,30 @@ function snapshotFilename(entityId, pulledAt) {
47171
47619
  return `${safe}__${yyyy}-${mm}-${dd}-${hh}.json`;
47172
47620
  }
47173
47621
  function indexPath() {
47174
- return join69(MARKETING_PATHS.insightsDir(), "_index.json");
47622
+ return join70(MARKETING_PATHS.insightsDir(), "_index.json");
47175
47623
  }
47176
47624
  function readIndex() {
47177
47625
  const p = indexPath();
47178
- if (!existsSync75(p)) return { latest: {}, updated_at: "1970-01-01T00:00:00Z" };
47626
+ if (!existsSync76(p)) return { latest: {}, updated_at: "1970-01-01T00:00:00Z" };
47179
47627
  try {
47180
- return JSON.parse(readFileSync54(p, "utf8"));
47628
+ return JSON.parse(readFileSync55(p, "utf8"));
47181
47629
  } catch {
47182
47630
  return { latest: {}, updated_at: "1970-01-01T00:00:00Z" };
47183
47631
  }
47184
47632
  }
47185
47633
  function writeIndex(idx) {
47186
47634
  const p = indexPath();
47187
- mkdirSync33(MARKETING_PATHS.insightsDir(), { recursive: true });
47635
+ mkdirSync34(MARKETING_PATHS.insightsDir(), { recursive: true });
47188
47636
  const tmp = `${p}.tmp.${process.pid}.${randomBytes3(4).toString("hex")}`;
47189
- writeFileSync38(tmp, JSON.stringify(idx, null, 2) + "\n", "utf8");
47637
+ writeFileSync39(tmp, JSON.stringify(idx, null, 2) + "\n", "utf8");
47190
47638
  __require("fs").renameSync(tmp, p);
47191
47639
  }
47192
47640
  function saveInsightsSnapshot(snap) {
47193
- mkdirSync33(MARKETING_PATHS.insightsDir(), { recursive: true });
47641
+ mkdirSync34(MARKETING_PATHS.insightsDir(), { recursive: true });
47194
47642
  const filename = snapshotFilename(snap.entity_id, new Date(snap.pulled_at));
47195
- const fullPath = join69(MARKETING_PATHS.insightsDir(), filename);
47643
+ const fullPath = join70(MARKETING_PATHS.insightsDir(), filename);
47196
47644
  const tmp = `${fullPath}.tmp.${process.pid}.${randomBytes3(4).toString("hex")}`;
47197
- writeFileSync38(tmp, JSON.stringify(snap, null, 2) + "\n", "utf8");
47645
+ writeFileSync39(tmp, JSON.stringify(snap, null, 2) + "\n", "utf8");
47198
47646
  __require("fs").renameSync(tmp, fullPath);
47199
47647
  const idx = readIndex();
47200
47648
  idx.latest[snap.entity_id] = filename;
@@ -47206,10 +47654,10 @@ function getCachedInsights(entityId) {
47206
47654
  const idx = readIndex();
47207
47655
  const filename = idx.latest[entityId];
47208
47656
  if (!filename) return null;
47209
- const fullPath = join69(MARKETING_PATHS.insightsDir(), filename);
47210
- if (!existsSync75(fullPath)) return null;
47657
+ const fullPath = join70(MARKETING_PATHS.insightsDir(), filename);
47658
+ if (!existsSync76(fullPath)) return null;
47211
47659
  try {
47212
- const snap = JSON.parse(readFileSync54(fullPath, "utf8"));
47660
+ const snap = JSON.parse(readFileSync55(fullPath, "utf8"));
47213
47661
  const ageMs = Date.now() - new Date(snap.pulled_at).getTime();
47214
47662
  if (ageMs > INSIGHTS_TTL_MS) return null;
47215
47663
  return snap;
@@ -47221,20 +47669,20 @@ function getLatestSnapshot(entityId) {
47221
47669
  const idx = readIndex();
47222
47670
  const filename = idx.latest[entityId];
47223
47671
  if (!filename) return null;
47224
- const fullPath = join69(MARKETING_PATHS.insightsDir(), filename);
47225
- if (!existsSync75(fullPath)) return null;
47672
+ const fullPath = join70(MARKETING_PATHS.insightsDir(), filename);
47673
+ if (!existsSync76(fullPath)) return null;
47226
47674
  try {
47227
- return JSON.parse(readFileSync54(fullPath, "utf8"));
47675
+ return JSON.parse(readFileSync55(fullPath, "utf8"));
47228
47676
  } catch {
47229
47677
  return null;
47230
47678
  }
47231
47679
  }
47232
47680
  function getPriorSnapshot(entityId, beforeMs) {
47233
47681
  const dir = MARKETING_PATHS.insightsDir();
47234
- if (!existsSync75(dir)) return null;
47682
+ if (!existsSync76(dir)) return null;
47235
47683
  const safe = entityId.replace(/[^A-Za-z0-9_-]/g, "_");
47236
47684
  const candidates = readdirSync17(dir).filter((f) => f.startsWith(`${safe}__`) && f.endsWith(".json")).map((f) => {
47237
- const p = join69(dir, f);
47685
+ const p = join70(dir, f);
47238
47686
  const stat = statSync13(p);
47239
47687
  return { f, p, mtimeMs: stat.mtimeMs };
47240
47688
  }).sort((a, b) => b.mtimeMs - a.mtimeMs);
@@ -47242,7 +47690,7 @@ function getPriorSnapshot(entityId, beforeMs) {
47242
47690
  for (const c of candidates) {
47243
47691
  if (c.mtimeMs <= cutoff) {
47244
47692
  try {
47245
- return JSON.parse(readFileSync54(c.p, "utf8"));
47693
+ return JSON.parse(readFileSync55(c.p, "utf8"));
47246
47694
  } catch {
47247
47695
  continue;
47248
47696
  }
@@ -47878,8 +48326,8 @@ var init_kill = __esm({
47878
48326
  });
47879
48327
 
47880
48328
  // src/cli/commands/marketing/doctor.ts
47881
- import { readFileSync as readFileSync55, readdirSync as readdirSync18, statSync as statSync14 } from "fs";
47882
- import { join as join70 } from "path";
48329
+ import { readFileSync as readFileSync56, readdirSync as readdirSync18, statSync as statSync14 } from "fs";
48330
+ import { join as join71 } from "path";
47883
48331
  function registerMarketingDoctor(parent) {
47884
48332
  parent.command("doctor").description("Run diagnostics: env, FK integrity, retroactive secret scan, Reinfluence health.").option("--scan", "Run retroactive secret scan over the entire _dream_context/ tree", false).action(async (opts) => {
47885
48333
  console.log(header("Marketing doctor"));
@@ -47960,7 +48408,7 @@ function scanForSecrets(root) {
47960
48408
  for (const file of walkText(root)) {
47961
48409
  let txt;
47962
48410
  try {
47963
- txt = readFileSync55(file, "utf8");
48411
+ txt = readFileSync56(file, "utf8");
47964
48412
  } catch {
47965
48413
  continue;
47966
48414
  }
@@ -47987,7 +48435,7 @@ function* walkText(dir) {
47987
48435
  }
47988
48436
  for (const e of entries) {
47989
48437
  if (e.startsWith(".") && (e === ".env" || e === ".env.local")) continue;
47990
- const full = join70(dir, e);
48438
+ const full = join71(dir, e);
47991
48439
  let stat;
47992
48440
  try {
47993
48441
  stat = statSync14(full);
@@ -48025,8 +48473,8 @@ var init_doctor2 = __esm({
48025
48473
  });
48026
48474
 
48027
48475
  // src/lib/marketing/entity-store.ts
48028
- import { existsSync as existsSync77, readFileSync as readFileSync56, readdirSync as readdirSync19 } from "fs";
48029
- import { join as join71 } from "path";
48476
+ import { existsSync as existsSync78, readFileSync as readFileSync57, readdirSync as readdirSync19 } from "fs";
48477
+ import { join as join72 } from "path";
48030
48478
  function dirFor(kind) {
48031
48479
  switch (kind) {
48032
48480
  case "campaign":
@@ -48045,24 +48493,24 @@ function newEntityId(kind) {
48045
48493
  }
48046
48494
  function entityPaths(kind, id) {
48047
48495
  const d = dirFor(kind);
48048
- return { json: join71(d, `${id}.json`), md: join71(d, `${id}.md`) };
48496
+ return { json: join72(d, `${id}.json`), md: join72(d, `${id}.md`) };
48049
48497
  }
48050
48498
  function loadEntity(kind, id) {
48051
48499
  const { json } = entityPaths(kind, id);
48052
- if (!existsSync77(json)) return null;
48500
+ if (!existsSync78(json)) return null;
48053
48501
  try {
48054
- return JSON.parse(readFileSync56(json, "utf8"));
48502
+ return JSON.parse(readFileSync57(json, "utf8"));
48055
48503
  } catch {
48056
48504
  return null;
48057
48505
  }
48058
48506
  }
48059
48507
  function listEntities(kind) {
48060
48508
  const d = dirFor(kind);
48061
- if (!existsSync77(d)) return [];
48509
+ if (!existsSync78(d)) return [];
48062
48510
  const out = [];
48063
48511
  for (const f of readdirSync19(d).filter((x) => x.endsWith(".json"))) {
48064
48512
  try {
48065
- out.push(JSON.parse(readFileSync56(join71(d, f), "utf8")));
48513
+ out.push(JSON.parse(readFileSync57(join72(d, f), "utf8")));
48066
48514
  } catch {
48067
48515
  }
48068
48516
  }
@@ -48256,7 +48704,7 @@ var init_campaign = __esm({
48256
48704
  });
48257
48705
 
48258
48706
  // src/cli/commands/marketing/adset.ts
48259
- import { existsSync as existsSync78, readFileSync as readFileSync57 } from "fs";
48707
+ import { existsSync as existsSync79, readFileSync as readFileSync58 } from "fs";
48260
48708
  function registerMarketingAdSet(parent) {
48261
48709
  const cmd = parent.command("adset").description("Manage adsets.");
48262
48710
  cmd.command("create").description("Create an adset (PAUSED). --daily-budget required (no fallback).").requiredOption("--campaign <id>", "parent campaign local id").requiredOption("--name <name>", "adset name").requiredOption("--daily-budget <amount>", "daily budget (major-currency units)").requiredOption("--targeting <file>", "JSON file with Meta targeting spec").option("--currency <code>", "currency code", "TRY").option("--optimization-goal <goal>", "OFFSITE_CONVERSIONS|LINK_CLICKS|...", "OFFSITE_CONVERSIONS").option("--billing-event <event>", "IMPRESSIONS|LINK_CLICKS|THRUPLAY", "IMPRESSIONS").option("--custom-event-type <evt>", "e.g. PURCHASE, COMPLETE_REGISTRATION (for OFFSITE_CONVERSIONS)").option("--no-dry-run", "Actually create on Meta").action(async (opts) => {
@@ -48276,13 +48724,13 @@ function registerMarketingAdSet(parent) {
48276
48724
  }
48277
48725
  throw e;
48278
48726
  }
48279
- if (!existsSync78(opts.targeting)) {
48727
+ if (!existsSync79(opts.targeting)) {
48280
48728
  error(`Targeting file not found: ${opts.targeting}`);
48281
48729
  process.exit(1);
48282
48730
  }
48283
48731
  let targeting;
48284
48732
  try {
48285
- targeting = JSON.parse(readFileSync57(opts.targeting, "utf8"));
48733
+ targeting = JSON.parse(readFileSync58(opts.targeting, "utf8"));
48286
48734
  } catch (e) {
48287
48735
  error(`Failed to parse targeting JSON: ${e.message}`);
48288
48736
  process.exit(1);
@@ -48539,12 +48987,12 @@ var init_creative = __esm({
48539
48987
  });
48540
48988
 
48541
48989
  // src/cli/commands/marketing/asset.ts
48542
- import { existsSync as existsSync79, statSync as statSync15 } from "fs";
48990
+ import { existsSync as existsSync80, statSync as statSync15 } from "fs";
48543
48991
  import { extname as extname5 } from "path";
48544
48992
  function registerMarketingAsset(parent) {
48545
48993
  const cmd = parent.command("asset").description("Upload creative assets to Meta.");
48546
48994
  cmd.command("upload <path>").description("Upload a video (>50MB \u2192 chunked) or image to Meta. Returns id/hash.").option("--type <type>", "override auto-detection (video|image)").option("--name <name>", "asset name (videos)").option("--no-dry-run", "Actually upload to Meta").action(async (path2, opts) => {
48547
- if (!existsSync79(path2)) {
48995
+ if (!existsSync80(path2)) {
48548
48996
  error(`File not found: ${path2}`);
48549
48997
  process.exit(1);
48550
48998
  }
@@ -48712,8 +49160,8 @@ var init_ad = __esm({
48712
49160
  });
48713
49161
 
48714
49162
  // src/lib/marketing/launch.ts
48715
- import { existsSync as existsSync80, readFileSync as readFileSync58, writeFileSync as writeFileSync39, mkdirSync as mkdirSync34, renameSync as renameSync8, readdirSync as readdirSync20 } from "fs";
48716
- import { dirname as dirname42, join as join72, basename as basename22 } from "path";
49163
+ import { existsSync as existsSync81, readFileSync as readFileSync59, writeFileSync as writeFileSync40, mkdirSync as mkdirSync35, renameSync as renameSync8, readdirSync as readdirSync20 } from "fs";
49164
+ import { dirname as dirname43, join as join73, basename as basename22 } from "path";
48717
49165
  import { randomBytes as randomBytes4 } from "crypto";
48718
49166
  function buildLaunchSummary(cohortId) {
48719
49167
  const cohort = loadCohort(cohortId);
@@ -48757,15 +49205,15 @@ function isoTs2() {
48757
49205
  return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
48758
49206
  }
48759
49207
  function atomicWriteFile3(path2, data) {
48760
- mkdirSync34(dirname42(path2), { recursive: true });
49208
+ mkdirSync35(dirname43(path2), { recursive: true });
48761
49209
  const tmp = `${path2}.tmp.${process.pid}.${randomBytes4(4).toString("hex")}`;
48762
- writeFileSync39(tmp, data, "utf8");
49210
+ writeFileSync40(tmp, data, "utf8");
48763
49211
  renameSync8(tmp, path2);
48764
49212
  }
48765
49213
  function readWal(path2) {
48766
- if (!existsSync80(path2)) return null;
49214
+ if (!existsSync81(path2)) return null;
48767
49215
  try {
48768
- return JSON.parse(readFileSync58(path2, "utf8"));
49216
+ return JSON.parse(readFileSync59(path2, "utf8"));
48769
49217
  } catch {
48770
49218
  return null;
48771
49219
  }
@@ -48775,13 +49223,13 @@ function writeWal(path2, wal) {
48775
49223
  }
48776
49224
  function findWalByRunId(runId) {
48777
49225
  const dir = MARKETING_PATHS.runsDir();
48778
- if (!existsSync80(dir)) return null;
49226
+ if (!existsSync81(dir)) return null;
48779
49227
  for (const f of readdirSync20(dir)) {
48780
49228
  if (!f.endsWith(".json")) continue;
48781
49229
  if (f.startsWith("by-idem")) continue;
48782
49230
  const stem = f.replace(/\.json$/, "");
48783
49231
  if (stem === runId || f === runId || basename22(f, ".json") === runId) {
48784
- return join72(dir, f);
49232
+ return join73(dir, f);
48785
49233
  }
48786
49234
  }
48787
49235
  return null;
@@ -48821,7 +49269,7 @@ function createLaunchWal(args) {
48821
49269
  flipped_count: 0,
48822
49270
  error: null
48823
49271
  };
48824
- const walPath = join72(MARKETING_PATHS.runsDir(), `${id}.json`);
49272
+ const walPath = join73(MARKETING_PATHS.runsDir(), `${id}.json`);
48825
49273
  writeWal(walPath, wal);
48826
49274
  return { walPath, wal };
48827
49275
  }
@@ -49052,7 +49500,7 @@ var init_launch2 = __esm({
49052
49500
  });
49053
49501
 
49054
49502
  // src/cli/commands/marketing/learnings.ts
49055
- import { existsSync as existsSync81, readFileSync as readFileSync59 } from "fs";
49503
+ import { existsSync as existsSync82, readFileSync as readFileSync60 } from "fs";
49056
49504
  function registerMarketingLearnings(parent) {
49057
49505
  const cmd = parent.command("learnings").description("Performance Monitor learnings ledger (per-day .md + index).");
49058
49506
  cmd.command("show").description("Show today's (or specified day's) learnings file.").option("--date <YYYY-MM-DD>", "Day to show (default: today UTC)").option("--id <id>", "Show a single entry by id").action((opts) => {
@@ -49195,8 +49643,8 @@ async function resolveBody(body, bodyFile) {
49195
49643
  if (body) return body;
49196
49644
  if (bodyFile === "-") return readStdin3();
49197
49645
  if (bodyFile) {
49198
- if (!existsSync81(bodyFile)) throw new Error(`Body file not found: ${bodyFile}`);
49199
- return readFileSync59(bodyFile, "utf8");
49646
+ if (!existsSync82(bodyFile)) throw new Error(`Body file not found: ${bodyFile}`);
49647
+ return readFileSync60(bodyFile, "utf8");
49200
49648
  }
49201
49649
  return null;
49202
49650
  }
@@ -49226,29 +49674,29 @@ var init_learnings2 = __esm({
49226
49674
 
49227
49675
  // src/lib/marketing/rem-sleep.ts
49228
49676
  import {
49229
- existsSync as existsSync82,
49230
- mkdirSync as mkdirSync35,
49231
- readFileSync as readFileSync60,
49232
- writeFileSync as writeFileSync40,
49677
+ existsSync as existsSync83,
49678
+ mkdirSync as mkdirSync36,
49679
+ readFileSync as readFileSync61,
49680
+ writeFileSync as writeFileSync41,
49233
49681
  readdirSync as readdirSync21,
49234
49682
  statSync as statSync16,
49235
49683
  unlinkSync as unlinkSync3,
49236
49684
  renameSync as renameSync9
49237
49685
  } from "fs";
49238
- import { dirname as dirname43, join as join73 } from "path";
49686
+ import { dirname as dirname44, join as join74 } from "path";
49239
49687
  import { randomBytes as randomBytes5 } from "crypto";
49240
49688
  function atomicWriteFile4(path2, data) {
49241
- mkdirSync35(dirname43(path2), { recursive: true });
49689
+ mkdirSync36(dirname44(path2), { recursive: true });
49242
49690
  const tmp = `${path2}.tmp.${process.pid}.${randomBytes5(4).toString("hex")}`;
49243
- writeFileSync40(tmp, data, "utf8");
49691
+ writeFileSync41(tmp, data, "utf8");
49244
49692
  renameSync9(tmp, path2);
49245
49693
  }
49246
49694
  function pruneRuns(opts = {}) {
49247
49695
  const keepLast = opts.keepLast ?? 100;
49248
49696
  const dir = MARKETING_PATHS.runsDir();
49249
- if (!existsSync82(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
49697
+ if (!existsSync83(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
49250
49698
  const files = readdirSync21(dir).filter((f) => f.endsWith(".json")).map((f) => {
49251
- const p = join73(dir, f);
49699
+ const p = join74(dir, f);
49252
49700
  try {
49253
49701
  return { f, p, mtimeMs: statSync16(p).mtimeMs };
49254
49702
  } catch {
@@ -49282,13 +49730,13 @@ function compactInsights(opts = {}) {
49282
49730
  const weeklyAfterDays = opts.weeklyAfterDays ?? 14;
49283
49731
  const now = opts.now ?? /* @__PURE__ */ new Date();
49284
49732
  const dir = MARKETING_PATHS.insightsDir();
49285
- if (!existsSync82(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
49733
+ if (!existsSync83(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
49286
49734
  const files = [];
49287
49735
  for (const f of readdirSync21(dir)) {
49288
49736
  if (!f.endsWith(".json") || f.startsWith("_")) continue;
49289
49737
  const m = f.match(SNAP_RE);
49290
49738
  if (!m) continue;
49291
- const p = join73(dir, f);
49739
+ const p = join74(dir, f);
49292
49740
  try {
49293
49741
  const stat = statSync16(p);
49294
49742
  files.push({ f, p, mtimeMs: stat.mtimeMs, entityId: m[1], bucket: m[2] });
@@ -49354,7 +49802,7 @@ function mergeDailyLearnings(opts = {}) {
49354
49802
  const retainDays = opts.retainDays ?? 7;
49355
49803
  const now = opts.now ?? /* @__PURE__ */ new Date();
49356
49804
  const dir = MARKETING_PATHS.learningsDir();
49357
- if (!existsSync82(dir)) {
49805
+ if (!existsSync83(dir)) {
49358
49806
  return { scanned: 0, merged: 0, archivePath: null, droppedRejected: 0, mergedFiles: [] };
49359
49807
  }
49360
49808
  const dayMs = 24 * 60 * 60 * 1e3;
@@ -49365,7 +49813,7 @@ function mergeDailyLearnings(opts = {}) {
49365
49813
  if (!m) continue;
49366
49814
  const date = m[1];
49367
49815
  const dateMs = (/* @__PURE__ */ new Date(`${date}T00:00:00Z`)).getTime();
49368
- if (dateMs < cutoff) candidates.push({ f, p: join73(dir, f), date });
49816
+ if (dateMs < cutoff) candidates.push({ f, p: join74(dir, f), date });
49369
49817
  }
49370
49818
  if (candidates.length === 0) {
49371
49819
  return { scanned: 0, merged: 0, archivePath: null, droppedRejected: 0, mergedFiles: [] };
@@ -49379,10 +49827,10 @@ function mergeDailyLearnings(opts = {}) {
49379
49827
  const mergedFiles = [];
49380
49828
  let lastArchivePath = null;
49381
49829
  for (const [q, list] of byQuarter) {
49382
- const archivePath = join73(dir, `_archive-${q}.md`);
49830
+ const archivePath = join74(dir, `_archive-${q}.md`);
49383
49831
  list.sort((a, b) => a.date.localeCompare(b.date));
49384
49832
  for (const c of list) {
49385
- const existingArchive = existsSync82(archivePath) ? readFileSync60(archivePath, "utf8") : `# Marketing learnings archive \u2014 ${q}
49833
+ const existingArchive = existsSync83(archivePath) ? readFileSync61(archivePath, "utf8") : `# Marketing learnings archive \u2014 ${q}
49386
49834
  `;
49387
49835
  const dateMarker = `# Marketing learnings \u2014 ${c.date}`;
49388
49836
  const alreadyMerged = existingArchive.includes(dateMarker);
@@ -49391,7 +49839,7 @@ function mergeDailyLearnings(opts = {}) {
49391
49839
  continue;
49392
49840
  }
49393
49841
  if (!alreadyMerged) {
49394
- const body = readFileSync60(c.p, "utf8").trimEnd();
49842
+ const body = readFileSync61(c.p, "utf8").trimEnd();
49395
49843
  const next2 = existingArchive.trimEnd() + "\n\n" + body + "\n";
49396
49844
  atomicWriteFile4(archivePath, next2);
49397
49845
  }
@@ -49434,14 +49882,14 @@ function quarterKey(yyyymmdd) {
49434
49882
  }
49435
49883
  function redactRunsSweep(opts = {}) {
49436
49884
  const dir = MARKETING_PATHS.runsDir();
49437
- if (!existsSync82(dir)) return { scanned: 0, rewritten: 0, rewrittenFiles: [] };
49885
+ if (!existsSync83(dir)) return { scanned: 0, rewritten: 0, rewrittenFiles: [] };
49438
49886
  const files = readdirSync21(dir).filter((f) => f.endsWith(".json"));
49439
49887
  const rewrittenFiles = [];
49440
49888
  for (const f of files) {
49441
- const p = join73(dir, f);
49889
+ const p = join74(dir, f);
49442
49890
  let raw;
49443
49891
  try {
49444
- raw = readFileSync60(p, "utf8");
49892
+ raw = readFileSync61(p, "utf8");
49445
49893
  } catch {
49446
49894
  continue;
49447
49895
  }
@@ -49463,7 +49911,7 @@ function redactRunsSweep(opts = {}) {
49463
49911
  function runRemSleep(opts = {}) {
49464
49912
  const ranAt = (opts.now ?? /* @__PURE__ */ new Date()).toISOString();
49465
49913
  const root = marketingRootIfExists();
49466
- if (!root || !existsSync82(root)) {
49914
+ if (!root || !existsSync83(root)) {
49467
49915
  return {
49468
49916
  ranAt,
49469
49917
  marketingPresent: false,
@@ -49485,7 +49933,7 @@ function runRemSleep(opts = {}) {
49485
49933
  now: opts.now
49486
49934
  });
49487
49935
  const redaction = redactRunsSweep({ dryRun: opts.dryRun });
49488
- void mkdirSync35;
49936
+ void mkdirSync36;
49489
49937
  return { ranAt, marketingPresent: true, runs, insights, learnings, redaction };
49490
49938
  }
49491
49939
  var SNAP_RE;
@@ -49582,9 +50030,9 @@ var init_git_guard = __esm({
49582
50030
  });
49583
50031
 
49584
50032
  // src/cli/commands/marketing/hooks.ts
49585
- import { existsSync as existsSync83, readFileSync as readFileSync61, writeFileSync as writeFileSync41, chmodSync as chmodSync3, mkdirSync as mkdirSync36, statSync as statSync17 } from "fs";
50033
+ import { existsSync as existsSync84, readFileSync as readFileSync62, writeFileSync as writeFileSync42, chmodSync as chmodSync3, mkdirSync as mkdirSync37, statSync as statSync17 } from "fs";
49586
50034
  import { execFileSync as execFileSync6 } from "child_process";
49587
- import { join as join74 } from "path";
50035
+ import { join as join75 } from "path";
49588
50036
  function findGitDir(cwd = process.cwd()) {
49589
50037
  try {
49590
50038
  const out = execFileSync6("git", ["rev-parse", "--git-dir"], {
@@ -49593,7 +50041,7 @@ function findGitDir(cwd = process.cwd()) {
49593
50041
  stdio: ["ignore", "pipe", "ignore"]
49594
50042
  }).trim();
49595
50043
  if (!out) return null;
49596
- return out.startsWith("/") ? out : join74(cwd, out);
50044
+ return out.startsWith("/") ? out : join75(cwd, out);
49597
50045
  } catch {
49598
50046
  return null;
49599
50047
  }
@@ -49624,11 +50072,11 @@ function registerMarketingHooks(parent) {
49624
50072
  error("Not inside a git repository (or `git` is not on PATH).");
49625
50073
  process.exit(1);
49626
50074
  }
49627
- const hooksDir = join74(gitDir, "hooks");
49628
- mkdirSync36(hooksDir, { recursive: true });
49629
- const target = join74(hooksDir, "pre-commit");
49630
- if (existsSync83(target)) {
49631
- const existing = readFileSync61(target, "utf-8");
50075
+ const hooksDir = join75(gitDir, "hooks");
50076
+ mkdirSync37(hooksDir, { recursive: true });
50077
+ const target = join75(hooksDir, "pre-commit");
50078
+ if (existsSync84(target)) {
50079
+ const existing = readFileSync62(target, "utf-8");
49632
50080
  if (existing.includes(MANAGED_MARKER)) {
49633
50081
  info("pre-commit hook already managed by dreamcontext \u2014 refreshing.");
49634
50082
  } else if (!opts.force) {
@@ -49640,7 +50088,7 @@ function registerMarketingHooks(parent) {
49640
50088
  warn("Overwriting existing pre-commit hook (--force).");
49641
50089
  }
49642
50090
  }
49643
- writeFileSync41(target, HOOK_LAUNCHER, "utf-8");
50091
+ writeFileSync42(target, HOOK_LAUNCHER, "utf-8");
49644
50092
  try {
49645
50093
  chmodSync3(target, 493);
49646
50094
  } catch {
@@ -49679,26 +50127,26 @@ exec dreamcontext mk hooks check-staged
49679
50127
  });
49680
50128
 
49681
50129
  // src/lib/marketing/council-personas.ts
49682
- import { existsSync as existsSync84, readFileSync as readFileSync62, readdirSync as readdirSync22 } from "fs";
50130
+ import { existsSync as existsSync85, readFileSync as readFileSync63, readdirSync as readdirSync22 } from "fs";
49683
50131
  import { fileURLToPath as fileURLToPath9 } from "url";
49684
- import { join as join75, dirname as dirname44 } from "path";
50132
+ import { join as join76, dirname as dirname45 } from "path";
49685
50133
  function findPersonasDir() {
49686
50134
  const candidates = [
49687
50135
  // dev: src/lib/marketing/council-personas.ts → ../../../skill-packs/...
49688
- join75(__dirname_local, "..", "..", "..", PERSONA_SUBPATH),
50136
+ join76(__dirname_local, "..", "..", "..", PERSONA_SUBPATH),
49689
50137
  // built: dist/index.js → ./skill-packs/...
49690
- join75(__dirname_local, PERSONA_SUBPATH),
50138
+ join76(__dirname_local, PERSONA_SUBPATH),
49691
50139
  // tsup-bundled (deeper nesting if ever): ../skill-packs/...
49692
- join75(__dirname_local, "..", PERSONA_SUBPATH),
49693
- join75(__dirname_local, "..", "..", PERSONA_SUBPATH)
50140
+ join76(__dirname_local, "..", PERSONA_SUBPATH),
50141
+ join76(__dirname_local, "..", "..", PERSONA_SUBPATH)
49694
50142
  ];
49695
50143
  for (const candidate of candidates) {
49696
- if (existsSync84(candidate)) return candidate;
50144
+ if (existsSync85(candidate)) return candidate;
49697
50145
  }
49698
50146
  return null;
49699
50147
  }
49700
50148
  function parsePersonaFile(filePath) {
49701
- const raw = readFileSync62(filePath, "utf-8");
50149
+ const raw = readFileSync63(filePath, "utf-8");
49702
50150
  const parsed = (0, import_gray_matter5.default)(raw);
49703
50151
  const data = parsed.data;
49704
50152
  const slug = typeof data.slug === "string" ? data.slug.trim() : "";
@@ -49718,9 +50166,9 @@ function parsePersonaFile(filePath) {
49718
50166
  }
49719
50167
  function loadAllPersonas(personasDir) {
49720
50168
  const dir = personasDir ?? findPersonasDir();
49721
- if (!dir || !existsSync84(dir)) return [];
50169
+ if (!dir || !existsSync85(dir)) return [];
49722
50170
  const files = readdirSync22(dir).filter((n) => n.endsWith(".md")).sort();
49723
- return files.map((name) => parsePersonaFile(join75(dir, name)));
50171
+ return files.map((name) => parsePersonaFile(join76(dir, name)));
49724
50172
  }
49725
50173
  function selectPersonas(all, requested) {
49726
50174
  if (requested.length === 0) return [...all];
@@ -49739,23 +50187,23 @@ var init_council_personas = __esm({
49739
50187
  import_gray_matter5 = __toESM(require_gray_matter(), 1);
49740
50188
  __dirname_local = (() => {
49741
50189
  try {
49742
- return dirname44(fileURLToPath9(import.meta.url));
50190
+ return dirname45(fileURLToPath9(import.meta.url));
49743
50191
  } catch {
49744
50192
  return process.cwd();
49745
50193
  }
49746
50194
  })();
49747
50195
  VALID_MODELS2 = /* @__PURE__ */ new Set(["opus", "sonnet", "haiku"]);
49748
- PERSONA_SUBPATH = join75("skill-packs", "meta-marketing", "council-personas");
50196
+ PERSONA_SUBPATH = join76("skill-packs", "meta-marketing", "council-personas");
49749
50197
  }
49750
50198
  });
49751
50199
 
49752
50200
  // src/cli/commands/marketing/council.ts
49753
50201
  import { spawnSync as spawnSync4 } from "child_process";
49754
- import { existsSync as existsSync85 } from "fs";
50202
+ import { existsSync as existsSync86 } from "fs";
49755
50203
  function resolveDreamcontextEntry() {
49756
50204
  const node = process.argv[0];
49757
50205
  const script = process.argv[1];
49758
- if (script && existsSync85(script)) {
50206
+ if (script && existsSync86(script)) {
49759
50207
  return { node, script };
49760
50208
  }
49761
50209
  return { node, script: null };
@@ -49927,8 +50375,8 @@ var init_marketing = __esm({
49927
50375
  });
49928
50376
 
49929
50377
  // src/cli/commands/memory.ts
49930
- import { existsSync as existsSync86, unlinkSync as unlinkSync4 } from "fs";
49931
- import { join as join76, dirname as dirname45 } from "path";
50378
+ import { existsSync as existsSync87, unlinkSync as unlinkSync4 } from "fs";
50379
+ import { join as join77, dirname as dirname46 } from "path";
49932
50380
  function collectVault(value, previous) {
49933
50381
  return [...previous, value];
49934
50382
  }
@@ -49940,7 +50388,7 @@ function parseTypes(value) {
49940
50388
  return filtered.length > 0 ? filtered : void 0;
49941
50389
  }
49942
50390
  function recallFederated(contextRoot, query, topK, types, opts) {
49943
- const projectRoot = dirname45(contextRoot);
50391
+ const projectRoot = dirname46(contextRoot);
49944
50392
  const { target: currentTarget } = currentVaultTarget(projectRoot);
49945
50393
  const byName = /* @__PURE__ */ new Map();
49946
50394
  const add = (t) => {
@@ -50093,7 +50541,7 @@ function registerMemoryCommand(program2) {
50093
50541
  const summary = opts.summary ?? (text.length > 200 ? text.slice(0, 197) + "..." : text);
50094
50542
  const references = opts.references ? opts.references.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
50095
50543
  const authors = opts.person ? opts.person.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
50096
- const changelogPath = join76(root, "core", "CHANGELOG.json");
50544
+ const changelogPath = join77(root, "core", "CHANGELOG.json");
50097
50545
  const entry = {
50098
50546
  date: today(),
50099
50547
  type: opts.type ?? "note",
@@ -50111,8 +50559,8 @@ function registerMemoryCommand(program2) {
50111
50559
  memory.command("update").argument("<slug>", "Knowledge file slug (without .md)").option("-d, --description <desc>", "New description (replaces existing)").option("-t, --tags <tags>", "New tags (comma-separated, replaces existing)").option("-c, --content <content>", "New body content (replaces existing)").option("--append <text>", "Append text to body (preserves existing content)").option("--pin", "Set pinned: true").option("--unpin", "Set pinned: false").description("Update a knowledge file (frontmatter and/or body)").action(
50112
50560
  async (slug, opts) => {
50113
50561
  const root = ensureContextRoot();
50114
- const filePath = join76(root, "knowledge", `${slug}.md`);
50115
- if (!existsSync86(filePath)) {
50562
+ const filePath = join77(root, "knowledge", `${slug}.md`);
50563
+ if (!existsSync87(filePath)) {
50116
50564
  error(`Knowledge file not found: ${slug}.md`);
50117
50565
  return;
50118
50566
  }
@@ -50159,8 +50607,8 @@ ${opts.append}
50159
50607
  );
50160
50608
  memory.command("delete").argument("<slug>", "Knowledge file slug to delete (without .md)").option("-f, --force", "Skip confirmation prompt").description("Delete a knowledge file (irreversible; use git to recover)").action(async (slug, opts) => {
50161
50609
  const root = ensureContextRoot();
50162
- const filePath = join76(root, "knowledge", `${slug}.md`);
50163
- if (!existsSync86(filePath)) {
50610
+ const filePath = join77(root, "knowledge", `${slug}.md`);
50611
+ if (!existsSync87(filePath)) {
50164
50612
  error(`Knowledge file not found: ${slug}.md`);
50165
50613
  return;
50166
50614
  }
@@ -50268,13 +50716,13 @@ var init_memory = __esm({
50268
50716
 
50269
50717
  // src/cli/commands/upgrade.ts
50270
50718
  import { execFileSync as execFileSync8 } from "child_process";
50271
- import { dirname as dirname46 } from "path";
50719
+ import { dirname as dirname47 } from "path";
50272
50720
  function defaultInstaller(args) {
50273
50721
  execFileSync8("npm", args, { stdio: "inherit" });
50274
50722
  }
50275
50723
  function projectRootForCache() {
50276
50724
  const contextDir = resolveContextRoot();
50277
- return contextDir ? dirname46(contextDir) : process.cwd();
50725
+ return contextDir ? dirname47(contextDir) : process.cwd();
50278
50726
  }
50279
50727
  function defaultLiveLatest() {
50280
50728
  let latest = null;
@@ -50597,9 +51045,9 @@ var init_vaults3 = __esm({
50597
51045
  });
50598
51046
 
50599
51047
  // src/cli/commands/connections.ts
50600
- import { dirname as dirname47 } from "path";
51048
+ import { dirname as dirname48 } from "path";
50601
51049
  function currentVaultName2(contextRoot) {
50602
- return currentVaultTarget(dirname47(contextRoot)).name;
51050
+ return currentVaultTarget(dirname48(contextRoot)).name;
50603
51051
  }
50604
51052
  function registerConnectionsCommand(program2) {
50605
51053
  program2.command("connect <vault>").description("Connect this vault to a peer for federation (out|in|both)").option("-d, --direction <direction>", "Connection direction: out | in | both", "both").option("--topics <list>", "Comma-separated topic filter (default: all topics)").action((vault, opts) => {
@@ -50681,17 +51129,17 @@ var init_connections3 = __esm({
50681
51129
  });
50682
51130
 
50683
51131
  // src/lib/federation-ingest.ts
50684
- import { existsSync as existsSync87, mkdirSync as mkdirSync37 } from "fs";
50685
- import { join as join77 } from "path";
51132
+ import { existsSync as existsSync88, mkdirSync as mkdirSync38 } from "fs";
51133
+ import { join as join78 } from "path";
50686
51134
  function ingestEntry(contextRoot, entry) {
50687
- const knowledgeDir = join77(contextRoot, "knowledge");
50688
- mkdirSync37(knowledgeDir, { recursive: true });
51135
+ const knowledgeDir = join78(contextRoot, "knowledge");
51136
+ mkdirSync38(knowledgeDir, { recursive: true });
50689
51137
  const baseSlug = slugFromTitle(entry.title);
50690
- const canonicalPath = join77(knowledgeDir, `${baseSlug}.md`);
50691
- const collided = existsSync87(canonicalPath);
51138
+ const canonicalPath = join78(knowledgeDir, `${baseSlug}.md`);
51139
+ const collided = existsSync88(canonicalPath);
50692
51140
  const slug = collided ? `${baseSlug}--from-${sanitizeVault(entry.origin.vault)}` : baseSlug;
50693
- const targetPath = join77(knowledgeDir, `${slug}.md`);
50694
- if (!existsSync87(targetPath)) {
51141
+ const targetPath = join78(knowledgeDir, `${slug}.md`);
51142
+ if (!existsSync88(targetPath)) {
50695
51143
  writeFrontmatter(
50696
51144
  targetPath,
50697
51145
  {
@@ -50767,9 +51215,9 @@ var init_federation_ingest = __esm({
50767
51215
  });
50768
51216
 
50769
51217
  // src/cli/commands/federation.ts
50770
- import { dirname as dirname48 } from "path";
51218
+ import { dirname as dirname49 } from "path";
50771
51219
  function currentVaultName3(contextRoot) {
50772
- return currentVaultTarget(dirname48(contextRoot)).name;
51220
+ return currentVaultTarget(dirname49(contextRoot)).name;
50773
51221
  }
50774
51222
  function outboundConnections(contextRoot) {
50775
51223
  return listConnections(contextRoot).filter(
@@ -50982,12 +51430,12 @@ var init_people = __esm({
50982
51430
  });
50983
51431
 
50984
51432
  // src/cli/commands/config.ts
50985
- import { dirname as dirname49 } from "path";
50986
- import { existsSync as existsSync88, readFileSync as readFileSync64, writeFileSync as writeFileSync43 } from "fs";
50987
- import { join as join78 } from "path";
51433
+ import { dirname as dirname50 } from "path";
51434
+ import { existsSync as existsSync89, readFileSync as readFileSync65, writeFileSync as writeFileSync44 } from "fs";
51435
+ import { join as join79 } from "path";
50988
51436
  function resolveProjectRoot() {
50989
51437
  const contextRoot = resolveContextRoot();
50990
- return contextRoot ? dirname49(contextRoot) : null;
51438
+ return contextRoot ? dirname50(contextRoot) : null;
50991
51439
  }
50992
51440
  function requireProjectRoot() {
50993
51441
  const projectRoot = resolveProjectRoot();
@@ -51146,7 +51594,7 @@ function registerConfigCommand(program2) {
51146
51594
  const liveToken = resolveClickUpToken(projectRoot);
51147
51595
  let connected = false;
51148
51596
  if (liveToken) {
51149
- const contextRoot = join78(projectRoot, "_dream_context");
51597
+ const contextRoot = join79(projectRoot, "_dream_context");
51150
51598
  const probe = createClickUpBackend(contextRoot, readSetupConfig(projectRoot));
51151
51599
  const test = await probe.testConnection();
51152
51600
  if (test.ok) {
@@ -51189,7 +51637,7 @@ function registerConfigCommand(program2) {
51189
51637
  cfgNow = readSetupConfig(projectRoot);
51190
51638
  }
51191
51639
  if (connected && cfgNow?.clickup?.listId) {
51192
- const contextRoot = join78(projectRoot, "_dream_context");
51640
+ const contextRoot = join79(projectRoot, "_dream_context");
51193
51641
  const backend2 = createClickUpBackend(contextRoot, cfgNow);
51194
51642
  if (await esm_default4({ message: "Create the recommended custom fields on the list (urgency, summary, RICE, \u2026)?", default: true })) {
51195
51643
  const result = await backend2.provisionRemote();
@@ -51244,13 +51692,13 @@ function registerConfigCommand(program2) {
51244
51692
  const contextRoot = resolveContextRoot();
51245
51693
  let userMdSynced = false;
51246
51694
  if (contextRoot) {
51247
- const userMdPath = join78(contextRoot, "core", "1.user.md");
51248
- if (existsSync88(userMdPath)) {
51695
+ const userMdPath = join79(contextRoot, "core", "1.user.md");
51696
+ if (existsSync89(userMdPath)) {
51249
51697
  try {
51250
- const before = readFileSync64(userMdPath, "utf-8");
51698
+ const before = readFileSync65(userMdPath, "utf-8");
51251
51699
  const after = ensurePeopleSection(before, roster);
51252
51700
  if (after !== before) {
51253
- writeFileSync43(userMdPath, after, "utf-8");
51701
+ writeFileSync44(userMdPath, after, "utf-8");
51254
51702
  userMdSynced = true;
51255
51703
  }
51256
51704
  } catch (err) {
@@ -51294,7 +51742,7 @@ function registerConfigCommand(program2) {
51294
51742
  config.command("clickup-list <teamId> <spaceId> <listId>").description("Set the ClickUp team/space/list the tasks sync against").option("--migrate", "When changing lists: reset the sync ledger so the next sync recreates every local task in the NEW list").option("--keep", "When changing lists: keep existing task mappings (tasks were moved in ClickUp itself)").action(async (teamId, spaceId, listId, opts) => {
51295
51743
  const projectRoot = requireProjectRoot();
51296
51744
  if (!projectRoot) return;
51297
- const contextRoot = join78(projectRoot, "_dream_context");
51745
+ const contextRoot = join79(projectRoot, "_dream_context");
51298
51746
  const existing = readSetupConfig(projectRoot)?.clickup ?? {};
51299
51747
  const ledger = new SyncLedger(contextRoot);
51300
51748
  const changingList = !!existing.listId && existing.listId !== listId && ledger.readMap().length > 0;
@@ -51335,8 +51783,8 @@ function registerConfigCommand(program2) {
51335
51783
  if (!value) {
51336
51784
  if (!process.stdin.isTTY) {
51337
51785
  try {
51338
- const { readFileSync: readFileSync65 } = await import("fs");
51339
- value = readFileSync65(0, "utf-8").trim();
51786
+ const { readFileSync: readFileSync66 } = await import("fs");
51787
+ value = readFileSync66(0, "utf-8").trim();
51340
51788
  } catch {
51341
51789
  value = "";
51342
51790
  }
@@ -51695,12 +52143,12 @@ var init_feedback2 = __esm({
51695
52143
  });
51696
52144
 
51697
52145
  // src/cli/commands/migrations.ts
51698
- import { dirname as dirname50 } from "path";
52146
+ import { dirname as dirname51 } from "path";
51699
52147
  function registerMigrationsCommand(program2) {
51700
52148
  const migrations = program2.command("migrations").description("Inspect and record brain structure migrations");
51701
52149
  migrations.command("pending").description("Print pending agent task instructions for any unfinished migrations").action(() => {
51702
52150
  const root = ensureContextRoot();
51703
- const projectRoot = dirname50(root);
52151
+ const projectRoot = dirname51(root);
51704
52152
  const config = readSetupConfig(projectRoot);
51705
52153
  const fromVersion = config?.setupVersion ?? "0.0.0";
51706
52154
  const toVersion = dreamcontextVersion();