dreamcontext 0.14.1 → 0.14.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/dist/dashboard/assets/{BrainCanvas3D-iDGz4HV0.js → BrainCanvas3D-B1Ia2HWN.js} +1 -1
  2. package/dist/dashboard/assets/{_baseUniq-BKTLnguK.js → _baseUniq-B74oJzMc.js} +1 -1
  3. package/dist/dashboard/assets/{ar-SA-G6X2FPQ2-WxRw8CvG.js → ar-SA-G6X2FPQ2-DOKHn365.js} +1 -1
  4. package/dist/dashboard/assets/{arc-CXFvfgn5.js → arc-B-uBpPoM.js} +1 -1
  5. package/dist/dashboard/assets/{architectureDiagram-Q4EWVU46-CgpaMT3q.js → architectureDiagram-Q4EWVU46-D2lyk9NB.js} +1 -1
  6. package/dist/dashboard/assets/{az-AZ-76LH7QW2-Tml7S2e-.js → az-AZ-76LH7QW2-CgyZJLLo.js} +1 -1
  7. package/dist/dashboard/assets/{bg-BG-XCXSNQG7-C3fv9p_Z.js → bg-BG-XCXSNQG7-BPLlwY2s.js} +1 -1
  8. package/dist/dashboard/assets/{blockDiagram-DXYQGD6D-CeVR1IHD.js → blockDiagram-DXYQGD6D-Df8Y7Srr.js} +1 -1
  9. package/dist/dashboard/assets/{bn-BD-2XOGV67Q-qnJuYH4H.js → bn-BD-2XOGV67Q-CY-dhlzi.js} +1 -1
  10. package/dist/dashboard/assets/{c4Diagram-AHTNJAMY-xcFu2zZM.js → c4Diagram-AHTNJAMY-D7TG6J6Q.js} +1 -1
  11. package/dist/dashboard/assets/{ca-ES-6MX7JW3Y-4tyHbEgd.js → ca-ES-6MX7JW3Y-DFf13e9p.js} +1 -1
  12. package/dist/dashboard/assets/channel-CqCT8-qB.js +1 -0
  13. package/dist/dashboard/assets/{chunk-4BX2VUAB-J7mFJb__.js → chunk-4BX2VUAB-DCA-ERlu.js} +1 -1
  14. package/dist/dashboard/assets/{chunk-4TB4RGXK-DqrxE_QA.js → chunk-4TB4RGXK-Bczdxdod.js} +1 -1
  15. package/dist/dashboard/assets/{chunk-55IACEB6-D8eCITwq.js → chunk-55IACEB6-B3649L4a.js} +1 -1
  16. package/dist/dashboard/assets/{chunk-EDXVE4YY-DBzJ4Kk6.js → chunk-EDXVE4YY-Bwj1fYhG.js} +1 -1
  17. package/dist/dashboard/assets/{chunk-FMBD7UC4-5rx_crEA.js → chunk-FMBD7UC4-oY1KO--2.js} +1 -1
  18. package/dist/dashboard/assets/{chunk-OYMX7WX6-CLE6jH1t.js → chunk-OYMX7WX6-B4MPzc-c.js} +1 -1
  19. package/dist/dashboard/assets/{chunk-QZHKN3VN-OS-irsoP.js → chunk-QZHKN3VN-mVSSFcuA.js} +1 -1
  20. package/dist/dashboard/assets/{chunk-YZCP3GAM-Bucdr9No.js → chunk-YZCP3GAM-DeRyq2BY.js} +1 -1
  21. package/dist/dashboard/assets/classDiagram-6PBFFD2Q-C9WQPvu9.js +1 -0
  22. package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-C9WQPvu9.js +1 -0
  23. package/dist/dashboard/assets/clone-B0kf3g9o.js +1 -0
  24. package/dist/dashboard/assets/{cose-bilkent-S5V4N54A-0zXaPrUS.js → cose-bilkent-S5V4N54A-BTtdOgy5.js} +1 -1
  25. package/dist/dashboard/assets/{cs-CZ-2BRQDIVT-BTejWsyZ.js → cs-CZ-2BRQDIVT-BzC5Rf0R.js} +1 -1
  26. package/dist/dashboard/assets/{da-DK-5WZEPLOC-DWf9m3vM.js → da-DK-5WZEPLOC-gF4jrIY7.js} +1 -1
  27. package/dist/dashboard/assets/{dagre-KV5264BT-B_fWcb4P.js → dagre-KV5264BT-8Cpaf4My.js} +1 -1
  28. package/dist/dashboard/assets/{de-DE-XR44H4JA-6DFCnmxt.js → de-DE-XR44H4JA-BzHDEugW.js} +1 -1
  29. package/dist/dashboard/assets/{diagram-5BDNPKRD-BDjjAQT6.js → diagram-5BDNPKRD-BUa2eqbA.js} +1 -1
  30. package/dist/dashboard/assets/{diagram-G4DWMVQ6-CgDZIIvU.js → diagram-G4DWMVQ6-CsHVo990.js} +1 -1
  31. package/dist/dashboard/assets/{diagram-MMDJMWI5-OsjvtQBN.js → diagram-MMDJMWI5-CFdSOuIW.js} +1 -1
  32. package/dist/dashboard/assets/{diagram-TYMM5635-DOB390r8.js → diagram-TYMM5635-Cv2e3TBK.js} +1 -1
  33. package/dist/dashboard/assets/{el-GR-BZB4AONW-BCXqQAzU.js → el-GR-BZB4AONW-Bw-xG8H1.js} +1 -1
  34. package/dist/dashboard/assets/{erDiagram-SMLLAGMA-uT8z1D4S.js → erDiagram-SMLLAGMA-Di1x3Ld5.js} +1 -1
  35. package/dist/dashboard/assets/{es-ES-U4NZUMDT-daNwi4rl.js → es-ES-U4NZUMDT-BgdmgnEL.js} +1 -1
  36. package/dist/dashboard/assets/{eu-ES-A7QVB2H4-CP2B7v-S.js → eu-ES-A7QVB2H4-C_-W1jiT.js} +1 -1
  37. package/dist/dashboard/assets/{fa-IR-HGAKTJCU-B7fyLZjD.js → fa-IR-HGAKTJCU-D-Z42ygz.js} +1 -1
  38. package/dist/dashboard/assets/{fi-FI-Z5N7JZ37--r4W4BJL.js → fi-FI-Z5N7JZ37-CKqV9a_l.js} +1 -1
  39. package/dist/dashboard/assets/{flowDiagram-DWJPFMVM-BAfgGiph.js → flowDiagram-DWJPFMVM-C0HsaC5L.js} +1 -1
  40. package/dist/dashboard/assets/{fr-FR-RHASNOE6-D_z2sz4o.js → fr-FR-RHASNOE6-DPDm5F3m.js} +1 -1
  41. package/dist/dashboard/assets/{ganttDiagram-T4ZO3ILL-C493I8Kn.js → ganttDiagram-T4ZO3ILL-T-R79Oea.js} +1 -1
  42. package/dist/dashboard/assets/{gitGraphDiagram-UUTBAWPF-DD3Jw4hy.js → gitGraphDiagram-UUTBAWPF-DmdlPMiD.js} +1 -1
  43. package/dist/dashboard/assets/{gl-ES-HMX3MZ6V-3iPIpzVQ.js → gl-ES-HMX3MZ6V-c2pDP6q3.js} +1 -1
  44. package/dist/dashboard/assets/{graph-CJvnKdzN.js → graph-55sHob5M.js} +1 -1
  45. package/dist/dashboard/assets/{he-IL-6SHJWFNN-BnseHvRA.js → he-IL-6SHJWFNN-QzeRcOiz.js} +1 -1
  46. package/dist/dashboard/assets/{hi-IN-IWLTKZ5I-Cdvylq2s.js → hi-IN-IWLTKZ5I-CmRjYfDv.js} +1 -1
  47. package/dist/dashboard/assets/{hu-HU-A5ZG7DT2-cYA2nqI5.js → hu-HU-A5ZG7DT2-DQS4XtgQ.js} +1 -1
  48. package/dist/dashboard/assets/{id-ID-SAP4L64H-ByI8qeN-.js → id-ID-SAP4L64H-D-BFw5MU.js} +1 -1
  49. package/dist/dashboard/assets/{index-DRgJ1sc2.js → index-C2j0AERU.js} +1 -1
  50. package/dist/dashboard/assets/{index-CdlG9S--.css → index-MPnw9upZ.css} +2 -2
  51. package/dist/dashboard/assets/{index-D85kugqO.js → index-pZP-3m96.js} +205 -205
  52. package/dist/dashboard/assets/{infoDiagram-42DDH7IO-BJyNzQje.js → infoDiagram-42DDH7IO-BaT4J3uc.js} +1 -1
  53. package/dist/dashboard/assets/{ishikawaDiagram-UXIWVN3A-DWwmai-U.js → ishikawaDiagram-UXIWVN3A-DsizYWBB.js} +1 -1
  54. package/dist/dashboard/assets/{it-IT-JPQ66NNP-Cm3-aA2z.js → it-IT-JPQ66NNP-CFAPcTjk.js} +1 -1
  55. package/dist/dashboard/assets/{ja-JP-DBVTYXUO-BtKUGXop.js → ja-JP-DBVTYXUO-Bzs_hBtx.js} +1 -1
  56. package/dist/dashboard/assets/{journeyDiagram-VCZTEJTY-CWpo_QlB.js → journeyDiagram-VCZTEJTY-B9kB5yN9.js} +1 -1
  57. package/dist/dashboard/assets/{kaa-6HZHGXH3-Cz-3C5qm.js → kaa-6HZHGXH3-CqRi76QS.js} +1 -1
  58. package/dist/dashboard/assets/{kab-KAB-ZGHBKWFO-CquppFs3.js → kab-KAB-ZGHBKWFO-wSqF6nkL.js} +1 -1
  59. package/dist/dashboard/assets/{kanban-definition-6JOO6SKY-CZisoM6K.js → kanban-definition-6JOO6SKY-DasidrnL.js} +1 -1
  60. package/dist/dashboard/assets/{kk-KZ-P5N5QNE5-B2l0aVOL.js → kk-KZ-P5N5QNE5-ins4bRlm.js} +1 -1
  61. package/dist/dashboard/assets/{km-KH-HSX4SM5Z-gnd97XjM.js → km-KH-HSX4SM5Z-BjJepDRC.js} +1 -1
  62. package/dist/dashboard/assets/{ko-KR-MTYHY66A-CZ7y0WRr.js → ko-KR-MTYHY66A-Cmak8rUq.js} +1 -1
  63. package/dist/dashboard/assets/{ku-TR-6OUDTVRD-cJLiwVTI.js → ku-TR-6OUDTVRD-Dbz6ljVD.js} +1 -1
  64. package/dist/dashboard/assets/{layout-ZskR1t-z.js → layout-DMQli9Le.js} +1 -1
  65. package/dist/dashboard/assets/{linear-nhlpqszd.js → linear-B6VVSyMW.js} +1 -1
  66. package/dist/dashboard/assets/{lt-LT-XHIRWOB4-Ij6EZ9jl.js → lt-LT-XHIRWOB4-CEmAxA9u.js} +1 -1
  67. package/dist/dashboard/assets/{lv-LV-5QDEKY6T-o1fSS6fk.js → lv-LV-5QDEKY6T-CJR-At7g.js} +1 -1
  68. package/dist/dashboard/assets/{min-DWO9jrZ-.js → min-CqkwiHUc.js} +1 -1
  69. package/dist/dashboard/assets/{mindmap-definition-QFDTVHPH-hvcnCi0m.js → mindmap-definition-QFDTVHPH-bsYCrNtj.js} +1 -1
  70. package/dist/dashboard/assets/{mr-IN-CRQNXWMA-CbMNXet8.js → mr-IN-CRQNXWMA-P4spwjT8.js} +1 -1
  71. package/dist/dashboard/assets/{my-MM-5M5IBNSE-BLZNRrAe.js → my-MM-5M5IBNSE-a1rvArEV.js} +1 -1
  72. package/dist/dashboard/assets/{nb-NO-T6EIAALU-B3vJdKTo.js → nb-NO-T6EIAALU-Dw_J2QCA.js} +1 -1
  73. package/dist/dashboard/assets/{nl-NL-IS3SIHDZ-B6D5z-iI.js → nl-NL-IS3SIHDZ-DyJZtP9s.js} +1 -1
  74. package/dist/dashboard/assets/{nn-NO-6E72VCQL-5zTuWq4x.js → nn-NO-6E72VCQL-4acyfJJj.js} +1 -1
  75. package/dist/dashboard/assets/{oc-FR-POXYY2M6-CjWsH2WL.js → oc-FR-POXYY2M6-D8pDlGpO.js} +1 -1
  76. package/dist/dashboard/assets/{pa-IN-N4M65BXN-BoIcIn-E.js → pa-IN-N4M65BXN-CUXWRM9Z.js} +1 -1
  77. package/dist/dashboard/assets/{percentages-BXMCSKIN-F5X-Tg4w.js → percentages-BXMCSKIN-jDtw9CS_.js} +7 -7
  78. package/dist/dashboard/assets/{pica-kqAcDU9z.js → pica-D2k8QhiT.js} +1 -1
  79. package/dist/dashboard/assets/{pieDiagram-DEJITSTG-nYd2z-pn.js → pieDiagram-DEJITSTG-BY5lDpxM.js} +1 -1
  80. package/dist/dashboard/assets/{pl-PL-T2D74RX3-GchO6UuX.js → pl-PL-T2D74RX3-BTVl1PaU.js} +1 -1
  81. package/dist/dashboard/assets/{pt-BR-5N22H2LF-BUsepHJF.js → pt-BR-5N22H2LF-CRV4c2FR.js} +1 -1
  82. package/dist/dashboard/assets/{pt-PT-UZXXM6DQ-CCrWB7t1.js → pt-PT-UZXXM6DQ-Ciz73XBG.js} +1 -1
  83. package/dist/dashboard/assets/{quadrantDiagram-34T5L4WZ-CyQyFV43.js → quadrantDiagram-34T5L4WZ-CkCyPark.js} +1 -1
  84. package/dist/dashboard/assets/{requirementDiagram-MS252O5E-DzDNbaAz.js → requirementDiagram-MS252O5E-pkDzqMen.js} +1 -1
  85. package/dist/dashboard/assets/{ro-RO-JPDTUUEW-Bg8qasSV.js → ro-RO-JPDTUUEW-B5tB2ZMk.js} +1 -1
  86. package/dist/dashboard/assets/{ru-RU-B4JR7IUQ-l7KGf_aH.js → ru-RU-B4JR7IUQ-CjaSKApe.js} +1 -1
  87. package/dist/dashboard/assets/{sankeyDiagram-XADWPNL6-t78W7pty.js → sankeyDiagram-XADWPNL6-CrziMmSl.js} +1 -1
  88. package/dist/dashboard/assets/{sequenceDiagram-FGHM5R23-C-A4YWsY.js → sequenceDiagram-FGHM5R23-D5zUE04i.js} +1 -1
  89. package/dist/dashboard/assets/{si-LK-N5RQ5JYF-Bvh5jeZQ.js → si-LK-N5RQ5JYF-QK81fzaG.js} +1 -1
  90. package/dist/dashboard/assets/{sk-SK-C5VTKIMK-Cw6feZYR.js → sk-SK-C5VTKIMK-TANqzQvg.js} +1 -1
  91. package/dist/dashboard/assets/{sl-SI-NN7IZMDC-B-NqJ9YS.js → sl-SI-NN7IZMDC-Dht86ddT.js} +1 -1
  92. package/dist/dashboard/assets/{stateDiagram-FHFEXIEX-DIcQEopN.js → stateDiagram-FHFEXIEX-CcR_Q14Z.js} +1 -1
  93. package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-DIVPLDRd.js +1 -0
  94. package/dist/dashboard/assets/{subset-shared.chunk-w-9tnfIy.js → subset-shared.chunk-NAGN_SBv.js} +1 -1
  95. package/dist/dashboard/assets/{subset-worker.chunk-BF01ymYz.js → subset-worker.chunk-wsRwU71V.js} +1 -1
  96. package/dist/dashboard/assets/{sv-SE-XGPEYMSR-Ktas5ybY.js → sv-SE-XGPEYMSR-DidGUaol.js} +1 -1
  97. package/dist/dashboard/assets/{ta-IN-2NMHFXQM-WVntmT4J.js → ta-IN-2NMHFXQM-YZmBodpj.js} +1 -1
  98. package/dist/dashboard/assets/{th-TH-HPSO5L25-DP9jkhxy.js → th-TH-HPSO5L25-CVvvXQFu.js} +1 -1
  99. package/dist/dashboard/assets/{timeline-definition-GMOUNBTQ-CQLRxE6-.js → timeline-definition-GMOUNBTQ-B8I1QieK.js} +1 -1
  100. package/dist/dashboard/assets/{tr-TR-DEFEU3FU-DUBzAzD0.js → tr-TR-DEFEU3FU-DjyXDfoR.js} +1 -1
  101. package/dist/dashboard/assets/{uk-UA-QMV73CPH-DBIjqvxV.js → uk-UA-QMV73CPH-1pRnjZIi.js} +1 -1
  102. package/dist/dashboard/assets/{vennDiagram-DHZGUBPP-ChnhJ1dN.js → vennDiagram-DHZGUBPP-BsBRDs0e.js} +1 -1
  103. package/dist/dashboard/assets/{vi-VN-M7AON7JQ-D47IGQ3F.js → vi-VN-M7AON7JQ-CualwmWX.js} +1 -1
  104. package/dist/dashboard/assets/{wardley-RL74JXVD-CnuAa4Oy.js → wardley-RL74JXVD-BP4Ewc0H.js} +1 -1
  105. package/dist/dashboard/assets/{wardleyDiagram-NUSXRM2D-D63qjR_j.js → wardleyDiagram-NUSXRM2D-B_WTb-rg.js} +1 -1
  106. package/dist/dashboard/assets/{xychartDiagram-5P7HB3ND-BUdyr5Wc.js → xychartDiagram-5P7HB3ND-vB-uMt25.js} +1 -1
  107. package/dist/dashboard/assets/{zh-CN-LNUGB5OW-_ICN38Lj.js → zh-CN-LNUGB5OW-CQjWtZ9Y.js} +1 -1
  108. package/dist/dashboard/assets/{zh-HK-E62DVLB3-Bjez10pk.js → zh-HK-E62DVLB3-DzC49dFs.js} +1 -1
  109. package/dist/dashboard/assets/{zh-TW-RAJ6MFWO-Do-CPv3_.js → zh-TW-RAJ6MFWO-C4KJuhZE.js} +1 -1
  110. package/dist/dashboard/index.html +2 -2
  111. package/dist/index.js +1034 -364
  112. package/package.json +1 -1
  113. package/skill/SKILL.md +4 -3
  114. package/skill/references/brain-sync.md +131 -0
  115. package/skill/references/integrations.md +7 -4
  116. package/skill/references/sleep.md +1 -1
  117. package/skill-sync/references/merge-rules.md +68 -2
  118. package/dist/dashboard/assets/channel-CTaS69UP.js +0 -1
  119. package/dist/dashboard/assets/classDiagram-6PBFFD2Q-DYWavBQh.js +0 -1
  120. package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-DYWavBQh.js +0 -1
  121. package/dist/dashboard/assets/clone-Dpdgvgqp.js +0 -1
  122. package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-CFAZrDsQ.js +0 -1
package/dist/index.js CHANGED
@@ -17951,7 +17951,7 @@ function sanitizeGitHub(raw) {
17951
17951
  function sanitizeBrainRepo(raw) {
17952
17952
  if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return void 0;
17953
17953
  const o = raw;
17954
- const mode = o.mode === "separate" ? "separate" : "in-tree";
17954
+ const mode = o.mode === "separate" ? "separate" : o.mode === "full-repo" ? "full-repo" : "in-tree";
17955
17955
  const out = { mode };
17956
17956
  if (typeof o.enabled === "boolean") out.enabled = o.enabled;
17957
17957
  if (typeof o.remote === "string") out.remote = o.remote;
@@ -38063,6 +38063,7 @@ __export(git_exports, {
38063
38063
  attemptMerge: () => attemptMerge,
38064
38064
  clone: () => clone,
38065
38065
  commit: () => commit,
38066
+ currentBranch: () => currentBranch,
38066
38067
  currentSha: () => currentSha,
38067
38068
  fetch: () => fetch2,
38068
38069
  getRemoteUrl: () => getRemoteUrl,
@@ -38134,6 +38135,14 @@ function currentSha(cwd) {
38134
38135
  return null;
38135
38136
  }
38136
38137
  }
38138
+ function currentBranch(cwd) {
38139
+ try {
38140
+ const branch = run2(cwd, ["symbolic-ref", "--short", "HEAD"]).trim();
38141
+ return branch && branch !== "HEAD" ? branch : null;
38142
+ } catch {
38143
+ return null;
38144
+ }
38145
+ }
38137
38146
  function addRemote(cwd, name, url) {
38138
38147
  run2(cwd, ["remote", "add", name, url]);
38139
38148
  }
@@ -38381,6 +38390,34 @@ function scrubStagedFiles(cwd, opts) {
38381
38390
  }
38382
38391
  return hits;
38383
38392
  }
38393
+ function scrubCommitRange(cwd, range) {
38394
+ let raw;
38395
+ try {
38396
+ raw = execFileSync6("git", ["diff", "--name-only", "-z", range], {
38397
+ cwd,
38398
+ encoding: "utf-8",
38399
+ stdio: ["ignore", "pipe", "ignore"]
38400
+ });
38401
+ } catch {
38402
+ return [];
38403
+ }
38404
+ const files = raw.split("\0").filter((p) => p.length > 0);
38405
+ const hits = [];
38406
+ for (const relPath of files) {
38407
+ let content;
38408
+ try {
38409
+ content = execFileSync6("git", ["show", `HEAD:${relPath}`], {
38410
+ cwd,
38411
+ encoding: "utf-8",
38412
+ stdio: ["ignore", "pipe", "ignore"]
38413
+ });
38414
+ } catch {
38415
+ continue;
38416
+ }
38417
+ hits.push(...scrubContent(relPath, content));
38418
+ }
38419
+ return hits;
38420
+ }
38384
38421
  function summarizeScrub(hits) {
38385
38422
  return {
38386
38423
  blocks: hits.filter((h) => h.severity === "block"),
@@ -38595,10 +38632,20 @@ function mergeMarkdownDoc(base, ours, theirs) {
38595
38632
  if (result.conflictSections.length > 0) return { merged: null, needsAgent: true };
38596
38633
  return { merged: result.merged, needsAgent: false };
38597
38634
  }
38598
- function resolveConflicts(cwd, conflicts) {
38635
+ function isCodePath(relPath, opts) {
38636
+ if (!opts.fullRepo) return false;
38637
+ const norm2 = relPath.replace(/\\/g, "/");
38638
+ return !norm2.startsWith("_dream_context/");
38639
+ }
38640
+ function resolveConflicts(cwd, conflicts, opts = {}) {
38599
38641
  const resolved = [];
38600
38642
  const deferredToAgent = [];
38643
+ const deferredToHuman = [];
38601
38644
  for (const relPath of conflicts) {
38645
+ if (isCodePath(relPath, opts)) {
38646
+ deferredToHuman.push({ path: relPath, class: "code" });
38647
+ continue;
38648
+ }
38602
38649
  const cls = classifyPath(relPath);
38603
38650
  const { base, ours, theirs } = readOursTheirsBase(cwd, relPath);
38604
38651
  let mergedContent = null;
@@ -38636,7 +38683,7 @@ function resolveConflicts(cwd, conflicts) {
38636
38683
  resolved.push(relPath);
38637
38684
  }
38638
38685
  }
38639
- return { resolved, deferredToAgent };
38686
+ return { resolved, deferredToAgent, deferredToHuman };
38640
38687
  }
38641
38688
  var import_gray_matter7, STATUS_ORDER2;
38642
38689
  var init_semantic_merge = __esm({
@@ -38679,6 +38726,7 @@ function writeConflictReport(contextRoot, input2) {
38679
38726
  remoteRef: input2.remoteRef,
38680
38727
  resolvedByCli: input2.resolvedByCli,
38681
38728
  deferred,
38729
+ ...input2.codeConflicts && input2.codeConflicts.length > 0 ? { codeConflicts: input2.codeConflicts } : {},
38682
38730
  status: "awaiting-agent"
38683
38731
  };
38684
38732
  writeFileSync33(reportPath(contextRoot), `${JSON.stringify(report, null, 2)}
@@ -39013,7 +39061,10 @@ function isOwnRepoRoot(contextRoot, gitModule = git_exports) {
39013
39061
  }
39014
39062
  }
39015
39063
  function resolveMode2(config) {
39016
- return config?.brainRepo?.mode === "separate" ? "separate" : "in-tree";
39064
+ const mode = config?.brainRepo?.mode;
39065
+ if (mode === "separate") return "separate";
39066
+ if (mode === "full-repo") return "full-repo";
39067
+ return "in-tree";
39017
39068
  }
39018
39069
  function resolveBrainSyncEnabled(projectRoot, config, gitModule = git_exports) {
39019
39070
  const explicit = config?.brainRepo?.enabled;
@@ -39080,6 +39131,17 @@ function buildBrainGitignore(taskBackend) {
39080
39131
  return `${lines.join("\n")}
39081
39132
  `;
39082
39133
  }
39134
+ function ensureFullRepoGitignore(projectRoot, taskBackend) {
39135
+ const entries = [...FULL_REPO_LOCAL_GITIGNORE_ENTRIES];
39136
+ if (taskBackend && taskBackend !== "local") entries.push("_dream_context/state/*.md");
39137
+ try {
39138
+ return ensureGitignoreEntries(projectRoot, entries, {
39139
+ comment: "dreamcontext full-repo sync \u2014 machine-local brain state + secrets (never sync)"
39140
+ });
39141
+ } catch {
39142
+ return [];
39143
+ }
39144
+ }
39083
39145
  async function bootstrapBrainRepo(opts) {
39084
39146
  const g = opts.gitModule ?? git_exports;
39085
39147
  const scrub = opts.scrubStagedFilesImpl ?? scrubStagedFiles;
@@ -39246,7 +39308,7 @@ function releaseBrainLock(contextRoot) {
39246
39308
  function currentTaskBackend(projectRoot) {
39247
39309
  return readSetupConfig(projectRoot)?.taskBackend;
39248
39310
  }
39249
- var BRAIN_MARKER_TOPIC, BRAIN_MARKER_FILE, FALLBACK_AUTHOR, BRAIN_LOCK_STALE_MS;
39311
+ var BRAIN_MARKER_TOPIC, BRAIN_MARKER_FILE, FALLBACK_AUTHOR, FULL_REPO_LOCAL_GITIGNORE_ENTRIES, BRAIN_LOCK_STALE_MS;
39250
39312
  var init_brain_repo = __esm({
39251
39313
  "src/lib/git-sync/brain-repo.ts"() {
39252
39314
  "use strict";
@@ -39264,15 +39326,52 @@ var init_brain_repo = __esm({
39264
39326
  BRAIN_MARKER_TOPIC = "dreamcontext-brain";
39265
39327
  BRAIN_MARKER_FILE = ".dreamcontext-brain";
39266
39328
  FALLBACK_AUTHOR = { name: "dreamcontext-sync", email: "noreply@dreamcontext.local" };
39329
+ FULL_REPO_LOCAL_GITIGNORE_ENTRIES = [
39330
+ // Secrets — never sync, regardless of anything else.
39331
+ "_dream_context/state/.secrets.json",
39332
+ "_dream_context/**/.env",
39333
+ // Machine-local brain runtime — per-machine; must never sync (merge churn, or
39334
+ // in the sync lock's case, cross-machine lock contention).
39335
+ "_dream_context/state/.brain-merge/",
39336
+ "_dream_context/state/.brain-local.json",
39337
+ "_dream_context/state/.sleep.json",
39338
+ "_dream_context/state/.sleep-history.json",
39339
+ "_dream_context/state/.agent-sessions.json",
39340
+ "_dream_context/state/.agent-session-map/",
39341
+ "_dream_context/state/.session-digests/",
39342
+ "_dream_context/state/.conflicts/",
39343
+ "_dream_context/state/.version-check.json",
39344
+ "_dream_context/state/.auto-upgrade.json",
39345
+ "_dream_context/state/.lab-prefs.json",
39346
+ "_dream_context/state/.tasks-sync.lock",
39347
+ "_dream_context/state/.tasks-sync.json",
39348
+ "_dream_context/state/.tasks-queue.json",
39349
+ "_dream_context/tmp/",
39350
+ // Lab analytics credentials — the example (key names only) still syncs.
39351
+ "_dream_context/lab/credentials.json",
39352
+ "_dream_context/lab/credentials.*",
39353
+ "!_dream_context/lab/credentials.example.json"
39354
+ ];
39267
39355
  BRAIN_LOCK_STALE_MS = 5 * 6e4;
39268
39356
  }
39269
39357
  });
39270
39358
 
39271
39359
  // src/lib/git-sync/sync-engine.ts
39272
39360
  import { dirname as dirname25 } from "path";
39361
+ function syncCommitMessage(ctx) {
39362
+ return ctx.mode === "full-repo" ? "chore: sync project (dreamcontext)" : "chore(brain): sync";
39363
+ }
39364
+ function autoCheckpointMessage(ctx) {
39365
+ return ctx.mode === "full-repo" ? "chore: checkpoint local edits before team merge (dreamcontext)" : "chore(brain): auto-checkpoint local edits before team merge";
39366
+ }
39273
39367
  function isBlockingScrub(scrub, strict) {
39274
39368
  return scrub.blocks.length > 0 || strict && scrub.warns.length > 0;
39275
39369
  }
39370
+ function codeConflictNote(paths) {
39371
+ const first = paths[0] ?? "a code file";
39372
+ const more = paths.length > 1 ? ` (+${paths.length - 1} more)` : "";
39373
+ return `Code conflict in ${first}${more} \u2014 the team changed it too. Resolve it in your editor, commit the merge, then run sync again.`;
39374
+ }
39276
39375
  function computeNeedsTaskSync(config, paths) {
39277
39376
  if (config?.taskBackend !== "github" && config?.taskBackend !== "clickup") return false;
39278
39377
  return paths.some((p) => {
@@ -39306,7 +39405,6 @@ async function runBrainSync(opts, depsOverride = {}) {
39306
39405
  }
39307
39406
  const mode = resolveMode2(config);
39308
39407
  const gitCwd = mode === "separate" ? contextRoot : projectRoot;
39309
- const ctx = { d, contextRoot, gitCwd, projectRoot, config, strict: !!opts.strict };
39310
39408
  if (!d.git.isGitRepo(gitCwd)) {
39311
39409
  return {
39312
39410
  action: "no-remote",
@@ -39314,6 +39412,32 @@ async function runBrainSync(opts, depsOverride = {}) {
39314
39412
  note: "No git repository found for the brain. Run `dreamcontext brain init` or `brain attach` first."
39315
39413
  };
39316
39414
  }
39415
+ let branch = DEFAULT_BRANCH;
39416
+ if (mode === "full-repo") {
39417
+ const live = d.git.currentBranch(gitCwd);
39418
+ if (!live) {
39419
+ return {
39420
+ action: "detached-head",
39421
+ scrub: EMPTY_SCRUB,
39422
+ note: "You're on a detached HEAD \u2014 check out a branch before syncing the whole project."
39423
+ };
39424
+ }
39425
+ branch = live;
39426
+ }
39427
+ const ctx = {
39428
+ d,
39429
+ contextRoot,
39430
+ gitCwd,
39431
+ projectRoot,
39432
+ config,
39433
+ mode,
39434
+ branch,
39435
+ remoteRef: `${REMOTE_NAME}/${branch}`,
39436
+ strict: !!opts.strict,
39437
+ foreground: !!opts.foreground,
39438
+ noCheckpoint: !!opts.noCheckpoint
39439
+ };
39440
+ if (mode === "full-repo") ensureFullRepoGitignore(projectRoot, config?.taskBackend);
39317
39441
  if (mode === "in-tree") {
39318
39442
  if (!d.acquireBrainLock(contextRoot)) return { action: "locked", scrub: EMPTY_SCRUB };
39319
39443
  try {
@@ -39339,6 +39463,24 @@ async function runBrainSync(opts, depsOverride = {}) {
39339
39463
  return { action: "invalid-flag", scrub: EMPTY_SCRUB, note: "No pending team-merge handoff to resume." };
39340
39464
  }
39341
39465
  if (hasMerge && !opts.continue) {
39466
+ const report = readConflictReport(contextRoot);
39467
+ if (!report) {
39468
+ return {
39469
+ action: "user-merge-in-progress",
39470
+ scrub: EMPTY_SCRUB,
39471
+ note: "Finish your in-progress git merge first, then run sync again."
39472
+ };
39473
+ }
39474
+ if (report.codeConflicts && report.codeConflicts.length > 0) {
39475
+ return {
39476
+ action: "code-conflict",
39477
+ scrub: EMPTY_SCRUB,
39478
+ conflicts: report.codeConflicts,
39479
+ codeConflicts: report.codeConflicts,
39480
+ report: "state/.brain-merge/report.json",
39481
+ note: codeConflictNote(report.codeConflicts)
39482
+ };
39483
+ }
39342
39484
  return { action: "already-awaiting-agent", scrub: EMPTY_SCRUB, note: "A team merge is awaiting resolution \u2014 run /dream-sync to reconcile." };
39343
39485
  }
39344
39486
  if (pending && !hasMerge && !opts.resume) {
@@ -39355,7 +39497,7 @@ async function runBrainSync(opts, depsOverride = {}) {
39355
39497
  else if (opts.mode === "pull-only") result = await pullOnlySync(ctx);
39356
39498
  else if (opts.mode === "push-only") result = await pushOnlySync(ctx);
39357
39499
  else result = await autoSync(ctx);
39358
- healPlatformLinksBestEffort(projectRoot, contextRoot);
39500
+ if (mode !== "full-repo") healPlatformLinksBestEffort(projectRoot, contextRoot);
39359
39501
  return result;
39360
39502
  } finally {
39361
39503
  d.releaseBrainLock(contextRoot);
@@ -39389,8 +39531,8 @@ function withMergeOutcome(result, preMergeScrub) {
39389
39531
  async function fetchRemoteIfExists(ctx, token) {
39390
39532
  const { d, gitCwd } = ctx;
39391
39533
  return d.withGitCredentials(token, async (env2) => {
39392
- const exists = d.git.remoteBranchExists(gitCwd, REMOTE_NAME, REMOTE_BRANCH, env2);
39393
- if (exists) d.git.fetch(gitCwd, REMOTE_NAME, REMOTE_BRANCH, env2);
39534
+ const exists = d.git.remoteBranchExists(gitCwd, REMOTE_NAME, ctx.branch, env2);
39535
+ if (exists) d.git.fetch(gitCwd, REMOTE_NAME, ctx.branch, env2);
39394
39536
  return exists;
39395
39537
  });
39396
39538
  }
@@ -39398,7 +39540,7 @@ function mergeAndMaybeDefer(ctx, opts) {
39398
39540
  const { d, gitCwd, contextRoot, projectRoot, config } = ctx;
39399
39541
  let mergeResult;
39400
39542
  try {
39401
- mergeResult = d.git.attemptMerge(gitCwd, REMOTE_REF);
39543
+ mergeResult = d.git.attemptMerge(gitCwd, ctx.remoteRef);
39402
39544
  } catch (err) {
39403
39545
  if (err instanceof Error && /unrelated histories/i.test(err.message)) {
39404
39546
  throw new GitSyncError(
@@ -39411,11 +39553,39 @@ function mergeAndMaybeDefer(ctx, opts) {
39411
39553
  const blocked2 = scrubAndCommitMerge(ctx, !!opts.effectiveStrict, MERGE_COMMIT_MESSAGE);
39412
39554
  return { result: blocked2, needsTaskSync: false };
39413
39555
  }
39414
- const resolution = d.resolveConflicts(gitCwd, mergeResult.conflicts);
39556
+ const resolution = d.resolveConflicts(gitCwd, mergeResult.conflicts, { fullRepo: ctx.mode === "full-repo" });
39415
39557
  const needsTaskSync = computeNeedsTaskSync(config, resolution.resolved);
39558
+ if (resolution.deferredToHuman.length > 0) {
39559
+ const codePaths = resolution.deferredToHuman.map((x) => x.path);
39560
+ if (ctx.foreground) {
39561
+ writeConflictReport(contextRoot, {
39562
+ remoteRef: ctx.remoteRef,
39563
+ resolvedByCli: resolution.resolved,
39564
+ deferred: resolution.deferredToAgent.map((x) => {
39565
+ const snap = d.git.readOursTheirsBase(gitCwd, x.path);
39566
+ return { path: x.path, class: x.class, reason: "overlapping edits to same section", ...snap };
39567
+ }),
39568
+ codeConflicts: codePaths
39569
+ });
39570
+ } else {
39571
+ d.git.abortMerge(gitCwd);
39572
+ }
39573
+ return {
39574
+ result: {
39575
+ action: "code-conflict",
39576
+ scrub: EMPTY_SCRUB,
39577
+ conflicts: codePaths,
39578
+ codeConflicts: codePaths,
39579
+ report: ctx.foreground ? "state/.brain-merge/report.json" : void 0,
39580
+ note: codeConflictNote(codePaths),
39581
+ needsTaskSync
39582
+ },
39583
+ needsTaskSync
39584
+ };
39585
+ }
39416
39586
  if (resolution.deferredToAgent.length > 0) {
39417
39587
  writeConflictReport(contextRoot, {
39418
- remoteRef: REMOTE_REF,
39588
+ remoteRef: ctx.remoteRef,
39419
39589
  resolvedByCli: resolution.resolved,
39420
39590
  deferred: resolution.deferredToAgent.map((x) => {
39421
39591
  const snap = d.git.readOursTheirsBase(gitCwd, x.path);
@@ -39447,7 +39617,7 @@ async function pushWithRetry(ctx, scrub) {
39447
39617
  const tryPush = async () => {
39448
39618
  try {
39449
39619
  await d.withGitCredentials(token.token, async (env2) => {
39450
- d.git.push(gitCwd, REMOTE_NAME, REMOTE_BRANCH, env2);
39620
+ d.git.push(gitCwd, REMOTE_NAME, ctx.branch, env2);
39451
39621
  });
39452
39622
  return true;
39453
39623
  } catch {
@@ -39469,17 +39639,18 @@ async function autoSync(ctx) {
39469
39639
  const token = d.resolveBrainSyncToken(projectRoot);
39470
39640
  if (!token) return { action: "no-remote", scrub: EMPTY_SCRUB, note: "No GitHub token found for the brain repo (per-project secrets or GITHUB_TOKEN/GH_TOKEN env)." };
39471
39641
  const remoteExists = await fetchRemoteIfExists(ctx, token.token);
39472
- const aheadCount = remoteExists ? d.git.revListCount(gitCwd, `HEAD..${REMOTE_REF}`) : 0;
39642
+ const aheadCount = remoteExists ? d.git.revListCount(gitCwd, `HEAD..${ctx.remoteRef}`) : 0;
39643
+ const localAhead = remoteExists ? d.git.revListCount(gitCwd, `${ctx.remoteRef}..HEAD`) : 0;
39473
39644
  const dirty = d.git.statusPorcelainTracked(gitCwd);
39474
39645
  const needsBootstrapPush = !remoteExists && !!d.git.currentSha(gitCwd);
39475
- if (aheadCount === 0 && dirty.length === 0 && !needsBootstrapPush) return { action: "noop", scrub: EMPTY_SCRUB };
39646
+ if (aheadCount === 0 && localAhead === 0 && dirty.length === 0 && !needsBootstrapPush) return { action: "noop", scrub: EMPTY_SCRUB };
39476
39647
  let scrub = EMPTY_SCRUB;
39477
39648
  if (dirty.length > 0) {
39478
39649
  d.git.stageAll(gitCwd);
39479
39650
  const hits = d.scrubStagedFiles(gitCwd);
39480
39651
  scrub = summarizeScrub(hits);
39481
39652
  if (isBlockingScrub(scrub, ctx.strict)) return { action: "blocked-scrub", scrub };
39482
- d.git.commit(gitCwd, "chore(brain): sync", authorFor(ctx));
39653
+ d.git.commit(gitCwd, syncCommitMessage(ctx), authorFor(ctx));
39483
39654
  }
39484
39655
  let needsTaskSync = false;
39485
39656
  if (aheadCount > 0) {
@@ -39487,6 +39658,11 @@ async function autoSync(ctx) {
39487
39658
  if (outcome.result) return withMergeOutcome(outcome.result, scrub);
39488
39659
  needsTaskSync = outcome.needsTaskSync;
39489
39660
  }
39661
+ if (remoteExists && localAhead > 0) {
39662
+ const rangeScrub = summarizeScrub(d.scrubCommitRange(gitCwd, `${ctx.remoteRef}..HEAD`));
39663
+ if (isBlockingScrub(rangeScrub, ctx.strict)) return { action: "blocked-scrub", scrub: rangeScrub };
39664
+ if (rangeScrub.blocks.length > 0 || rangeScrub.warns.length > 0) scrub = rangeScrub;
39665
+ }
39490
39666
  const pushResult = await pushWithRetry(ctx, scrub);
39491
39667
  return { ...pushResult, needsTaskSync: needsTaskSync || pushResult.needsTaskSync };
39492
39668
  }
@@ -39498,24 +39674,33 @@ async function pullOnlySync(ctx) {
39498
39674
  return { action: "noop", scrub: EMPTY_SCRUB, note: "Remote brain repo is empty \u2014 nothing to pull yet. Run `dreamcontext brain sync` to push the first commit." };
39499
39675
  }
39500
39676
  const beforeSha = d.git.currentSha(gitCwd);
39501
- const aheadCount = d.git.revListCount(gitCwd, `HEAD..${REMOTE_REF}`);
39677
+ const aheadCount = d.git.revListCount(gitCwd, `HEAD..${ctx.remoteRef}`);
39502
39678
  if (aheadCount === 0) return { action: "noop", scrub: EMPTY_SCRUB };
39503
39679
  const dirty = d.git.statusPorcelainTracked(gitCwd);
39504
39680
  let scrub = EMPTY_SCRUB;
39681
+ let checkpointSha;
39505
39682
  if (dirty.length > 0) {
39683
+ if (ctx.noCheckpoint) {
39684
+ return {
39685
+ action: "noop",
39686
+ scrub: EMPTY_SCRUB,
39687
+ note: "You have uncommitted local edits and auto-checkpoint-on-open is off \u2014 skipped the pull so your WIP is untouched. Sync from the sidebar when ready."
39688
+ };
39689
+ }
39506
39690
  d.git.stageAll(gitCwd);
39507
39691
  const hits = d.scrubStagedFiles(gitCwd);
39508
39692
  scrub = summarizeScrub(hits);
39509
- if (scrub.blocks.length > 0 || scrub.warns.length > 0) {
39693
+ const blocks = ctx.foreground ? scrub.blocks.length > 0 : scrub.blocks.length > 0 || scrub.warns.length > 0;
39694
+ if (blocks) {
39510
39695
  return {
39511
39696
  action: "blocked-scrub",
39512
39697
  scrub,
39513
- note: "Your local brain edits contain something that looks sensitive \u2014 review and run `dreamcontext brain sync` manually."
39698
+ note: "Your local edits contain something that looks sensitive \u2014 review and run sync manually."
39514
39699
  };
39515
39700
  }
39516
- d.git.commit(gitCwd, AUTO_CHECKPOINT_MESSAGE, authorFor(ctx));
39701
+ checkpointSha = d.git.commit(gitCwd, autoCheckpointMessage(ctx), authorFor(ctx)) ?? void 0;
39517
39702
  }
39518
- const outcome = mergeAndMaybeDefer(ctx, { abortOnDefer: true, markPendingOnDefer: true, effectiveStrict: true });
39703
+ const outcome = mergeAndMaybeDefer(ctx, { abortOnDefer: true, markPendingOnDefer: true, effectiveStrict: !ctx.foreground });
39519
39704
  if (outcome.result) return withMergeOutcome(outcome.result, scrub);
39520
39705
  const afterSha = d.git.currentSha(gitCwd);
39521
39706
  const pulledUpdates = beforeSha && afterSha ? d.git.revListCount(gitCwd, `${beforeSha}..${afterSha}`) : aheadCount;
@@ -39525,15 +39710,19 @@ async function pullOnlySync(ctx) {
39525
39710
  pendingAgentMerge: false,
39526
39711
  needsTaskSync: outcome.needsTaskSync
39527
39712
  });
39528
- return { action: "pulled", scrub, pulledUpdates, needsTaskSync: outcome.needsTaskSync };
39713
+ return { action: "pulled", scrub, pulledUpdates, needsTaskSync: outcome.needsTaskSync, checkpointed: !!checkpointSha, checkpointSha };
39529
39714
  }
39530
39715
  async function pushOnlySync(ctx) {
39531
39716
  const { d, gitCwd } = ctx;
39532
39717
  d.git.stageAll(gitCwd);
39533
39718
  const hits = d.scrubStagedFiles(gitCwd);
39534
- const scrub = summarizeScrub(hits);
39719
+ let scrub = summarizeScrub(hits);
39535
39720
  if (isBlockingScrub(scrub, ctx.strict)) return { action: "blocked-scrub", scrub };
39536
- d.git.commit(gitCwd, "chore(brain): sync", authorFor(ctx));
39721
+ d.git.commit(gitCwd, syncCommitMessage(ctx), authorFor(ctx));
39722
+ const base = d.git.revParse(gitCwd, ctx.remoteRef) ? ctx.remoteRef : EMPTY_TREE_SHA;
39723
+ const rangeScrub = summarizeScrub(d.scrubCommitRange(gitCwd, `${base}..HEAD`));
39724
+ if (isBlockingScrub(rangeScrub, ctx.strict)) return { action: "blocked-scrub", scrub: rangeScrub };
39725
+ if (rangeScrub.blocks.length > 0 || rangeScrub.warns.length > 0) scrub = rangeScrub;
39537
39726
  return pushWithRetry(ctx, scrub);
39538
39727
  }
39539
39728
  async function continueMerge(ctx) {
@@ -39563,7 +39752,7 @@ async function resumeHandoff(ctx) {
39563
39752
  const hits = d.scrubStagedFiles(gitCwd);
39564
39753
  const s = summarizeScrub(hits);
39565
39754
  if (isBlockingScrub(s, ctx.strict)) return { action: "blocked-scrub", scrub: s };
39566
- d.git.commit(gitCwd, "chore(brain): sync", authorFor(ctx));
39755
+ d.git.commit(gitCwd, syncCommitMessage(ctx), authorFor(ctx));
39567
39756
  }
39568
39757
  const outcome = mergeAndMaybeDefer(ctx, { abortOnDefer: false, markPendingOnDefer: false });
39569
39758
  if (outcome.result) return withMergeOutcome(outcome.result, scrub);
@@ -39573,7 +39762,7 @@ async function resumeHandoff(ctx) {
39573
39762
  }
39574
39763
  return pushResult;
39575
39764
  }
39576
- var REMOTE_NAME, REMOTE_BRANCH, REMOTE_REF, AUTO_CHECKPOINT_MESSAGE, MERGE_COMMIT_MESSAGE, AGENT_MERGE_COMMIT_MESSAGE, EMPTY_SCRUB, defaultDeps;
39765
+ var REMOTE_NAME, DEFAULT_BRANCH, EMPTY_TREE_SHA, MERGE_COMMIT_MESSAGE, AGENT_MERGE_COMMIT_MESSAGE, EMPTY_SCRUB, defaultDeps;
39577
39766
  var init_sync_engine = __esm({
39578
39767
  "src/lib/git-sync/sync-engine.ts"() {
39579
39768
  "use strict";
@@ -39590,9 +39779,8 @@ var init_sync_engine = __esm({
39590
39779
  init_identity();
39591
39780
  init_id();
39592
39781
  REMOTE_NAME = "origin";
39593
- REMOTE_BRANCH = "main";
39594
- REMOTE_REF = `${REMOTE_NAME}/${REMOTE_BRANCH}`;
39595
- AUTO_CHECKPOINT_MESSAGE = "chore(brain): auto-checkpoint local edits before team merge";
39782
+ DEFAULT_BRANCH = "main";
39783
+ EMPTY_TREE_SHA = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
39596
39784
  MERGE_COMMIT_MESSAGE = "chore(brain): merge team updates";
39597
39785
  AGENT_MERGE_COMMIT_MESSAGE = "chore(brain): merge team updates (agent-resolved)";
39598
39786
  EMPTY_SCRUB = { blocks: [], warns: [] };
@@ -39600,6 +39788,7 @@ var init_sync_engine = __esm({
39600
39788
  git: git_exports,
39601
39789
  resolveConflicts,
39602
39790
  scrubStagedFiles,
39791
+ scrubCommitRange,
39603
39792
  resolveBrainSyncToken,
39604
39793
  withGitCredentials,
39605
39794
  acquireBrainLock,
@@ -39764,8 +39953,8 @@ function registerBrainCommand(program2) {
39764
39953
  const local = readBrainLocal(projectRoot);
39765
39954
  console.log(header("Brain Repo Status"));
39766
39955
  info(`Cloud sync: ${enabledResolution.enabled ? "ON" : "OFF"} (${enabledResolution.source})`);
39767
- info(`Mode: ${mode}`);
39768
- if (mode === "separate") {
39956
+ info(`Mode: ${mode}${mode === "full-repo" ? " (whole project \u2192 origin)" : ""}`);
39957
+ if (mode !== "in-tree") {
39769
39958
  const remote = isGitRepo(gitCwd) ? getRemoteUrl(gitCwd, "origin") : null;
39770
39959
  info(`Remote: ${remote ?? "(none configured)"}`);
39771
39960
  }
@@ -39867,7 +40056,7 @@ function registerBrainCommand(program2) {
39867
40056
  const projectRoot = dirname26(contextRoot);
39868
40057
  const config = readSetupConfig(projectRoot);
39869
40058
  if (!opts.status && resolveMode2(config) !== "separate") {
39870
- warn("The platform layer only helps in separate mode \u2014 in-tree brains already live in the code repo, so CLAUDE.md/.claude are shareable as-is.");
40059
+ warn("The platform layer only helps in separate mode \u2014 in-tree and full-repo brains already live in the code repo, so CLAUDE.md/.claude sync as-is.");
39871
40060
  info("Set up a separate brain repo first (`dreamcontext brain init` / `brain attach`).");
39872
40061
  process.exitCode = 1;
39873
40062
  return;
@@ -41162,19 +41351,93 @@ var init_chunker = __esm({
41162
41351
  });
41163
41352
 
41164
41353
  // src/lib/embeddings/embedder.ts
41354
+ import { existsSync as existsSync53 } from "fs";
41355
+ import { createRequire } from "module";
41165
41356
  import { homedir as homedir4 } from "os";
41166
41357
  import { join as join54 } from "path";
41358
+ function recordProgress(p) {
41359
+ if (!p.file) return;
41360
+ const prev = modelStatus.files.get(p.file);
41361
+ modelStatus.files.set(p.file, {
41362
+ file: p.file,
41363
+ status: p.status,
41364
+ loaded: p.loaded ?? prev?.loaded ?? 0,
41365
+ total: p.total ?? prev?.total ?? 0,
41366
+ progress: p.status === "done" ? 100 : p.progress ?? prev?.progress ?? 0
41367
+ });
41368
+ }
41369
+ function isEmbedPackageInstalled() {
41370
+ if (pkgInstalledCache !== null) return pkgInstalledCache;
41371
+ try {
41372
+ createRequire(import.meta.url).resolve("@huggingface/transformers");
41373
+ pkgInstalledCache = true;
41374
+ } catch {
41375
+ pkgInstalledCache = false;
41376
+ }
41377
+ return pkgInstalledCache;
41378
+ }
41379
+ function isEmbedModelDownloaded() {
41380
+ const root = join54(EMBED_MODEL_CACHE_DIR, EMBED_MODEL);
41381
+ return existsSync53(join54(root, "onnx", "model_quantized.onnx")) && existsSync53(join54(root, "config.json")) && existsSync53(join54(root, "tokenizer.json"));
41382
+ }
41383
+ function getEmbedModelStatus() {
41384
+ const downloaded = isEmbedModelDownloaded();
41385
+ const files = [...modelStatus.files.values()];
41386
+ const totalBytes = files.reduce((s, f) => s + (f.total || 0), 0);
41387
+ const loadedBytes = files.reduce((s, f) => s + (f.loaded || 0), 0);
41388
+ let state;
41389
+ if (modelStatus.state === "error") state = "error";
41390
+ else if (downloaded) state = "ready";
41391
+ else if (modelStatus.state === "downloading") state = "downloading";
41392
+ else state = "not_downloaded";
41393
+ const progress = state === "ready" ? 100 : totalBytes > 0 ? Math.min(99, Math.round(loadedBytes / totalBytes * 100)) : 0;
41394
+ return {
41395
+ model: EMBED_MODEL,
41396
+ state,
41397
+ downloaded,
41398
+ packageInstalled: isEmbedPackageInstalled(),
41399
+ progress,
41400
+ loadedBytes,
41401
+ totalBytes,
41402
+ files,
41403
+ error: modelStatus.error ?? null,
41404
+ errorCode: modelStatus.errorCode ?? null
41405
+ };
41406
+ }
41407
+ function startEmbedModelDownload() {
41408
+ if (modelStatus.state === "not_downloaded" || modelStatus.state === "error") {
41409
+ extractorPromise = null;
41410
+ modelStatus.files.clear();
41411
+ modelStatus.error = void 0;
41412
+ modelStatus.errorCode = void 0;
41413
+ }
41414
+ void getExtractor();
41415
+ return getEmbedModelStatus();
41416
+ }
41167
41417
  async function getExtractor() {
41168
41418
  if (extractorPromise === null) {
41419
+ modelStatus.state = "downloading";
41420
+ modelStatus.startedAt = Date.now();
41421
+ modelStatus.endedAt = void 0;
41169
41422
  extractorPromise = (async () => {
41170
41423
  try {
41171
41424
  const tf = await import("@huggingface/transformers");
41172
- tf.env.cacheDir = join54(homedir4(), ".dreamcontext", "models");
41173
- const pipe = await tf.pipeline("feature-extraction", EMBED_MODEL, { dtype: "q8" });
41425
+ tf.env.cacheDir = EMBED_MODEL_CACHE_DIR;
41426
+ const pipe = await tf.pipeline("feature-extraction", EMBED_MODEL, {
41427
+ dtype: "q8",
41428
+ progress_callback: recordProgress
41429
+ });
41430
+ modelStatus.state = "ready";
41431
+ modelStatus.endedAt = Date.now();
41174
41432
  return pipe;
41175
41433
  } catch (err) {
41434
+ const msg = err instanceof Error ? err.message : String(err);
41435
+ modelStatus.state = "error";
41436
+ modelStatus.error = msg;
41437
+ modelStatus.errorCode = /cannot find (module|package)|ERR_MODULE_NOT_FOUND/i.test(msg) ? "package_missing" : "download_failed";
41438
+ modelStatus.endedAt = Date.now();
41176
41439
  if (process.env.DREAMCONTEXT_DEBUG) {
41177
- console.error(`[embed] model load failed: ${err instanceof Error ? err.message : String(err)}`);
41440
+ console.error(`[embed] model load failed: ${msg}`);
41178
41441
  }
41179
41442
  return null;
41180
41443
  }
@@ -41185,7 +41448,7 @@ async function getExtractor() {
41185
41448
  async function embeddingsAvailable() {
41186
41449
  return await getExtractor() !== null;
41187
41450
  }
41188
- async function embedPassages(texts) {
41451
+ async function embedPassages(texts, onProgress) {
41189
41452
  const extractor = await getExtractor();
41190
41453
  if (extractor === null) return null;
41191
41454
  const out = [];
@@ -41196,6 +41459,7 @@ async function embedPassages(texts) {
41196
41459
  for (let j = 0; j < batch.length; j++) {
41197
41460
  out.push(res.data.slice(j * dims, (j + 1) * dims));
41198
41461
  }
41462
+ onProgress?.(Math.min(i + BATCH_SIZE, texts.length), texts.length);
41199
41463
  }
41200
41464
  return out;
41201
41465
  }
@@ -41205,18 +41469,21 @@ async function embedQuery(text) {
41205
41469
  const res = await extractor(`query: ${text}`, { pooling: "mean", normalize: true });
41206
41470
  return res.data.slice(0, res.dims[res.dims.length - 1]);
41207
41471
  }
41208
- var EMBED_MODEL, BATCH_SIZE, extractorPromise;
41472
+ var EMBED_MODEL, EMBED_MODEL_CACHE_DIR, BATCH_SIZE, extractorPromise, modelStatus, pkgInstalledCache;
41209
41473
  var init_embedder = __esm({
41210
41474
  "src/lib/embeddings/embedder.ts"() {
41211
41475
  "use strict";
41212
41476
  EMBED_MODEL = process.env.DREAMCONTEXT_EMBED_MODEL ?? "Xenova/multilingual-e5-small";
41477
+ EMBED_MODEL_CACHE_DIR = join54(homedir4(), ".dreamcontext", "models");
41213
41478
  BATCH_SIZE = 16;
41214
41479
  extractorPromise = null;
41480
+ modelStatus = { state: "not_downloaded", files: /* @__PURE__ */ new Map() };
41481
+ pkgInstalledCache = null;
41215
41482
  }
41216
41483
  });
41217
41484
 
41218
41485
  // src/lib/embeddings/store.ts
41219
- import { existsSync as existsSync53, mkdirSync as mkdirSync31, readFileSync as readFileSync39, renameSync as renameSync12, statSync as statSync9, writeFileSync as writeFileSync39 } from "fs";
41486
+ import { existsSync as existsSync54, mkdirSync as mkdirSync31, readFileSync as readFileSync39, renameSync as renameSync12, statSync as statSync9, writeFileSync as writeFileSync39 } from "fs";
41220
41487
  import { join as join55 } from "path";
41221
41488
  function encodeVector(v) {
41222
41489
  return Buffer.from(v.buffer, v.byteOffset, v.byteLength).toString("base64");
@@ -41231,7 +41498,7 @@ function cachePath2(contextRoot) {
41231
41498
  function loadCache(contextRoot) {
41232
41499
  const empty = { version: CACHE_VERSION, model: EMBED_MODEL, docs: {}, vectors: {} };
41233
41500
  const path2 = cachePath2(contextRoot);
41234
- if (!existsSync53(path2)) return empty;
41501
+ if (!existsSync54(path2)) return empty;
41235
41502
  try {
41236
41503
  const parsed = JSON.parse(readFileSync39(path2, "utf-8"));
41237
41504
  if (parsed.version !== CACHE_VERSION || parsed.model !== EMBED_MODEL) return empty;
@@ -41245,7 +41512,7 @@ function saveCache(contextRoot, cache) {
41245
41512
  const dir = join55(contextRoot, CACHE_DIR);
41246
41513
  mkdirSync31(dir, { recursive: true });
41247
41514
  const ignorePath = join55(dir, ".gitignore");
41248
- if (!existsSync53(ignorePath)) writeFileSync39(ignorePath, "*\n");
41515
+ if (!existsSync54(ignorePath)) writeFileSync39(ignorePath, "*\n");
41249
41516
  const tmp = cachePath2(contextRoot) + ".tmp";
41250
41517
  writeFileSync39(tmp, JSON.stringify(cache));
41251
41518
  renameSync12(tmp, cachePath2(contextRoot));
@@ -41259,7 +41526,36 @@ function statOf(path2) {
41259
41526
  }
41260
41527
  }
41261
41528
  function embeddingCacheExists(contextRoot) {
41262
- return existsSync53(cachePath2(contextRoot));
41529
+ return existsSync54(cachePath2(contextRoot));
41530
+ }
41531
+ function embeddingCacheChunkCount(contextRoot) {
41532
+ try {
41533
+ const cache = loadCache(contextRoot);
41534
+ let n = 0;
41535
+ for (const doc of Object.values(cache.docs)) n += doc.hashes.length;
41536
+ return n;
41537
+ } catch {
41538
+ return 0;
41539
+ }
41540
+ }
41541
+ function embeddingCacheUsable(contextRoot) {
41542
+ const path2 = cachePath2(contextRoot);
41543
+ let mtimeMs;
41544
+ try {
41545
+ mtimeMs = statSync9(path2).mtimeMs;
41546
+ } catch {
41547
+ usableMemo.delete(path2);
41548
+ return false;
41549
+ }
41550
+ const memo = usableMemo.get(path2);
41551
+ if (memo && memo.mtimeMs === mtimeMs) return memo.usable;
41552
+ const usable = Object.keys(loadCache(contextRoot).vectors).length > 0;
41553
+ usableMemo.set(path2, { mtimeMs, usable });
41554
+ if (usableMemo.size > USABLE_MEMO_MAX) {
41555
+ const oldest = usableMemo.keys().next().value;
41556
+ if (oldest !== void 0) usableMemo.delete(oldest);
41557
+ }
41558
+ return usable;
41263
41559
  }
41264
41560
  async function refreshEmbeddings(contextRoot, corpus, embed = embedPassages, opts = {}) {
41265
41561
  const cache = loadCache(contextRoot);
@@ -41303,28 +41599,36 @@ async function refreshEmbeddings(contextRoot, corpus, embed = embedPassages, opt
41303
41599
  let embeddedCount = 0;
41304
41600
  if (missing.length > 0) {
41305
41601
  const texts = missing.map((h) => chunkTextByHash.get(h) ?? "");
41306
- const vectors = await embed(texts);
41602
+ const vectors = await embed(texts, opts.onProgress);
41307
41603
  if (vectors === null) return null;
41308
41604
  for (let i = 0; i < missing.length; i++) {
41309
41605
  cache.vectors[missing[i]] = encodeVector(vectors[i]);
41310
41606
  }
41311
41607
  embeddedCount = missing.length;
41312
41608
  }
41313
- const referenced = /* @__PURE__ */ new Set();
41314
- const newDocs = {};
41315
- for (const [key2, { entry }] of wanted) {
41316
- newDocs[key2] = entry;
41317
- for (const h of entry.hashes) referenced.add(h);
41318
- }
41319
41609
  let evicted = 0;
41320
- const newVectors = {};
41321
- for (const [h, v] of Object.entries(cache.vectors)) {
41322
- if (referenced.has(h)) newVectors[h] = v;
41323
- else evicted++;
41324
- }
41325
- const docsChanged = Object.keys(newDocs).length !== Object.keys(cache.docs).length || Object.keys(newDocs).some((k) => cache.docs[k] !== newDocs[k]);
41326
- cache.docs = newDocs;
41327
- cache.vectors = newVectors;
41610
+ let docsChanged = false;
41611
+ if (opts.additive) {
41612
+ for (const [key2, { entry }] of wanted) {
41613
+ if (cache.docs[key2] !== entry) docsChanged = true;
41614
+ cache.docs[key2] = entry;
41615
+ }
41616
+ } else {
41617
+ const referenced = /* @__PURE__ */ new Set();
41618
+ const newDocs = {};
41619
+ for (const [key2, { entry }] of wanted) {
41620
+ newDocs[key2] = entry;
41621
+ for (const h of entry.hashes) referenced.add(h);
41622
+ }
41623
+ const newVectors = {};
41624
+ for (const [h, v] of Object.entries(cache.vectors)) {
41625
+ if (referenced.has(h)) newVectors[h] = v;
41626
+ else evicted++;
41627
+ }
41628
+ docsChanged = Object.keys(newDocs).length !== Object.keys(cache.docs).length || Object.keys(newDocs).some((k) => cache.docs[k] !== newDocs[k]);
41629
+ cache.docs = newDocs;
41630
+ cache.vectors = newVectors;
41631
+ }
41328
41632
  if (embeddedCount > 0 || evicted > 0 || docsChanged) saveCache(contextRoot, cache);
41329
41633
  const chunks = [];
41330
41634
  let dims = 0;
@@ -41338,12 +41642,13 @@ async function refreshEmbeddings(contextRoot, corpus, embed = embedPassages, opt
41338
41642
  chunks.push({ docKey: key2, seq, hash, vector });
41339
41643
  }
41340
41644
  }
41645
+ const distinctHashes = new Set(chunks.map((c) => c.hash)).size;
41341
41646
  return {
41342
41647
  index: { chunks, dims },
41343
- stats: { embedded: embeddedCount, reused: referenced.size - embeddedCount, evicted }
41648
+ stats: { embedded: embeddedCount, reused: Math.max(0, distinctHashes - embeddedCount), evicted }
41344
41649
  };
41345
41650
  }
41346
- var CACHE_VERSION, CACHE_DIR, CACHE_FILE;
41651
+ var CACHE_VERSION, CACHE_DIR, CACHE_FILE, usableMemo, USABLE_MEMO_MAX;
41347
41652
  var init_store = __esm({
41348
41653
  "src/lib/embeddings/store.ts"() {
41349
41654
  "use strict";
@@ -41353,6 +41658,8 @@ var init_store = __esm({
41353
41658
  CACHE_VERSION = 1;
41354
41659
  CACHE_DIR = ".embeddings";
41355
41660
  CACHE_FILE = "cache.json";
41661
+ usableMemo = /* @__PURE__ */ new Map();
41662
+ USABLE_MEMO_MAX = 32;
41356
41663
  }
41357
41664
  });
41358
41665
 
@@ -41534,7 +41841,7 @@ var init_sleep_consolidation = __esm({
41534
41841
  });
41535
41842
 
41536
41843
  // src/cli/commands/sleep.ts
41537
- import { existsSync as existsSync54 } from "fs";
41844
+ import { existsSync as existsSync55 } from "fs";
41538
41845
  import { join as join56, dirname as dirname28 } from "path";
41539
41846
  function getSleepPath(root) {
41540
41847
  return join56(root, "state", ".sleep.json");
@@ -41565,7 +41872,7 @@ function freshDefaults() {
41565
41872
  }
41566
41873
  function readSleepState(root) {
41567
41874
  const filePath = getSleepPath(root);
41568
- if (!existsSync54(filePath)) {
41875
+ if (!existsSync55(filePath)) {
41569
41876
  return freshDefaults();
41570
41877
  }
41571
41878
  try {
@@ -41574,7 +41881,7 @@ function readSleepState(root) {
41574
41881
  const historyPath = getSleepHistoryPath(root);
41575
41882
  let existing = [];
41576
41883
  try {
41577
- if (existsSync54(historyPath)) {
41884
+ if (existsSync55(historyPath)) {
41578
41885
  existing = readJsonArray(historyPath);
41579
41886
  }
41580
41887
  } catch {
@@ -41601,7 +41908,7 @@ function readSleepState(root) {
41601
41908
  }
41602
41909
  function readSleepHistory(root) {
41603
41910
  const filePath = getSleepHistoryPath(root);
41604
- if (!existsSync54(filePath)) return [];
41911
+ if (!existsSync55(filePath)) return [];
41605
41912
  try {
41606
41913
  return readJsonArray(filePath);
41607
41914
  } catch {
@@ -41858,6 +42165,11 @@ function registerSleepCommand(program2) {
41858
42165
  ${source_default.dim(`${history.length} total consolidation(s)`)}`);
41859
42166
  });
41860
42167
  }
42168
+ function resolveRecallMode(root) {
42169
+ const env2 = process.env.DREAMCONTEXT_RECALL_MODE;
42170
+ if (env2 && RECALL_MODES.includes(env2)) return env2;
42171
+ return readSleepState(root).recall_mode ?? "haiku";
42172
+ }
41861
42173
  function registerRecallCommand(program2) {
41862
42174
  const recall = program2.command("recall").description("Control memory recall mode (haiku / raw / hybrid / off)");
41863
42175
  recall.command("status").description("Show current recall mode").action(() => {
@@ -41902,6 +42214,7 @@ function registerRecallCommand(program2) {
41902
42214
  success("Recall mode set to hybrid \u2014 BM25 + dense RRF fusion (experimental; falls back to BM25 if the embedding model is unavailable)");
41903
42215
  });
41904
42216
  }
42217
+ var RECALL_MODES;
41905
42218
  var init_sleep = __esm({
41906
42219
  "src/cli/commands/sleep.ts"() {
41907
42220
  "use strict";
@@ -41920,11 +42233,12 @@ var init_sleep = __esm({
41920
42233
  init_recall();
41921
42234
  init_store();
41922
42235
  init_sleep_consolidation();
42236
+ RECALL_MODES = ["haiku", "raw", "hybrid", "off"];
41923
42237
  }
41924
42238
  });
41925
42239
 
41926
42240
  // src/cli/commands/knowledge.ts
41927
- import { existsSync as existsSync55 } from "fs";
42241
+ import { existsSync as existsSync56 } from "fs";
41928
42242
  import { join as join57 } from "path";
41929
42243
  function getKnowledgeDir() {
41930
42244
  const root = ensureContextRoot();
@@ -41936,7 +42250,7 @@ function registerKnowledgeCommand(program2) {
41936
42250
  const dir = getKnowledgeDir();
41937
42251
  const slug = slugify(name);
41938
42252
  const filePath = join57(dir, `${slug}.md`);
41939
- if (existsSync55(filePath)) {
42253
+ if (existsSync56(filePath)) {
41940
42254
  error(`Knowledge file already exists: ${slug}.md`);
41941
42255
  return;
41942
42256
  }
@@ -42076,7 +42390,7 @@ ${content || "(Content to be added)"}
42076
42390
  knowledge.command("touch").argument("<slug>", "Knowledge file slug").description("Record access to a knowledge file (for decay tracking)").action((slug) => {
42077
42391
  const root = ensureContextRoot();
42078
42392
  const knowledgePath2 = join57(root, "knowledge", `${slug}.md`);
42079
- if (!existsSync55(knowledgePath2)) {
42393
+ if (!existsSync56(knowledgePath2)) {
42080
42394
  error(`Knowledge file not found: ${slug}.md`);
42081
42395
  return;
42082
42396
  }
@@ -42131,7 +42445,7 @@ var init_member_match = __esm({
42131
42445
  });
42132
42446
 
42133
42447
  // src/lib/objectives-store.ts
42134
- import { existsSync as existsSync56, mkdirSync as mkdirSync32, unlinkSync as unlinkSync7 } from "fs";
42448
+ import { existsSync as existsSync57, mkdirSync as mkdirSync32, unlinkSync as unlinkSync7 } from "fs";
42135
42449
  import { join as join58, basename as basename14 } from "path";
42136
42450
  function objectivesDir(contextRoot) {
42137
42451
  return join58(contextRoot, "core", "objectives");
@@ -42230,7 +42544,7 @@ function readObjectiveFile(filePath) {
42230
42544
  }
42231
42545
  function listObjectives(contextRoot) {
42232
42546
  const dir = objectivesDir(contextRoot);
42233
- if (!existsSync56(dir)) return [];
42547
+ if (!existsSync57(dir)) return [];
42234
42548
  const files = import_fast_glob12.default.sync("*.md", { cwd: dir, absolute: true }).sort();
42235
42549
  const out = [];
42236
42550
  for (const file of files) {
@@ -42243,7 +42557,7 @@ function listObjectives(contextRoot) {
42243
42557
  }
42244
42558
  function getObjective(contextRoot, slug) {
42245
42559
  const path2 = objectivePath(contextRoot, slug);
42246
- if (!isSafeObjectiveSlug(slug) || !existsSync56(path2)) return null;
42560
+ if (!isSafeObjectiveSlug(slug) || !existsSync57(path2)) return null;
42247
42561
  try {
42248
42562
  return readObjectiveFile(path2);
42249
42563
  } catch {
@@ -42286,7 +42600,7 @@ function createObjective(contextRoot, input2) {
42286
42600
  );
42287
42601
  }
42288
42602
  const path2 = objectivePath(contextRoot, slug);
42289
- if (existsSync56(path2)) {
42603
+ if (existsSync57(path2)) {
42290
42604
  throw new ObjectiveError(`Objective already exists: ${slug}`);
42291
42605
  }
42292
42606
  validateDateRange(input2.start_date, input2.target_date);
@@ -42391,7 +42705,7 @@ function deleteObjective(contextRoot, slug) {
42391
42705
  }
42392
42706
  const unhealedTasks = [];
42393
42707
  const stateDir = join58(contextRoot, "state");
42394
- if (existsSync56(stateDir)) {
42708
+ if (existsSync57(stateDir)) {
42395
42709
  for (const file of import_fast_glob12.default.sync("*.md", { cwd: stateDir, absolute: true })) {
42396
42710
  let objectives;
42397
42711
  try {
@@ -43410,7 +43724,7 @@ var init_tasks = __esm({
43410
43724
  });
43411
43725
 
43412
43726
  // src/lib/roadmap-model.ts
43413
- import { existsSync as existsSync57 } from "fs";
43727
+ import { existsSync as existsSync58 } from "fs";
43414
43728
  import { join as join60, basename as basename16 } from "path";
43415
43729
  function strOrNull3(v) {
43416
43730
  if (v === void 0 || v === null) return null;
@@ -43419,7 +43733,7 @@ function strOrNull3(v) {
43419
43733
  }
43420
43734
  function loadTaskRefs(contextRoot) {
43421
43735
  const stateDir = join60(contextRoot, "state");
43422
- if (!existsSync57(stateDir)) return [];
43736
+ if (!existsSync58(stateDir)) return [];
43423
43737
  const files = import_fast_glob14.default.sync("*.md", { cwd: stateDir, absolute: true }).sort();
43424
43738
  const out = [];
43425
43739
  for (const file of files) {
@@ -43948,7 +44262,7 @@ var init_roadmap = __esm({
43948
44262
  });
43949
44263
 
43950
44264
  // src/lib/lab/required-credentials.ts
43951
- import { existsSync as existsSync59, mkdirSync as mkdirSync34, writeFileSync as writeFileSync41 } from "fs";
44265
+ import { existsSync as existsSync60, mkdirSync as mkdirSync34, writeFileSync as writeFileSync41 } from "fs";
43952
44266
  import { join as join62 } from "path";
43953
44267
  function requiredCredentialKeys(manifest) {
43954
44268
  const keys = /* @__PURE__ */ new Set();
@@ -43980,7 +44294,7 @@ function collectRequiredCredentialKeys(contextRoot) {
43980
44294
  function writeCredentialsExample(contextRoot) {
43981
44295
  const keys = collectRequiredCredentialKeys(contextRoot);
43982
44296
  const path2 = join62(contextRoot, "lab", "credentials.example.json");
43983
- if (keys.length === 0 && !existsSync59(path2)) return;
44297
+ if (keys.length === 0 && !existsSync60(path2)) return;
43984
44298
  const example = {};
43985
44299
  for (const key2 of keys) example[key2] = "";
43986
44300
  mkdirSync34(join62(contextRoot, "lab"), { recursive: true });
@@ -44012,7 +44326,7 @@ var init_types2 = __esm({
44012
44326
  });
44013
44327
 
44014
44328
  // src/lib/lab/store.ts
44015
- import { existsSync as existsSync60, mkdirSync as mkdirSync35, readFileSync as readFileSync40, renameSync as renameSync13, writeFileSync as writeFileSync42 } from "fs";
44329
+ import { existsSync as existsSync61, mkdirSync as mkdirSync35, readFileSync as readFileSync40, renameSync as renameSync13, writeFileSync as writeFileSync42 } from "fs";
44016
44330
  import { join as join63, basename as basename17 } from "path";
44017
44331
  function labDir(contextRoot) {
44018
44332
  return join63(contextRoot, "lab");
@@ -44143,7 +44457,7 @@ function readInsightFile(filePath) {
44143
44457
  }
44144
44458
  function listInsights(contextRoot) {
44145
44459
  const dir = insightsDir(contextRoot);
44146
- if (!existsSync60(dir)) return [];
44460
+ if (!existsSync61(dir)) return [];
44147
44461
  const files = import_fast_glob15.default.sync("*.md", { cwd: dir, absolute: true }).sort();
44148
44462
  const out = [];
44149
44463
  for (const file of files) {
@@ -44156,7 +44470,7 @@ function listInsights(contextRoot) {
44156
44470
  }
44157
44471
  function getInsight(contextRoot, slug) {
44158
44472
  const path2 = insightPath(contextRoot, slug);
44159
- if (!isSafeInsightSlug(slug) || !existsSync60(path2)) return null;
44473
+ if (!isSafeInsightSlug(slug) || !existsSync61(path2)) return null;
44160
44474
  try {
44161
44475
  return readInsightFile(path2);
44162
44476
  } catch {
@@ -44165,7 +44479,7 @@ function getInsight(contextRoot, slug) {
44165
44479
  }
44166
44480
  function readCache(contextRoot, slug) {
44167
44481
  const path2 = cachePath3(contextRoot, slug);
44168
- if (!existsSync60(path2)) return null;
44482
+ if (!existsSync61(path2)) return null;
44169
44483
  try {
44170
44484
  const parsed = JSON.parse(readFileSync40(path2, "utf-8"));
44171
44485
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
@@ -44202,7 +44516,7 @@ function createInsight(contextRoot, input2) {
44202
44516
  validateManifestForWrite(input2);
44203
44517
  const slug = input2.slug.trim();
44204
44518
  const path2 = insightPath(contextRoot, slug);
44205
- if (existsSync60(path2)) throw new LabError(`Insight already exists: ${slug}`);
44519
+ if (existsSync61(path2)) throw new LabError(`Insight already exists: ${slug}`);
44206
44520
  const adapter = input2.adapter ?? "http";
44207
44521
  const source = adapter === "script" ? { adapter: "script", script: { file: `scripts/${slug}.mjs` } } : {
44208
44522
  adapter: "http",
@@ -44295,14 +44609,14 @@ var init_store2 = __esm({
44295
44609
  });
44296
44610
 
44297
44611
  // src/lib/lab/credentials.ts
44298
- import { chmodSync as chmodSync5, existsSync as existsSync61, mkdirSync as mkdirSync36, readFileSync as readFileSync41, writeFileSync as writeFileSync43 } from "fs";
44612
+ import { chmodSync as chmodSync5, existsSync as existsSync62, mkdirSync as mkdirSync36, readFileSync as readFileSync41, writeFileSync as writeFileSync43 } from "fs";
44299
44613
  import { join as join64 } from "path";
44300
44614
  function credentialsPath(contextRoot) {
44301
44615
  return join64(contextRoot, "lab", "credentials.json");
44302
44616
  }
44303
44617
  function readCredentials(contextRoot) {
44304
44618
  const path2 = credentialsPath(contextRoot);
44305
- if (!existsSync61(path2)) return {};
44619
+ if (!existsSync62(path2)) return {};
44306
44620
  try {
44307
44621
  const parsed = JSON.parse(readFileSync41(path2, "utf-8"));
44308
44622
  if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return {};
@@ -44719,7 +45033,7 @@ var init_rollup = __esm({
44719
45033
 
44720
45034
  // src/lib/lab/sync.ts
44721
45035
  import { createHash as createHash5 } from "crypto";
44722
- import { existsSync as existsSync62, readFileSync as readFileSync42 } from "fs";
45036
+ import { existsSync as existsSync63, readFileSync as readFileSync42 } from "fs";
44723
45037
  function appendHistory(prior, event) {
44724
45038
  const bounded = event.error && event.error.length > HISTORY_ERROR_MAX ? { ...event, error: `${event.error.slice(0, HISTORY_ERROR_MAX)}\u2026` } : event;
44725
45039
  const priorHistory = Array.isArray(prior?.history) ? prior.history : [];
@@ -44745,7 +45059,7 @@ function computeScriptHash(manifest) {
44745
45059
  if (!manifest.source || manifest.source.adapter !== "script") return null;
44746
45060
  try {
44747
45061
  const abs = scriptFilePath(manifest);
44748
- if (!existsSync62(abs)) return null;
45062
+ if (!existsSync63(abs)) return null;
44749
45063
  return createHash5("sha256").update(readFileSync42(abs)).digest("hex");
44750
45064
  } catch {
44751
45065
  return null;
@@ -45104,7 +45418,7 @@ var init_lab = __esm({
45104
45418
  });
45105
45419
 
45106
45420
  // src/cli/commands/update.ts
45107
- import { existsSync as existsSync63, readdirSync as readdirSync12, rmSync as rmSync8 } from "fs";
45421
+ import { existsSync as existsSync64, readdirSync as readdirSync12, rmSync as rmSync8 } from "fs";
45108
45422
  import { join as join65 } from "path";
45109
45423
  function buildUpdateSummary(input2) {
45110
45424
  const { platforms, installedCount, packs, removed, setupVersion } = input2;
@@ -45128,7 +45442,7 @@ function buildUpdateSummary(input2) {
45128
45442
  }
45129
45443
  function detectInstalledPlatforms(projectRoot) {
45130
45444
  return SUPPORTED_PLATFORMS.filter(
45131
- (p) => existsSync63(join65(platformSkillRoot(projectRoot, p), "dreamcontext", "SKILL.md"))
45445
+ (p) => existsSync64(join65(platformSkillRoot(projectRoot, p), "dreamcontext", "SKILL.md"))
45132
45446
  );
45133
45447
  }
45134
45448
  function detectInstalledPacks(projectRoot, platforms) {
@@ -45141,11 +45455,11 @@ function detectInstalledPacks(projectRoot, platforms) {
45141
45455
  const found = /* @__PURE__ */ new Set();
45142
45456
  for (const platform2 of platforms) {
45143
45457
  const root = platformSkillRoot(projectRoot, platform2);
45144
- if (!existsSync63(root)) continue;
45458
+ if (!existsSync64(root)) continue;
45145
45459
  for (const name of readdirSync12(root)) {
45146
45460
  if (name === "dreamcontext") continue;
45147
45461
  if (!knownNames.has(name)) continue;
45148
- if (existsSync63(join65(root, name, "SKILL.md"))) found.add(name);
45462
+ if (existsSync64(join65(root, name, "SKILL.md"))) found.add(name);
45149
45463
  }
45150
45464
  }
45151
45465
  return [...found].sort();
@@ -45353,11 +45667,11 @@ var init_update = __esm({
45353
45667
  });
45354
45668
 
45355
45669
  // src/lib/core-index.ts
45356
- import { existsSync as existsSync64 } from "fs";
45670
+ import { existsSync as existsSync65 } from "fs";
45357
45671
  import { join as join66, basename as basename18 } from "path";
45358
45672
  function buildCoreIndex(contextRoot) {
45359
45673
  const coreDir = join66(contextRoot, "core");
45360
- if (!existsSync64(coreDir)) return [];
45674
+ if (!existsSync65(coreDir)) return [];
45361
45675
  const files = import_fast_glob16.default.sync("[3-9]*", { cwd: coreDir, absolute: true });
45362
45676
  const entries = [];
45363
45677
  for (const file of files) {
@@ -45499,7 +45813,7 @@ var init_secrets2 = __esm({
45499
45813
 
45500
45814
  // src/lib/marketing/store.ts
45501
45815
  import {
45502
- existsSync as existsSync65,
45816
+ existsSync as existsSync66,
45503
45817
  mkdirSync as mkdirSync37,
45504
45818
  openSync,
45505
45819
  closeSync,
@@ -45557,7 +45871,7 @@ function pidAlive(pid) {
45557
45871
  function acquireLock() {
45558
45872
  const lockPath = MARKETING_PATHS.lockFile();
45559
45873
  mkdirSync37(marketingRoot(), { recursive: true });
45560
- if (existsSync65(lockPath)) {
45874
+ if (existsSync66(lockPath)) {
45561
45875
  const heldRaw = readFileSync43(lockPath, "utf8").trim();
45562
45876
  const heldPid = Number.parseInt(heldRaw, 10);
45563
45877
  if (pidAlive(heldPid)) {
@@ -45574,7 +45888,7 @@ function acquireLock() {
45574
45888
  } catch (e) {
45575
45889
  const code = e.code;
45576
45890
  if (code === "EEXIST") {
45577
- const heldRaw = existsSync65(lockPath) ? readFileSync43(lockPath, "utf8").trim() : "?";
45891
+ const heldRaw = existsSync66(lockPath) ? readFileSync43(lockPath, "utf8").trim() : "?";
45578
45892
  throw new LockBusyError(Number.parseInt(heldRaw, 10) || -1);
45579
45893
  }
45580
45894
  throw e;
@@ -45654,7 +45968,7 @@ function appendIndex(runId, verb, status) {
45654
45968
  `;
45655
45969
  let header2 = "";
45656
45970
  let body = "";
45657
- if (existsSync65(path2)) {
45971
+ if (existsSync66(path2)) {
45658
45972
  body = readFileSync43(path2, "utf8");
45659
45973
  } else {
45660
45974
  header2 = "# Marketing runs (LIFO)\n\n";
@@ -45685,7 +45999,7 @@ var init_store3 = __esm({
45685
45999
  });
45686
46000
 
45687
46001
  // src/lib/marketing/cohort.ts
45688
- import { existsSync as existsSync66, readFileSync as readFileSync44, readdirSync as readdirSync14 } from "fs";
46002
+ import { existsSync as existsSync67, readFileSync as readFileSync44, readdirSync as readdirSync14 } from "fs";
45689
46003
  import { join as join69 } from "path";
45690
46004
  function newCohortId() {
45691
46005
  return `coh_${idgen()}`;
@@ -45699,7 +46013,7 @@ function cohortPaths(id) {
45699
46013
  }
45700
46014
  function loadCohort(id) {
45701
46015
  const { json } = cohortPaths(id);
45702
- if (!existsSync66(json)) return null;
46016
+ if (!existsSync67(json)) return null;
45703
46017
  try {
45704
46018
  return JSON.parse(readFileSync44(json, "utf8"));
45705
46019
  } catch {
@@ -45708,7 +46022,7 @@ function loadCohort(id) {
45708
46022
  }
45709
46023
  function listCohorts() {
45710
46024
  const dir = MARKETING_PATHS.cohortsDir();
45711
- if (!existsSync66(dir)) return [];
46025
+ if (!existsSync67(dir)) return [];
45712
46026
  const files = readdirSync14(dir).filter((f) => f.endsWith(".json"));
45713
46027
  const cohorts = [];
45714
46028
  for (const f of files) {
@@ -45766,7 +46080,7 @@ var init_cohort = __esm({
45766
46080
 
45767
46081
  // src/lib/marketing/learnings.ts
45768
46082
  import {
45769
- existsSync as existsSync67,
46083
+ existsSync as existsSync68,
45770
46084
  mkdirSync as mkdirSync38,
45771
46085
  readFileSync as readFileSync45,
45772
46086
  writeFileSync as writeFileSync45,
@@ -45788,7 +46102,7 @@ function todayDateString(now = /* @__PURE__ */ new Date()) {
45788
46102
  }
45789
46103
  function loadIndex() {
45790
46104
  const path2 = MARKETING_PATHS.learningsIndex();
45791
- if (!existsSync67(path2)) {
46105
+ if (!existsSync68(path2)) {
45792
46106
  return { version: INDEX_VERSION, entries: [] };
45793
46107
  }
45794
46108
  try {
@@ -45806,7 +46120,7 @@ function saveIndex(index) {
45806
46120
  }
45807
46121
  function loadByDate(date) {
45808
46122
  const path2 = MARKETING_PATHS.learningsFile(date);
45809
- if (!existsSync67(path2)) return null;
46123
+ if (!existsSync68(path2)) return null;
45810
46124
  return readFileSync45(path2, "utf8");
45811
46125
  }
45812
46126
  function renderEntryBlock(entry, body) {
@@ -45842,7 +46156,7 @@ function ensureDailyHeader(date, existing) {
45842
46156
  }
45843
46157
  function appendToDayFile(entry, body) {
45844
46158
  const path2 = MARKETING_PATHS.learningsFile(entry.date_file);
45845
- const existing = existsSync67(path2) ? readFileSync45(path2, "utf8") : null;
46159
+ const existing = existsSync68(path2) ? readFileSync45(path2, "utf8") : null;
45846
46160
  const base = ensureDailyHeader(entry.date_file, existing);
45847
46161
  const block = renderEntryBlock(entry, body);
45848
46162
  const next = existing && existing.startsWith("# Marketing learnings") ? existing.endsWith("\n") ? existing + block : existing + "\n" + block : base + block;
@@ -45850,7 +46164,7 @@ function appendToDayFile(entry, body) {
45850
46164
  }
45851
46165
  function rewriteDayFileForStatusUpdate(oldEntry, newEntry) {
45852
46166
  const path2 = MARKETING_PATHS.learningsFile(oldEntry.date_file);
45853
- if (!existsSync67(path2)) return;
46167
+ if (!existsSync68(path2)) return;
45854
46168
  const text = readFileSync45(path2, "utf8");
45855
46169
  const re = new RegExp(
45856
46170
  `<!-- entry ([^>]*?id=${escapeRegExp(oldEntry.id)}[^>]*) -->`
@@ -45959,10 +46273,10 @@ var init_learnings = __esm({
45959
46273
  });
45960
46274
 
45961
46275
  // src/lib/marketing/snapshot.ts
45962
- import { existsSync as existsSync68, readFileSync as readFileSync46 } from "fs";
46276
+ import { existsSync as existsSync69, readFileSync as readFileSync46 } from "fs";
45963
46277
  function buildMarketingSnapshot(opts = {}) {
45964
46278
  const root = marketingRootIfExists();
45965
- if (!root || !existsSync68(root)) return null;
46279
+ if (!root || !existsSync69(root)) return null;
45966
46280
  const now = opts.now ?? /* @__PURE__ */ new Date();
45967
46281
  const lines = ["## Marketing\n"];
45968
46282
  const cohorts = listCohorts();
@@ -46019,7 +46333,7 @@ function cohortHypothesisLine(c) {
46019
46333
  }
46020
46334
  function readLastInsightsPull() {
46021
46335
  const idxPath = MARKETING_PATHS.insightsDir() + "/_index.json";
46022
- if (!existsSync68(idxPath)) return null;
46336
+ if (!existsSync69(idxPath)) return null;
46023
46337
  try {
46024
46338
  const raw = JSON.parse(readFileSync46(idxPath, "utf8"));
46025
46339
  return raw.updated_at && raw.updated_at !== "1970-01-01T00:00:00Z" ? raw.updated_at : null;
@@ -46119,7 +46433,7 @@ var init_setup_drift = __esm({
46119
46433
  });
46120
46434
 
46121
46435
  // src/lib/asset-drift-cache.ts
46122
- import { existsSync as existsSync69, readFileSync as readFileSync47, writeFileSync as writeFileSync46, mkdirSync as mkdirSync39 } from "fs";
46436
+ import { existsSync as existsSync70, readFileSync as readFileSync47, writeFileSync as writeFileSync46, mkdirSync as mkdirSync39 } from "fs";
46123
46437
  import { join as join70, dirname as dirname35 } from "path";
46124
46438
  function assetDriftCachePath(contextRoot) {
46125
46439
  return join70(contextRoot, "state", ".asset-drift.json");
@@ -46127,7 +46441,7 @@ function assetDriftCachePath(contextRoot) {
46127
46441
  function readAssetDriftCache(contextRoot) {
46128
46442
  try {
46129
46443
  const p = assetDriftCachePath(contextRoot);
46130
- if (!existsSync69(p)) return null;
46444
+ if (!existsSync70(p)) return null;
46131
46445
  const parsed = JSON.parse(readFileSync47(p, "utf-8"));
46132
46446
  if (!parsed || typeof parsed.cliVersion !== "string" || typeof parsed.setupVersion !== "string" || typeof parsed.usedAssetsChanged !== "boolean") {
46133
46447
  return null;
@@ -46267,14 +46581,14 @@ var init_federation_recall = __esm({
46267
46581
  });
46268
46582
 
46269
46583
  // src/lib/federation-peer-summary.ts
46270
- import { existsSync as existsSync70, mkdirSync as mkdirSync40, readFileSync as readFileSync48, writeFileSync as writeFileSync47 } from "fs";
46584
+ import { existsSync as existsSync71, mkdirSync as mkdirSync40, readFileSync as readFileSync48, writeFileSync as writeFileSync47 } from "fs";
46271
46585
  import { dirname as dirname37, join as join71 } from "path";
46272
46586
  function peerSummaryCachePath(contextRoot) {
46273
46587
  return join71(contextRoot, CACHE_REL_PATH2);
46274
46588
  }
46275
46589
  function readPeerSummaryCache(contextRoot) {
46276
46590
  const path2 = peerSummaryCachePath(contextRoot);
46277
- if (!existsSync70(path2)) return null;
46591
+ if (!existsSync71(path2)) return null;
46278
46592
  try {
46279
46593
  const parsed = JSON.parse(readFileSync48(path2, "utf-8"));
46280
46594
  if (!parsed || typeof parsed !== "object" || !Array.isArray(parsed.peers)) return null;
@@ -46294,7 +46608,8 @@ function sanitizePeer(raw) {
46294
46608
  whatItIs: typeof raw.whatItIs === "string" ? raw.whatItIs : "",
46295
46609
  lastActivity: strArr(raw.lastActivity),
46296
46610
  activeTask: typeof raw.activeTask === "string" ? raw.activeTask : "",
46297
- topTags: strArr(raw.topTags)
46611
+ topTags: strArr(raw.topTags),
46612
+ pinnedKnowledge: strArr(raw.pinnedKnowledge)
46298
46613
  };
46299
46614
  }
46300
46615
  function buildPeerSummary(peerRoot, peerName) {
@@ -46303,12 +46618,13 @@ function buildPeerSummary(peerRoot, peerName) {
46303
46618
  whatItIs: readWhatItIs(peerRoot),
46304
46619
  lastActivity: readLastActivity(peerRoot),
46305
46620
  activeTask: readActiveTask(peerRoot),
46306
- topTags: readTopTags(peerRoot)
46621
+ topTags: readTopTags(peerRoot),
46622
+ pinnedKnowledge: readPinnedTitles(peerRoot)
46307
46623
  };
46308
46624
  }
46309
46625
  function readWhatItIs(peerRoot) {
46310
46626
  const soulPath = join71(peerRoot, "core", "0.soul.md");
46311
- if (!existsSync70(soulPath)) return "";
46627
+ if (!existsSync71(soulPath)) return "";
46312
46628
  try {
46313
46629
  const { data, content } = readFrontmatter(soulPath);
46314
46630
  const name = typeof data.name === "string" ? data.name : "";
@@ -46326,7 +46642,7 @@ function readWhatItIs(peerRoot) {
46326
46642
  }
46327
46643
  function readLastActivity(peerRoot) {
46328
46644
  const path2 = join71(peerRoot, "core", "CHANGELOG.json");
46329
- if (!existsSync70(path2)) return [];
46645
+ if (!existsSync71(path2)) return [];
46330
46646
  try {
46331
46647
  const entries = readJsonArray(path2);
46332
46648
  const out = [];
@@ -46345,7 +46661,7 @@ function readLastActivity(peerRoot) {
46345
46661
  }
46346
46662
  function readActiveTask(peerRoot) {
46347
46663
  const stateDir = join71(peerRoot, "state");
46348
- if (!existsSync70(stateDir)) return "";
46664
+ if (!existsSync71(stateDir)) return "";
46349
46665
  let files;
46350
46666
  try {
46351
46667
  files = import_fast_glob17.default.sync("*.md", { cwd: stateDir, absolute: true });
@@ -46375,7 +46691,7 @@ function readTopTags(peerRoot) {
46375
46691
  const counts = /* @__PURE__ */ new Map();
46376
46692
  const dirs = [join71(peerRoot, "knowledge"), join71(peerRoot, "core", "features")];
46377
46693
  for (const dir of dirs) {
46378
- if (!existsSync70(dir)) continue;
46694
+ if (!existsSync71(dir)) continue;
46379
46695
  let files;
46380
46696
  try {
46381
46697
  files = import_fast_glob17.default.sync("*.md", { cwd: dir, absolute: true });
@@ -46396,6 +46712,32 @@ function readTopTags(peerRoot) {
46396
46712
  }
46397
46713
  return Array.from(counts.entries()).sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, MAX_TAGS).map(([t]) => t);
46398
46714
  }
46715
+ function readPinnedTitles(peerRoot) {
46716
+ const seen = /* @__PURE__ */ new Set();
46717
+ const globs = [
46718
+ [join71(peerRoot, "knowledge"), "**/*.md"],
46719
+ [join71(peerRoot, "core", "features"), "*.md"]
46720
+ ];
46721
+ for (const [dir, pattern] of globs) {
46722
+ if (!existsSync71(dir)) continue;
46723
+ let files;
46724
+ try {
46725
+ files = import_fast_glob17.default.sync(pattern, { cwd: dir, absolute: true });
46726
+ } catch {
46727
+ continue;
46728
+ }
46729
+ for (const file of files) {
46730
+ try {
46731
+ const { data } = readFrontmatter(file);
46732
+ if (data.pinned !== true) continue;
46733
+ const title = String(data.name ?? data.title ?? "").trim();
46734
+ if (title) seen.add(title);
46735
+ } catch {
46736
+ }
46737
+ }
46738
+ }
46739
+ return Array.from(seen).sort((a, b) => a.localeCompare(b)).slice(0, MAX_PINNED);
46740
+ }
46399
46741
  function refreshPeerSummaries(contextRoot, home) {
46400
46742
  const { name, target } = currentVaultTarget(dirname37(contextRoot), home);
46401
46743
  const targets = resolveConnectedVaults(target, contextRoot, home).filter(
@@ -46420,7 +46762,7 @@ function writePeerSummaryCache(contextRoot, cache) {
46420
46762
  mkdirSync40(dirname37(path2), { recursive: true });
46421
46763
  writeFileSync47(path2, JSON.stringify(cache, null, 2) + "\n", "utf-8");
46422
46764
  }
46423
- var import_fast_glob17, CACHE_REL_PATH2, MAX_ACTIVITY, MAX_TAGS, WHAT_IT_IS_CHARS;
46765
+ var import_fast_glob17, CACHE_REL_PATH2, MAX_ACTIVITY, MAX_TAGS, MAX_PINNED, WHAT_IT_IS_CHARS;
46424
46766
  var init_federation_peer_summary = __esm({
46425
46767
  "src/lib/federation-peer-summary.ts"() {
46426
46768
  "use strict";
@@ -46432,6 +46774,7 @@ var init_federation_peer_summary = __esm({
46432
46774
  CACHE_REL_PATH2 = "state/.peer-summaries.json";
46433
46775
  MAX_ACTIVITY = 2;
46434
46776
  MAX_TAGS = 5;
46777
+ MAX_PINNED = 5;
46435
46778
  WHAT_IT_IS_CHARS = 200;
46436
46779
  }
46437
46780
  });
@@ -46541,7 +46884,7 @@ var init_snapshot_budget = __esm({
46541
46884
  });
46542
46885
 
46543
46886
  // src/cli/commands/snapshot.ts
46544
- import { readFileSync as readFileSync49, existsSync as existsSync71, statSync as statSync10 } from "fs";
46887
+ import { readFileSync as readFileSync49, existsSync as existsSync72, statSync as statSync10 } from "fs";
46545
46888
  import { join as join72, basename as basename20, dirname as dirname38 } from "path";
46546
46889
  function extractFirstParagraph(content) {
46547
46890
  const lines = content.split("\n");
@@ -46577,7 +46920,7 @@ function sortTaskEntriesByActivity(entries) {
46577
46920
  }
46578
46921
  function getActiveTaskEntries(root) {
46579
46922
  const stateDir = join72(root, "state");
46580
- if (!existsSync71(stateDir)) return [];
46923
+ if (!existsSync72(stateDir)) return [];
46581
46924
  const taskFiles = import_fast_glob18.default.sync("*.md", { cwd: stateDir, absolute: true });
46582
46925
  const entries = [];
46583
46926
  const declaredFields = loadTaskOverride(root)?.customFields ?? [];
@@ -46626,14 +46969,14 @@ function getActiveTaskEntries(root) {
46626
46969
  }
46627
46970
  function resolveActiveTaskPath(root) {
46628
46971
  const stateDir = join72(root, "state");
46629
- if (!existsSync71(stateDir)) return null;
46972
+ if (!existsSync72(stateDir)) return null;
46630
46973
  const overridePath = join72(stateDir, ".active-task");
46631
- if (existsSync71(overridePath)) {
46974
+ if (existsSync72(overridePath)) {
46632
46975
  try {
46633
46976
  const slug = readFileSync49(overridePath, "utf-8").trim();
46634
46977
  if (slug) {
46635
46978
  const taskPath = join72(stateDir, `${slug}.md`);
46636
- if (existsSync71(taskPath)) return taskPath;
46979
+ if (existsSync72(taskPath)) return taskPath;
46637
46980
  }
46638
46981
  } catch {
46639
46982
  }
@@ -46677,7 +47020,7 @@ function getActiveProductKnowledge(root) {
46677
47020
  if (!product) return [];
46678
47021
  if (!config.multiProduct.includes(product)) return [];
46679
47022
  const productKnowledgePath = join72(root, "knowledge", "products", `${product}.md`);
46680
- if (!existsSync71(productKnowledgePath)) return [];
47023
+ if (!existsSync72(productKnowledgePath)) return [];
46681
47024
  let raw;
46682
47025
  try {
46683
47026
  raw = readFileSync49(productKnowledgePath, "utf-8");
@@ -46732,7 +47075,7 @@ function getVersionNudge(root) {
46732
47075
  function getMigrationNote(root) {
46733
47076
  try {
46734
47077
  const sleepPath = join72(root, "state", ".sleep.json");
46735
- if (!existsSync71(sleepPath)) return "";
47078
+ if (!existsSync72(sleepPath)) return "";
46736
47079
  const raw = readFileSync49(sleepPath, "utf-8");
46737
47080
  const parsed = JSON.parse(raw);
46738
47081
  if (!parsed || !Array.isArray(parsed.pendingMigrationNotices) || parsed.pendingMigrationNotices.length === 0) {
@@ -46909,14 +47252,14 @@ function generateSnapshot(rootOverride) {
46909
47252
  }
46910
47253
  };
46911
47254
  const soulPath = join72(root, "core", "0.soul.md");
46912
- if (existsSync71(soulPath)) {
47255
+ if (existsSync72(soulPath)) {
46913
47256
  const content = readFileSync49(soulPath, "utf-8").trim();
46914
47257
  parts.push("## Soul (Agent Identity, Principles, Rules)\n");
46915
47258
  parts.push(content);
46916
47259
  parts.push("");
46917
47260
  }
46918
47261
  const userPath = join72(root, "core", "1.user.md");
46919
- if (existsSync71(userPath)) {
47262
+ if (existsSync72(userPath)) {
46920
47263
  const content = readFileSync49(userPath, "utf-8").trim();
46921
47264
  parts.push("## User (Preferences, Project Details, Rules)\n");
46922
47265
  parts.push(content);
@@ -46931,7 +47274,7 @@ function generateSnapshot(rootOverride) {
46931
47274
  flush("task-override", { neverEvict: true });
46932
47275
  }
46933
47276
  const memoryPath = join72(root, "core", "2.memory.md");
46934
- if (existsSync71(memoryPath)) {
47277
+ if (existsSync72(memoryPath)) {
46935
47278
  const content = readFileSync49(memoryPath, "utf-8").trim();
46936
47279
  if (content) {
46937
47280
  parts.push("## Memory (Technical Decisions, Known Issues, Session Log)\n");
@@ -46998,7 +47341,7 @@ function generateSnapshot(rootOverride) {
46998
47341
  const taskNames = [];
46999
47342
  const taskTags = [];
47000
47343
  const stateDir = join72(root, "state");
47001
- if (existsSync71(stateDir)) {
47344
+ if (existsSync72(stateDir)) {
47002
47345
  const taskFiles = import_fast_glob18.default.sync("*.md", { cwd: stateDir, absolute: true });
47003
47346
  for (const file of taskFiles) {
47004
47347
  try {
@@ -47041,7 +47384,7 @@ function generateSnapshot(rootOverride) {
47041
47384
  return authors.length > 0 ? ` \u2014 by ${authors.join(", ")}` : "";
47042
47385
  };
47043
47386
  const changelogPath = join72(root, "core", "CHANGELOG.json");
47044
- if (existsSync71(changelogPath)) {
47387
+ if (existsSync72(changelogPath)) {
47045
47388
  try {
47046
47389
  const entries = readJsonArray(changelogPath);
47047
47390
  const tier1 = entries.slice(0, CHANGELOG_TIER1);
@@ -47098,7 +47441,7 @@ function generateSnapshot(rootOverride) {
47098
47441
  }
47099
47442
  }
47100
47443
  const releasesPath = join72(root, "core", "RELEASES.json");
47101
- if (existsSync71(releasesPath)) {
47444
+ if (existsSync72(releasesPath)) {
47102
47445
  try {
47103
47446
  const releases = readJsonArray(releasesPath);
47104
47447
  if (releases.length > 0) {
@@ -47151,7 +47494,7 @@ function generateSnapshot(rootOverride) {
47151
47494
  });
47152
47495
  }
47153
47496
  const featuresPath = featuresDir(root);
47154
- if (existsSync71(featuresPath)) {
47497
+ if (existsSync72(featuresPath)) {
47155
47498
  const featureFiles = import_fast_glob18.default.sync("*.md", { cwd: featuresPath, absolute: true });
47156
47499
  const features = [];
47157
47500
  const featureMeta = [];
@@ -47240,7 +47583,7 @@ function generateSnapshot(rootOverride) {
47240
47583
  const warmEntries = [];
47241
47584
  const activeTaskTags = [];
47242
47585
  const stDir = join72(root, "state");
47243
- if (existsSync71(stDir)) {
47586
+ if (existsSync72(stDir)) {
47244
47587
  const tFiles = import_fast_glob18.default.sync("*.md", { cwd: stDir, absolute: true });
47245
47588
  for (const file of tFiles) {
47246
47589
  try {
@@ -47372,6 +47715,7 @@ ${pendingFederation} legacy peer digest entr${pendingFederation === 1 ? "y" : "i
47372
47715
  for (const act of p.lastActivity) lines.push(` Last: ${act}`);
47373
47716
  if (p.activeTask) lines.push(` In progress: ${p.activeTask}`);
47374
47717
  if (p.topTags.length > 0) lines.push(` Tags: ${p.topTags.join(", ")}`);
47718
+ if (p.pinnedKnowledge.length > 0) lines.push(` Pinned docs: ${p.pinnedKnowledge.join(", ")}`);
47375
47719
  }
47376
47720
  lines.push("");
47377
47721
  lines.push(
@@ -47403,7 +47747,7 @@ function generateSubagentBriefing() {
47403
47747
  parts.push("");
47404
47748
  }
47405
47749
  const soulPath = join72(root, "core", "0.soul.md");
47406
- if (existsSync71(soulPath)) {
47750
+ if (existsSync72(soulPath)) {
47407
47751
  const { data, content } = readFrontmatter(soulPath);
47408
47752
  const projectName = typeof data.name === "string" ? data.name : "";
47409
47753
  const lines = content.split("\n");
@@ -47438,7 +47782,7 @@ function generateSubagentBriefing() {
47438
47782
  } catch {
47439
47783
  }
47440
47784
  const featuresPath = featuresDir(root);
47441
- if (existsSync71(featuresPath)) {
47785
+ if (existsSync72(featuresPath)) {
47442
47786
  const featureFiles = import_fast_glob18.default.sync("*.md", { cwd: featuresPath, absolute: true });
47443
47787
  const features = [];
47444
47788
  for (const file of featureFiles) {
@@ -47506,7 +47850,7 @@ function generateSubagentBriefing() {
47506
47850
  parts.push("");
47507
47851
  }
47508
47852
  const coreDir = join72(root, "core");
47509
- if (existsSync71(coreDir)) {
47853
+ if (existsSync72(coreDir)) {
47510
47854
  const allCoreFiles = import_fast_glob18.default.sync(["[0-9]*"], { cwd: coreDir, absolute: true });
47511
47855
  allCoreFiles.sort((a, b) => basename20(a).localeCompare(basename20(b), void 0, { numeric: true }));
47512
47856
  if (allCoreFiles.length > 0) {
@@ -47608,7 +47952,7 @@ var init_snapshot2 = __esm({
47608
47952
  });
47609
47953
 
47610
47954
  // src/cli/commands/transcript.ts
47611
- import { readFileSync as readFileSync50, existsSync as existsSync72, statSync as statSync11 } from "fs";
47955
+ import { readFileSync as readFileSync50, existsSync as existsSync73, statSync as statSync11 } from "fs";
47612
47956
  function isSystemNoiseMessage(text) {
47613
47957
  const t = text.trim();
47614
47958
  if (!t) return true;
@@ -47627,7 +47971,7 @@ function distillTranscript(transcriptPath, sinceTimestamp) {
47627
47971
  errors: [],
47628
47972
  bookmarks: []
47629
47973
  };
47630
- if (!existsSync72(transcriptPath)) return result;
47974
+ if (!existsSync73(transcriptPath)) return result;
47631
47975
  try {
47632
47976
  const stat = statSync11(transcriptPath);
47633
47977
  if (stat.size === 0 || stat.size > MAX_TRANSCRIPT_BYTES) return result;
@@ -47806,7 +48150,7 @@ function registerTranscriptCommand(program2) {
47806
48150
  error(`No transcript path for session: ${sessionId}`);
47807
48151
  return;
47808
48152
  }
47809
- if (!existsSync72(session.transcript_path)) {
48153
+ if (!existsSync73(session.transcript_path)) {
47810
48154
  error(`Transcript file not found: ${session.transcript_path}`);
47811
48155
  return;
47812
48156
  }
@@ -47900,7 +48244,7 @@ var init_salience = __esm({
47900
48244
  });
47901
48245
 
47902
48246
  // src/lib/marketing/path-guards.ts
47903
- import { existsSync as existsSync73, realpathSync as realpathSync3 } from "fs";
48247
+ import { existsSync as existsSync74, realpathSync as realpathSync3 } from "fs";
47904
48248
  import { basename as basename21, dirname as dirname39, resolve as resolve13, sep as sep9 } from "path";
47905
48249
  function isMarketingEnvPath(filePath, from) {
47906
48250
  if (!filePath) return false;
@@ -47915,7 +48259,7 @@ function isMarketingEnvPath(filePath, from) {
47915
48259
  }
47916
48260
  function realpathOrSelf(p) {
47917
48261
  try {
47918
- return existsSync73(p) ? realpathSync3(p) : p;
48262
+ return existsSync74(p) ? realpathSync3(p) : p;
47919
48263
  } catch {
47920
48264
  return p;
47921
48265
  }
@@ -47923,7 +48267,7 @@ function realpathOrSelf(p) {
47923
48267
  function realpathOfNearestAncestor(p) {
47924
48268
  let current = p;
47925
48269
  const tail = [];
47926
- while (current && current !== sep9 && !existsSync73(current)) {
48270
+ while (current && current !== sep9 && !existsSync74(current)) {
47927
48271
  tail.unshift(basename21(current));
47928
48272
  current = dirname39(current);
47929
48273
  }
@@ -47943,6 +48287,9 @@ var init_path_guards = __esm({
47943
48287
  });
47944
48288
 
47945
48289
  // src/lib/embeddings/hybrid.ts
48290
+ function hybridReady(root, mode) {
48291
+ return mode === "hybrid" && isEmbedModelDownloaded() && embeddingCacheUsable(root);
48292
+ }
47946
48293
  function denseRank(queryVec, index, topK = POOL) {
47947
48294
  const best = /* @__PURE__ */ new Map();
47948
48295
  for (const chunk of index.chunks) {
@@ -48001,7 +48348,11 @@ function fallbackSnippet(doc) {
48001
48348
  async function hybridSearch(query, corpus, contextRoot, topK = 10, opts = {}) {
48002
48349
  const bm25Hits = bm25Search(query, corpus, POOL, opts);
48003
48350
  const [refreshed, queryVec] = await Promise.all([
48004
- refreshEmbeddings(contextRoot, corpus),
48351
+ // ADD-ONLY: `corpus` may be type-scoped (e.g. the dashboard Knowledge search
48352
+ // asks only for knowledge+feature). Never evict out-of-scope vectors here, or
48353
+ // the next full-corpus query would re-embed the whole corpus inline. Pruning
48354
+ // is the explicit refreshers' job.
48355
+ refreshEmbeddings(contextRoot, corpus, void 0, { additive: true }),
48005
48356
  embedQuery(query)
48006
48357
  ]);
48007
48358
  if (refreshed === null || queryVec === null) return bm25Hits.slice(0, topK);
@@ -48211,7 +48562,7 @@ If pure greeting: {"skip":true}`;
48211
48562
  });
48212
48563
 
48213
48564
  // src/cli/commands/asset-drift.ts
48214
- import { mkdtempSync as mkdtempSync2, rmSync as rmSync9, existsSync as existsSync74, readFileSync as readFileSync51, readdirSync as readdirSync15 } from "fs";
48565
+ import { mkdtempSync as mkdtempSync2, rmSync as rmSync9, existsSync as existsSync75, readFileSync as readFileSync51, readdirSync as readdirSync15 } from "fs";
48215
48566
  import { tmpdir as tmpdir3 } from "os";
48216
48567
  import { join as join73, dirname as dirname40 } from "path";
48217
48568
  function walkFiles(dir, base, out) {
@@ -48236,7 +48587,7 @@ async function computeUsedAssetsChanged(projectRoot, config) {
48236
48587
  if (rel.endsWith("settings.json")) continue;
48237
48588
  if (rel.startsWith("_dream_context/")) continue;
48238
48589
  const onDisk = join73(projectRoot, rel);
48239
- if (!existsSync74(onDisk)) return true;
48590
+ if (!existsSync75(onDisk)) return true;
48240
48591
  if (!readFileSync51(join73(tmp, rel)).equals(readFileSync51(onDisk))) return true;
48241
48592
  }
48242
48593
  return false;
@@ -48278,7 +48629,7 @@ var init_asset_drift = __esm({
48278
48629
  });
48279
48630
 
48280
48631
  // src/lib/initializer-detect.ts
48281
- import { existsSync as existsSync75, statSync as statSync12, readdirSync as readdirSync16, readFileSync as readFileSync52 } from "fs";
48632
+ import { existsSync as existsSync76, statSync as statSync12, readdirSync as readdirSync16, readFileSync as readFileSync52 } from "fs";
48282
48633
  import { join as join74, dirname as dirname41, basename as basename22, extname as extname2, isAbsolute as isAbsolute2, resolve as resolve14, sep as sep10 } from "path";
48283
48634
  import { homedir as homedir5 } from "os";
48284
48635
  function isUntouchedTemplateCore(root) {
@@ -48288,7 +48639,7 @@ function isUntouchedTemplateCore(root) {
48288
48639
  let templateCount = 0;
48289
48640
  for (const f of files) {
48290
48641
  const p = join74(root, "core", f);
48291
- if (!existsSync75(p)) continue;
48642
+ if (!existsSync76(p)) continue;
48292
48643
  let content;
48293
48644
  try {
48294
48645
  content = readFileSync52(p, "utf-8");
@@ -48308,7 +48659,7 @@ function isUntouchedTemplateCore(root) {
48308
48659
  function knowledgeIsEmpty(root) {
48309
48660
  try {
48310
48661
  const kdir = join74(root, "knowledge");
48311
- if (!existsSync75(kdir)) return true;
48662
+ if (!existsSync76(kdir)) return true;
48312
48663
  const stack = [{ dir: kdir, top: true }];
48313
48664
  while (stack.length) {
48314
48665
  const { dir, top } = stack.pop();
@@ -48336,7 +48687,7 @@ function knowledgeIsEmpty(root) {
48336
48687
  function featuresAreZero(root) {
48337
48688
  try {
48338
48689
  const fdir = featuresDir(root);
48339
- if (!existsSync75(fdir)) return true;
48690
+ if (!existsSync76(fdir)) return true;
48340
48691
  const entries = readdirSync16(fdir, { withFileTypes: true });
48341
48692
  return !entries.some(
48342
48693
  (e) => e.isFile() && !e.name.startsWith(".") && e.name.toLowerCase().endsWith(".md")
@@ -48358,7 +48709,7 @@ function classifyBrain(root) {
48358
48709
  function hasProjectSignal(cwd) {
48359
48710
  try {
48360
48711
  for (const m of PROJECT_MARKERS) {
48361
- if (existsSync75(join74(cwd, m))) return true;
48712
+ if (existsSync76(join74(cwd, m))) return true;
48362
48713
  }
48363
48714
  for (const d of PROJECT_DIRS) {
48364
48715
  try {
@@ -48650,7 +49001,7 @@ var init_initializer_detect = __esm({
48650
49001
  });
48651
49002
 
48652
49003
  // src/lib/agent-session-map.ts
48653
- import { existsSync as existsSync76, lstatSync as lstatSync3, mkdirSync as mkdirSync41, readFileSync as readFileSync53, writeFileSync as writeFileSync48, renameSync as renameSync16, readdirSync as readdirSync17, unlinkSync as unlinkSync9, statSync as statSync13 } from "fs";
49004
+ import { existsSync as existsSync77, lstatSync as lstatSync3, mkdirSync as mkdirSync41, readFileSync as readFileSync53, writeFileSync as writeFileSync48, renameSync as renameSync16, readdirSync as readdirSync17, unlinkSync as unlinkSync9, statSync as statSync13 } from "fs";
48654
49005
  import { join as join75, dirname as dirname42, basename as basename23 } from "path";
48655
49006
  import { randomUUID as randomUUID3 } from "crypto";
48656
49007
  function mapDir(contextRoot) {
@@ -48680,10 +49031,10 @@ function listEntryFiles(dir) {
48680
49031
  }
48681
49032
  function ensureMapDir(contextRoot) {
48682
49033
  const stateDir = join75(contextRoot, "state");
48683
- if (existsSync76(stateDir) && !lstatSync3(stateDir).isDirectory()) return null;
49034
+ if (existsSync77(stateDir) && !lstatSync3(stateDir).isDirectory()) return null;
48684
49035
  const dir = mapDir(contextRoot);
48685
- if (existsSync76(dir) && !lstatSync3(dir).isDirectory()) return null;
48686
- if (!existsSync76(dir)) {
49036
+ if (existsSync77(dir) && !lstatSync3(dir).isDirectory()) return null;
49037
+ if (!existsSync77(dir)) {
48687
49038
  try {
48688
49039
  ensureGitignoreEntries(dirname42(contextRoot), ["_dream_context/state/.agent-session-map/"], {
48689
49040
  comment: "dreamcontext: machine-local agent tab \u2192 live Claude session map"
@@ -48705,7 +49056,7 @@ function recordAgentSession(contextRoot, tabId, sessionId) {
48705
49056
  const dir = ensureMapDir(contextRoot);
48706
49057
  if (!dir) return;
48707
49058
  const path2 = join75(dir, `${tabId}.json`);
48708
- if (existsSync76(path2) && !lstatSync3(path2).isFile()) return;
49059
+ if (existsSync77(path2) && !lstatSync3(path2).isFile()) return;
48709
49060
  const prev = readEntry(path2);
48710
49061
  const entry = { current: sessionId, updated: (/* @__PURE__ */ new Date()).toISOString() };
48711
49062
  if (prev?.current === sessionId && prev.firstPrompt) entry.firstPrompt = prev.firstPrompt;
@@ -48773,7 +49124,7 @@ function recordAgentFirstPrompt(contextRoot, tabId, sessionId, prompt) {
48773
49124
  const dir = ensureMapDir(contextRoot);
48774
49125
  if (!dir) return;
48775
49126
  const path2 = join75(dir, `${tabId}.json`);
48776
- if (existsSync76(path2) && !lstatSync3(path2).isFile()) return;
49127
+ if (existsSync77(path2) && !lstatSync3(path2).isFile()) return;
48777
49128
  const prev = readEntry(path2);
48778
49129
  if (prev?.current === sessionId && prev.firstPrompt) return;
48779
49130
  writeEntryAtomic(path2, { current: sessionId, updated: (/* @__PURE__ */ new Date()).toISOString(), firstPrompt: clean });
@@ -48796,7 +49147,7 @@ var init_agent_session_map = __esm({
48796
49147
  });
48797
49148
 
48798
49149
  // src/cli/commands/hook.ts
48799
- import { readFileSync as readFileSync54, existsSync as existsSync77, statSync as statSync14 } from "fs";
49150
+ import { readFileSync as readFileSync54, existsSync as existsSync78, statSync as statSync14 } from "fs";
48800
49151
  import { execFileSync as execFileSync9, spawn as spawn3 } from "child_process";
48801
49152
  import { get as httpGet, request as httpRequest } from "http";
48802
49153
  import { dirname as dirname43, resolve as resolve15, join as join76, extname as extname3, basename as basename24, relative as relative5 } from "path";
@@ -48813,7 +49164,7 @@ function readStdin() {
48813
49164
  }
48814
49165
  }
48815
49166
  function analyzeTranscript(transcriptPath) {
48816
- if (!existsSync77(transcriptPath)) return ZERO_ANALYSIS;
49167
+ if (!existsSync78(transcriptPath)) return ZERO_ANALYSIS;
48817
49168
  try {
48818
49169
  const stat = statSync14(transcriptPath);
48819
49170
  if (stat.size === 0 || stat.size > MAX_TRANSCRIPT_BYTES2) return ZERO_ANALYSIS;
@@ -48919,21 +49270,21 @@ function findProjectConfig(filePath) {
48919
49270
  for (let i = 0; i <= MAX_WALK_LEVELS; i++) {
48920
49271
  if (!formatter) {
48921
49272
  for (const name of BIOME_CONFIGS) {
48922
- if (existsSync77(join76(dir, name))) {
49273
+ if (existsSync78(join76(dir, name))) {
48923
49274
  formatter = { type: "biome", configPath: join76(dir, name), projectRoot: dir };
48924
49275
  break;
48925
49276
  }
48926
49277
  }
48927
49278
  if (!formatter) {
48928
49279
  for (const name of PRETTIER_CONFIGS) {
48929
- if (existsSync77(join76(dir, name))) {
49280
+ if (existsSync78(join76(dir, name))) {
48930
49281
  formatter = { type: "prettier", configPath: join76(dir, name), projectRoot: dir };
48931
49282
  break;
48932
49283
  }
48933
49284
  }
48934
49285
  }
48935
49286
  }
48936
- if (!tsconfig && existsSync77(join76(dir, "tsconfig.json"))) {
49287
+ if (!tsconfig && existsSync78(join76(dir, "tsconfig.json"))) {
48937
49288
  tsconfig = join76(dir, "tsconfig.json");
48938
49289
  }
48939
49290
  if (formatter && tsconfig) break;
@@ -48945,7 +49296,7 @@ function findProjectConfig(filePath) {
48945
49296
  }
48946
49297
  function resolveLocalBin(binName, projectRoot) {
48947
49298
  const localBin = join76(projectRoot, "node_modules", ".bin", binName);
48948
- return existsSync77(localBin) ? localBin : null;
49299
+ return existsSync78(localBin) ? localBin : null;
48949
49300
  }
48950
49301
  function runFormatter(detection, filePath) {
48951
49302
  try {
@@ -49256,7 +49607,7 @@ function registerHookCommand(program2) {
49256
49607
  recordTabSessionFromHook(root, sessionId);
49257
49608
  const state = readSleepState(root);
49258
49609
  const stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
49259
- const transcriptOnDisk = !!transcriptPath && existsSync77(transcriptPath);
49610
+ const transcriptOnDisk = !!transcriptPath && existsSync78(transcriptPath);
49260
49611
  const analysis = transcriptOnDisk ? analyzeTranscript(transcriptPath) : ZERO_ANALYSIS;
49261
49612
  const { changeCount, toolCount } = analysis;
49262
49613
  const score = transcriptOnDisk ? Math.max(
@@ -49353,7 +49704,7 @@ function registerHookCommand(program2) {
49353
49704
  dirty = true;
49354
49705
  continue;
49355
49706
  }
49356
- if (!existsSync77(session.transcript_path)) {
49707
+ if (!existsSync78(session.transcript_path)) {
49357
49708
  const stoppedMs = Date.parse(session.stopped_at ?? "") || 0;
49358
49709
  if (Date.now() - stoppedMs < 7 * 24 * 60 * 60 * 1e3) continue;
49359
49710
  session.change_count = 0;
@@ -49376,7 +49727,7 @@ function registerHookCommand(program2) {
49376
49727
  }
49377
49728
  for (const session of state.sessions) {
49378
49729
  if (!session.transcript_path) continue;
49379
- if (!existsSync77(session.transcript_path)) continue;
49730
+ if (!existsSync78(session.transcript_path)) continue;
49380
49731
  if (digestExists(root, session.session_id) && !digestIsPartial(root, session.session_id)) continue;
49381
49732
  try {
49382
49733
  const distilled = distillTranscript(session.transcript_path);
@@ -49425,7 +49776,8 @@ function registerHookCommand(program2) {
49425
49776
  const projectRoot = dirname43(root);
49426
49777
  const cfg = readSetupConfig(projectRoot);
49427
49778
  const enabledResolution = resolveBrainSyncEnabled(projectRoot, cfg);
49428
- if (enabledResolution.enabled && cfg?.brainRepo?.mode === "separate" && cfg?.brainRepo?.autoSync) {
49779
+ const pullMode = cfg?.brainRepo?.mode;
49780
+ if (enabledResolution.enabled && (pullMode === "separate" || pullMode === "full-repo") && cfg?.brainRepo?.autoSync) {
49429
49781
  spawnBrainPull(root);
49430
49782
  }
49431
49783
  const local = readBrainLocal(projectRoot);
@@ -49567,7 +49919,7 @@ function registerHookCommand(program2) {
49567
49919
  try {
49568
49920
  const prompt = String(input2.prompt ?? "");
49569
49921
  if (prompt.trim().length >= 8) {
49570
- const recallMode = process.env.DREAMCONTEXT_RECALL_MODE ?? state.recall_mode ?? "haiku";
49922
+ const recallMode = resolveRecallMode(root);
49571
49923
  if (recallMode !== "off") {
49572
49924
  let hits = [];
49573
49925
  let mode = "BM25";
@@ -49585,7 +49937,7 @@ function registerHookCommand(program2) {
49585
49937
  const corpus = buildCorpus(root);
49586
49938
  hits = bm25Search(prompt, corpus, 3);
49587
49939
  }
49588
- } else if (recallMode === "hybrid") {
49940
+ } else if (hybridReady(root, recallMode)) {
49589
49941
  const corpus = buildCorpus(root);
49590
49942
  hits = await hybridSearch(prompt, corpus, root, 3);
49591
49943
  mode = "Hybrid";
@@ -49723,7 +50075,7 @@ function registerHookCommand(program2) {
49723
50075
  try {
49724
50076
  const sessionId = input2 && typeof input2.session_id === "string" ? input2.session_id : "";
49725
50077
  const transcriptPath = input2 && typeof input2.transcript_path === "string" ? input2.transcript_path : "";
49726
- if (sessionId && transcriptPath && existsSync77(transcriptPath)) {
50078
+ if (sessionId && transcriptPath && existsSync78(transcriptPath)) {
49727
50079
  const distilled = distillTranscript(transcriptPath);
49728
50080
  writeDigest(root, sessionId, buildDigest(distilled), { partial: true });
49729
50081
  }
@@ -49839,7 +50191,7 @@ var init_hook = __esm({
49839
50191
  });
49840
50192
 
49841
50193
  // src/cli/commands/doctor.ts
49842
- import { existsSync as existsSync78, readFileSync as readFileSync55, readdirSync as readdirSync18, statSync as statSync15 } from "fs";
50194
+ import { existsSync as existsSync79, readFileSync as readFileSync55, readdirSync as readdirSync18, statSync as statSync15 } from "fs";
49843
50195
  import { join as join77 } from "path";
49844
50196
  import { dirname as dirname44 } from "path";
49845
50197
  function stripDocumentedMentions(content) {
@@ -49850,7 +50202,7 @@ function stripDocumentedMentions(content) {
49850
50202
  }
49851
50203
  function checkFile(root, relPath, label, required) {
49852
50204
  const fullPath = join77(root, relPath);
49853
- if (!existsSync78(fullPath)) {
50205
+ if (!existsSync79(fullPath)) {
49854
50206
  return {
49855
50207
  name: label,
49856
50208
  status: required ? "error" : "warn",
@@ -49880,7 +50232,7 @@ function checkFile(root, relPath, label, required) {
49880
50232
  }
49881
50233
  function checkJson(root, relPath, label) {
49882
50234
  const fullPath = join77(root, relPath);
49883
- if (!existsSync78(fullPath)) {
50235
+ if (!existsSync79(fullPath)) {
49884
50236
  return { name: label, status: "error", message: `Missing: ${relPath}` };
49885
50237
  }
49886
50238
  try {
@@ -49893,7 +50245,7 @@ function checkJson(root, relPath, label) {
49893
50245
  }
49894
50246
  function checkDirectory(root, relPath, label) {
49895
50247
  const fullPath = join77(root, relPath);
49896
- if (!existsSync78(fullPath)) {
50248
+ if (!existsSync79(fullPath)) {
49897
50249
  return { name: label, status: "error", message: `Missing directory: ${relPath}` };
49898
50250
  }
49899
50251
  return { name: label, status: "ok", message: relPath };
@@ -49904,10 +50256,10 @@ function checkDataStructures(root) {
49904
50256
  const dirAbs = join77(root, dirRel);
49905
50257
  const oldRel = "core/data-structures";
49906
50258
  const oldAbs = join77(root, oldRel);
49907
- const oldExists = existsSync78(oldAbs);
50259
+ const oldExists = existsSync79(oldAbs);
49908
50260
  const legacyRel = "core/5.data_structures.sql";
49909
- const legacyExists = existsSync78(join77(root, legacyRel));
49910
- if (!existsSync78(dirAbs)) {
50261
+ const legacyExists = existsSync79(join77(root, legacyRel));
50262
+ if (!existsSync79(dirAbs)) {
49911
50263
  if (oldExists) {
49912
50264
  results.push({
49913
50265
  name: "Data structures",
@@ -49980,7 +50332,7 @@ function checkDataStructures(root) {
49980
50332
  function checkFeaturesMigrated(root) {
49981
50333
  const oldRel = "core/features";
49982
50334
  const oldAbs = join77(root, oldRel);
49983
- if (!existsSync78(oldAbs)) {
50335
+ if (!existsSync79(oldAbs)) {
49984
50336
  return { name: "Features (migration)", status: "ok", message: "knowledge/features/" };
49985
50337
  }
49986
50338
  let mdFiles = [];
@@ -50075,7 +50427,7 @@ function checkLab(root) {
50075
50427
  const results = [];
50076
50428
  const insights = listInsights(root);
50077
50429
  const credentialsPath2 = join77(root, "lab", "credentials.json");
50078
- if (existsSync78(credentialsPath2)) {
50430
+ if (existsSync79(credentialsPath2)) {
50079
50431
  const projectRoot = dirname44(root);
50080
50432
  const config = readSetupConfig(projectRoot);
50081
50433
  const mode = resolveMode2(config);
@@ -50111,7 +50463,7 @@ function checkLab(root) {
50111
50463
  }
50112
50464
  }
50113
50465
  if (m.credentials_used.length > 0) {
50114
- const creds = existsSync78(credentialsPath2) ? (() => {
50466
+ const creds = existsSync79(credentialsPath2) ? (() => {
50115
50467
  try {
50116
50468
  return JSON.parse(readFileSync55(credentialsPath2, "utf-8"));
50117
50469
  } catch {
@@ -50161,7 +50513,7 @@ function checkBrainRepo(root) {
50161
50513
  if (config?.taskBackend !== "github") return results;
50162
50514
  if (resolveMode2(config) !== "separate") return results;
50163
50515
  const gitignorePath = join77(root, ".gitignore");
50164
- if (!existsSync78(gitignorePath)) return results;
50516
+ if (!existsSync79(gitignorePath)) return results;
50165
50517
  if (!gitignoreCovers(root, ["state/*.md"])) {
50166
50518
  results.push({
50167
50519
  name: "Brain repo",
@@ -50204,17 +50556,17 @@ function registerDoctorCommand(program2) {
50204
50556
  ...checkBrainRepo(root),
50205
50557
  ...checkPlatformLayer(root),
50206
50558
  // Taxonomy vocabulary (non-fatal: absent means DEFAULT_VOCABULARY used)
50207
- ...!existsSync78(join77(root, "core", "taxonomy.json")) ? [{
50559
+ ...!existsSync79(join77(root, "core", "taxonomy.json")) ? [{
50208
50560
  name: "Taxonomy vocabulary",
50209
50561
  status: "warn",
50210
50562
  message: "core/taxonomy.json not found \u2014 run `dreamcontext taxonomy init` to scaffold it"
50211
50563
  }] : [checkJson(root, "core/taxonomy.json", "Taxonomy vocabulary")],
50212
50564
  // Sleep state (optional — created on first Stop hook)
50213
- ...existsSync78(join77(root, "state", ".sleep.json")) ? [checkJson(root, "state/.sleep.json", "Sleep state")] : [],
50214
- ...existsSync78(join77(root, "state", ".platforms.json")) ? [checkJson(root, "state/.platforms.json", "Platform defaults")] : []
50565
+ ...existsSync79(join77(root, "state", ".sleep.json")) ? [checkJson(root, "state/.sleep.json", "Sleep state")] : [],
50566
+ ...existsSync79(join77(root, "state", ".platforms.json")) ? [checkJson(root, "state/.platforms.json", "Platform defaults")] : []
50215
50567
  ];
50216
50568
  const sleepPath = join77(root, "state", ".sleep.json");
50217
- if (existsSync78(sleepPath)) {
50569
+ if (existsSync79(sleepPath)) {
50218
50570
  try {
50219
50571
  const parsed = JSON.parse(readFileSync55(sleepPath, "utf-8"));
50220
50572
  if (typeof parsed.debt !== "number" || parsed.debt < 0) {
@@ -50388,7 +50740,7 @@ var init_middleware = __esm({
50388
50740
  });
50389
50741
 
50390
50742
  // src/server/static.ts
50391
- import { existsSync as existsSync79, readFileSync as readFileSync56, statSync as statSync16 } from "fs";
50743
+ import { existsSync as existsSync80, readFileSync as readFileSync56, statSync as statSync16 } from "fs";
50392
50744
  import { join as join78, extname as extname4 } from "path";
50393
50745
  function serveStatic(req, res, staticDir) {
50394
50746
  const url = new URL(req.url || "/", `http://${req.headers.host}`);
@@ -50398,10 +50750,10 @@ function serveStatic(req, res, staticDir) {
50398
50750
  res.end("Forbidden");
50399
50751
  return;
50400
50752
  }
50401
- if (existsSync79(filePath) && statSync16(filePath).isDirectory()) {
50753
+ if (existsSync80(filePath) && statSync16(filePath).isDirectory()) {
50402
50754
  filePath = join78(filePath, "index.html");
50403
50755
  }
50404
- if (existsSync79(filePath) && statSync16(filePath).isFile()) {
50756
+ if (existsSync80(filePath) && statSync16(filePath).isFile()) {
50405
50757
  const ext = extname4(filePath);
50406
50758
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
50407
50759
  const content = readFileSync56(filePath);
@@ -50417,7 +50769,7 @@ function serveStatic(req, res, staticDir) {
50417
50769
  const looksLikeFile = extname4(url.pathname) !== "";
50418
50770
  if (acceptsHtml || !looksLikeFile) {
50419
50771
  const indexPath2 = join78(staticDir, "index.html");
50420
- if (existsSync79(indexPath2)) {
50772
+ if (existsSync80(indexPath2)) {
50421
50773
  const content = readFileSync56(indexPath2);
50422
50774
  res.writeHead(200, {
50423
50775
  "Content-Type": "text/html; charset=utf-8",
@@ -51180,8 +51532,8 @@ async function handleSleepUpdate(req, res, _params, contextRoot) {
51180
51532
  sendError(res, 400, "invalid_body", "Request body must be JSON.");
51181
51533
  return;
51182
51534
  }
51183
- if (body.recall_mode !== void 0 && !RECALL_MODES.includes(body.recall_mode)) {
51184
- sendError(res, 400, "invalid_value", `recall_mode must be one of: ${RECALL_MODES.join(", ")}.`);
51535
+ if (body.recall_mode !== void 0 && !RECALL_MODES2.includes(body.recall_mode)) {
51536
+ sendError(res, 400, "invalid_value", `recall_mode must be one of: ${RECALL_MODES2.join(", ")}.`);
51185
51537
  return;
51186
51538
  }
51187
51539
  const state = readSleepState(contextRoot);
@@ -51212,26 +51564,114 @@ async function handleSleepUpdate(req, res, _params, contextRoot) {
51212
51564
  const updatedState = readSleepState(contextRoot);
51213
51565
  sendJson(res, 200, updatedState);
51214
51566
  }
51215
- var RECALL_MODES;
51567
+ var RECALL_MODES2;
51216
51568
  var init_sleep2 = __esm({
51217
51569
  "src/server/routes/sleep.ts"() {
51218
51570
  "use strict";
51219
51571
  init_sleep();
51220
51572
  init_middleware();
51221
51573
  init_change_tracker2();
51222
- RECALL_MODES = ["haiku", "raw", "hybrid", "off"];
51574
+ RECALL_MODES2 = ["haiku", "raw", "hybrid", "off"];
51575
+ }
51576
+ });
51577
+
51578
+ // src/server/routes/embeddings.ts
51579
+ async function handleEmbeddingModelStatus(_req, res) {
51580
+ sendJson(res, 200, getEmbedModelStatus());
51581
+ }
51582
+ async function handleEmbeddingModelDownload(_req, res) {
51583
+ const status = startEmbedModelDownload();
51584
+ sendJson(res, 200, { ok: true, ...status });
51585
+ }
51586
+ function indexStatusFor(contextRoot) {
51587
+ const run3 = indexRuns.get(contextRoot);
51588
+ const usable = embeddingCacheUsable(contextRoot);
51589
+ let state;
51590
+ if (run3?.state === "building") state = "building";
51591
+ else if (run3?.state === "error" && !usable) state = "error";
51592
+ else if (usable) state = "ready";
51593
+ else state = "not_built";
51594
+ const progress = state === "ready" ? 100 : state === "building" && run3 && run3.total > 0 ? Math.min(99, Math.round(run3.done / run3.total * 100)) : 0;
51595
+ return {
51596
+ state,
51597
+ progress,
51598
+ done: run3?.done ?? 0,
51599
+ total: run3?.total ?? 0,
51600
+ // Prefer the just-built count; else read the real count off the usable cache
51601
+ // (fixes a "0 sections indexed" display when the index was built earlier).
51602
+ chunks: run3?.chunks || (state === "ready" ? embeddingCacheChunkCount(contextRoot) : 0),
51603
+ error: run3?.error ?? null
51604
+ };
51605
+ }
51606
+ async function handleEmbeddingIndexStatus(_req, res, _params, contextRoot) {
51607
+ if (!contextRoot) {
51608
+ sendError(res, 400, "no_vault", "No vault selected.");
51609
+ return;
51610
+ }
51611
+ sendJson(res, 200, indexStatusFor(contextRoot));
51612
+ }
51613
+ async function handleEmbeddingIndexBuild(_req, res, _params, contextRoot) {
51614
+ if (!contextRoot) {
51615
+ sendError(res, 400, "no_vault", "No vault selected.");
51616
+ return;
51617
+ }
51618
+ if (!isEmbedModelDownloaded()) {
51619
+ sendError(res, 409, "model_missing", "Download the embedding model first.");
51620
+ return;
51621
+ }
51622
+ const existing = indexRuns.get(contextRoot);
51623
+ if (existing?.state === "building") {
51624
+ sendJson(res, 200, { ok: true, ...indexStatusFor(contextRoot) });
51625
+ return;
51626
+ }
51627
+ const run3 = { state: "building", done: 0, total: 0, chunks: 0, error: null, startedAt: Date.now() };
51628
+ indexRuns.set(contextRoot, run3);
51629
+ void (async () => {
51630
+ try {
51631
+ const corpus = buildCorpus(contextRoot);
51632
+ const result = await refreshEmbeddings(contextRoot, corpus, void 0, {
51633
+ onProgress: (done, total) => {
51634
+ run3.done = done;
51635
+ run3.total = total;
51636
+ }
51637
+ });
51638
+ if (result === null) {
51639
+ run3.state = "error";
51640
+ run3.error = "Embedding model unavailable \u2014 could not build the index.";
51641
+ } else {
51642
+ run3.state = "ready";
51643
+ run3.chunks = result.index.chunks.length;
51644
+ }
51645
+ } catch (err) {
51646
+ run3.state = "error";
51647
+ run3.error = err instanceof Error ? err.message : "Index build failed.";
51648
+ } finally {
51649
+ run3.endedAt = Date.now();
51650
+ }
51651
+ })();
51652
+ sendJson(res, 200, { ok: true, ...indexStatusFor(contextRoot) });
51653
+ }
51654
+ var indexRuns;
51655
+ var init_embeddings = __esm({
51656
+ "src/server/routes/embeddings.ts"() {
51657
+ "use strict";
51658
+ init_middleware();
51659
+ init_embedder();
51660
+ init_recall();
51661
+ init_store();
51662
+ indexRuns = /* @__PURE__ */ new Map();
51223
51663
  }
51224
51664
  });
51225
51665
 
51226
51666
  // src/server/routes/core.ts
51227
- import { existsSync as existsSync80, readdirSync as readdirSync19 } from "fs";
51667
+ import { existsSync as existsSync81, readdirSync as readdirSync19 } from "fs";
51228
51668
  import { join as join79 } from "path";
51229
51669
  function getCoreDir(contextRoot) {
51230
51670
  return join79(contextRoot, "core");
51231
51671
  }
51232
51672
  async function handleCoreList(_req, res, _params, contextRoot) {
51233
51673
  const coreDir = getCoreDir(contextRoot);
51234
- if (!existsSync80(coreDir)) {
51674
+ if (!existsSync81(coreDir)) {
51235
51675
  sendJson(res, 200, { files: [] });
51236
51676
  return;
51237
51677
  }
@@ -51261,7 +51701,7 @@ async function handleCoreGet(_req, res, params, contextRoot) {
51261
51701
  sendError(res, 400, "invalid_path", "Invalid filename.");
51262
51702
  return;
51263
51703
  }
51264
- if (!existsSync80(filePath)) {
51704
+ if (!existsSync81(filePath)) {
51265
51705
  sendError(res, 404, "not_found", `Core file not found: ${filename}`);
51266
51706
  return;
51267
51707
  }
@@ -51312,7 +51752,7 @@ async function handleCoreUpdate(req, res, params, contextRoot) {
51312
51752
  sendError(res, 400, "invalid_path", "Invalid filename.");
51313
51753
  return;
51314
51754
  }
51315
- if (!existsSync80(filePath)) {
51755
+ if (!existsSync81(filePath)) {
51316
51756
  sendError(res, 404, "not_found", `Core file not found: ${filename}`);
51317
51757
  return;
51318
51758
  }
@@ -57937,7 +58377,7 @@ var require_lib4 = __commonJS({
57937
58377
  });
57938
58378
 
57939
58379
  // src/server/routes/knowledge.ts
57940
- import { existsSync as existsSync81, readFileSync as readFileSync57, statSync as statSync17 } from "fs";
58380
+ import { existsSync as existsSync82, readFileSync as readFileSync57, statSync as statSync17 } from "fs";
57941
58381
  import { join as join80, dirname as dirname46, basename as basename25, extname as extname5 } from "path";
57942
58382
  function getKnowledgeDir2(contextRoot) {
57943
58383
  return join80(contextRoot, "knowledge");
@@ -58021,7 +58461,7 @@ async function handleKnowledgeGet(_req, res, params, contextRoot) {
58021
58461
  sendError(res, 400, "invalid_path", `Invalid knowledge slug: ${slug}`);
58022
58462
  return;
58023
58463
  }
58024
- if (!existsSync81(filePath)) {
58464
+ if (!existsSync82(filePath)) {
58025
58465
  sendError(res, 404, "not_found", `Knowledge file not found: ${slug}`);
58026
58466
  return;
58027
58467
  }
@@ -58048,7 +58488,7 @@ async function handleKnowledgeAssets(_req, res, params, contextRoot) {
58048
58488
  sendError(res, 400, "invalid_path", `Invalid knowledge slug: ${slug}`);
58049
58489
  return;
58050
58490
  }
58051
- if (!existsSync81(filePath)) {
58491
+ if (!existsSync82(filePath)) {
58052
58492
  sendError(res, 404, "not_found", `Knowledge file not found: ${slug}`);
58053
58493
  return;
58054
58494
  }
@@ -58073,7 +58513,7 @@ async function handleKnowledgeAssets(_req, res, params, contextRoot) {
58073
58513
  // co-located self-contained board folder
58074
58514
  safeChildPath2(boardDir, join80("Attachments", basename25(path2)))
58075
58515
  ];
58076
- const abs = candidates.find((c) => c !== null && existsSync81(c));
58516
+ const abs = candidates.find((c) => c !== null && existsSync82(c));
58077
58517
  if (!abs) continue;
58078
58518
  const loaded = await loadAssetDataURL(abs, maxDim, quality);
58079
58519
  if (!loaded) continue;
@@ -58098,7 +58538,7 @@ async function handleKnowledgeUpdate(req, res, params, contextRoot) {
58098
58538
  sendError(res, 400, "invalid_path", `Invalid knowledge slug: ${slug}`);
58099
58539
  return;
58100
58540
  }
58101
- if (!existsSync81(filePath)) {
58541
+ if (!existsSync82(filePath)) {
58102
58542
  sendError(res, 404, "not_found", `Knowledge file not found: ${slug}`);
58103
58543
  return;
58104
58544
  }
@@ -58169,11 +58609,11 @@ var init_knowledge2 = __esm({
58169
58609
  });
58170
58610
 
58171
58611
  // src/server/routes/changelog.ts
58172
- import { existsSync as existsSync82 } from "fs";
58612
+ import { existsSync as existsSync83 } from "fs";
58173
58613
  import { join as join81 } from "path";
58174
58614
  async function handleChangelogGet(_req, res, _params, contextRoot) {
58175
58615
  const filePath = join81(contextRoot, "core", "CHANGELOG.json");
58176
- if (!existsSync82(filePath)) {
58616
+ if (!existsSync83(filePath)) {
58177
58617
  sendJson(res, 200, { entries: [] });
58178
58618
  return;
58179
58619
  }
@@ -58186,7 +58626,7 @@ async function handleChangelogGet(_req, res, _params, contextRoot) {
58186
58626
  }
58187
58627
  async function handleReleasesGet(_req, res, _params, contextRoot) {
58188
58628
  const filePath = join81(contextRoot, "core", "RELEASES.json");
58189
- if (!existsSync82(filePath)) {
58629
+ if (!existsSync83(filePath)) {
58190
58630
  sendJson(res, 200, { entries: [] });
58191
58631
  return;
58192
58632
  }
@@ -58324,7 +58764,7 @@ async function handleReleasesUpdate(req, res, params, contextRoot) {
58324
58764
  return;
58325
58765
  }
58326
58766
  const filePath = join81(contextRoot, "core", "RELEASES.json");
58327
- if (!existsSync82(filePath)) {
58767
+ if (!existsSync83(filePath)) {
58328
58768
  sendError(res, 404, "not_found", `Release not found: ${params.version}`);
58329
58769
  return;
58330
58770
  }
@@ -58406,7 +58846,7 @@ async function handleReleasesDelete(_req, res, params, contextRoot) {
58406
58846
  const filePath = join81(contextRoot, "core", "RELEASES.json");
58407
58847
  const wasActive = getActivePlanningVersion(contextRoot) === params.version;
58408
58848
  let wasRegistered = false;
58409
- if (existsSync82(filePath)) {
58849
+ if (existsSync83(filePath)) {
58410
58850
  const entries = readJsonArray(filePath);
58411
58851
  for (const entry of entries) {
58412
58852
  if (!entry.status) entry.status = "released";
@@ -58447,7 +58887,7 @@ var init_changelog = __esm({
58447
58887
  });
58448
58888
 
58449
58889
  // src/lib/graph.ts
58450
- import { existsSync as existsSync83, readFileSync as readFileSync58 } from "fs";
58890
+ import { existsSync as existsSync84, readFileSync as readFileSync58 } from "fs";
58451
58891
  import { join as join82, basename as basename26 } from "path";
58452
58892
  function buildGraph(contextRoot) {
58453
58893
  const nodes = [];
@@ -58469,7 +58909,7 @@ function buildGraph(contextRoot) {
58469
58909
  { prefix: "2", group: "memory" }
58470
58910
  ];
58471
58911
  for (const { prefix, group } of foundational) {
58472
- if (!existsSync83(coreDir)) continue;
58912
+ if (!existsSync84(coreDir)) continue;
58473
58913
  const matches = import_fast_glob19.default.sync(`${prefix}.*.md`, { cwd: coreDir, absolute: true });
58474
58914
  for (const file of matches) {
58475
58915
  try {
@@ -58489,7 +58929,7 @@ function buildGraph(contextRoot) {
58489
58929
  }
58490
58930
  }
58491
58931
  }
58492
- if (existsSync83(coreDir)) {
58932
+ if (existsSync84(coreDir)) {
58493
58933
  const others = import_fast_glob19.default.sync("[3-9]*.md", { cwd: coreDir, absolute: true });
58494
58934
  for (const file of others) {
58495
58935
  const filename = basename26(file);
@@ -58510,7 +58950,7 @@ function buildGraph(contextRoot) {
58510
58950
  }
58511
58951
  }
58512
58952
  const featuresPath = featuresDir(contextRoot);
58513
- if (existsSync83(featuresPath)) {
58953
+ if (existsSync84(featuresPath)) {
58514
58954
  const files = import_fast_glob19.default.sync("*.md", { cwd: featuresPath, absolute: true });
58515
58955
  for (const file of files) {
58516
58956
  const fileSlug = basename26(file, ".md");
@@ -58541,7 +58981,7 @@ function buildGraph(contextRoot) {
58541
58981
  }
58542
58982
  }
58543
58983
  const stateDir = join82(contextRoot, "state");
58544
- if (existsSync83(stateDir)) {
58984
+ if (existsSync84(stateDir)) {
58545
58985
  const files = import_fast_glob19.default.sync("*.md", { cwd: stateDir, absolute: true });
58546
58986
  for (const file of files) {
58547
58987
  const fileSlug = basename26(file, ".md");
@@ -58593,7 +59033,7 @@ function buildGraph(contextRoot) {
58593
59033
  );
58594
59034
  }
58595
59035
  const inboxDir2 = join82(contextRoot, "inbox");
58596
- if (existsSync83(inboxDir2)) {
59036
+ if (existsSync84(inboxDir2)) {
58597
59037
  const files = import_fast_glob19.default.sync("*.md", { cwd: inboxDir2, absolute: true });
58598
59038
  for (const file of files) {
58599
59039
  const slug = basename26(file, ".md");
@@ -58616,7 +59056,7 @@ function buildGraph(contextRoot) {
58616
59056
  }
58617
59057
  const releasesPath = join82(coreDir, "RELEASES.json");
58618
59058
  let releases = [];
58619
- if (existsSync83(releasesPath)) {
59059
+ if (existsSync84(releasesPath)) {
58620
59060
  try {
58621
59061
  const parsed = JSON.parse(readFileSync58(releasesPath, "utf-8"));
58622
59062
  if (Array.isArray(parsed)) releases = parsed;
@@ -58715,7 +59155,7 @@ var init_graph = __esm({
58715
59155
  });
58716
59156
 
58717
59157
  // src/server/routes/graph.ts
58718
- import { existsSync as existsSync84, readFileSync as readFileSync59 } from "fs";
59158
+ import { existsSync as existsSync85, readFileSync as readFileSync59 } from "fs";
58719
59159
  import { normalize, resolve as resolve16, sep as sep11 } from "path";
58720
59160
  async function handleGraphGet(_req, res, _params, contextRoot) {
58721
59161
  try {
@@ -58739,7 +59179,7 @@ async function handleGraphContentGet(req, res, _params, contextRoot) {
58739
59179
  sendError(res, 400, "invalid_path", "Path escapes context root.");
58740
59180
  return;
58741
59181
  }
58742
- if (!existsSync84(absTarget)) {
59182
+ if (!existsSync85(absTarget)) {
58743
59183
  sendError(res, 404, "not_found", `Path not found: ${rawPath}`);
58744
59184
  return;
58745
59185
  }
@@ -58790,7 +59230,7 @@ var init_graph2 = __esm({
58790
59230
  });
58791
59231
 
58792
59232
  // src/lib/council.ts
58793
- import { existsSync as existsSync85, mkdirSync as mkdirSync42, readFileSync as readFileSync60 } from "fs";
59233
+ import { existsSync as existsSync86, mkdirSync as mkdirSync42, readFileSync as readFileSync60 } from "fs";
58794
59234
  import { join as join83, resolve as resolve17, sep as sep12 } from "path";
58795
59235
  import { fileURLToPath as fileURLToPath7 } from "url";
58796
59236
  function getCouncilDir() {
@@ -58833,14 +59273,14 @@ function ensureCouncilDir() {
58833
59273
  const dir = getCouncilDir();
58834
59274
  mkdirSync42(dir, { recursive: true });
58835
59275
  const indexPath2 = getCouncilIndexPath();
58836
- if (!existsSync85(indexPath2)) {
59276
+ if (!existsSync86(indexPath2)) {
58837
59277
  writeJsonArray(indexPath2, []);
58838
59278
  }
58839
59279
  return dir;
58840
59280
  }
58841
59281
  function ensureDebateExists(debateId) {
58842
59282
  const dir = getDebateDir(debateId);
58843
- if (!existsSync85(dir)) {
59283
+ if (!existsSync86(dir)) {
58844
59284
  throw new Error(`Debate not found: ${debateId}`);
58845
59285
  }
58846
59286
  return dir;
@@ -58848,7 +59288,7 @@ function ensureDebateExists(debateId) {
58848
59288
  function ensurePersonaExists(debateId, personaSlug) {
58849
59289
  ensureDebateExists(debateId);
58850
59290
  const dir = getPersonaDir(debateId, personaSlug);
58851
- if (!existsSync85(dir)) {
59291
+ if (!existsSync86(dir)) {
58852
59292
  throw new Error(`Persona not found in ${debateId}: ${personaSlug}`);
58853
59293
  }
58854
59294
  return dir;
@@ -58860,7 +59300,7 @@ function readDebateFrontmatter(debateId) {
58860
59300
  }
58861
59301
  function loadCouncilIndex() {
58862
59302
  const indexPath2 = getCouncilIndexPath();
58863
- if (!existsSync85(indexPath2)) return [];
59303
+ if (!existsSync86(indexPath2)) return [];
58864
59304
  return readJsonArray(indexPath2);
58865
59305
  }
58866
59306
  function saveCouncilIndex(entries) {
@@ -58887,7 +59327,7 @@ function loadTemplate(filename) {
58887
59327
  join83(__dirname6, "..", "..", "src", "templates", filename)
58888
59328
  ];
58889
59329
  for (const path2 of candidates) {
58890
- if (existsSync85(path2)) {
59330
+ if (existsSync86(path2)) {
58891
59331
  return readFileSync60(path2, "utf-8");
58892
59332
  }
58893
59333
  }
@@ -58963,7 +59403,7 @@ function parseReportRounds(reportContent) {
58963
59403
  }
58964
59404
  function getPersonaRoundSummary(debateId, personaSlug, round) {
58965
59405
  const reportPath2 = join83(getPersonaDir(debateId, personaSlug), "report.md");
58966
- if (!existsSync85(reportPath2)) return null;
59406
+ if (!existsSync86(reportPath2)) return null;
58967
59407
  const { content } = readFrontmatter(reportPath2);
58968
59408
  const entries = parseReportRounds(content);
58969
59409
  const entry = entries.find((e) => e.round === round);
@@ -58997,7 +59437,7 @@ var init_council = __esm({
58997
59437
  });
58998
59438
 
58999
59439
  // src/server/routes/council.ts
59000
- import { existsSync as existsSync86 } from "fs";
59440
+ import { existsSync as existsSync87 } from "fs";
59001
59441
  import { join as join84, resolve as resolve18, sep as sep13 } from "path";
59002
59442
  function getCouncilDir2(contextRoot) {
59003
59443
  return join84(contextRoot, "council");
@@ -59054,13 +59494,13 @@ function toParsedRound(entry) {
59054
59494
  }
59055
59495
  function loadPersonaDetail(debateDir, slug) {
59056
59496
  const personaDir = join84(debateDir, slug);
59057
- if (!existsSync86(personaDir)) return null;
59497
+ if (!existsSync87(personaDir)) return null;
59058
59498
  const personaFile = join84(personaDir, "context-and-persona.md");
59059
59499
  const reportFile = join84(personaDir, "report.md");
59060
59500
  let fm = { name: slug, model: "unknown", aspects: [], round_entries: 0 };
59061
59501
  let persona = "";
59062
59502
  let crossContext = {};
59063
- if (existsSync86(personaFile)) {
59503
+ if (existsSync87(personaFile)) {
59064
59504
  const parsed = readFrontmatter(personaFile);
59065
59505
  fm = {
59066
59506
  name: parsed.data.name ?? slug,
@@ -59073,13 +59513,13 @@ function loadPersonaDetail(debateDir, slug) {
59073
59513
  crossContext = split.crossContext;
59074
59514
  }
59075
59515
  let rounds = [];
59076
- if (existsSync86(reportFile)) {
59516
+ if (existsSync87(reportFile)) {
59077
59517
  const { content } = readFrontmatter(reportFile);
59078
59518
  rounds = parseReportRounds(content).map(toParsedRound);
59079
59519
  }
59080
59520
  const researchIndex = join84(personaDir, "researches", "index.json");
59081
59521
  let researches = [];
59082
- if (existsSync86(researchIndex)) {
59522
+ if (existsSync87(researchIndex)) {
59083
59523
  try {
59084
59524
  researches = readJsonArray(researchIndex);
59085
59525
  } catch {
@@ -59090,7 +59530,7 @@ function loadPersonaDetail(debateDir, slug) {
59090
59530
  }
59091
59531
  async function handleCouncilList(_req, res, _params, contextRoot) {
59092
59532
  const indexPath2 = join84(getCouncilDir2(contextRoot), "index.json");
59093
- if (!existsSync86(indexPath2)) {
59533
+ if (!existsSync87(indexPath2)) {
59094
59534
  sendJson(res, 200, { debates: [] });
59095
59535
  return;
59096
59536
  }
@@ -59099,7 +59539,7 @@ async function handleCouncilList(_req, res, _params, contextRoot) {
59099
59539
  const enriched = debates.map((d) => {
59100
59540
  const debateFile = join84(getCouncilDir2(contextRoot), d.id, "debate.md");
59101
59541
  let personaSlugs = [];
59102
- if (existsSync86(debateFile)) {
59542
+ if (existsSync87(debateFile)) {
59103
59543
  try {
59104
59544
  const fm = readFrontmatter(debateFile).data;
59105
59545
  if (Array.isArray(fm.personas)) personaSlugs = fm.personas;
@@ -59124,12 +59564,12 @@ async function handleCouncilGet(_req, res, params, contextRoot) {
59124
59564
  const councilDir = getCouncilDir2(contextRoot);
59125
59565
  const debateDirUnchecked = join84(councilDir, debateId);
59126
59566
  const debateDir = assertWithin(councilDir, debateDirUnchecked);
59127
- if (!debateDir || !existsSync86(debateDir)) {
59567
+ if (!debateDir || !existsSync87(debateDir)) {
59128
59568
  sendError(res, 404, "not_found", `Debate not found: ${debateId}`);
59129
59569
  return;
59130
59570
  }
59131
59571
  const debateFile = join84(debateDir, "debate.md");
59132
- if (!existsSync86(debateFile)) {
59572
+ if (!existsSync87(debateFile)) {
59133
59573
  sendError(res, 404, "not_found", `Debate metadata missing: ${debateId}`);
59134
59574
  return;
59135
59575
  }
@@ -59147,10 +59587,10 @@ async function handleCouncilGet(_req, res, params, contextRoot) {
59147
59587
  updated_at: String(fmRaw.updated_at ?? "")
59148
59588
  };
59149
59589
  const roundLogFile = join84(debateDir, "round-log.md");
59150
- const roundLog = existsSync86(roundLogFile) ? readFrontmatter(roundLogFile).content : null;
59590
+ const roundLog = existsSync87(roundLogFile) ? readFrontmatter(roundLogFile).content : null;
59151
59591
  const finalReportFile = join84(debateDir, "final-report.md");
59152
59592
  let finalReport = null;
59153
- if (existsSync86(finalReportFile)) {
59593
+ if (existsSync87(finalReportFile)) {
59154
59594
  const parsed = readFrontmatter(finalReportFile);
59155
59595
  finalReport = { frontmatter: parsed.data, content: parsed.content };
59156
59596
  }
@@ -59180,7 +59620,7 @@ async function handleCouncilResearchGet(_req, res, params, contextRoot) {
59180
59620
  councilDir,
59181
59621
  join84(councilDir, debateId, personaSlug, "researches", `${researchSlug}.md`)
59182
59622
  );
59183
- if (!researchFile || !existsSync86(researchFile)) {
59623
+ if (!researchFile || !existsSync87(researchFile)) {
59184
59624
  sendError(res, 404, "not_found", `Research not found: ${researchSlug}`);
59185
59625
  return;
59186
59626
  }
@@ -59345,9 +59785,9 @@ var init_config = __esm({
59345
59785
 
59346
59786
  // src/server/routes/vaults.ts
59347
59787
  import { dirname as dirname48, resolve as resolve19 } from "path";
59348
- import { existsSync as existsSync87 } from "fs";
59788
+ import { existsSync as existsSync88 } from "fs";
59349
59789
  async function handleVaultsGet(_req, res, _params, contextRoot) {
59350
- const vaults = listVaults().map((v) => ({ ...v, exists: existsSync87(resolve19(v.path)) }));
59790
+ const vaults = listVaults().map((v) => ({ ...v, exists: existsSync88(resolve19(v.path)) }));
59351
59791
  const current = contextRoot ? vaults.find((v) => resolve19(v.path) === resolve19(dirname48(contextRoot)))?.name ?? null : null;
59352
59792
  sendJson(res, 200, { vaults, current });
59353
59793
  }
@@ -59443,7 +59883,7 @@ var init_ensure_cli = __esm({
59443
59883
 
59444
59884
  // src/server/routes/launcher.ts
59445
59885
  import { basename as basename27, isAbsolute as isAbsolute3, join as join85, resolve as resolve20, sep as sep14 } from "path";
59446
- import { existsSync as existsSync88, mkdirSync as mkdirSync43, readdirSync as readdirSync20, statSync as statSync18, createReadStream, readFileSync as readFileSync61, writeFileSync as writeFileSync50 } from "fs";
59886
+ import { existsSync as existsSync89, mkdirSync as mkdirSync43, readdirSync as readdirSync20, statSync as statSync18, createReadStream, readFileSync as readFileSync61, writeFileSync as writeFileSync50 } from "fs";
59447
59887
  import { homedir as homedir6 } from "os";
59448
59888
  import { execFile as execFile2, spawn as spawn4 } from "child_process";
59449
59889
  import { promisify as promisify2 } from "util";
@@ -59467,7 +59907,7 @@ async function handleLauncherDiscover(req, res, _params, _contextRoot) {
59467
59907
  return;
59468
59908
  }
59469
59909
  const resolvedRoot = resolve20(root);
59470
- if (!existsSync88(resolvedRoot)) {
59910
+ if (!existsSync89(resolvedRoot)) {
59471
59911
  sendError(res, 400, "invalid_root", `Path does not exist: ${resolvedRoot}`);
59472
59912
  return;
59473
59913
  }
@@ -59535,14 +59975,14 @@ async function scaffoldProject(a, runner = defaultCliRunner, home) {
59535
59975
  throw new ScaffoldError("parentDir must be an absolute path.");
59536
59976
  }
59537
59977
  const resolvedParent = resolve20(parentDir);
59538
- if (!existsSync88(resolvedParent) || !statSync18(resolvedParent).isDirectory()) {
59978
+ if (!existsSync89(resolvedParent) || !statSync18(resolvedParent).isDirectory()) {
59539
59979
  throw new ScaffoldError(`Parent directory does not exist: ${resolvedParent}`);
59540
59980
  }
59541
59981
  target = resolve20(resolvedParent, name);
59542
59982
  if (target !== join85(resolvedParent, name) || !target.startsWith(resolvedParent + sep14)) {
59543
59983
  throw new ScaffoldError("Resolved project path escapes the parent directory.");
59544
59984
  }
59545
- if (isNonEmptyDir(target) && !existsSync88(join85(target, "_dream_context"))) {
59985
+ if (isNonEmptyDir(target) && !existsSync89(join85(target, "_dream_context"))) {
59546
59986
  throw new ScaffoldError(`A non-empty folder already exists at ${target}.`);
59547
59987
  }
59548
59988
  mkdirSync43(target, { recursive: true });
@@ -59552,13 +59992,13 @@ async function scaffoldProject(a, runner = defaultCliRunner, home) {
59552
59992
  throw new ScaffoldError("projectPath must be an absolute path.");
59553
59993
  }
59554
59994
  target = resolve20(projectPath);
59555
- if (!existsSync88(target) || !statSync18(target).isDirectory()) {
59995
+ if (!existsSync89(target) || !statSync18(target).isDirectory()) {
59556
59996
  throw new ScaffoldError(`Folder does not exist: ${target}`);
59557
59997
  }
59558
59998
  } else {
59559
59999
  throw new ScaffoldError("mode must be 'new' or 'existing'.");
59560
60000
  }
59561
- const alreadyProject = existsSync88(join85(target, "_dream_context"));
60001
+ const alreadyProject = existsSync89(join85(target, "_dream_context"));
59562
60002
  if (!alreadyProject) {
59563
60003
  const initArgs = ["init", "--yes", "--platforms", platformArg, "--name", name];
59564
60004
  if (a.description?.trim()) initArgs.push("--description", a.description.trim());
@@ -59613,13 +60053,13 @@ async function handleLauncherDetect(req, res, _params, _contextRoot) {
59613
60053
  return;
59614
60054
  }
59615
60055
  const resolved = resolve20(path2);
59616
- if (!existsSync88(resolved)) {
60056
+ if (!existsSync89(resolved)) {
59617
60057
  sendError(res, 400, "invalid_path", `Path does not exist: ${resolved}`);
59618
60058
  return;
59619
60059
  }
59620
60060
  sendJson(res, 200, {
59621
60061
  stack: detectTechStack(resolved) ?? "",
59622
- hasContext: existsSync88(join85(resolved, "_dream_context")),
60062
+ hasContext: existsSync89(join85(resolved, "_dream_context")),
59623
60063
  name: basename27(resolved)
59624
60064
  });
59625
60065
  }
@@ -59646,7 +60086,7 @@ async function handleSleepyConfigGet(_req, res, _params, _contextRoot) {
59646
60086
  let hotkey = "Alt+Cmd+S";
59647
60087
  try {
59648
60088
  const p = sleepyConfigPath();
59649
- if (existsSync88(p)) {
60089
+ if (existsSync89(p)) {
59650
60090
  const raw = JSON.parse(readFileSync61(p, "utf-8"));
59651
60091
  enabled = raw.enabled === true;
59652
60092
  if (typeof raw.hotkey === "string" && raw.hotkey.trim()) hotkey = raw.hotkey;
@@ -59692,7 +60132,7 @@ async function handleAgentSettingsGet(_req, res, _params, _contextRoot) {
59692
60132
  let settings = { ...AGENT_UI_DEFAULTS };
59693
60133
  try {
59694
60134
  const p = agentSettingsPath();
59695
- if (existsSync88(p)) {
60135
+ if (existsSync89(p)) {
59696
60136
  settings = coerceAgentSettings(JSON.parse(readFileSync61(p, "utf-8")));
59697
60137
  }
59698
60138
  } catch {
@@ -59729,7 +60169,7 @@ async function handleSleepyVideo(req, res, _params, _contextRoot) {
59729
60169
  return;
59730
60170
  }
59731
60171
  const file = join85(dir, `${mode}.mp4`);
59732
- if (!existsSync88(file)) {
60172
+ if (!existsSync89(file)) {
59733
60173
  res.writeHead(404);
59734
60174
  res.end();
59735
60175
  return;
@@ -59761,7 +60201,7 @@ async function handleSleepyAnim(req, res, _params, _contextRoot) {
59761
60201
  }
59762
60202
  const dir = process.env.DREAMCONTEXT_SLEEPY_DIR;
59763
60203
  const file = dir ? join85(dir, `${mode}.webp`) : "";
59764
- if (!file || !existsSync88(file)) {
60204
+ if (!file || !existsSync89(file)) {
59765
60205
  res.writeHead(404);
59766
60206
  res.end();
59767
60207
  return;
@@ -59813,14 +60253,14 @@ async function handleLauncherCapture(req, res, _params, _contextRoot) {
59813
60253
  return;
59814
60254
  }
59815
60255
  const cwd = resolve20(vault.path);
59816
- if (!existsSync88(cwd)) {
60256
+ if (!existsSync89(cwd)) {
59817
60257
  sendError(res, 400, "missing_vault", `Vault path no longer exists: ${cwd}`);
59818
60258
  return;
59819
60259
  }
59820
60260
  if (mode === "learn") {
59821
60261
  try {
59822
60262
  const changelogPath = join85(cwd, "_dream_context", "core", "CHANGELOG.json");
59823
- if (!existsSync88(changelogPath)) {
60263
+ if (!existsSync89(changelogPath)) {
59824
60264
  sendError(res, 400, "not_initialized", `"${vaultName}" has no _dream_context \u2014 run init first.`);
59825
60265
  return;
59826
60266
  }
@@ -59940,7 +60380,7 @@ async function handleLauncherDefaults(_req, res, _params, _contextRoot) {
59940
60380
  sendJson(res, 200, { home, defaultParent: join85(home, "projects") });
59941
60381
  }
59942
60382
  function computeVaultStatus(v, latest) {
59943
- const exists = existsSync88(resolve20(v.path));
60383
+ const exists = existsSync89(resolve20(v.path));
59944
60384
  let setupVersion = "0.0.0";
59945
60385
  let shareable = false;
59946
60386
  if (exists) {
@@ -59992,7 +60432,7 @@ async function handleLauncherUpdate(req, res, _params, _contextRoot) {
59992
60432
  return;
59993
60433
  }
59994
60434
  const target = resolve20(vault.path);
59995
- if (!existsSync88(target)) {
60435
+ if (!existsSync89(target)) {
59996
60436
  sendError(res, 400, "missing_vault", `Vault path no longer exists: ${target}`);
59997
60437
  return;
59998
60438
  }
@@ -60071,7 +60511,7 @@ async function handleLauncherUpgradeStatus(_req, res, _params, _contextRoot) {
60071
60511
  async function handleLauncherRelaunch(_req, res, _params, _contextRoot) {
60072
60512
  const manifest = readAppManifest();
60073
60513
  const appPath = manifest?.path;
60074
- if (!appPath || !existsSync88(appPath)) {
60514
+ if (!appPath || !existsSync89(appPath)) {
60075
60515
  sendJson(res, 200, { ok: false, reason: "app_not_installed" });
60076
60516
  return;
60077
60517
  }
@@ -60098,7 +60538,7 @@ async function handleLauncherFederationGraph(_req, res, _params, _contextRoot) {
60098
60538
  const connections = [];
60099
60539
  const seen = /* @__PURE__ */ new Set();
60100
60540
  for (const v of vaults) {
60101
- if (!existsSync88(resolve20(v.path))) continue;
60541
+ if (!existsSync89(resolve20(v.path))) continue;
60102
60542
  const conns = listConnections(join85(resolve20(v.path), "_dream_context"));
60103
60543
  for (const c of conns) {
60104
60544
  if (!known.has(c.vault)) continue;
@@ -60257,7 +60697,7 @@ async function handleLauncherShareable(req, res, _params, _contextRoot) {
60257
60697
  return;
60258
60698
  }
60259
60699
  const root = resolve20(vault.path);
60260
- if (!existsSync88(root)) {
60700
+ if (!existsSync89(root)) {
60261
60701
  sendError(res, 400, "missing_vault", `Vault path no longer exists: ${root}`);
60262
60702
  return;
60263
60703
  }
@@ -60333,13 +60773,13 @@ var init_launcher = __esm({
60333
60773
 
60334
60774
  // src/server/routes/ui-settings.ts
60335
60775
  import { dirname as dirname50, join as join86 } from "path";
60336
- import { existsSync as existsSync89, mkdirSync as mkdirSync44, readFileSync as readFileSync62, writeFileSync as writeFileSync51 } from "fs";
60776
+ import { existsSync as existsSync90, mkdirSync as mkdirSync44, readFileSync as readFileSync62, writeFileSync as writeFileSync51 } from "fs";
60337
60777
  function settingsPath(contextRoot) {
60338
60778
  return join86(contextRoot, BRAIN_SETTINGS_REL_PATH);
60339
60779
  }
60340
60780
  async function handleBrainSettingsGet(_req, res, _params, contextRoot) {
60341
60781
  const path2 = settingsPath(contextRoot);
60342
- if (!existsSync89(path2)) {
60782
+ if (!existsSync90(path2)) {
60343
60783
  sendJson(res, 200, { settings: {} });
60344
60784
  return;
60345
60785
  }
@@ -60381,7 +60821,7 @@ function makeSettingsHandlers(relPath, logTag) {
60381
60821
  const pathFor = (contextRoot) => join86(contextRoot, relPath);
60382
60822
  const get = async (_req, res, _params, contextRoot) => {
60383
60823
  const path2 = pathFor(contextRoot);
60384
- if (!existsSync89(path2)) {
60824
+ if (!existsSync90(path2)) {
60385
60825
  sendJson(res, 200, { settings: {} });
60386
60826
  return;
60387
60827
  }
@@ -60870,7 +61310,7 @@ var init_lab2 = __esm({
60870
61310
 
60871
61311
  // src/server/routes/board.ts
60872
61312
  import { dirname as dirname52, join as join87 } from "path";
60873
- import { existsSync as existsSync90, mkdirSync as mkdirSync45, readFileSync as readFileSync63, writeFileSync as writeFileSync52 } from "fs";
61313
+ import { existsSync as existsSync91, mkdirSync as mkdirSync45, readFileSync as readFileSync63, writeFileSync as writeFileSync52 } from "fs";
60874
61314
  function sharedPath(contextRoot) {
60875
61315
  return join87(contextRoot, SHARED_REL_PATH);
60876
61316
  }
@@ -60878,7 +61318,7 @@ function localPath(contextRoot) {
60878
61318
  return join87(contextRoot, LOCAL_REL_PATH);
60879
61319
  }
60880
61320
  function readBlob(path2) {
60881
- if (!existsSync90(path2)) return {};
61321
+ if (!existsSync91(path2)) return {};
60882
61322
  try {
60883
61323
  const raw = JSON.parse(readFileSync63(path2, "utf-8"));
60884
61324
  return raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
@@ -60959,7 +61399,7 @@ var init_board = __esm({
60959
61399
  // src/server/routes/sleepy-chat.ts
60960
61400
  import { spawn as spawn5 } from "child_process";
60961
61401
  import { dirname as dirname53, join as join88 } from "path";
60962
- import { existsSync as existsSync91, mkdirSync as mkdirSync46, readFileSync as readFileSync64, writeFileSync as writeFileSync53 } from "fs";
61402
+ import { existsSync as existsSync92, mkdirSync as mkdirSync46, readFileSync as readFileSync64, writeFileSync as writeFileSync53 } from "fs";
60963
61403
  import { randomUUID as randomUUID5 } from "crypto";
60964
61404
  function modelFor(tier) {
60965
61405
  return tier === "intelligent" ? "opus" : "sonnet";
@@ -61003,7 +61443,7 @@ function readStore(contextRoot) {
61003
61443
  function writeStore(contextRoot, store) {
61004
61444
  try {
61005
61445
  const dir = join88(contextRoot, "state");
61006
- if (!existsSync91(dir)) mkdirSync46(dir, { recursive: true });
61446
+ if (!existsSync92(dir)) mkdirSync46(dir, { recursive: true });
61007
61447
  store.messages = store.messages.slice(-MESSAGES_MAX);
61008
61448
  writeFileSync53(storePath(contextRoot), JSON.stringify(store, null, 2), "utf-8");
61009
61449
  } catch (err) {
@@ -65101,21 +65541,21 @@ var init_wrapper = __esm({
65101
65541
  // src/server/routes/agent-terminal.ts
65102
65542
  import { spawn as spawn6 } from "child_process";
65103
65543
  import { randomUUID as randomUUID6 } from "crypto";
65104
- import { createRequire } from "module";
65544
+ import { createRequire as createRequire2 } from "module";
65105
65545
  import { basename as basename28, dirname as dirname54, join as join89 } from "path";
65106
- import { existsSync as existsSync92, readdirSync as readdirSync21, statSync as statSync19, chmodSync as chmodSync6, readFileSync as readFileSync65 } from "fs";
65546
+ import { existsSync as existsSync93, readdirSync as readdirSync21, statSync as statSync19, chmodSync as chmodSync6, readFileSync as readFileSync65 } from "fs";
65107
65547
  import { homedir as homedir7 } from "os";
65108
65548
  function ensurePtyHelperExecutable() {
65109
65549
  try {
65110
- const require2 = createRequire(import.meta.url);
65550
+ const require2 = createRequire2(import.meta.url);
65111
65551
  const root = dirname54(dirname54(require2.resolve("node-pty")));
65112
65552
  const candidates = [join89(root, "build", "Release", "spawn-helper")];
65113
65553
  const prebuilds = join89(root, "prebuilds");
65114
- if (existsSync92(prebuilds)) {
65554
+ if (existsSync93(prebuilds)) {
65115
65555
  for (const d of readdirSync21(prebuilds)) candidates.push(join89(prebuilds, d, "spawn-helper"));
65116
65556
  }
65117
65557
  for (const p of candidates) {
65118
- if (!existsSync92(p)) continue;
65558
+ if (!existsSync93(p)) continue;
65119
65559
  const mode = statSync19(p).mode;
65120
65560
  if ((mode & 73) !== 73) chmodSync6(p, mode | 493);
65121
65561
  }
@@ -65170,7 +65610,7 @@ function resolveVaultProjectRoot(name) {
65170
65610
  if (!name) return null;
65171
65611
  if (/[/\\:.\x00]/.test(name)) return null;
65172
65612
  const v = listVaults().find((x) => x.name === name);
65173
- if (!v || !existsSync92(v.path)) return null;
65613
+ if (!v || !existsSync93(v.path)) return null;
65174
65614
  return v.path;
65175
65615
  }
65176
65616
  async function handleAgentCapabilities(_req, res) {
@@ -65242,7 +65682,7 @@ function cliPackageRoot() {
65242
65682
  let dir = process.argv[1] ? dirname54(process.argv[1]) : "";
65243
65683
  if (!dir) return null;
65244
65684
  for (let i = 0; i < 8; i++) {
65245
- if (existsSync92(join89(dir, "package.json"))) return dir;
65685
+ if (existsSync93(join89(dir, "package.json"))) return dir;
65246
65686
  const parent = dirname54(dir);
65247
65687
  if (parent === dir) break;
65248
65688
  dir = parent;
@@ -65419,12 +65859,12 @@ function findFirstTranscriptPath(ids) {
65419
65859
  if (wanted.length === 0) return null;
65420
65860
  try {
65421
65861
  const base = join89(homedir7(), ".claude", "projects");
65422
- if (!existsSync92(base)) return null;
65862
+ if (!existsSync93(base)) return null;
65423
65863
  const dirs = readdirSync21(base);
65424
65864
  for (const id of wanted) {
65425
65865
  for (const dir of dirs) {
65426
65866
  const p = join89(base, dir, `${id}.jsonl`);
65427
- if (existsSync92(p)) return p;
65867
+ if (existsSync93(p)) return p;
65428
65868
  }
65429
65869
  }
65430
65870
  } catch {
@@ -65964,7 +66404,7 @@ var init_agent_drop = __esm({
65964
66404
 
65965
66405
  // src/server/routes/agent-sessions.ts
65966
66406
  import { join as join91, dirname as dirname55 } from "path";
65967
- import { existsSync as existsSync93, mkdirSync as mkdirSync48, readFileSync as readFileSync66, writeFileSync as writeFileSync55, renameSync as renameSync17 } from "fs";
66407
+ import { existsSync as existsSync94, mkdirSync as mkdirSync48, readFileSync as readFileSync66, writeFileSync as writeFileSync55, renameSync as renameSync17 } from "fs";
65968
66408
  import { randomUUID as randomUUID8 } from "crypto";
65969
66409
  function storePath2(contextRoot) {
65970
66410
  return join91(contextRoot, ROSTER_REL_PATH);
@@ -66004,7 +66444,7 @@ function writeRoster(contextRoot, sessions) {
66004
66444
  } catch {
66005
66445
  }
66006
66446
  const dir = join91(contextRoot, "state");
66007
- if (!existsSync93(dir)) mkdirSync48(dir, { recursive: true });
66447
+ if (!existsSync94(dir)) mkdirSync48(dir, { recursive: true });
66008
66448
  const path2 = storePath2(contextRoot);
66009
66449
  const tmp = `${path2}.${randomUUID8()}.tmp`;
66010
66450
  writeFileSync55(tmp, JSON.stringify({ sessions }, null, 2) + "\n", "utf-8");
@@ -66142,7 +66582,7 @@ var init_connections2 = __esm({
66142
66582
  });
66143
66583
 
66144
66584
  // src/lib/federation-digest.ts
66145
- import { existsSync as existsSync94 } from "fs";
66585
+ import { existsSync as existsSync95 } from "fs";
66146
66586
  import { join as join92 } from "path";
66147
66587
  function buildInterestProfile(peerRoot, topics) {
66148
66588
  if (topics && topics.length > 0) {
@@ -66163,7 +66603,7 @@ function buildInterestProfile(peerRoot, topics) {
66163
66603
  }
66164
66604
  function activeTaskTerms(peerRoot) {
66165
66605
  const stateDir = join92(peerRoot, "state");
66166
- if (!existsSync94(stateDir)) return [];
66606
+ if (!existsSync95(stateDir)) return [];
66167
66607
  let files;
66168
66608
  try {
66169
66609
  files = import_fast_glob21.default.sync("*.md", { cwd: stateDir, absolute: true });
@@ -66521,8 +66961,10 @@ function corpusFor(contextRoot, types) {
66521
66961
  async function handleRecallGet(req, res, _params, contextRoot) {
66522
66962
  const url = new URL(req.url ?? "/", `http://${req.headers.host ?? "localhost"}`);
66523
66963
  const query = (url.searchParams.get("q") ?? "").trim();
66964
+ const useHybrid = hybridReady(contextRoot, resolveRecallMode(contextRoot));
66965
+ const mode = useHybrid ? "hybrid" : "bm25";
66524
66966
  if (!query) {
66525
- sendJson(res, 200, { query: "", hits: [], tookMs: 0 });
66967
+ sendJson(res, 200, { query: "", mode, hits: [], tookMs: 0 });
66526
66968
  return;
66527
66969
  }
66528
66970
  const types = parseTypes(url.searchParams.get("types")) ?? ALL_TYPES;
@@ -66531,9 +66973,9 @@ async function handleRecallGet(req, res, _params, contextRoot) {
66531
66973
  try {
66532
66974
  const started = Date.now();
66533
66975
  const corpus = corpusFor(contextRoot, types);
66534
- const hits = bm25Search(query, corpus, topK);
66976
+ const hits = useHybrid ? await hybridSearch(query, corpus, contextRoot, topK) : bm25Search(query, corpus, topK);
66535
66977
  const tookMs = Date.now() - started;
66536
- sendJson(res, 200, { query, tookMs, hits: hits.map(serializeHit) });
66978
+ sendJson(res, 200, { query, mode, tookMs, hits: hits.map(serializeHit) });
66537
66979
  } catch (err) {
66538
66980
  sendError(res, 500, "recall_failed", err instanceof Error ? err.message : "Recall failed");
66539
66981
  }
@@ -66572,7 +67014,9 @@ var init_recall2 = __esm({
66572
67014
  "src/server/routes/recall.ts"() {
66573
67015
  "use strict";
66574
67016
  init_recall();
67017
+ init_hybrid();
66575
67018
  init_recall_query_extractor();
67019
+ init_sleep();
66576
67020
  init_middleware();
66577
67021
  ALL_TYPES = ["knowledge", "feature", "task", "memory", "changelog"];
66578
67022
  CORPUS_TTL_MS = 8e3;
@@ -66890,8 +67334,88 @@ var init_team_fetch = __esm({
66890
67334
  }
66891
67335
  });
66892
67336
 
67337
+ // src/lib/git-sync/failure.ts
67338
+ function githubSlug(s) {
67339
+ const m = s.match(/github\.com[/:]([^/\s]+\/[^/\s'".]+)/i);
67340
+ return m ? m[1].replace(/\.git$/, "") : void 0;
67341
+ }
67342
+ function extractRepo(message, fallbackRepo) {
67343
+ const perm = message.match(/Permission to ([^\s]+?)(?:\.git)? denied/i);
67344
+ if (perm) return perm[1];
67345
+ const fromMsg = githubSlug(message);
67346
+ if (fromMsg) return fromMsg;
67347
+ if (fallbackRepo) return githubSlug(fallbackRepo) ?? fallbackRepo;
67348
+ return void 0;
67349
+ }
67350
+ function classifySyncError(rawMessage, repoHint) {
67351
+ const m = rawMessage || "";
67352
+ const repo = extractRepo(m, repoHint);
67353
+ const named = repo ? ` on ${repo}` : "";
67354
+ if (/non-fast-forward.*twice|rejected.*non-fast-forward|Push rejected \(non-fast-forward\) twice/i.test(m)) {
67355
+ return {
67356
+ kind: "push-rejected",
67357
+ recovery: "retry",
67358
+ repo,
67359
+ message: "The team pushed while your sync was in flight. Retry \u2014 dreamcontext will merge their changes and push again."
67360
+ };
67361
+ }
67362
+ if (/Contents\b.*write|permission to .* denied|protected branch|not authorized|remote: Permission|must have push access|403\b/i.test(m)) {
67363
+ return {
67364
+ kind: "permission",
67365
+ recovery: "check-permissions",
67366
+ repo,
67367
+ message: `Your GitHub token can't write to${named || " this repo"}. Give it Contents (read & write) access${repo ? ` on ${repo}` : ""}, then retry.`
67368
+ };
67369
+ }
67370
+ if (/authentication failed|could not read Username|bad credentials|invalid credentials|401\b|terminal prompts disabled|Support for password authentication|no github token found/i.test(m)) {
67371
+ return {
67372
+ kind: "auth",
67373
+ recovery: "reconnect-github",
67374
+ repo,
67375
+ message: "Your GitHub sign-in expired or is invalid. Reconnect GitHub to keep syncing."
67376
+ };
67377
+ }
67378
+ if (/could ?n[o']t resolve host|could not resolve host|connection timed out|failed to connect|network is unreachable|temporary failure in name resolution|unable to access .*(?:Could not resolve|timed out|Failed to connect)|getaddrinfo|ENOTFOUND|ETIMEDOUT/i.test(m)) {
67379
+ return {
67380
+ kind: "network",
67381
+ recovery: "wait-online",
67382
+ repo,
67383
+ message: "You're offline \u2014 sync will retry automatically when you're back online. Nothing was lost."
67384
+ };
67385
+ }
67386
+ if (/unrelated histories/i.test(m)) {
67387
+ return {
67388
+ kind: "unknown",
67389
+ recovery: "manual",
67390
+ repo,
67391
+ message: "The remote contains content that did not come from this brain (e.g. a README). Attach an empty repo or reconcile the histories manually."
67392
+ };
67393
+ }
67394
+ return {
67395
+ kind: "unknown",
67396
+ recovery: "retry",
67397
+ repo,
67398
+ message: rawMessage.trim() || "Sync failed. Retry, or check your connection and GitHub access."
67399
+ };
67400
+ }
67401
+ var init_failure = __esm({
67402
+ "src/lib/git-sync/failure.ts"() {
67403
+ "use strict";
67404
+ }
67405
+ });
67406
+
66893
67407
  // src/server/routes/brain.ts
66894
67408
  import { dirname as dirname61 } from "path";
67409
+ function mergeKindFor(contextRoot, hasMergeHead2, pendingAgentMerge) {
67410
+ if (hasMergeHead2) {
67411
+ const report = readConflictReport(contextRoot);
67412
+ if (!report) return "user";
67413
+ if (report.codeConflicts && report.codeConflicts.length > 0) return "code";
67414
+ return "agent";
67415
+ }
67416
+ if (pendingAgentMerge) return "agent";
67417
+ return null;
67418
+ }
66895
67419
  function gate2(res) {
66896
67420
  if (!isDesktop()) {
66897
67421
  sendError(res, 403, "desktop_only", "Brain cloud-sync is only available in the desktop app.");
@@ -66921,6 +67445,17 @@ async function handleBrainStatus(_req, res, _params, contextRoot) {
66921
67445
  } catch {
66922
67446
  mergeInProgress = false;
66923
67447
  }
67448
+ } else if (mode === "full-repo") {
67449
+ try {
67450
+ remote = isGitRepo(projectRoot) ? getRemoteUrl(projectRoot, "origin") : null;
67451
+ } catch {
67452
+ remote = null;
67453
+ }
67454
+ try {
67455
+ mergeInProgress = hasMergeHead(projectRoot);
67456
+ } catch {
67457
+ mergeInProgress = false;
67458
+ }
66924
67459
  }
66925
67460
  let codeOrigin = null;
66926
67461
  try {
@@ -66928,6 +67463,15 @@ async function handleBrainStatus(_req, res, _params, contextRoot) {
66928
67463
  } catch {
66929
67464
  codeOrigin = null;
66930
67465
  }
67466
+ const mergeKind = mergeKindFor(contextRoot, mergeInProgress, !!local.pendingAgentMerge);
67467
+ let codeConflicts = [];
67468
+ if (mergeKind === "code") {
67469
+ try {
67470
+ codeConflicts = readConflictReport(contextRoot)?.codeConflicts ?? [];
67471
+ } catch {
67472
+ codeConflicts = [];
67473
+ }
67474
+ }
66931
67475
  sendJson(res, 200, {
66932
67476
  enabled: enabled.enabled,
66933
67477
  source: enabled.source,
@@ -66936,6 +67480,8 @@ async function handleBrainStatus(_req, res, _params, contextRoot) {
66936
67480
  hasRemote: !!remote,
66937
67481
  codeOrigin,
66938
67482
  mergeInProgress,
67483
+ mergeKind,
67484
+ codeConflicts,
66939
67485
  pendingAgentMerge: !!local.pendingAgentMerge,
66940
67486
  pulledUpdates: local.pulledUpdates ?? 0
66941
67487
  });
@@ -67077,18 +67623,48 @@ async function handleBrainDisconnect(_req, res, _params, contextRoot) {
67077
67623
  }
67078
67624
  async function handleBrainSync(req, res, _params, contextRoot) {
67079
67625
  if (!gate2(res)) return;
67626
+ const projectRoot = dirname61(contextRoot);
67080
67627
  const body = await parseJsonBody(req);
67081
67628
  const mode = body?.mode === "auto" ? "auto" : "pull-only";
67629
+ const foreground = body?.foreground !== false;
67630
+ const noCheckpoint = body?.noCheckpoint === true;
67082
67631
  try {
67083
- const result = await runBrainSync({ cwd: contextRoot, mode });
67632
+ const result = await runBrainSync({ cwd: contextRoot, mode, foreground, noCheckpoint });
67633
+ let failure;
67634
+ if (result.action === "no-remote" && /token/i.test(result.note ?? "")) {
67635
+ failure = classifySyncError(result.note ?? "no github token found", syncRepoHint(projectRoot, result));
67636
+ }
67084
67637
  sendJson(res, 200, {
67085
67638
  action: result.action,
67086
67639
  pulledUpdates: result.pulledUpdates ?? 0,
67087
67640
  scrub: { blocks: result.scrub.blocks, warns: result.scrub.warns },
67088
- note: result.note
67641
+ note: result.note,
67642
+ checkpointed: !!result.checkpointed,
67643
+ checkpointSha: result.checkpointSha,
67644
+ codeConflicts: result.codeConflicts,
67645
+ failure
67089
67646
  });
67090
67647
  } catch (err) {
67091
- sendError(res, 502, "sync_failed", err.message);
67648
+ const failure = classifySyncError(err.message, syncRepoHint(projectRoot));
67649
+ sendJson(res, 200, {
67650
+ action: "error",
67651
+ pulledUpdates: 0,
67652
+ scrub: { blocks: [], warns: [] },
67653
+ note: failure.message,
67654
+ failure
67655
+ });
67656
+ }
67657
+ }
67658
+ function syncRepoHint(projectRoot, _result) {
67659
+ const config = readSetupConfig(projectRoot);
67660
+ const mode = resolveMode2(config);
67661
+ try {
67662
+ if (mode === "full-repo" || mode === "in-tree") {
67663
+ return (isGitRepo(projectRoot) ? getRemoteUrl(projectRoot, "origin") : null) ?? void 0;
67664
+ }
67665
+ return config?.brainRepo?.remote ?? void 0;
67666
+ } catch {
67667
+ return config?.brainRepo?.remote ?? void 0;
67092
67668
  }
67093
67669
  }
67094
67670
  async function handleBrainSettingsGet2(_req, res, _params, contextRoot) {
@@ -67127,6 +67703,82 @@ async function handleBrainSettingsPost(req, res, _params, contextRoot) {
67127
67703
  remote: next?.brainRepo?.remote ?? null
67128
67704
  });
67129
67705
  }
67706
+ async function handleBrainScope(req, res, _params, contextRoot) {
67707
+ if (!gate2(res)) return;
67708
+ const projectRoot = dirname61(contextRoot);
67709
+ const body = await parseJsonBody(req);
67710
+ const scope = body?.scope === "full-repo" ? "full-repo" : body?.scope === "brain" ? "brain" : null;
67711
+ if (!scope) {
67712
+ sendError(res, 400, "invalid_body", "scope must be 'full-repo' or 'brain'.");
67713
+ return;
67714
+ }
67715
+ const config = readSetupConfig(projectRoot);
67716
+ const existing = config?.brainRepo ?? { mode: "in-tree" };
67717
+ if (scope === "full-repo") {
67718
+ let origin = null;
67719
+ try {
67720
+ origin = isGitRepo(projectRoot) ? getRemoteUrl(projectRoot, "origin") : null;
67721
+ } catch {
67722
+ origin = null;
67723
+ }
67724
+ if (!origin) {
67725
+ sendError(res, 400, "no_origin", "Whole-project sync needs a GitHub `origin` on this project. Add one (git remote add origin \u2026) and try again.");
67726
+ return;
67727
+ }
67728
+ updateSetupConfig(projectRoot, {
67729
+ brainRepo: { ...existing, mode: "full-repo", enabled: true, autoSync: true }
67730
+ });
67731
+ ensureFullRepoGitignore(projectRoot, config?.taskBackend);
67732
+ } else {
67733
+ const nextMode = existing.remote ? "separate" : "in-tree";
67734
+ updateSetupConfig(projectRoot, { brainRepo: { ...existing, mode: nextMode } });
67735
+ }
67736
+ const next = readSetupConfig(projectRoot);
67737
+ const resolved = resolveBrainSyncEnabled(projectRoot, next);
67738
+ sendJson(res, 200, {
67739
+ enabled: resolved.enabled,
67740
+ source: resolved.source,
67741
+ mode: resolveMode2(next),
67742
+ autoSync: next?.brainRepo?.autoSync ?? false,
67743
+ remote: next?.brainRepo?.remote ?? null
67744
+ });
67745
+ }
67746
+ function isSafeToGitignore(relPath) {
67747
+ const p = relPath.replace(/\\/g, "/").trim();
67748
+ if (!p) return false;
67749
+ if (/[!#*?[\]\r\n\0]/.test(p)) return false;
67750
+ if (p.startsWith("/") || p.split("/").includes("..")) return false;
67751
+ return SAFE_TO_GITIGNORE.test(p);
67752
+ }
67753
+ async function handleBrainScrubIgnore(req, res, _params, contextRoot) {
67754
+ if (!gate2(res)) return;
67755
+ const projectRoot = dirname61(contextRoot);
67756
+ const body = await parseJsonBody(req);
67757
+ const rawPath = typeof body?.path === "string" ? body.path.trim() : "";
67758
+ if (!rawPath) {
67759
+ sendError(res, 400, "invalid_body", "path is required.");
67760
+ return;
67761
+ }
67762
+ const relPath = rawPath.replace(/\\/g, "/");
67763
+ if (relPath.startsWith("/") || relPath.split("/").includes("..")) {
67764
+ sendError(res, 400, "invalid_path", "That path is not allowed.");
67765
+ return;
67766
+ }
67767
+ if (!isSafeToGitignore(relPath)) {
67768
+ sendError(res, 400, "unsafe_path", "That looks like a real source file \u2014 remove the secret from it instead of un-tracking it.");
67769
+ return;
67770
+ }
67771
+ const mode = resolveMode2(readSetupConfig(projectRoot));
67772
+ const root = mode === "separate" ? contextRoot : projectRoot;
67773
+ try {
67774
+ const added = ensureGitignoreEntries(root, [relPath], {
67775
+ comment: "dreamcontext: excluded a scrub-blocked local secret file (added from the dashboard)"
67776
+ });
67777
+ sendJson(res, 200, { ok: true, added, path: relPath });
67778
+ } catch (err) {
67779
+ sendError(res, 502, "gitignore_failed", err.message);
67780
+ }
67781
+ }
67130
67782
  async function handleBrainTeamUpdates(_req, res) {
67131
67783
  if (!gate2(res)) return;
67132
67784
  const vaults = listVaults().map((v) => {
@@ -67155,6 +67807,7 @@ async function handleBrainTeamFetch(req, res) {
67155
67807
  sendError(res, 502, "team_fetch_failed", err.message);
67156
67808
  }
67157
67809
  }
67810
+ var SAFE_TO_GITIGNORE;
67158
67811
  var init_brain2 = __esm({
67159
67812
  "src/server/routes/brain.ts"() {
67160
67813
  "use strict";
@@ -67169,7 +67822,11 @@ var init_brain2 = __esm({
67169
67822
  init_sync_engine();
67170
67823
  init_auth_store();
67171
67824
  init_team_fetch();
67825
+ init_conflict_report();
67826
+ init_failure();
67827
+ init_gitignore();
67172
67828
  init_vaults();
67829
+ SAFE_TO_GITIGNORE = /(^|\/)([^/]*\.env(\.[^/]+)?|[^/]*\.local\.[^/]+|[^/]*secrets?[^/]*\.(json|ya?ml|toml|env)|credentials?[^/]*\.(json|ya?ml|toml|env)|[^/]*\.(pem|key|p12|pfx|keystore|jks)|id_rsa[^/]*|id_ed25519[^/]*)$/i;
67173
67830
  }
67174
67831
  });
67175
67832
 
@@ -67221,6 +67878,10 @@ function buildRouter() {
67221
67878
  router.post("/api/tasks/:slug/insert", handleTasksInsert);
67222
67879
  router.get("/api/sleep", handleSleepGet);
67223
67880
  router.patch("/api/sleep", handleSleepUpdate);
67881
+ router.get("/api/embeddings/status", handleEmbeddingModelStatus);
67882
+ router.post("/api/embeddings/download", handleEmbeddingModelDownload);
67883
+ router.get("/api/embeddings/index/status", handleEmbeddingIndexStatus);
67884
+ router.post("/api/embeddings/index", handleEmbeddingIndexBuild);
67224
67885
  router.get("/api/core", handleCoreList);
67225
67886
  router.get("/api/core/:filename", handleCoreGet);
67226
67887
  router.put("/api/core/:filename", handleCoreUpdate);
@@ -67246,6 +67907,8 @@ function buildRouter() {
67246
67907
  router.post("/api/brain/sync", handleBrainSync);
67247
67908
  router.get("/api/brain/settings", handleBrainSettingsGet2);
67248
67909
  router.post("/api/brain/settings", handleBrainSettingsPost);
67910
+ router.post("/api/brain/scope", handleBrainScope);
67911
+ router.post("/api/brain/scrub/ignore", handleBrainScrubIgnore);
67249
67912
  router.get("/api/graph", handleGraphGet);
67250
67913
  router.get("/api/graph/content", handleGraphContentGet);
67251
67914
  router.get("/api/council", handleCouncilList);
@@ -67453,6 +68116,7 @@ var init_server = __esm({
67453
68116
  init_health();
67454
68117
  init_tasks2();
67455
68118
  init_sleep2();
68119
+ init_embeddings();
67456
68120
  init_core2();
67457
68121
  init_knowledge2();
67458
68122
  init_changelog();
@@ -67482,7 +68146,7 @@ var init_server = __esm({
67482
68146
  init_lifecycle();
67483
68147
  init_admin();
67484
68148
  init_manifest();
67485
- VAULT_AGNOSTIC_PREFIXES = ["/api/health", "/api/admin/shutdown", "/api/vaults", "/api/launcher", "/api/sleepy", "/api/agent/capabilities", "/api/agent/install", "/api/agent/model-config", "/api/agent/session-model", "/api/agent/session-stats", "/api/brain/auth", "/api/brain/team"];
68149
+ VAULT_AGNOSTIC_PREFIXES = ["/api/health", "/api/admin/shutdown", "/api/vaults", "/api/launcher", "/api/sleepy", "/api/embeddings", "/api/agent/capabilities", "/api/agent/install", "/api/agent/model-config", "/api/agent/session-model", "/api/agent/session-stats", "/api/brain/auth", "/api/brain/team"];
67486
68150
  }
67487
68151
  });
67488
68152
 
@@ -67666,7 +68330,7 @@ var init_trigger = __esm({
67666
68330
  });
67667
68331
 
67668
68332
  // src/lib/reflection.ts
67669
- import { existsSync as existsSync95, mkdirSync as mkdirSync49, writeFileSync as writeFileSync56 } from "fs";
68333
+ import { existsSync as existsSync96, mkdirSync as mkdirSync49, writeFileSync as writeFileSync56 } from "fs";
67670
68334
  import { join as join95, dirname as dirname62 } from "path";
67671
68335
  function buildExclusionSet(corpus, excludedExtra) {
67672
68336
  const excluded = new Set(excludedExtra);
@@ -67848,7 +68512,7 @@ function reflectionPath(root) {
67848
68512
  function writeReflection(root, md) {
67849
68513
  const outPath = reflectionPath(root);
67850
68514
  const dir = dirname62(outPath);
67851
- if (!existsSync95(dir)) {
68515
+ if (!existsSync96(dir)) {
67852
68516
  mkdirSync49(dir, { recursive: true });
67853
68517
  }
67854
68518
  const tsMatch = md.match(/Generated: ([^\n]+)/);
@@ -68036,12 +68700,12 @@ var init_reflection = __esm({
68036
68700
  });
68037
68701
 
68038
68702
  // src/cli/commands/reflect.ts
68039
- import { existsSync as existsSync96, readFileSync as readFileSync69 } from "fs";
68703
+ import { existsSync as existsSync97, readFileSync as readFileSync69 } from "fs";
68040
68704
  import { join as join96 } from "path";
68041
68705
  function buildBookmarkSessions(root) {
68042
68706
  const sleepPath = join96(root, "state", ".sleep.json");
68043
68707
  const result = /* @__PURE__ */ new Map();
68044
- if (!existsSync96(sleepPath)) return result;
68708
+ if (!existsSync97(sleepPath)) return result;
68045
68709
  try {
68046
68710
  const parsed = JSON.parse(readFileSync69(sleepPath, "utf-8"));
68047
68711
  const bookmarks = parsed.bookmarks ?? [];
@@ -68061,7 +68725,7 @@ function buildExcludedExtra(root) {
68061
68725
  join96(root, "core", "1.user.md")
68062
68726
  ];
68063
68727
  for (const filePath of coreFiles) {
68064
- if (!existsSync96(filePath)) continue;
68728
+ if (!existsSync97(filePath)) continue;
68065
68729
  try {
68066
68730
  const content = readFileSync69(filePath, "utf-8");
68067
68731
  for (const tok of tokenize(content)) {
@@ -68114,7 +68778,7 @@ var init_reflect = __esm({
68114
68778
  });
68115
68779
 
68116
68780
  // src/cli/commands/council.ts
68117
- import { existsSync as existsSync97, mkdirSync as mkdirSync50, readFileSync as readFileSync70, writeFileSync as writeFileSync57 } from "fs";
68781
+ import { existsSync as existsSync98, mkdirSync as mkdirSync50, readFileSync as readFileSync70, writeFileSync as writeFileSync57 } from "fs";
68118
68782
  import { join as join97 } from "path";
68119
68783
  function roundRunningStatus(n) {
68120
68784
  return `round_${n}_running`;
@@ -68205,7 +68869,7 @@ function registerAgent(council) {
68205
68869
  }
68206
68870
  const personaDir = getPersonaDir(debateId, slug);
68207
68871
  const personaFile = join97(personaDir, "context-and-persona.md");
68208
- if (existsSync97(personaFile) && !opts.force) {
68872
+ if (existsSync98(personaFile) && !opts.force) {
68209
68873
  error(`Persona already exists: ${slug}`, "Use --force to overwrite.");
68210
68874
  process.exit(1);
68211
68875
  }
@@ -68261,7 +68925,7 @@ function registerRound(council) {
68261
68925
  if (n >= 2) {
68262
68926
  for (const persona of personas) {
68263
68927
  const personaFile = join97(getPersonaDir(debateId, persona), "context-and-persona.md");
68264
- if (!existsSync97(personaFile)) continue;
68928
+ if (!existsSync98(personaFile)) continue;
68265
68929
  const existing = readFileSync70(personaFile, "utf-8");
68266
68930
  if (existing.includes(crossContextHeader)) {
68267
68931
  continue;
@@ -68293,7 +68957,7 @@ ${peerLines.join("\n\n")}`;
68293
68957
  updated_at: today()
68294
68958
  });
68295
68959
  const logFile = join97(getDebateDir(debateId), "round-log.md");
68296
- const logExisting = existsSync97(logFile) ? readFileSync70(logFile, "utf-8") : "";
68960
+ const logExisting = existsSync98(logFile) ? readFileSync70(logFile, "utf-8") : "";
68297
68961
  const logEntry = `
68298
68962
  ## Round ${n} started \u2014 ${today()}
68299
68963
  - Personas: ${formatPersonaList(personas)}
@@ -68338,7 +69002,7 @@ ${peerLines.join("\n\n")}`;
68338
69002
  updated_at: today()
68339
69003
  });
68340
69004
  const logFile = join97(getDebateDir(debateId), "round-log.md");
68341
- const logExisting = existsSync97(logFile) ? readFileSync70(logFile, "utf-8") : "";
69005
+ const logExisting = existsSync98(logFile) ? readFileSync70(logFile, "utf-8") : "";
68342
69006
  const logEntry = `
68343
69007
  ## Round ${n} complete \u2014 ${today()}
68344
69008
  - All ${personas.length} personas submitted reports.
@@ -68488,10 +69152,10 @@ function registerResearch(council) {
68488
69152
  const researchesDir = join97(getPersonaDir(debateId, personaSlug), "researches");
68489
69153
  mkdirSync50(researchesDir, { recursive: true });
68490
69154
  const indexPath2 = join97(researchesDir, "index.json");
68491
- if (!existsSync97(indexPath2)) writeJsonArray(indexPath2, []);
69155
+ if (!existsSync98(indexPath2)) writeJsonArray(indexPath2, []);
68492
69156
  const slug = slugify(topic);
68493
69157
  const file = join97(researchesDir, `${slug}.md`);
68494
- if (existsSync97(file)) {
69158
+ if (existsSync98(file)) {
68495
69159
  error(`Research note already exists: ${slug}.md`);
68496
69160
  process.exit(1);
68497
69161
  }
@@ -68523,7 +69187,7 @@ ${body.trim()}
68523
69187
  ensurePersonaExists(debateId, personaSlug);
68524
69188
  const researchesDir = join97(getPersonaDir(debateId, personaSlug), "researches");
68525
69189
  const indexPath2 = join97(researchesDir, "index.json");
68526
- if (!existsSync97(indexPath2)) {
69190
+ if (!existsSync98(indexPath2)) {
68527
69191
  console.log(source_default.dim("(no researches)"));
68528
69192
  return;
68529
69193
  }
@@ -68568,7 +69232,7 @@ function registerSynthesize(council) {
68568
69232
  manifest.push(`_dream_context/council/${debateId}/${persona}/context-and-persona.md`);
68569
69233
  manifest.push(`_dream_context/council/${debateId}/${persona}/report.md`);
68570
69234
  const researchesIndex = join97(personaDir, "researches", "index.json");
68571
- if (existsSync97(researchesIndex)) {
69235
+ if (existsSync98(researchesIndex)) {
68572
69236
  manifest.push(`_dream_context/council/${debateId}/${persona}/researches/`);
68573
69237
  }
68574
69238
  }
@@ -68587,7 +69251,7 @@ function registerComplete(council) {
68587
69251
  try {
68588
69252
  const data = readDebateFrontmatter(debateId);
68589
69253
  const finalReport = join97(getDebateDir(debateId), "final-report.md");
68590
- if (!existsSync97(finalReport)) {
69254
+ if (!existsSync98(finalReport)) {
68591
69255
  error("final-report.md not found.", "Synthesizer must write it before calling `council complete`.");
68592
69256
  process.exit(1);
68593
69257
  }
@@ -68624,7 +69288,7 @@ function registerPromote(council) {
68624
69288
  process.exit(1);
68625
69289
  }
68626
69290
  const finalReport = join97(getDebateDir(debateId), "final-report.md");
68627
- if (!existsSync97(finalReport)) {
69291
+ if (!existsSync98(finalReport)) {
68628
69292
  error("final-report.md not found.");
68629
69293
  process.exit(1);
68630
69294
  }
@@ -68642,7 +69306,7 @@ ${sec.body.trim()}` : null;
68642
69306
  const slug = slugify(data.topic).slice(0, 80) || debateId;
68643
69307
  const filename = `decision-${slug}.md`;
68644
69308
  const target = join97(knowledgeDir, filename);
68645
- if (existsSync97(target) && !opts.force) {
69309
+ if (existsSync98(target) && !opts.force) {
68646
69310
  error(`Knowledge file exists: ${filename}`, "Use --force to overwrite.");
68647
69311
  process.exit(1);
68648
69312
  }
@@ -68729,7 +69393,7 @@ function registerShow(council) {
68729
69393
  console.log(` created: ${data.created_at}`);
68730
69394
  console.log(` updated: ${data.updated_at}`);
68731
69395
  const logFile = join97(getDebateDir(debateId), "round-log.md");
68732
- if (existsSync97(logFile)) {
69396
+ if (existsSync98(logFile)) {
68733
69397
  console.log("\n" + source_default.dim("\u2500\u2500\u2500 Round log \u2500\u2500\u2500"));
68734
69398
  console.log(readFileSync70(logFile, "utf-8"));
68735
69399
  }
@@ -68923,11 +69587,11 @@ var init_env_loader = __esm({
68923
69587
  });
68924
69588
 
68925
69589
  // src/lib/marketing/config.ts
68926
- import { existsSync as existsSync98, readFileSync as readFileSync71, writeFileSync as writeFileSync58, mkdirSync as mkdirSync51 } from "fs";
69590
+ import { existsSync as existsSync99, readFileSync as readFileSync71, writeFileSync as writeFileSync58, mkdirSync as mkdirSync51 } from "fs";
68927
69591
  import { dirname as dirname63 } from "path";
68928
69592
  function readEnvFile() {
68929
69593
  const path2 = MARKETING_PATHS.envFile();
68930
- if (!existsSync98(path2)) return {};
69594
+ if (!existsSync99(path2)) return {};
68931
69595
  const raw = readFileSync71(path2, "utf8");
68932
69596
  const parsed = parseEnv(raw);
68933
69597
  if (parsed.errors.length > 0) {
@@ -68972,7 +69636,7 @@ function requireEnv(keys = REQUIRED_KEYS) {
68972
69636
  }
68973
69637
  function loadConfig() {
68974
69638
  const path2 = MARKETING_PATHS.configFile();
68975
- if (!existsSync98(path2)) return { ...EMPTY_CONFIG, feature_flags: { ...EMPTY_CONFIG.feature_flags } };
69639
+ if (!existsSync99(path2)) return { ...EMPTY_CONFIG, feature_flags: { ...EMPTY_CONFIG.feature_flags } };
68976
69640
  try {
68977
69641
  const raw = readFileSync71(path2, "utf8");
68978
69642
  const parsed = JSON.parse(raw);
@@ -68994,14 +69658,14 @@ function writeConfig(cfg) {
68994
69658
  }
68995
69659
  function ensureConfigFile() {
68996
69660
  const path2 = MARKETING_PATHS.configFile();
68997
- if (existsSync98(path2)) return loadConfig();
69661
+ if (existsSync99(path2)) return loadConfig();
68998
69662
  const cfg = { ...EMPTY_CONFIG, feature_flags: { ...EMPTY_CONFIG.feature_flags } };
68999
69663
  writeConfig(cfg);
69000
69664
  return cfg;
69001
69665
  }
69002
69666
  function ensureEnvFile() {
69003
69667
  const path2 = MARKETING_PATHS.envFile();
69004
- if (existsSync98(path2)) return;
69668
+ if (existsSync99(path2)) return;
69005
69669
  mkdirSync51(marketingRoot(), { recursive: true });
69006
69670
  writeFileSync58(path2, ENV_TEMPLATE, { encoding: "utf8", mode: 384 });
69007
69671
  }
@@ -69044,7 +69708,7 @@ REINFLUENCE_BIN= # optional override; default uses .venv
69044
69708
 
69045
69709
  // src/lib/marketing/bootstrap.ts
69046
69710
  import { spawn as spawn7, spawnSync as spawnSync2 } from "child_process";
69047
- import { existsSync as existsSync99, mkdirSync as mkdirSync52, cpSync as cpSync3 } from "fs";
69711
+ import { existsSync as existsSync100, mkdirSync as mkdirSync52, cpSync as cpSync3 } from "fs";
69048
69712
  import { fileURLToPath as fileURLToPath9 } from "url";
69049
69713
  import { dirname as dirname64, resolve as resolve22, join as join98 } from "path";
69050
69714
  function findBundledReinfluence() {
@@ -69056,7 +69720,7 @@ function findBundledReinfluence() {
69056
69720
  resolve22(__dirname7, "..", "..", "..", "tools", "reinfluence")
69057
69721
  ];
69058
69722
  for (const c of candidates) {
69059
- if (existsSync99(join98(c, "__main__.py"))) return c;
69723
+ if (existsSync100(join98(c, "__main__.py"))) return c;
69060
69724
  }
69061
69725
  throw new Error(
69062
69726
  "Bundled reinfluence not found. Reinstall dreamcontext or set REINFLUENCE_BIN."
@@ -69098,7 +69762,7 @@ async function bootstrapMarketing(opts = {}) {
69098
69762
  throw new Error("python3 not found on PATH. Install Python 3.10+ and retry.");
69099
69763
  }
69100
69764
  const venv = MARKETING_PATHS.venvDir();
69101
- if (!existsSync99(MARKETING_PATHS.venvPython())) {
69765
+ if (!existsSync100(MARKETING_PATHS.venvPython())) {
69102
69766
  log(`creating venv \u2192 ${venv}`);
69103
69767
  const r2 = runBlocking(py, ["-m", "venv", venv]);
69104
69768
  if (r2.code !== 0) {
@@ -69169,7 +69833,7 @@ function subprocessEnv() {
69169
69833
  };
69170
69834
  }
69171
69835
  function isBootstrapped() {
69172
- return existsSync99(MARKETING_PATHS.venvPython()) && existsSync99(join98(MARKETING_PATHS.reinfluenceDir(), "__main__.py"));
69836
+ return existsSync100(MARKETING_PATHS.venvPython()) && existsSync100(join98(MARKETING_PATHS.reinfluenceDir(), "__main__.py"));
69173
69837
  }
69174
69838
  var __filename, __dirname7;
69175
69839
  var init_bootstrap = __esm({
@@ -69246,7 +69910,7 @@ var init_init2 = __esm({
69246
69910
  });
69247
69911
 
69248
69912
  // src/lib/marketing/vision.ts
69249
- import { existsSync as existsSync100, readFileSync as readFileSync72, writeFileSync as writeFileSync59 } from "fs";
69913
+ import { existsSync as existsSync101, readFileSync as readFileSync72, writeFileSync as writeFileSync59 } from "fs";
69250
69914
  import { dirname as dirname65, join as join99 } from "path";
69251
69915
  function pickVisionProvider(env2 = process.env) {
69252
69916
  const oai = env2.OPENAI_VISION_API_KEY;
@@ -69290,7 +69954,7 @@ async function readImageAsBase64(framePath) {
69290
69954
  return buf.toString("base64");
69291
69955
  }
69292
69956
  async function labelHookFrame(framePath, opts) {
69293
- if (!existsSync100(framePath)) return [];
69957
+ if (!existsSync101(framePath)) return [];
69294
69958
  const fetcher = opts.fetcher ?? defaultFetcher;
69295
69959
  const prompt = opts.promptOverride ?? PROMPT;
69296
69960
  const b64 = await readImageAsBase64(framePath);
@@ -69383,7 +70047,7 @@ async function runVisionPassOnPost(postJsonPath, opts = {}) {
69383
70047
  const fs = await import("fs");
69384
70048
  fs.renameSync(tmp, postJsonPath);
69385
70049
  const mdPath = join99(dirname65(postJsonPath), `${shortcode}.md`);
69386
- if (existsSync100(mdPath)) {
70050
+ if (existsSync101(mdPath)) {
69387
70051
  try {
69388
70052
  const md = readFileSync72(mdPath, "utf-8");
69389
70053
  const refreshed = updatePatternTagsInBridge(md, post.pattern_tags);
@@ -69462,7 +70126,7 @@ Example output: ["talking-head","prop-driven"]`;
69462
70126
  // src/lib/marketing/competitors.ts
69463
70127
  import { spawn as spawn8 } from "child_process";
69464
70128
  import { spawnSync as spawnSync3 } from "child_process";
69465
- import { existsSync as existsSync101, mkdirSync as mkdirSync54, statfsSync } from "fs";
70129
+ import { existsSync as existsSync102, mkdirSync as mkdirSync54, statfsSync } from "fs";
69466
70130
  import { dirname as dirname66, join as join100, basename as basename30, extname as extname6 } from "path";
69467
70131
  function which(cmd) {
69468
70132
  const r = spawnSync3(process.platform === "win32" ? "where" : "which", [cmd], { encoding: "utf8" });
@@ -69673,7 +70337,7 @@ function persistPost(evt) {
69673
70337
  const bridgePath = join100(postsDir, `${evt.shortcode}.md`);
69674
70338
  writeJsonWithBridge(jsonPath, bridgePath, json, renderPostBridge(json));
69675
70339
  const metaPath = join100(handleDir, "meta.json");
69676
- if (!existsSync101(metaPath)) {
70340
+ if (!existsSync102(metaPath)) {
69677
70341
  writeJsonWithBridge(
69678
70342
  metaPath,
69679
70343
  join100(handleDir, "meta.md"),
@@ -69693,7 +70357,7 @@ First seen: ${(/* @__PURE__ */ new Date()).toISOString()}
69693
70357
  return jsonPath;
69694
70358
  }
69695
70359
  function moveAsset(src, dest) {
69696
- if (!existsSync101(src)) return dest;
70360
+ if (!existsSync102(src)) return dest;
69697
70361
  mkdirSync54(dirname66(dest), { recursive: true });
69698
70362
  const fs = __require("fs");
69699
70363
  try {
@@ -69755,7 +70419,7 @@ var init_competitors = __esm({
69755
70419
  });
69756
70420
 
69757
70421
  // src/cli/commands/marketing/competitor.ts
69758
- import { existsSync as existsSync102, readdirSync as readdirSync23, statSync as statSync21 } from "fs";
70422
+ import { existsSync as existsSync103, readdirSync as readdirSync23, statSync as statSync21 } from "fs";
69759
70423
  import { join as join101 } from "path";
69760
70424
  function registerMarketingCompetitor(parent) {
69761
70425
  const cmd = parent.command("competitor").description("Ingest competitor IG / YouTube content (Reinfluence pipeline).");
@@ -69806,7 +70470,7 @@ function registerMarketingCompetitor(parent) {
69806
70470
  });
69807
70471
  cmd.command("list").description("List ingested competitor handles.").action(() => {
69808
70472
  const dir = MARKETING_PATHS.competitorsDir();
69809
- if (!existsSync102(dir)) {
70473
+ if (!existsSync103(dir)) {
69810
70474
  info("No competitors ingested yet.");
69811
70475
  return;
69812
70476
  }
@@ -69826,7 +70490,7 @@ function registerMarketingCompetitor(parent) {
69826
70490
  console.log(header("Competitors"));
69827
70491
  for (const handle of handles) {
69828
70492
  const postsDir = join101(dir, handle, "posts");
69829
- const postCount = existsSync102(postsDir) ? readdirSync23(postsDir).filter((f) => f.endsWith(".json")).length : 0;
70493
+ const postCount = existsSync103(postsDir) ? readdirSync23(postsDir).filter((f) => f.endsWith(".json")).length : 0;
69830
70494
  console.log(` ${source_default.cyan("@" + handle)} ${source_default.dim(`${postCount} post(s)`)}`);
69831
70495
  }
69832
70496
  });
@@ -69839,11 +70503,11 @@ function registerMarketingCompetitor(parent) {
69839
70503
  }
69840
70504
  info(`Provider: ${provider.provider}`);
69841
70505
  const competitorsDir = MARKETING_PATHS.competitorsDir();
69842
- const handles = opts.handle ? [opts.handle] : existsSync102(competitorsDir) ? readdirSync23(competitorsDir).filter((h) => !h.startsWith("_") && statSync21(join101(competitorsDir, h)).isDirectory()) : [];
70506
+ const handles = opts.handle ? [opts.handle] : existsSync103(competitorsDir) ? readdirSync23(competitorsDir).filter((h) => !h.startsWith("_") && statSync21(join101(competitorsDir, h)).isDirectory()) : [];
69843
70507
  const matches = [];
69844
70508
  for (const h of handles) {
69845
70509
  const candidate = join101(competitorsDir, h, "posts", `${shortcode}.json`);
69846
- if (existsSync102(candidate)) matches.push(candidate);
70510
+ if (existsSync103(candidate)) matches.push(candidate);
69847
70511
  }
69848
70512
  if (matches.length === 0) {
69849
70513
  error(`No post JSON found for shortcode "${shortcode}".`);
@@ -69878,7 +70542,7 @@ function registerMarketingCompetitor(parent) {
69878
70542
  process.exit(1);
69879
70543
  }
69880
70544
  const competitorsDir = MARKETING_PATHS.competitorsDir();
69881
- if (!existsSync102(competitorsDir)) {
70545
+ if (!existsSync103(competitorsDir)) {
69882
70546
  warn("No competitors directory yet \u2014 nothing to relabel.");
69883
70547
  return;
69884
70548
  }
@@ -69887,7 +70551,7 @@ function registerMarketingCompetitor(parent) {
69887
70551
  let skipped = 0;
69888
70552
  for (const h of handles) {
69889
70553
  const postsDir = join101(competitorsDir, h, "posts");
69890
- if (!existsSync102(postsDir)) continue;
70554
+ if (!existsSync103(postsDir)) continue;
69891
70555
  for (const f of readdirSync23(postsDir).filter((n) => n.endsWith(".json"))) {
69892
70556
  const path2 = join101(postsDir, f);
69893
70557
  if (opts.dryRun) {
@@ -69936,7 +70600,7 @@ var init_competitor = __esm({
69936
70600
  });
69937
70601
 
69938
70602
  // src/lib/marketing/meta-fetch.ts
69939
- import { existsSync as existsSync103, mkdirSync as mkdirSync55, readFileSync as readFileSync73, writeFileSync as writeFileSync60, statSync as statSync22, openSync as openSync2, readSync, closeSync as closeSync2 } from "fs";
70603
+ import { existsSync as existsSync104, mkdirSync as mkdirSync55, readFileSync as readFileSync73, writeFileSync as writeFileSync60, statSync as statSync22, openSync as openSync2, readSync, closeSync as closeSync2 } from "fs";
69940
70604
  import { dirname as dirname67, basename as basename31 } from "path";
69941
70605
  import { randomUUID as randomUUID10 } from "crypto";
69942
70606
  function getQueue(accountId) {
@@ -69987,7 +70651,7 @@ function idemCachePath(key2) {
69987
70651
  }
69988
70652
  function readIdem(key2) {
69989
70653
  const p = idemCachePath(key2);
69990
- if (!existsSync103(p)) return null;
70654
+ if (!existsSync104(p)) return null;
69991
70655
  try {
69992
70656
  return JSON.parse(readFileSync73(p, "utf8"));
69993
70657
  } catch {
@@ -70733,7 +71397,7 @@ var init_account = __esm({
70733
71397
  });
70734
71398
 
70735
71399
  // src/lib/marketing/hypothesis.ts
70736
- import { existsSync as existsSync104, readFileSync as readFileSync74 } from "fs";
71400
+ import { existsSync as existsSync105, readFileSync as readFileSync74 } from "fs";
70737
71401
  function validateHypothesis(raw, options2 = {}) {
70738
71402
  const errors = [];
70739
71403
  const fieldErrors = {};
@@ -70800,7 +71464,7 @@ function validateHypothesis(raw, options2 = {}) {
70800
71464
  };
70801
71465
  }
70802
71466
  function loadHypothesisFile(path2, options2 = {}) {
70803
- if (!existsSync104(path2)) {
71467
+ if (!existsSync105(path2)) {
70804
71468
  return { ok: false, errors: [`Hypothesis file not found: ${path2}`] };
70805
71469
  }
70806
71470
  let parsed;
@@ -70993,7 +71657,7 @@ var init_cohort2 = __esm({
70993
71657
  });
70994
71658
 
70995
71659
  // src/lib/marketing/insights-cache.ts
70996
- import { existsSync as existsSync105, readFileSync as readFileSync75, mkdirSync as mkdirSync56, writeFileSync as writeFileSync61, readdirSync as readdirSync24, statSync as statSync23 } from "fs";
71660
+ import { existsSync as existsSync106, readFileSync as readFileSync75, mkdirSync as mkdirSync56, writeFileSync as writeFileSync61, readdirSync as readdirSync24, statSync as statSync23 } from "fs";
70997
71661
  import { join as join102 } from "path";
70998
71662
  import { randomBytes as randomBytes4 } from "crypto";
70999
71663
  function snapshotFilename(entityId, pulledAt) {
@@ -71009,7 +71673,7 @@ function indexPath() {
71009
71673
  }
71010
71674
  function readIndex() {
71011
71675
  const p = indexPath();
71012
- if (!existsSync105(p)) return { latest: {}, updated_at: "1970-01-01T00:00:00Z" };
71676
+ if (!existsSync106(p)) return { latest: {}, updated_at: "1970-01-01T00:00:00Z" };
71013
71677
  try {
71014
71678
  return JSON.parse(readFileSync75(p, "utf8"));
71015
71679
  } catch {
@@ -71041,7 +71705,7 @@ function getCachedInsights(entityId) {
71041
71705
  const filename = idx.latest[entityId];
71042
71706
  if (!filename) return null;
71043
71707
  const fullPath = join102(MARKETING_PATHS.insightsDir(), filename);
71044
- if (!existsSync105(fullPath)) return null;
71708
+ if (!existsSync106(fullPath)) return null;
71045
71709
  try {
71046
71710
  const snap = JSON.parse(readFileSync75(fullPath, "utf8"));
71047
71711
  const ageMs = Date.now() - new Date(snap.pulled_at).getTime();
@@ -71056,7 +71720,7 @@ function getLatestSnapshot(entityId) {
71056
71720
  const filename = idx.latest[entityId];
71057
71721
  if (!filename) return null;
71058
71722
  const fullPath = join102(MARKETING_PATHS.insightsDir(), filename);
71059
- if (!existsSync105(fullPath)) return null;
71723
+ if (!existsSync106(fullPath)) return null;
71060
71724
  try {
71061
71725
  return JSON.parse(readFileSync75(fullPath, "utf8"));
71062
71726
  } catch {
@@ -71065,7 +71729,7 @@ function getLatestSnapshot(entityId) {
71065
71729
  }
71066
71730
  function getPriorSnapshot(entityId, beforeMs) {
71067
71731
  const dir = MARKETING_PATHS.insightsDir();
71068
- if (!existsSync105(dir)) return null;
71732
+ if (!existsSync106(dir)) return null;
71069
71733
  const safe = entityId.replace(/[^A-Za-z0-9_-]/g, "_");
71070
71734
  const candidates = readdirSync24(dir).filter((f) => f.startsWith(`${safe}__`) && f.endsWith(".json")).map((f) => {
71071
71735
  const p = join102(dir, f);
@@ -71859,7 +72523,7 @@ var init_doctor2 = __esm({
71859
72523
  });
71860
72524
 
71861
72525
  // src/lib/marketing/entity-store.ts
71862
- import { existsSync as existsSync107, readFileSync as readFileSync77, readdirSync as readdirSync26 } from "fs";
72526
+ import { existsSync as existsSync108, readFileSync as readFileSync77, readdirSync as readdirSync26 } from "fs";
71863
72527
  import { join as join104 } from "path";
71864
72528
  function dirFor(kind) {
71865
72529
  switch (kind) {
@@ -71883,7 +72547,7 @@ function entityPaths(kind, id) {
71883
72547
  }
71884
72548
  function loadEntity(kind, id) {
71885
72549
  const { json } = entityPaths(kind, id);
71886
- if (!existsSync107(json)) return null;
72550
+ if (!existsSync108(json)) return null;
71887
72551
  try {
71888
72552
  return JSON.parse(readFileSync77(json, "utf8"));
71889
72553
  } catch {
@@ -71892,7 +72556,7 @@ function loadEntity(kind, id) {
71892
72556
  }
71893
72557
  function listEntities(kind) {
71894
72558
  const d = dirFor(kind);
71895
- if (!existsSync107(d)) return [];
72559
+ if (!existsSync108(d)) return [];
71896
72560
  const out = [];
71897
72561
  for (const f of readdirSync26(d).filter((x) => x.endsWith(".json"))) {
71898
72562
  try {
@@ -72090,7 +72754,7 @@ var init_campaign = __esm({
72090
72754
  });
72091
72755
 
72092
72756
  // src/cli/commands/marketing/adset.ts
72093
- import { existsSync as existsSync108, readFileSync as readFileSync78 } from "fs";
72757
+ import { existsSync as existsSync109, readFileSync as readFileSync78 } from "fs";
72094
72758
  function registerMarketingAdSet(parent) {
72095
72759
  const cmd = parent.command("adset").description("Manage adsets.");
72096
72760
  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) => {
@@ -72110,7 +72774,7 @@ function registerMarketingAdSet(parent) {
72110
72774
  }
72111
72775
  throw e;
72112
72776
  }
72113
- if (!existsSync108(opts.targeting)) {
72777
+ if (!existsSync109(opts.targeting)) {
72114
72778
  error(`Targeting file not found: ${opts.targeting}`);
72115
72779
  process.exit(1);
72116
72780
  }
@@ -72373,12 +73037,12 @@ var init_creative = __esm({
72373
73037
  });
72374
73038
 
72375
73039
  // src/cli/commands/marketing/asset.ts
72376
- import { existsSync as existsSync109, statSync as statSync25 } from "fs";
73040
+ import { existsSync as existsSync110, statSync as statSync25 } from "fs";
72377
73041
  import { extname as extname7 } from "path";
72378
73042
  function registerMarketingAsset(parent) {
72379
73043
  const cmd = parent.command("asset").description("Upload creative assets to Meta.");
72380
73044
  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) => {
72381
- if (!existsSync109(path2)) {
73045
+ if (!existsSync110(path2)) {
72382
73046
  error(`File not found: ${path2}`);
72383
73047
  process.exit(1);
72384
73048
  }
@@ -72546,7 +73210,7 @@ var init_ad = __esm({
72546
73210
  });
72547
73211
 
72548
73212
  // src/lib/marketing/launch.ts
72549
- import { existsSync as existsSync110, readFileSync as readFileSync79, writeFileSync as writeFileSync62, mkdirSync as mkdirSync57, renameSync as renameSync18, readdirSync as readdirSync27 } from "fs";
73213
+ import { existsSync as existsSync111, readFileSync as readFileSync79, writeFileSync as writeFileSync62, mkdirSync as mkdirSync57, renameSync as renameSync18, readdirSync as readdirSync27 } from "fs";
72550
73214
  import { dirname as dirname68, join as join105, basename as basename32 } from "path";
72551
73215
  import { randomBytes as randomBytes5 } from "crypto";
72552
73216
  function buildLaunchSummary(cohortId) {
@@ -72597,7 +73261,7 @@ function atomicWriteFile3(path2, data) {
72597
73261
  renameSync18(tmp, path2);
72598
73262
  }
72599
73263
  function readWal(path2) {
72600
- if (!existsSync110(path2)) return null;
73264
+ if (!existsSync111(path2)) return null;
72601
73265
  try {
72602
73266
  return JSON.parse(readFileSync79(path2, "utf8"));
72603
73267
  } catch {
@@ -72609,7 +73273,7 @@ function writeWal(path2, wal) {
72609
73273
  }
72610
73274
  function findWalByRunId(runId) {
72611
73275
  const dir = MARKETING_PATHS.runsDir();
72612
- if (!existsSync110(dir)) return null;
73276
+ if (!existsSync111(dir)) return null;
72613
73277
  for (const f of readdirSync27(dir)) {
72614
73278
  if (!f.endsWith(".json")) continue;
72615
73279
  if (f.startsWith("by-idem")) continue;
@@ -72886,7 +73550,7 @@ var init_launch2 = __esm({
72886
73550
  });
72887
73551
 
72888
73552
  // src/cli/commands/marketing/learnings.ts
72889
- import { existsSync as existsSync111, readFileSync as readFileSync80 } from "fs";
73553
+ import { existsSync as existsSync112, readFileSync as readFileSync80 } from "fs";
72890
73554
  function registerMarketingLearnings(parent) {
72891
73555
  const cmd = parent.command("learnings").description("Performance Monitor learnings ledger (per-day .md + index).");
72892
73556
  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) => {
@@ -73029,7 +73693,7 @@ async function resolveBody(body, bodyFile) {
73029
73693
  if (body) return body;
73030
73694
  if (bodyFile === "-") return readStdin3();
73031
73695
  if (bodyFile) {
73032
- if (!existsSync111(bodyFile)) throw new Error(`Body file not found: ${bodyFile}`);
73696
+ if (!existsSync112(bodyFile)) throw new Error(`Body file not found: ${bodyFile}`);
73033
73697
  return readFileSync80(bodyFile, "utf8");
73034
73698
  }
73035
73699
  return null;
@@ -73060,7 +73724,7 @@ var init_learnings2 = __esm({
73060
73724
 
73061
73725
  // src/lib/marketing/rem-sleep.ts
73062
73726
  import {
73063
- existsSync as existsSync112,
73727
+ existsSync as existsSync113,
73064
73728
  mkdirSync as mkdirSync58,
73065
73729
  readFileSync as readFileSync81,
73066
73730
  writeFileSync as writeFileSync63,
@@ -73080,7 +73744,7 @@ function atomicWriteFile4(path2, data) {
73080
73744
  function pruneRuns2(opts = {}) {
73081
73745
  const keepLast = opts.keepLast ?? 100;
73082
73746
  const dir = MARKETING_PATHS.runsDir();
73083
- if (!existsSync112(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
73747
+ if (!existsSync113(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
73084
73748
  const files = readdirSync28(dir).filter((f) => f.endsWith(".json")).map((f) => {
73085
73749
  const p = join106(dir, f);
73086
73750
  try {
@@ -73116,7 +73780,7 @@ function compactInsights(opts = {}) {
73116
73780
  const weeklyAfterDays = opts.weeklyAfterDays ?? 14;
73117
73781
  const now = opts.now ?? /* @__PURE__ */ new Date();
73118
73782
  const dir = MARKETING_PATHS.insightsDir();
73119
- if (!existsSync112(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
73783
+ if (!existsSync113(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
73120
73784
  const files = [];
73121
73785
  for (const f of readdirSync28(dir)) {
73122
73786
  if (!f.endsWith(".json") || f.startsWith("_")) continue;
@@ -73188,7 +73852,7 @@ function mergeDailyLearnings(opts = {}) {
73188
73852
  const retainDays = opts.retainDays ?? 7;
73189
73853
  const now = opts.now ?? /* @__PURE__ */ new Date();
73190
73854
  const dir = MARKETING_PATHS.learningsDir();
73191
- if (!existsSync112(dir)) {
73855
+ if (!existsSync113(dir)) {
73192
73856
  return { scanned: 0, merged: 0, archivePath: null, droppedRejected: 0, mergedFiles: [] };
73193
73857
  }
73194
73858
  const dayMs = 24 * 60 * 60 * 1e3;
@@ -73216,7 +73880,7 @@ function mergeDailyLearnings(opts = {}) {
73216
73880
  const archivePath = join106(dir, `_archive-${q}.md`);
73217
73881
  list.sort((a, b) => a.date.localeCompare(b.date));
73218
73882
  for (const c of list) {
73219
- const existingArchive = existsSync112(archivePath) ? readFileSync81(archivePath, "utf8") : `# Marketing learnings archive \u2014 ${q}
73883
+ const existingArchive = existsSync113(archivePath) ? readFileSync81(archivePath, "utf8") : `# Marketing learnings archive \u2014 ${q}
73220
73884
  `;
73221
73885
  const dateMarker = `# Marketing learnings \u2014 ${c.date}`;
73222
73886
  const alreadyMerged = existingArchive.includes(dateMarker);
@@ -73268,7 +73932,7 @@ function quarterKey(yyyymmdd) {
73268
73932
  }
73269
73933
  function redactRunsSweep(opts = {}) {
73270
73934
  const dir = MARKETING_PATHS.runsDir();
73271
- if (!existsSync112(dir)) return { scanned: 0, rewritten: 0, rewrittenFiles: [] };
73935
+ if (!existsSync113(dir)) return { scanned: 0, rewritten: 0, rewrittenFiles: [] };
73272
73936
  const files = readdirSync28(dir).filter((f) => f.endsWith(".json"));
73273
73937
  const rewrittenFiles = [];
73274
73938
  for (const f of files) {
@@ -73297,7 +73961,7 @@ function redactRunsSweep(opts = {}) {
73297
73961
  function runRemSleep(opts = {}) {
73298
73962
  const ranAt = (opts.now ?? /* @__PURE__ */ new Date()).toISOString();
73299
73963
  const root = marketingRootIfExists();
73300
- if (!root || !existsSync112(root)) {
73964
+ if (!root || !existsSync113(root)) {
73301
73965
  return {
73302
73966
  ranAt,
73303
73967
  marketingPresent: false,
@@ -73378,7 +74042,7 @@ var init_rem_sleep2 = __esm({
73378
74042
  });
73379
74043
 
73380
74044
  // src/cli/commands/marketing/hooks.ts
73381
- import { existsSync as existsSync113, readFileSync as readFileSync82, writeFileSync as writeFileSync64, chmodSync as chmodSync7, mkdirSync as mkdirSync59, statSync as statSync27 } from "fs";
74045
+ import { existsSync as existsSync114, readFileSync as readFileSync82, writeFileSync as writeFileSync64, chmodSync as chmodSync7, mkdirSync as mkdirSync59, statSync as statSync27 } from "fs";
73382
74046
  import { execFileSync as execFileSync10 } from "child_process";
73383
74047
  import { join as join107 } from "path";
73384
74048
  function findGitDir(cwd = process.cwd()) {
@@ -73423,7 +74087,7 @@ function registerMarketingHooks(parent) {
73423
74087
  const hooksDir = join107(gitDir, "hooks");
73424
74088
  mkdirSync59(hooksDir, { recursive: true });
73425
74089
  const target = join107(hooksDir, "pre-commit");
73426
- if (existsSync113(target)) {
74090
+ if (existsSync114(target)) {
73427
74091
  const existing = readFileSync82(target, "utf-8");
73428
74092
  if (existing.includes(MANAGED_MARKER)) {
73429
74093
  info("pre-commit hook already managed by dreamcontext \u2014 refreshing.");
@@ -73475,7 +74139,7 @@ exec dreamcontext mk hooks check-staged
73475
74139
  });
73476
74140
 
73477
74141
  // src/lib/marketing/council-personas.ts
73478
- import { existsSync as existsSync114, readFileSync as readFileSync83, readdirSync as readdirSync29 } from "fs";
74142
+ import { existsSync as existsSync115, readFileSync as readFileSync83, readdirSync as readdirSync29 } from "fs";
73479
74143
  import { fileURLToPath as fileURLToPath10 } from "url";
73480
74144
  import { join as join108, dirname as dirname70 } from "path";
73481
74145
  function findPersonasDir() {
@@ -73489,7 +74153,7 @@ function findPersonasDir() {
73489
74153
  join108(__dirname_local, "..", "..", PERSONA_SUBPATH)
73490
74154
  ];
73491
74155
  for (const candidate of candidates) {
73492
- if (existsSync114(candidate)) return candidate;
74156
+ if (existsSync115(candidate)) return candidate;
73493
74157
  }
73494
74158
  return null;
73495
74159
  }
@@ -73514,7 +74178,7 @@ function parsePersonaFile(filePath) {
73514
74178
  }
73515
74179
  function loadAllPersonas(personasDir) {
73516
74180
  const dir = personasDir ?? findPersonasDir();
73517
- if (!dir || !existsSync114(dir)) return [];
74181
+ if (!dir || !existsSync115(dir)) return [];
73518
74182
  const files = readdirSync29(dir).filter((n) => n.endsWith(".md")).sort();
73519
74183
  return files.map((name) => parsePersonaFile(join108(dir, name)));
73520
74184
  }
@@ -73547,11 +74211,11 @@ var init_council_personas = __esm({
73547
74211
 
73548
74212
  // src/cli/commands/marketing/council.ts
73549
74213
  import { spawnSync as spawnSync4 } from "child_process";
73550
- import { existsSync as existsSync115 } from "fs";
74214
+ import { existsSync as existsSync116 } from "fs";
73551
74215
  function resolveDreamcontextEntry() {
73552
74216
  const node = process.argv[0];
73553
74217
  const script = process.argv[1];
73554
- if (script && existsSync115(script)) {
74218
+ if (script && existsSync116(script)) {
73555
74219
  return { node, script };
73556
74220
  }
73557
74221
  return { node, script: null };
@@ -73723,7 +74387,7 @@ var init_marketing = __esm({
73723
74387
  });
73724
74388
 
73725
74389
  // src/cli/commands/memory.ts
73726
- import { existsSync as existsSync116, unlinkSync as unlinkSync12 } from "fs";
74390
+ import { existsSync as existsSync117, unlinkSync as unlinkSync12 } from "fs";
73727
74391
  import { join as join109, dirname as dirname71 } from "path";
73728
74392
  function collectVault(value, previous) {
73729
74393
  return [...previous, value];
@@ -73834,7 +74498,12 @@ function registerMemoryCommand(program2) {
73834
74498
  }
73835
74499
  const corpus = buildCorpus(root, types ? { types } : {});
73836
74500
  const vocab = loadProjectVocabulary(root);
73837
- const hits = process.env.DREAMCONTEXT_RECALL_MODE === "hybrid" ? await hybridSearch(query, corpus, root, topK, { aliasGroups: aliasGroups(vocab) }) : bm25Search(query, corpus, topK, { aliasGroups: aliasGroups(vocab) });
74501
+ const mode = resolveRecallMode(root);
74502
+ const useHybrid = hybridReady(root, mode);
74503
+ if (mode === "hybrid" && !useHybrid) {
74504
+ console.error(source_default.dim(" (hybrid recall selected but not warmed \u2014 using BM25. Run `dreamcontext embed refresh` to enable it.)"));
74505
+ }
74506
+ const hits = useHybrid ? await hybridSearch(query, corpus, root, topK, { aliasGroups: aliasGroups(vocab) }) : bm25Search(query, corpus, topK, { aliasGroups: aliasGroups(vocab) });
73838
74507
  if (opts.json) {
73839
74508
  const payload = hits.map((h) => ({
73840
74509
  type: h.doc.type,
@@ -73915,7 +74584,7 @@ function registerMemoryCommand(program2) {
73915
74584
  async (slug, opts) => {
73916
74585
  const root = ensureContextRoot();
73917
74586
  const filePath = join109(root, "knowledge", `${slug}.md`);
73918
- if (!existsSync116(filePath)) {
74587
+ if (!existsSync117(filePath)) {
73919
74588
  error(`Knowledge file not found: ${slug}.md`);
73920
74589
  return;
73921
74590
  }
@@ -73963,7 +74632,7 @@ ${opts.append}
73963
74632
  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) => {
73964
74633
  const root = ensureContextRoot();
73965
74634
  const filePath = join109(root, "knowledge", `${slug}.md`);
73966
- if (!existsSync116(filePath)) {
74635
+ if (!existsSync117(filePath)) {
73967
74636
  error(`Knowledge file not found: ${slug}.md`);
73968
74637
  return;
73969
74638
  }
@@ -74060,6 +74729,7 @@ var init_memory = __esm({
74060
74729
  init_format();
74061
74730
  init_recall();
74062
74731
  init_hybrid();
74732
+ init_sleep();
74063
74733
  init_federation_recall();
74064
74734
  init_taxonomy();
74065
74735
  init_frontmatter();
@@ -74079,7 +74749,7 @@ var init_memory = __esm({
74079
74749
  });
74080
74750
 
74081
74751
  // src/cli/commands/embed.ts
74082
- import { existsSync as existsSync117, statSync as statSync28, readFileSync as readFileSync85 } from "fs";
74752
+ import { existsSync as existsSync118, statSync as statSync28, readFileSync as readFileSync85 } from "fs";
74083
74753
  import { join as join110 } from "path";
74084
74754
  function registerEmbedCommand(program2) {
74085
74755
  const embed = program2.command("embed").description("EXPERIMENTAL: manage the local embedding index used by hybrid recall");
@@ -74111,7 +74781,7 @@ function registerEmbedCommand(program2) {
74111
74781
  const root = ensureContextRoot();
74112
74782
  console.log(header("Embedding Index"));
74113
74783
  const path2 = join110(root, ".embeddings", "cache.json");
74114
- if (!existsSync117(path2)) {
74784
+ if (!existsSync118(path2)) {
74115
74785
  info("No embedding cache \u2014 hybrid recall has not been used in this vault.");
74116
74786
  info(`Enable: ${source_default.cyan("dreamcontext recall hybrid")} (or DREAMCONTEXT_RECALL_MODE=hybrid), then run ${source_default.cyan("dreamcontext embed refresh")} to prewarm.`);
74117
74787
  return;
@@ -74144,12 +74814,12 @@ var init_embed = __esm({
74144
74814
  // src/cli/commands/upgrade.ts
74145
74815
  import { execFileSync as execFileSync12 } from "child_process";
74146
74816
  import { dirname as dirname72 } from "path";
74147
- import { existsSync as existsSync118 } from "fs";
74817
+ import { existsSync as existsSync119 } from "fs";
74148
74818
  function defaultInstaller(args) {
74149
74819
  execFileSync12("npm", args, { stdio: "inherit" });
74150
74820
  }
74151
74821
  function defaultProjectUpdater(vault) {
74152
- if (!existsSync118(vault.path)) {
74822
+ if (!existsSync119(vault.path)) {
74153
74823
  return { vault, ok: false, error: "project folder no longer exists" };
74154
74824
  }
74155
74825
  try {
@@ -74944,7 +75614,7 @@ var init_people = __esm({
74944
75614
 
74945
75615
  // src/cli/commands/config.ts
74946
75616
  import { dirname as dirname74 } from "path";
74947
- import { existsSync as existsSync119, readFileSync as readFileSync86, writeFileSync as writeFileSync66 } from "fs";
75617
+ import { existsSync as existsSync120, readFileSync as readFileSync86, writeFileSync as writeFileSync66 } from "fs";
74948
75618
  import { join as join112 } from "path";
74949
75619
  function resolveProjectRoot() {
74950
75620
  const contextRoot = resolveContextRoot();
@@ -75300,7 +75970,7 @@ function registerConfigCommand(program2) {
75300
75970
  let userMdSynced = false;
75301
75971
  if (contextRoot) {
75302
75972
  const userMdPath = join112(contextRoot, "core", "1.user.md");
75303
- if (existsSync119(userMdPath)) {
75973
+ if (existsSync120(userMdPath)) {
75304
75974
  try {
75305
75975
  const before = readFileSync86(userMdPath, "utf-8");
75306
75976
  const after = ensurePeopleSection(before, roster);