dreamcontext 0.8.2 → 0.8.5
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.
- package/README.md +98 -3
- package/agents/sleep-product.md +45 -0
- package/agents/sleep-state.md +3 -1
- package/agents/sleep-tasks.md +34 -13
- package/dist/agents/sleep-product.md +45 -0
- package/dist/agents/sleep-state.md +3 -1
- package/dist/agents/sleep-tasks.md +34 -13
- package/dist/dashboard/assets/{BrainCanvas3D-CNDjMlun.js → BrainCanvas3D-D8PjCqhM.js} +1 -1
- package/dist/dashboard/assets/{_baseUniq-DtoPVYjz.js → _baseUniq-Bh1FtvZ1.js} +1 -1
- package/dist/dashboard/assets/{ar-SA-G6X2FPQ2-D_dXe_8i.js → ar-SA-G6X2FPQ2-B2U2zDyG.js} +1 -1
- package/dist/dashboard/assets/{arc-8LFYH4lG.js → arc-CjP2r6kV.js} +1 -1
- package/dist/dashboard/assets/{architectureDiagram-Q4EWVU46-BIgEpM4v.js → architectureDiagram-Q4EWVU46-NKSTolLw.js} +1 -1
- package/dist/dashboard/assets/{az-AZ-76LH7QW2-C30ZBwgT.js → az-AZ-76LH7QW2-DVg6avJ2.js} +1 -1
- package/dist/dashboard/assets/{bg-BG-XCXSNQG7-D0R9pSdG.js → bg-BG-XCXSNQG7-DGe9j5k-.js} +1 -1
- package/dist/dashboard/assets/{blockDiagram-DXYQGD6D-DRTa0DpJ.js → blockDiagram-DXYQGD6D-9TIN16so.js} +1 -1
- package/dist/dashboard/assets/{bn-BD-2XOGV67Q-vkWxteG3.js → bn-BD-2XOGV67Q-gu4ZPvYK.js} +1 -1
- package/dist/dashboard/assets/{c4Diagram-AHTNJAMY-Do_gB8Cs.js → c4Diagram-AHTNJAMY-CnCRm_Qw.js} +1 -1
- package/dist/dashboard/assets/{ca-ES-6MX7JW3Y-CTyxGdzW.js → ca-ES-6MX7JW3Y-DkBWO2rb.js} +1 -1
- package/dist/dashboard/assets/channel-CvynutAQ.js +1 -0
- package/dist/dashboard/assets/{chunk-4BX2VUAB-DJlttKoY.js → chunk-4BX2VUAB-DWsjDEg5.js} +1 -1
- package/dist/dashboard/assets/{chunk-4TB4RGXK-BdixZX4J.js → chunk-4TB4RGXK-BsxBp2-h.js} +1 -1
- package/dist/dashboard/assets/{chunk-55IACEB6-CPhKaTLr.js → chunk-55IACEB6-DSTYhHTs.js} +1 -1
- package/dist/dashboard/assets/{chunk-EDXVE4YY-Bv0bQVvi.js → chunk-EDXVE4YY-9RDG5so7.js} +1 -1
- package/dist/dashboard/assets/{chunk-FMBD7UC4-DGjRdLDd.js → chunk-FMBD7UC4-BQQGv7tV.js} +1 -1
- package/dist/dashboard/assets/{chunk-OYMX7WX6-B-wzkRri.js → chunk-OYMX7WX6-B62jTGjc.js} +1 -1
- package/dist/dashboard/assets/{chunk-QZHKN3VN-BwK1NqpV.js → chunk-QZHKN3VN-CgTBTZrW.js} +1 -1
- package/dist/dashboard/assets/{chunk-YZCP3GAM-DjEwJGlh.js → chunk-YZCP3GAM-3Dg1saYb.js} +1 -1
- package/dist/dashboard/assets/classDiagram-6PBFFD2Q-DWhdz8wj.js +1 -0
- package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-DWhdz8wj.js +1 -0
- package/dist/dashboard/assets/clone-DJK7V3ll.js +1 -0
- package/dist/dashboard/assets/{cose-bilkent-S5V4N54A-BJXUn11L.js → cose-bilkent-S5V4N54A-B3idOsw5.js} +1 -1
- package/dist/dashboard/assets/{cs-CZ-2BRQDIVT-BjRikaNe.js → cs-CZ-2BRQDIVT-xyFkB9a5.js} +1 -1
- package/dist/dashboard/assets/{da-DK-5WZEPLOC-Cn3GTxbV.js → da-DK-5WZEPLOC-B3hFYjJY.js} +1 -1
- package/dist/dashboard/assets/{dagre-KV5264BT-BHn2c24z.js → dagre-KV5264BT-BoSSN-hv.js} +1 -1
- package/dist/dashboard/assets/{de-DE-XR44H4JA-IvGsdpTt.js → de-DE-XR44H4JA-Bkx00nEq.js} +1 -1
- package/dist/dashboard/assets/{diagram-5BDNPKRD-YrlF3B5a.js → diagram-5BDNPKRD-Buj8iksu.js} +1 -1
- package/dist/dashboard/assets/{diagram-G4DWMVQ6-DHONF1OD.js → diagram-G4DWMVQ6-DRBYjDWl.js} +1 -1
- package/dist/dashboard/assets/{diagram-MMDJMWI5-B1vJLt5b.js → diagram-MMDJMWI5-DdlofmeO.js} +1 -1
- package/dist/dashboard/assets/{diagram-TYMM5635-C8P5-4A3.js → diagram-TYMM5635-C8y8IvnA.js} +1 -1
- package/dist/dashboard/assets/{el-GR-BZB4AONW-B9GA8_lO.js → el-GR-BZB4AONW-SsFgxQNu.js} +1 -1
- package/dist/dashboard/assets/{erDiagram-SMLLAGMA-CjWWTCWe.js → erDiagram-SMLLAGMA-OZ3J3PG9.js} +1 -1
- package/dist/dashboard/assets/{es-ES-U4NZUMDT-Ct1wP_9r.js → es-ES-U4NZUMDT-BInO41Bx.js} +1 -1
- package/dist/dashboard/assets/{eu-ES-A7QVB2H4-C-49gWlR.js → eu-ES-A7QVB2H4-DjjnJ8cU.js} +1 -1
- package/dist/dashboard/assets/{fa-IR-HGAKTJCU-DUo8t-xv.js → fa-IR-HGAKTJCU-BjCsO05-.js} +1 -1
- package/dist/dashboard/assets/{fi-FI-Z5N7JZ37-DCObnr3i.js → fi-FI-Z5N7JZ37-kAJ6_O9R.js} +1 -1
- package/dist/dashboard/assets/{flowDiagram-DWJPFMVM-OQ_IRMqG.js → flowDiagram-DWJPFMVM-BvvULyyH.js} +1 -1
- package/dist/dashboard/assets/{fr-FR-RHASNOE6-0EGg3zhN.js → fr-FR-RHASNOE6-CrZukXCy.js} +1 -1
- package/dist/dashboard/assets/{ganttDiagram-T4ZO3ILL-DPTSBcnu.js → ganttDiagram-T4ZO3ILL-Sv7sneaT.js} +2 -2
- package/dist/dashboard/assets/{gitGraphDiagram-UUTBAWPF-BxfeiCqm.js → gitGraphDiagram-UUTBAWPF-BWplv5am.js} +1 -1
- package/dist/dashboard/assets/{gl-ES-HMX3MZ6V-WtVwXY6x.js → gl-ES-HMX3MZ6V-CY3NLwyQ.js} +1 -1
- package/dist/dashboard/assets/{graph-Du_3_o8q.js → graph-DU5PqGxo.js} +1 -1
- package/dist/dashboard/assets/{he-IL-6SHJWFNN-CfgspIku.js → he-IL-6SHJWFNN-DcuQngSU.js} +1 -1
- package/dist/dashboard/assets/{hi-IN-IWLTKZ5I-CS9l2g3B.js → hi-IN-IWLTKZ5I-DKr_uuss.js} +1 -1
- package/dist/dashboard/assets/{hu-HU-A5ZG7DT2-BQ46AerM.js → hu-HU-A5ZG7DT2-CgZklxQN.js} +1 -1
- package/dist/dashboard/assets/{id-ID-SAP4L64H-BeShJyKQ.js → id-ID-SAP4L64H-BFYAclqc.js} +1 -1
- package/dist/dashboard/assets/index-CPZ-rEGO.js +480 -0
- package/dist/dashboard/assets/{index-D7dWmypK.js → index-DhbH7HLB.js} +1 -1
- package/dist/dashboard/assets/index-DrwAz5zg.css +1 -0
- package/dist/dashboard/assets/{infoDiagram-42DDH7IO-CcFhyaQp.js → infoDiagram-42DDH7IO-DcL21hYD.js} +1 -1
- package/dist/dashboard/assets/{ishikawaDiagram-UXIWVN3A-9QJeD00p.js → ishikawaDiagram-UXIWVN3A-CP4-Ha6a.js} +1 -1
- package/dist/dashboard/assets/{it-IT-JPQ66NNP-csyvfk0t.js → it-IT-JPQ66NNP-DgbO8z_0.js} +1 -1
- package/dist/dashboard/assets/{ja-JP-DBVTYXUO-DctpJ2yz.js → ja-JP-DBVTYXUO-2nM4bVbo.js} +1 -1
- package/dist/dashboard/assets/{journeyDiagram-VCZTEJTY-CU4EYedt.js → journeyDiagram-VCZTEJTY-CZV9JSbl.js} +1 -1
- package/dist/dashboard/assets/{kaa-6HZHGXH3-D0tWzHt3.js → kaa-6HZHGXH3-DyVkacqp.js} +1 -1
- package/dist/dashboard/assets/{kab-KAB-ZGHBKWFO-BC-g4xJU.js → kab-KAB-ZGHBKWFO-CqnQNV46.js} +1 -1
- package/dist/dashboard/assets/{kanban-definition-6JOO6SKY-BxXqVmz1.js → kanban-definition-6JOO6SKY-CMFYpVon.js} +1 -1
- package/dist/dashboard/assets/{kk-KZ-P5N5QNE5-TLB3Lxri.js → kk-KZ-P5N5QNE5-CKaF_obh.js} +1 -1
- package/dist/dashboard/assets/{km-KH-HSX4SM5Z-DCh7cRAS.js → km-KH-HSX4SM5Z-DX5TUZuC.js} +1 -1
- package/dist/dashboard/assets/{ko-KR-MTYHY66A-BPIl5ido.js → ko-KR-MTYHY66A-DX2Igsee.js} +1 -1
- package/dist/dashboard/assets/{ku-TR-6OUDTVRD-TUpeN1Tm.js → ku-TR-6OUDTVRD-B0tZGs6G.js} +1 -1
- package/dist/dashboard/assets/{layout-CyrgfqIp.js → layout-3g_7BoW1.js} +1 -1
- package/dist/dashboard/assets/linear-CXZ_mpWm.js +1 -0
- package/dist/dashboard/assets/{lt-LT-XHIRWOB4-BRKyR_Xw.js → lt-LT-XHIRWOB4-BzCZwLwu.js} +1 -1
- package/dist/dashboard/assets/{lv-LV-5QDEKY6T-BANbTe4s.js → lv-LV-5QDEKY6T-Dn-Fj6_V.js} +1 -1
- package/dist/dashboard/assets/{min-lcwVZhZ7.js → min-bJtV9AiD.js} +1 -1
- package/dist/dashboard/assets/{mindmap-definition-QFDTVHPH-fVIbdlXp.js → mindmap-definition-QFDTVHPH-Dz61NELW.js} +1 -1
- package/dist/dashboard/assets/{mr-IN-CRQNXWMA-DLFutdXk.js → mr-IN-CRQNXWMA-D8KTtR8X.js} +1 -1
- package/dist/dashboard/assets/{my-MM-5M5IBNSE-CGWrcNBC.js → my-MM-5M5IBNSE-BbCYwFaj.js} +1 -1
- package/dist/dashboard/assets/{nb-NO-T6EIAALU-CGRDupuc.js → nb-NO-T6EIAALU-DEJxZlzk.js} +1 -1
- package/dist/dashboard/assets/{nl-NL-IS3SIHDZ-BKwBfrzp.js → nl-NL-IS3SIHDZ-DTQekKhh.js} +1 -1
- package/dist/dashboard/assets/{nn-NO-6E72VCQL-DDQkGe44.js → nn-NO-6E72VCQL-Otz1_Q7Y.js} +1 -1
- package/dist/dashboard/assets/{oc-FR-POXYY2M6-DufeHCWh.js → oc-FR-POXYY2M6-BO1pOtcy.js} +1 -1
- package/dist/dashboard/assets/{pa-IN-N4M65BXN-BUzelJDX.js → pa-IN-N4M65BXN-o_zcafD8.js} +1 -1
- package/dist/dashboard/assets/{percentages-BXMCSKIN-FxAvjywS.js → percentages-BXMCSKIN-C9aZbplb.js} +7 -7
- package/dist/dashboard/assets/{pica-Cek5bFnr.js → pica-B0_4dS6Q.js} +1 -1
- package/dist/dashboard/assets/{pieDiagram-DEJITSTG-PgIrKPnB.js → pieDiagram-DEJITSTG-CMwhT31D.js} +1 -1
- package/dist/dashboard/assets/{pl-PL-T2D74RX3-Bd-rxZs3.js → pl-PL-T2D74RX3-CvJKdZLx.js} +1 -1
- package/dist/dashboard/assets/{pt-BR-5N22H2LF-D0QJGoo5.js → pt-BR-5N22H2LF-DH69aomh.js} +1 -1
- package/dist/dashboard/assets/{pt-PT-UZXXM6DQ-DjumltMq.js → pt-PT-UZXXM6DQ-Bt_HMT7S.js} +1 -1
- package/dist/dashboard/assets/{quadrantDiagram-34T5L4WZ-C30tZOBh.js → quadrantDiagram-34T5L4WZ-BdXgbSGH.js} +1 -1
- package/dist/dashboard/assets/{requirementDiagram-MS252O5E-D3vhi-ZB.js → requirementDiagram-MS252O5E-Bq0YQege.js} +1 -1
- package/dist/dashboard/assets/{ro-RO-JPDTUUEW-DmEo8cEd.js → ro-RO-JPDTUUEW-DetQ1m4p.js} +1 -1
- package/dist/dashboard/assets/{ru-RU-B4JR7IUQ-ZHCu1nBu.js → ru-RU-B4JR7IUQ-B744z7Cd.js} +1 -1
- package/dist/dashboard/assets/{sankeyDiagram-XADWPNL6-Cmbs-PxO.js → sankeyDiagram-XADWPNL6-CTYt5Kku.js} +1 -1
- package/dist/dashboard/assets/{sequenceDiagram-FGHM5R23-DlBqk4uQ.js → sequenceDiagram-FGHM5R23-BbPhy9K6.js} +1 -1
- package/dist/dashboard/assets/{si-LK-N5RQ5JYF-iuqtpRqI.js → si-LK-N5RQ5JYF-DueeMRG5.js} +1 -1
- package/dist/dashboard/assets/{sk-SK-C5VTKIMK-BWFUWdaQ.js → sk-SK-C5VTKIMK-BivWC8UI.js} +1 -1
- package/dist/dashboard/assets/{sl-SI-NN7IZMDC-irYTfiq_.js → sl-SI-NN7IZMDC-CHxsSSJQ.js} +1 -1
- package/dist/dashboard/assets/{stateDiagram-FHFEXIEX-B6T9ib8G.js → stateDiagram-FHFEXIEX-DAPXkQkR.js} +1 -1
- package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-ZA5uLv7f.js +1 -0
- package/dist/dashboard/assets/{subset-shared.chunk-LTgWgeng.js → subset-shared.chunk-CxWeBga7.js} +1 -1
- package/dist/dashboard/assets/{subset-worker.chunk-CT_2iDuG.js → subset-worker.chunk-V3gpxiYs.js} +1 -1
- package/dist/dashboard/assets/{sv-SE-XGPEYMSR-BvDzjArd.js → sv-SE-XGPEYMSR-C-EJgqb-.js} +1 -1
- package/dist/dashboard/assets/{ta-IN-2NMHFXQM-DdsS_3Yq.js → ta-IN-2NMHFXQM-DAjiKKkH.js} +1 -1
- package/dist/dashboard/assets/{th-TH-HPSO5L25-Duadkok3.js → th-TH-HPSO5L25-Bq7BADtY.js} +1 -1
- package/dist/dashboard/assets/{timeline-definition-GMOUNBTQ-CHTQqVpC.js → timeline-definition-GMOUNBTQ-BJhY_iVV.js} +1 -1
- package/dist/dashboard/assets/{tr-TR-DEFEU3FU-CTnPpl_3.js → tr-TR-DEFEU3FU--adx_Tct.js} +1 -1
- package/dist/dashboard/assets/{uk-UA-QMV73CPH-CAqmQ01_.js → uk-UA-QMV73CPH-DfnkGhht.js} +1 -1
- package/dist/dashboard/assets/{vennDiagram-DHZGUBPP-tWl34rwo.js → vennDiagram-DHZGUBPP-BpuWdXIB.js} +1 -1
- package/dist/dashboard/assets/{vi-VN-M7AON7JQ-Cz7FDG8R.js → vi-VN-M7AON7JQ-RQSwYL0s.js} +1 -1
- package/dist/dashboard/assets/{wardley-RL74JXVD-UjdnBcpJ.js → wardley-RL74JXVD-BuB77QmE.js} +1 -1
- package/dist/dashboard/assets/{wardleyDiagram-NUSXRM2D-KhVWSzPf.js → wardleyDiagram-NUSXRM2D-BomUXaGE.js} +1 -1
- package/dist/dashboard/assets/{xychartDiagram-5P7HB3ND-SwtVQYTW.js → xychartDiagram-5P7HB3ND-BueWOzBo.js} +1 -1
- package/dist/dashboard/assets/{zh-CN-LNUGB5OW-B7cbFS35.js → zh-CN-LNUGB5OW-Bq_CyCdn.js} +1 -1
- package/dist/dashboard/assets/{zh-HK-E62DVLB3-CLi9BFmp.js → zh-HK-E62DVLB3-dhMk2wl1.js} +1 -1
- package/dist/dashboard/assets/{zh-TW-RAJ6MFWO-XAcgJHay.js → zh-TW-RAJ6MFWO-BTBKc5WB.js} +1 -1
- package/dist/dashboard/index.html +2 -2
- package/dist/index.js +1457 -780
- package/dist/skill-packs/goal-skill/SKILL.md +8 -6
- package/package.json +1 -1
- package/skill/SKILL.md +3 -3
- package/skill-packs/goal-skill/SKILL.md +8 -6
- package/dist/dashboard/assets/channel-C5p1t-nJ.js +0 -1
- package/dist/dashboard/assets/classDiagram-6PBFFD2Q-sTJpbWV4.js +0 -1
- package/dist/dashboard/assets/classDiagram-v2-HSJHXN6E-sTJpbWV4.js +0 -1
- package/dist/dashboard/assets/clone-DTslXBzp.js +0 -1
- package/dist/dashboard/assets/index-C9VT2u9E.js +0 -480
- package/dist/dashboard/assets/index-DoFaQKCx.css +0 -1
- package/dist/dashboard/assets/linear-B6cMUkoc.js +0 -1
- package/dist/dashboard/assets/stateDiagram-v2-QKLJ7IA2-CN0hAOp7.js +0 -1
package/dist/index.js
CHANGED
|
@@ -18458,11 +18458,11 @@ var init_install_claude_md = __esm({
|
|
|
18458
18458
|
import { existsSync as existsSync6, mkdirSync as mkdirSync4, readFileSync as readFileSync7, writeFileSync as writeFileSync7 } from "fs";
|
|
18459
18459
|
import { dirname as dirname4, join as join6 } from "path";
|
|
18460
18460
|
function applyClaudeAutoMemory(projectRoot, disable) {
|
|
18461
|
-
const
|
|
18461
|
+
const settingsPath2 = join6(projectRoot, ".claude", "settings.json");
|
|
18462
18462
|
let settings = {};
|
|
18463
|
-
if (existsSync6(
|
|
18463
|
+
if (existsSync6(settingsPath2)) {
|
|
18464
18464
|
try {
|
|
18465
|
-
const parsed = JSON.parse(readFileSync7(
|
|
18465
|
+
const parsed = JSON.parse(readFileSync7(settingsPath2, "utf-8"));
|
|
18466
18466
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
18467
18467
|
settings = parsed;
|
|
18468
18468
|
}
|
|
@@ -18473,8 +18473,8 @@ function applyClaudeAutoMemory(projectRoot, disable) {
|
|
|
18473
18473
|
const desired = !disable;
|
|
18474
18474
|
if (settings.autoMemoryEnabled === desired) return false;
|
|
18475
18475
|
settings.autoMemoryEnabled = desired;
|
|
18476
|
-
mkdirSync4(dirname4(
|
|
18477
|
-
writeFileSync7(
|
|
18476
|
+
mkdirSync4(dirname4(settingsPath2), { recursive: true });
|
|
18477
|
+
writeFileSync7(settingsPath2, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
18478
18478
|
return true;
|
|
18479
18479
|
}
|
|
18480
18480
|
var init_claude_settings = __esm({
|
|
@@ -22458,12 +22458,12 @@ async function resolvePlatforms(projectRoot, raw) {
|
|
|
22458
22458
|
return platforms;
|
|
22459
22459
|
}
|
|
22460
22460
|
function ensureClaudeHooks(projectRoot) {
|
|
22461
|
-
const
|
|
22461
|
+
const settingsPath2 = join9(projectRoot, ".claude", "settings.json");
|
|
22462
22462
|
const result = { added: [], migrated: false };
|
|
22463
22463
|
let settings = {};
|
|
22464
|
-
if (existsSync9(
|
|
22464
|
+
if (existsSync9(settingsPath2)) {
|
|
22465
22465
|
try {
|
|
22466
|
-
settings = JSON.parse(readFileSync10(
|
|
22466
|
+
settings = JSON.parse(readFileSync10(settingsPath2, "utf-8"));
|
|
22467
22467
|
} catch {
|
|
22468
22468
|
settings = {};
|
|
22469
22469
|
}
|
|
@@ -22497,7 +22497,7 @@ function ensureClaudeHooks(projectRoot) {
|
|
|
22497
22497
|
}
|
|
22498
22498
|
}
|
|
22499
22499
|
mkdirSync6(join9(projectRoot, ".claude"), { recursive: true });
|
|
22500
|
-
writeFileSync9(
|
|
22500
|
+
writeFileSync9(settingsPath2, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
22501
22501
|
return result;
|
|
22502
22502
|
}
|
|
22503
22503
|
function findPackageFile(subdir, filename) {
|
|
@@ -34672,6 +34672,170 @@ var init_migration_runner = __esm({
|
|
|
34672
34672
|
}
|
|
34673
34673
|
});
|
|
34674
34674
|
|
|
34675
|
+
// src/lib/sleep-consolidation.ts
|
|
34676
|
+
function sleepinessLevel(debt) {
|
|
34677
|
+
if (debt <= 3) return "Alert";
|
|
34678
|
+
if (debt <= 6) return "Drowsy";
|
|
34679
|
+
if (debt <= 9) return "Sleepy";
|
|
34680
|
+
return "Must Sleep";
|
|
34681
|
+
}
|
|
34682
|
+
function sleepinessRange(debt) {
|
|
34683
|
+
if (debt <= 3) return "0-3";
|
|
34684
|
+
if (debt <= 6) return "4-6";
|
|
34685
|
+
if (debt <= 9) return "7-9";
|
|
34686
|
+
return "10+";
|
|
34687
|
+
}
|
|
34688
|
+
function recomputeDebt(sessions) {
|
|
34689
|
+
return sessions.reduce((sum, s) => sum + (s.score ?? 0), 0);
|
|
34690
|
+
}
|
|
34691
|
+
function depthFromDebt(debt) {
|
|
34692
|
+
if (debt <= 3) return "light";
|
|
34693
|
+
if (debt <= 9) return "standard";
|
|
34694
|
+
return "deep";
|
|
34695
|
+
}
|
|
34696
|
+
function consolidationDepth(debt, opts = {}) {
|
|
34697
|
+
const base = depthFromDebt(debt);
|
|
34698
|
+
if (opts.userRequestedDeep) {
|
|
34699
|
+
return { depth: "deep", reason: "user requested deep consolidation", source: "user" };
|
|
34700
|
+
}
|
|
34701
|
+
const bump = Math.max(0, Math.min(2, opts.agentBump ?? 0));
|
|
34702
|
+
if (bump > 0) {
|
|
34703
|
+
const baseIdx = DEPTH_ORDER.indexOf(base);
|
|
34704
|
+
const idx = Math.min(DEPTH_ORDER.length - 1, baseIdx + bump);
|
|
34705
|
+
return {
|
|
34706
|
+
depth: DEPTH_ORDER[idx],
|
|
34707
|
+
reason: `agent bumped depth by ${bump} tier(s) from ${base}`,
|
|
34708
|
+
source: "agent"
|
|
34709
|
+
};
|
|
34710
|
+
}
|
|
34711
|
+
return { depth: base, reason: `debt ${debt} \u2192 ${base}`, source: "debt" };
|
|
34712
|
+
}
|
|
34713
|
+
function isDestructiveAllowed(depth) {
|
|
34714
|
+
return depth === "deep";
|
|
34715
|
+
}
|
|
34716
|
+
function applyConsolidation(state, epoch) {
|
|
34717
|
+
const next = cloneState(state);
|
|
34718
|
+
let sessionsProcessed = 0;
|
|
34719
|
+
let bookmarksProcessed = 0;
|
|
34720
|
+
let processedSessionIds = [];
|
|
34721
|
+
if (epoch) {
|
|
34722
|
+
const processedSessions = next.sessions.filter((s) => !s.stopped_at || s.stopped_at <= epoch);
|
|
34723
|
+
sessionsProcessed = processedSessions.length;
|
|
34724
|
+
processedSessionIds = processedSessions.map((s) => s.session_id);
|
|
34725
|
+
bookmarksProcessed = next.bookmarks.filter((b) => b.created_at <= epoch).length;
|
|
34726
|
+
next.sessions = next.sessions.filter((s) => {
|
|
34727
|
+
if (!s.stopped_at) return false;
|
|
34728
|
+
return s.stopped_at > epoch;
|
|
34729
|
+
});
|
|
34730
|
+
next.bookmarks = next.bookmarks.filter((b) => b.created_at > epoch);
|
|
34731
|
+
next.dashboard_changes = next.dashboard_changes.filter((c) => c.timestamp > epoch);
|
|
34732
|
+
next.debt = recomputeDebt(next.sessions);
|
|
34733
|
+
} else {
|
|
34734
|
+
sessionsProcessed = next.sessions.length;
|
|
34735
|
+
processedSessionIds = next.sessions.map((s) => s.session_id);
|
|
34736
|
+
bookmarksProcessed = next.bookmarks.length;
|
|
34737
|
+
next.sessions = [];
|
|
34738
|
+
next.bookmarks = [];
|
|
34739
|
+
next.dashboard_changes = [];
|
|
34740
|
+
next.debt = 0;
|
|
34741
|
+
}
|
|
34742
|
+
next.triggers = next.triggers.filter((t) => t.fired_count < t.max_fires);
|
|
34743
|
+
return { state: next, sessionsProcessed, bookmarksProcessed, processedSessionIds };
|
|
34744
|
+
}
|
|
34745
|
+
function upsertSessionOnStop(state, input2) {
|
|
34746
|
+
const next = cloneState(state);
|
|
34747
|
+
const existing = next.sessions.findIndex((s) => s.session_id === input2.session_id);
|
|
34748
|
+
if (existing >= 0) {
|
|
34749
|
+
const oldScore = next.sessions[existing].score ?? 0;
|
|
34750
|
+
next.debt = Math.max(0, next.debt - oldScore);
|
|
34751
|
+
const existingSlugs = next.sessions[existing].task_slugs ?? [];
|
|
34752
|
+
next.sessions[existing] = {
|
|
34753
|
+
...next.sessions[existing],
|
|
34754
|
+
transcript_path: input2.transcript_path,
|
|
34755
|
+
stopped_at: input2.stopped_at,
|
|
34756
|
+
last_assistant_message: input2.last_assistant_message,
|
|
34757
|
+
change_count: input2.change_count,
|
|
34758
|
+
tool_count: input2.tool_count,
|
|
34759
|
+
score: input2.score,
|
|
34760
|
+
task_slugs: [.../* @__PURE__ */ new Set([...existingSlugs, ...input2.task_slugs])]
|
|
34761
|
+
};
|
|
34762
|
+
next.debt += input2.score;
|
|
34763
|
+
} else {
|
|
34764
|
+
next.sessions.unshift({
|
|
34765
|
+
session_id: input2.session_id,
|
|
34766
|
+
transcript_path: input2.transcript_path,
|
|
34767
|
+
stopped_at: input2.stopped_at,
|
|
34768
|
+
last_assistant_message: input2.last_assistant_message,
|
|
34769
|
+
change_count: input2.change_count,
|
|
34770
|
+
tool_count: input2.tool_count,
|
|
34771
|
+
score: input2.score,
|
|
34772
|
+
task_slugs: input2.task_slugs
|
|
34773
|
+
});
|
|
34774
|
+
next.debt += input2.score;
|
|
34775
|
+
next.sessions_since_last_sleep = (next.sessions_since_last_sleep || 0) + 1;
|
|
34776
|
+
}
|
|
34777
|
+
return next;
|
|
34778
|
+
}
|
|
34779
|
+
function appendCompactionRecord(state, record) {
|
|
34780
|
+
const next = cloneState(state);
|
|
34781
|
+
next.compaction_log.unshift(record);
|
|
34782
|
+
if (next.compaction_log.length > COMPACTION_LOG_CAP) {
|
|
34783
|
+
next.compaction_log = next.compaction_log.slice(0, COMPACTION_LOG_CAP);
|
|
34784
|
+
}
|
|
34785
|
+
return next;
|
|
34786
|
+
}
|
|
34787
|
+
function validateSleepAdd(scoreStr, desc) {
|
|
34788
|
+
const score = parseInt(scoreStr, 10);
|
|
34789
|
+
if (isNaN(score) || score < 1 || score > 3) {
|
|
34790
|
+
return { ok: false, error: "Score must be 1, 2, or 3." };
|
|
34791
|
+
}
|
|
34792
|
+
if (!desc.trim()) {
|
|
34793
|
+
return { ok: false, error: "Description is required." };
|
|
34794
|
+
}
|
|
34795
|
+
return { ok: true };
|
|
34796
|
+
}
|
|
34797
|
+
function buildHistoryEntry(prevDebt, result, summary, today2) {
|
|
34798
|
+
return {
|
|
34799
|
+
date: today2,
|
|
34800
|
+
consolidated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34801
|
+
summary: summary.trim(),
|
|
34802
|
+
debt_before: prevDebt,
|
|
34803
|
+
debt_after: result.state.debt,
|
|
34804
|
+
sessions_processed: result.sessionsProcessed,
|
|
34805
|
+
bookmarks_processed: result.bookmarksProcessed,
|
|
34806
|
+
session_ids: result.processedSessionIds
|
|
34807
|
+
};
|
|
34808
|
+
}
|
|
34809
|
+
function finalizeSleepState(state, summary, today2) {
|
|
34810
|
+
const next = cloneState(state);
|
|
34811
|
+
next.last_sleep = today2;
|
|
34812
|
+
next.last_sleep_summary = summary.trim();
|
|
34813
|
+
next.sleep_started_at = null;
|
|
34814
|
+
next.sessions_since_last_sleep = 0;
|
|
34815
|
+
next.consolidation_depth = null;
|
|
34816
|
+
return next;
|
|
34817
|
+
}
|
|
34818
|
+
function cloneState(state) {
|
|
34819
|
+
return {
|
|
34820
|
+
...state,
|
|
34821
|
+
sessions: state.sessions.map((s) => ({ ...s, task_slugs: [...s.task_slugs ?? []] })),
|
|
34822
|
+
bookmarks: state.bookmarks.map((b) => ({ ...b })),
|
|
34823
|
+
triggers: state.triggers.map((t) => ({ ...t })),
|
|
34824
|
+
knowledge_access: { ...state.knowledge_access },
|
|
34825
|
+
dashboard_changes: state.dashboard_changes.map((c) => ({ ...c })),
|
|
34826
|
+
compaction_log: state.compaction_log.map((c) => ({ ...c })),
|
|
34827
|
+
pendingMigrationNotices: [...state.pendingMigrationNotices]
|
|
34828
|
+
};
|
|
34829
|
+
}
|
|
34830
|
+
var DEPTH_ORDER, COMPACTION_LOG_CAP;
|
|
34831
|
+
var init_sleep_consolidation = __esm({
|
|
34832
|
+
"src/lib/sleep-consolidation.ts"() {
|
|
34833
|
+
"use strict";
|
|
34834
|
+
DEPTH_ORDER = ["light", "standard", "deep"];
|
|
34835
|
+
COMPACTION_LOG_CAP = 20;
|
|
34836
|
+
}
|
|
34837
|
+
});
|
|
34838
|
+
|
|
34675
34839
|
// src/cli/commands/sleep.ts
|
|
34676
34840
|
import { existsSync as existsSync37 } from "fs";
|
|
34677
34841
|
import { join as join37, dirname as dirname18 } from "path";
|
|
@@ -34763,8 +34927,8 @@ function registerSleepCommand(program2) {
|
|
|
34763
34927
|
sleep2.command("status").description("Show current sleep debt level and history").action(() => {
|
|
34764
34928
|
const root = ensureContextRoot();
|
|
34765
34929
|
const state = readSleepState(root);
|
|
34766
|
-
const level =
|
|
34767
|
-
const range =
|
|
34930
|
+
const level = sleepinessLevel(state.debt);
|
|
34931
|
+
const range = sleepinessRange(state.debt);
|
|
34768
34932
|
console.log(header("Sleep State"));
|
|
34769
34933
|
console.log(` Debt: ${source_default.bold(String(state.debt))} ${source_default.dim(`(${range})`)} ${source_default.magentaBright(level)}`);
|
|
34770
34934
|
console.log(` Last sleep: ${state.last_sleep ? source_default.white(state.last_sleep) : source_default.dim("never")}`);
|
|
@@ -34792,16 +34956,13 @@ function registerSleepCommand(program2) {
|
|
|
34792
34956
|
}
|
|
34793
34957
|
});
|
|
34794
34958
|
sleep2.command("add").argument("<score>", "Debt score to add (1-3)").argument("<description...>", "Description of what happened").description("Record a debt-accumulating action").action((scoreStr, descParts) => {
|
|
34795
|
-
const score = parseInt(scoreStr, 10);
|
|
34796
|
-
if (isNaN(score) || score < 1 || score > 3) {
|
|
34797
|
-
error("Score must be 1, 2, or 3.");
|
|
34798
|
-
return;
|
|
34799
|
-
}
|
|
34800
34959
|
const description = descParts.join(" ");
|
|
34801
|
-
|
|
34802
|
-
|
|
34960
|
+
const valid = validateSleepAdd(scoreStr, description);
|
|
34961
|
+
if (!valid.ok) {
|
|
34962
|
+
error(valid.error);
|
|
34803
34963
|
return;
|
|
34804
34964
|
}
|
|
34965
|
+
const score = parseInt(scoreStr, 10);
|
|
34805
34966
|
const root = ensureContextRoot();
|
|
34806
34967
|
const state = readSleepState(root);
|
|
34807
34968
|
state.sessions.unshift({
|
|
@@ -34816,7 +34977,7 @@ function registerSleepCommand(program2) {
|
|
|
34816
34977
|
});
|
|
34817
34978
|
state.debt += score;
|
|
34818
34979
|
writeSleepState(root, state);
|
|
34819
|
-
const level =
|
|
34980
|
+
const level = sleepinessLevel(state.debt);
|
|
34820
34981
|
success(`Sleep debt: ${state.debt} (${level})`);
|
|
34821
34982
|
if (state.debt >= 10) {
|
|
34822
34983
|
warn("Must sleep! Debt is 10+. Consolidation needed.");
|
|
@@ -34824,12 +34985,14 @@ function registerSleepCommand(program2) {
|
|
|
34824
34985
|
info("Getting sleepy. Consider consolidating soon.");
|
|
34825
34986
|
}
|
|
34826
34987
|
});
|
|
34827
|
-
sleep2.command("start").description("Mark beginning of consolidation (sets epoch for safe clearing)").action(() => {
|
|
34988
|
+
sleep2.command("start").description("Mark beginning of consolidation (sets epoch for safe clearing)").option("--deep", "Force a deep consolidation (authorizes destructive knowledge ops)").action((opts) => {
|
|
34828
34989
|
const root = ensureContextRoot();
|
|
34829
34990
|
const state = readSleepState(root);
|
|
34830
34991
|
if (state.sleep_started_at) {
|
|
34831
34992
|
warn(`Consolidation already in progress (started ${state.sleep_started_at}). Overwriting epoch.`);
|
|
34832
34993
|
}
|
|
34994
|
+
const decision = consolidationDepth(state.debt, { userRequestedDeep: !!opts.deep });
|
|
34995
|
+
state.consolidation_depth = decision.depth;
|
|
34833
34996
|
state.pendingMigrationNotices = [];
|
|
34834
34997
|
const projectRoot = dirname18(root);
|
|
34835
34998
|
const config = readSetupConfig(projectRoot);
|
|
@@ -34853,6 +35016,10 @@ function registerSleepCommand(program2) {
|
|
|
34853
35016
|
state.sleep_started_at = (/* @__PURE__ */ new Date()).toISOString();
|
|
34854
35017
|
writeSleepState(root, state);
|
|
34855
35018
|
success(`Consolidation epoch set: ${state.sleep_started_at}`);
|
|
35019
|
+
info(`Consolidation depth: ${decision.depth} (source: ${decision.source}) \u2014 ${decision.reason}`);
|
|
35020
|
+
if (decision.depth !== "deep") {
|
|
35021
|
+
info("Light/standard consolidation: do NOT merge/summarize-replace/delete knowledge \u2014 flag candidates in the report instead.");
|
|
35022
|
+
}
|
|
34856
35023
|
});
|
|
34857
35024
|
sleep2.command("done").argument("<summary...>", "Summary of what was consolidated").description("Mark consolidation complete, reset debt").action(async (summaryParts) => {
|
|
34858
35025
|
const summary = summaryParts.join(" ");
|
|
@@ -34864,52 +35031,17 @@ function registerSleepCommand(program2) {
|
|
|
34864
35031
|
const state = readSleepState(root);
|
|
34865
35032
|
const previousDebt = state.debt;
|
|
34866
35033
|
const epoch = state.sleep_started_at;
|
|
34867
|
-
|
|
34868
|
-
|
|
34869
|
-
let processedSessionIds = [];
|
|
34870
|
-
if (epoch) {
|
|
34871
|
-
const processedSessions = state.sessions.filter((s) => !s.stopped_at || s.stopped_at <= epoch);
|
|
34872
|
-
sessionsProcessed = processedSessions.length;
|
|
34873
|
-
processedSessionIds = processedSessions.map((s) => s.session_id);
|
|
34874
|
-
bookmarksProcessed = state.bookmarks.filter((b) => b.created_at <= epoch).length;
|
|
34875
|
-
state.sessions = state.sessions.filter((s) => {
|
|
34876
|
-
if (!s.stopped_at) return false;
|
|
34877
|
-
return s.stopped_at > epoch;
|
|
34878
|
-
});
|
|
34879
|
-
state.bookmarks = state.bookmarks.filter((b) => b.created_at > epoch);
|
|
34880
|
-
state.dashboard_changes = state.dashboard_changes.filter((c) => c.timestamp > epoch);
|
|
34881
|
-
state.debt = state.sessions.reduce((sum, s) => sum + (s.score ?? 0), 0);
|
|
34882
|
-
} else {
|
|
34883
|
-
sessionsProcessed = state.sessions.length;
|
|
34884
|
-
processedSessionIds = state.sessions.map((s) => s.session_id);
|
|
34885
|
-
bookmarksProcessed = state.bookmarks.length;
|
|
34886
|
-
state.sessions = [];
|
|
34887
|
-
state.bookmarks = [];
|
|
34888
|
-
state.dashboard_changes = [];
|
|
34889
|
-
state.debt = 0;
|
|
34890
|
-
}
|
|
34891
|
-
state.triggers = state.triggers.filter((t) => t.fired_count < t.max_fires);
|
|
35034
|
+
const result = applyConsolidation(state, epoch);
|
|
35035
|
+
const today_ = today();
|
|
34892
35036
|
const history = readSleepHistory(root);
|
|
34893
|
-
history.unshift(
|
|
34894
|
-
date: today(),
|
|
34895
|
-
consolidated_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
34896
|
-
summary: summary.trim(),
|
|
34897
|
-
debt_before: previousDebt,
|
|
34898
|
-
debt_after: state.debt,
|
|
34899
|
-
sessions_processed: sessionsProcessed,
|
|
34900
|
-
bookmarks_processed: bookmarksProcessed,
|
|
34901
|
-
session_ids: processedSessionIds
|
|
34902
|
-
});
|
|
35037
|
+
history.unshift(buildHistoryEntry(previousDebt, result, summary, today_));
|
|
34903
35038
|
writeSleepHistory(root, history);
|
|
34904
|
-
|
|
34905
|
-
|
|
34906
|
-
|
|
34907
|
-
|
|
34908
|
-
writeSleepState(root, state);
|
|
34909
|
-
if (epoch && state.sessions.length > 0) {
|
|
34910
|
-
success(`Consolidation complete. Debt reduced from ${previousDebt} to ${state.debt}. ${state.sessions.length} post-epoch session(s) preserved.`);
|
|
35039
|
+
const finalState = finalizeSleepState(result.state, summary, today_);
|
|
35040
|
+
writeSleepState(root, finalState);
|
|
35041
|
+
if (epoch && finalState.sessions.length > 0) {
|
|
35042
|
+
success(`Consolidation complete. Debt reduced from ${previousDebt} to ${finalState.debt}. ${finalState.sessions.length} post-epoch session(s) preserved.`);
|
|
34911
35043
|
} else {
|
|
34912
|
-
success(`Consolidation complete. Debt reset from ${previousDebt} to ${
|
|
35044
|
+
success(`Consolidation complete. Debt reset from ${previousDebt} to ${finalState.debt}.`);
|
|
34913
35045
|
}
|
|
34914
35046
|
try {
|
|
34915
35047
|
const backend = getTaskBackend(root);
|
|
@@ -35001,6 +35133,7 @@ var init_sleep = __esm({
|
|
|
35001
35133
|
init_migration_runner();
|
|
35002
35134
|
init_setup_config();
|
|
35003
35135
|
init_manifest();
|
|
35136
|
+
init_sleep_consolidation();
|
|
35004
35137
|
}
|
|
35005
35138
|
});
|
|
35006
35139
|
|
|
@@ -36736,6 +36869,44 @@ var init_setup_drift = __esm({
|
|
|
36736
36869
|
}
|
|
36737
36870
|
});
|
|
36738
36871
|
|
|
36872
|
+
// src/lib/asset-drift-cache.ts
|
|
36873
|
+
import { existsSync as existsSync45, readFileSync as readFileSync34, writeFileSync as writeFileSync29, mkdirSync as mkdirSync22 } from "fs";
|
|
36874
|
+
import { join as join45, dirname as dirname22 } from "path";
|
|
36875
|
+
function assetDriftCachePath(contextRoot) {
|
|
36876
|
+
return join45(contextRoot, "state", ".asset-drift.json");
|
|
36877
|
+
}
|
|
36878
|
+
function readAssetDriftCache(contextRoot) {
|
|
36879
|
+
try {
|
|
36880
|
+
const p = assetDriftCachePath(contextRoot);
|
|
36881
|
+
if (!existsSync45(p)) return null;
|
|
36882
|
+
const parsed = JSON.parse(readFileSync34(p, "utf-8"));
|
|
36883
|
+
if (!parsed || typeof parsed.cliVersion !== "string" || typeof parsed.setupVersion !== "string" || typeof parsed.usedAssetsChanged !== "boolean") {
|
|
36884
|
+
return null;
|
|
36885
|
+
}
|
|
36886
|
+
return {
|
|
36887
|
+
cliVersion: parsed.cliVersion,
|
|
36888
|
+
setupVersion: parsed.setupVersion,
|
|
36889
|
+
usedAssetsChanged: parsed.usedAssetsChanged,
|
|
36890
|
+
checkedAt: typeof parsed.checkedAt === "number" ? parsed.checkedAt : 0
|
|
36891
|
+
};
|
|
36892
|
+
} catch {
|
|
36893
|
+
return null;
|
|
36894
|
+
}
|
|
36895
|
+
}
|
|
36896
|
+
function writeAssetDriftCache(contextRoot, cache) {
|
|
36897
|
+
const p = assetDriftCachePath(contextRoot);
|
|
36898
|
+
mkdirSync22(dirname22(p), { recursive: true });
|
|
36899
|
+
writeFileSync29(p, JSON.stringify(cache, null, 2) + "\n", "utf-8");
|
|
36900
|
+
}
|
|
36901
|
+
function cacheConfidentlyClean(cache, cliVersion, setupVersion) {
|
|
36902
|
+
return cache !== null && cache.cliVersion === cliVersion && cache.setupVersion === setupVersion && cache.usedAssetsChanged === false;
|
|
36903
|
+
}
|
|
36904
|
+
var init_asset_drift_cache = __esm({
|
|
36905
|
+
"src/lib/asset-drift-cache.ts"() {
|
|
36906
|
+
"use strict";
|
|
36907
|
+
}
|
|
36908
|
+
});
|
|
36909
|
+
|
|
36739
36910
|
// src/lib/snapshot-budget.ts
|
|
36740
36911
|
function estimateTokens(s) {
|
|
36741
36912
|
return Math.ceil(s.length / 4);
|
|
@@ -36841,8 +37012,8 @@ var init_snapshot_budget = __esm({
|
|
|
36841
37012
|
});
|
|
36842
37013
|
|
|
36843
37014
|
// src/cli/commands/snapshot.ts
|
|
36844
|
-
import { readFileSync as
|
|
36845
|
-
import { join as
|
|
37015
|
+
import { readFileSync as readFileSync35, existsSync as existsSync46, statSync as statSync5 } from "fs";
|
|
37016
|
+
import { join as join46, basename as basename12, dirname as dirname23 } from "path";
|
|
36846
37017
|
function extractFirstParagraph(content) {
|
|
36847
37018
|
const lines = content.split("\n");
|
|
36848
37019
|
const paragraphLines = [];
|
|
@@ -36876,8 +37047,8 @@ function sortTaskEntriesByActivity(entries) {
|
|
|
36876
37047
|
return [...entries].sort((a, b) => statusRank(a.status) - statusRank(b.status) || prioRank(a.priority) - prioRank(b.priority) || b.updated.localeCompare(a.updated));
|
|
36877
37048
|
}
|
|
36878
37049
|
function getActiveTaskEntries(root) {
|
|
36879
|
-
const stateDir =
|
|
36880
|
-
if (!
|
|
37050
|
+
const stateDir = join46(root, "state");
|
|
37051
|
+
if (!existsSync46(stateDir)) return [];
|
|
36881
37052
|
const taskFiles = import_fast_glob11.default.sync("*.md", { cwd: stateDir, absolute: true });
|
|
36882
37053
|
const entries = [];
|
|
36883
37054
|
for (const file of taskFiles) {
|
|
@@ -36909,15 +37080,15 @@ function getActiveTaskEntries(root) {
|
|
|
36909
37080
|
return entries;
|
|
36910
37081
|
}
|
|
36911
37082
|
function resolveActiveTaskPath(root) {
|
|
36912
|
-
const stateDir =
|
|
36913
|
-
if (!
|
|
36914
|
-
const overridePath =
|
|
36915
|
-
if (
|
|
37083
|
+
const stateDir = join46(root, "state");
|
|
37084
|
+
if (!existsSync46(stateDir)) return null;
|
|
37085
|
+
const overridePath = join46(stateDir, ".active-task");
|
|
37086
|
+
if (existsSync46(overridePath)) {
|
|
36916
37087
|
try {
|
|
36917
|
-
const slug =
|
|
37088
|
+
const slug = readFileSync35(overridePath, "utf-8").trim();
|
|
36918
37089
|
if (slug) {
|
|
36919
|
-
const taskPath =
|
|
36920
|
-
if (
|
|
37090
|
+
const taskPath = join46(stateDir, `${slug}.md`);
|
|
37091
|
+
if (existsSync46(taskPath)) return taskPath;
|
|
36921
37092
|
}
|
|
36922
37093
|
} catch {
|
|
36923
37094
|
}
|
|
@@ -36943,7 +37114,7 @@ function resolveActiveTaskPath(root) {
|
|
|
36943
37114
|
return candidates[0].path;
|
|
36944
37115
|
}
|
|
36945
37116
|
function getActiveProductKnowledge(root) {
|
|
36946
|
-
const config = readSetupConfig(
|
|
37117
|
+
const config = readSetupConfig(dirname23(root));
|
|
36947
37118
|
if (!config || !Array.isArray(config.multiProduct) || config.multiProduct.length === 0) {
|
|
36948
37119
|
return [];
|
|
36949
37120
|
}
|
|
@@ -36960,11 +37131,11 @@ function getActiveProductKnowledge(root) {
|
|
|
36960
37131
|
}
|
|
36961
37132
|
if (!product) return [];
|
|
36962
37133
|
if (!config.multiProduct.includes(product)) return [];
|
|
36963
|
-
const productKnowledgePath =
|
|
36964
|
-
if (!
|
|
37134
|
+
const productKnowledgePath = join46(root, "knowledge", "products", `${product}.md`);
|
|
37135
|
+
if (!existsSync46(productKnowledgePath)) return [];
|
|
36965
37136
|
let raw;
|
|
36966
37137
|
try {
|
|
36967
|
-
raw =
|
|
37138
|
+
raw = readFileSync35(productKnowledgePath, "utf-8");
|
|
36968
37139
|
} catch {
|
|
36969
37140
|
return [];
|
|
36970
37141
|
}
|
|
@@ -36999,7 +37170,7 @@ function getActiveProductKnowledge(root) {
|
|
|
36999
37170
|
}
|
|
37000
37171
|
function getVersionNudge(root) {
|
|
37001
37172
|
try {
|
|
37002
|
-
const projectRoot =
|
|
37173
|
+
const projectRoot = dirname23(root);
|
|
37003
37174
|
const cache = readVersionCache(projectRoot);
|
|
37004
37175
|
if (!cache || !isCacheFresh(cache)) return "";
|
|
37005
37176
|
const installedCli = dreamcontextVersion();
|
|
@@ -37015,9 +37186,9 @@ function getVersionNudge(root) {
|
|
|
37015
37186
|
}
|
|
37016
37187
|
function getMigrationNote(root) {
|
|
37017
37188
|
try {
|
|
37018
|
-
const sleepPath =
|
|
37019
|
-
if (!
|
|
37020
|
-
const raw =
|
|
37189
|
+
const sleepPath = join46(root, "state", ".sleep.json");
|
|
37190
|
+
if (!existsSync46(sleepPath)) return "";
|
|
37191
|
+
const raw = readFileSync35(sleepPath, "utf-8");
|
|
37021
37192
|
const parsed = JSON.parse(raw);
|
|
37022
37193
|
if (!parsed || !Array.isArray(parsed.pendingMigrationNotices) || parsed.pendingMigrationNotices.length === 0) {
|
|
37023
37194
|
return "";
|
|
@@ -37035,14 +37206,21 @@ Migrations applied since last session: ${notices.join("; ")}`;
|
|
|
37035
37206
|
}
|
|
37036
37207
|
function getDriftDirective(root) {
|
|
37037
37208
|
try {
|
|
37038
|
-
const projectRoot =
|
|
37209
|
+
const projectRoot = dirname23(root);
|
|
37039
37210
|
const config = readSetupConfig(projectRoot);
|
|
37040
37211
|
if (!config) return "";
|
|
37041
|
-
|
|
37042
|
-
|
|
37212
|
+
const cliVersion = dreamcontextVersion();
|
|
37213
|
+
const driftInput = {
|
|
37214
|
+
cliVersion,
|
|
37043
37215
|
setupVersion: config.setupVersion,
|
|
37044
37216
|
driftCheckEnv: process.env.DREAMCONTEXT_DRIFT_CHECK
|
|
37045
|
-
}
|
|
37217
|
+
};
|
|
37218
|
+
const state = resolveDriftState(driftInput);
|
|
37219
|
+
if (state === "stale" || state === "bootstrap") {
|
|
37220
|
+
const cache = readAssetDriftCache(root);
|
|
37221
|
+
if (cacheConfidentlyClean(cache, cliVersion, config.setupVersion)) return "";
|
|
37222
|
+
}
|
|
37223
|
+
return buildDriftDirective(driftInput) ?? "";
|
|
37046
37224
|
} catch {
|
|
37047
37225
|
return "";
|
|
37048
37226
|
}
|
|
@@ -37058,24 +37236,24 @@ function generateSnapshot(rootOverride) {
|
|
|
37058
37236
|
parts = [];
|
|
37059
37237
|
}
|
|
37060
37238
|
};
|
|
37061
|
-
const soulPath =
|
|
37062
|
-
if (
|
|
37063
|
-
const content =
|
|
37239
|
+
const soulPath = join46(root, "core", "0.soul.md");
|
|
37240
|
+
if (existsSync46(soulPath)) {
|
|
37241
|
+
const content = readFileSync35(soulPath, "utf-8").trim();
|
|
37064
37242
|
parts.push("## Soul (Agent Identity, Principles, Rules)\n");
|
|
37065
37243
|
parts.push(content);
|
|
37066
37244
|
parts.push("");
|
|
37067
37245
|
}
|
|
37068
|
-
const userPath =
|
|
37069
|
-
if (
|
|
37070
|
-
const content =
|
|
37246
|
+
const userPath = join46(root, "core", "1.user.md");
|
|
37247
|
+
if (existsSync46(userPath)) {
|
|
37248
|
+
const content = readFileSync35(userPath, "utf-8").trim();
|
|
37071
37249
|
parts.push("## User (Preferences, Project Details, Rules)\n");
|
|
37072
37250
|
parts.push(content);
|
|
37073
37251
|
parts.push("");
|
|
37074
37252
|
}
|
|
37075
37253
|
flush("identity", { neverEvict: true });
|
|
37076
|
-
const memoryPath =
|
|
37077
|
-
if (
|
|
37078
|
-
const content =
|
|
37254
|
+
const memoryPath = join46(root, "core", "2.memory.md");
|
|
37255
|
+
if (existsSync46(memoryPath)) {
|
|
37256
|
+
const content = readFileSync35(memoryPath, "utf-8").trim();
|
|
37079
37257
|
if (content) {
|
|
37080
37258
|
parts.push("## Memory (Technical Decisions, Known Issues, Session Log)\n");
|
|
37081
37259
|
parts.push(content);
|
|
@@ -37140,8 +37318,8 @@ function generateSnapshot(rootOverride) {
|
|
|
37140
37318
|
if (sleepState.triggers.length > 0) {
|
|
37141
37319
|
const taskNames = [];
|
|
37142
37320
|
const taskTags = [];
|
|
37143
|
-
const stateDir =
|
|
37144
|
-
if (
|
|
37321
|
+
const stateDir = join46(root, "state");
|
|
37322
|
+
if (existsSync46(stateDir)) {
|
|
37145
37323
|
const taskFiles = import_fast_glob11.default.sync("*.md", { cwd: stateDir, absolute: true });
|
|
37146
37324
|
for (const file of taskFiles) {
|
|
37147
37325
|
try {
|
|
@@ -37177,14 +37355,14 @@ function generateSnapshot(rootOverride) {
|
|
|
37177
37355
|
const CHANGELOG_TIER2 = 10;
|
|
37178
37356
|
const TIER1_BODY_CHARS = 300;
|
|
37179
37357
|
const TIER2_LINE_CHARS = 140;
|
|
37180
|
-
const multiPerson = isMultiPerson(readSetupConfig(
|
|
37358
|
+
const multiPerson = isMultiPerson(readSetupConfig(dirname23(root)));
|
|
37181
37359
|
const authorSuffix = (e) => {
|
|
37182
37360
|
if (!multiPerson) return "";
|
|
37183
37361
|
const authors = Array.isArray(e.authors) ? e.authors.filter((a) => typeof a === "string") : [];
|
|
37184
37362
|
return authors.length > 0 ? ` \u2014 by ${authors.join(", ")}` : "";
|
|
37185
37363
|
};
|
|
37186
|
-
const changelogPath =
|
|
37187
|
-
if (
|
|
37364
|
+
const changelogPath = join46(root, "core", "CHANGELOG.json");
|
|
37365
|
+
if (existsSync46(changelogPath)) {
|
|
37188
37366
|
try {
|
|
37189
37367
|
const entries = readJsonArray(changelogPath);
|
|
37190
37368
|
const tier1 = entries.slice(0, CHANGELOG_TIER1);
|
|
@@ -37240,8 +37418,8 @@ function generateSnapshot(rootOverride) {
|
|
|
37240
37418
|
} catch {
|
|
37241
37419
|
}
|
|
37242
37420
|
}
|
|
37243
|
-
const releasesPath =
|
|
37244
|
-
if (
|
|
37421
|
+
const releasesPath = join46(root, "core", "RELEASES.json");
|
|
37422
|
+
if (existsSync46(releasesPath)) {
|
|
37245
37423
|
try {
|
|
37246
37424
|
const releases = readJsonArray(releasesPath);
|
|
37247
37425
|
if (releases.length > 0) {
|
|
@@ -37277,8 +37455,8 @@ function generateSnapshot(rootOverride) {
|
|
|
37277
37455
|
}
|
|
37278
37456
|
}
|
|
37279
37457
|
flush("releases", { neverEvict: true });
|
|
37280
|
-
const featuresDir =
|
|
37281
|
-
if (
|
|
37458
|
+
const featuresDir = join46(root, "core", "features");
|
|
37459
|
+
if (existsSync46(featuresDir)) {
|
|
37282
37460
|
const featureFiles = import_fast_glob11.default.sync("*.md", { cwd: featuresDir, absolute: true });
|
|
37283
37461
|
const features = [];
|
|
37284
37462
|
const featureMeta = [];
|
|
@@ -37366,8 +37544,8 @@ function generateSnapshot(rootOverride) {
|
|
|
37366
37544
|
const pinnedEntries = [];
|
|
37367
37545
|
const warmEntries = [];
|
|
37368
37546
|
const activeTaskTags = [];
|
|
37369
|
-
const stDir =
|
|
37370
|
-
if (
|
|
37547
|
+
const stDir = join46(root, "state");
|
|
37548
|
+
if (existsSync46(stDir)) {
|
|
37371
37549
|
const tFiles = import_fast_glob11.default.sync("*.md", { cwd: stDir, absolute: true });
|
|
37372
37550
|
for (const file of tFiles) {
|
|
37373
37551
|
try {
|
|
@@ -37501,8 +37679,8 @@ function generateSubagentBriefing() {
|
|
|
37501
37679
|
parts.push('`dreamcontext memory recall "<keywords>"` (BM25 over knowledge/features/tasks/');
|
|
37502
37680
|
parts.push("memory/changelog, <100ms, zero token overhead) BEFORE Glob/Grep \u2014 it frequently");
|
|
37503
37681
|
parts.push("beats blind exploration outright.\n");
|
|
37504
|
-
const soulPath =
|
|
37505
|
-
if (
|
|
37682
|
+
const soulPath = join46(root, "core", "0.soul.md");
|
|
37683
|
+
if (existsSync46(soulPath)) {
|
|
37506
37684
|
const { data, content } = readFrontmatter(soulPath);
|
|
37507
37685
|
const projectName = typeof data.name === "string" ? data.name : "";
|
|
37508
37686
|
const lines = content.split("\n");
|
|
@@ -37521,8 +37699,8 @@ function generateSubagentBriefing() {
|
|
|
37521
37699
|
`);
|
|
37522
37700
|
}
|
|
37523
37701
|
}
|
|
37524
|
-
const featuresDir =
|
|
37525
|
-
if (
|
|
37702
|
+
const featuresDir = join46(root, "core", "features");
|
|
37703
|
+
if (existsSync46(featuresDir)) {
|
|
37526
37704
|
const featureFiles = import_fast_glob11.default.sync("*.md", { cwd: featuresDir, absolute: true });
|
|
37527
37705
|
const features = [];
|
|
37528
37706
|
for (const file of featureFiles) {
|
|
@@ -37589,8 +37767,8 @@ function generateSubagentBriefing() {
|
|
|
37589
37767
|
}
|
|
37590
37768
|
parts.push("");
|
|
37591
37769
|
}
|
|
37592
|
-
const coreDir =
|
|
37593
|
-
if (
|
|
37770
|
+
const coreDir = join46(root, "core");
|
|
37771
|
+
if (existsSync46(coreDir)) {
|
|
37594
37772
|
const allCoreFiles = import_fast_glob11.default.sync(["[0-9]*"], { cwd: coreDir, absolute: true });
|
|
37595
37773
|
allCoreFiles.sort((a, b) => basename12(a).localeCompare(basename12(b), void 0, { numeric: true }));
|
|
37596
37774
|
if (allCoreFiles.length > 0) {
|
|
@@ -37678,14 +37856,62 @@ var init_snapshot2 = __esm({
|
|
|
37678
37856
|
init_version_check();
|
|
37679
37857
|
init_manifest();
|
|
37680
37858
|
init_setup_drift();
|
|
37859
|
+
init_asset_drift_cache();
|
|
37681
37860
|
init_feature_freshness();
|
|
37682
37861
|
init_federation_inbox();
|
|
37683
37862
|
init_snapshot_budget();
|
|
37684
37863
|
}
|
|
37685
37864
|
});
|
|
37686
37865
|
|
|
37866
|
+
// src/lib/salience.ts
|
|
37867
|
+
function clamp(text) {
|
|
37868
|
+
const oneLine = text.replace(/\s+/g, " ").trim();
|
|
37869
|
+
return oneLine.length <= MAX_MESSAGE_CHARS ? oneLine : oneLine.slice(0, MAX_MESSAGE_CHARS - 1) + "\u2026";
|
|
37870
|
+
}
|
|
37871
|
+
function detectSalience(distilled) {
|
|
37872
|
+
const moments = [];
|
|
37873
|
+
const seen = /* @__PURE__ */ new Set();
|
|
37874
|
+
const push = (message, salience) => {
|
|
37875
|
+
const clamped = clamp(message);
|
|
37876
|
+
if (!clamped) return;
|
|
37877
|
+
const key = `${salience}::${clamped.toLowerCase()}`;
|
|
37878
|
+
if (seen.has(key)) return;
|
|
37879
|
+
seen.add(key);
|
|
37880
|
+
moments.push({ message: clamped, salience });
|
|
37881
|
+
};
|
|
37882
|
+
for (const msg of distilled.userMessages) {
|
|
37883
|
+
if (CORRECTION_RE.test(msg)) {
|
|
37884
|
+
push(`User correction: ${msg}`, 2);
|
|
37885
|
+
}
|
|
37886
|
+
}
|
|
37887
|
+
if (distilled.errors.length > 0 && distilled.codeChanges.length > 0) {
|
|
37888
|
+
const firstError = distilled.errors[0];
|
|
37889
|
+
push(`Error resolved by code change: ${firstError}`, 1);
|
|
37890
|
+
}
|
|
37891
|
+
const decisionSources = [
|
|
37892
|
+
...distilled.agentDecisions.filter((d) => !d.startsWith("[thinking]")),
|
|
37893
|
+
...distilled.userMessages
|
|
37894
|
+
];
|
|
37895
|
+
for (const src of decisionSources) {
|
|
37896
|
+
if (DECISION_RE.test(src)) {
|
|
37897
|
+
push(`Decision: ${src}`, 2);
|
|
37898
|
+
}
|
|
37899
|
+
}
|
|
37900
|
+
return moments.slice(0, MAX_MOMENTS);
|
|
37901
|
+
}
|
|
37902
|
+
var CORRECTION_RE, DECISION_RE, MAX_MOMENTS, MAX_MESSAGE_CHARS;
|
|
37903
|
+
var init_salience = __esm({
|
|
37904
|
+
"src/lib/salience.ts"() {
|
|
37905
|
+
"use strict";
|
|
37906
|
+
CORRECTION_RE = /\b(no|actually|wrong|instead|hayır|yanlış|değil)\b/i;
|
|
37907
|
+
DECISION_RE = /\b(decided|chose|switched to|will use|karar|seçtik)\b/i;
|
|
37908
|
+
MAX_MOMENTS = 5;
|
|
37909
|
+
MAX_MESSAGE_CHARS = 200;
|
|
37910
|
+
}
|
|
37911
|
+
});
|
|
37912
|
+
|
|
37687
37913
|
// src/cli/commands/transcript.ts
|
|
37688
|
-
import { readFileSync as
|
|
37914
|
+
import { readFileSync as readFileSync36, existsSync as existsSync47, statSync as statSync6 } from "fs";
|
|
37689
37915
|
function distillTranscript(transcriptPath, sinceTimestamp) {
|
|
37690
37916
|
const result = {
|
|
37691
37917
|
userMessages: [],
|
|
@@ -37694,11 +37920,11 @@ function distillTranscript(transcriptPath, sinceTimestamp) {
|
|
|
37694
37920
|
errors: [],
|
|
37695
37921
|
bookmarks: []
|
|
37696
37922
|
};
|
|
37697
|
-
if (!
|
|
37923
|
+
if (!existsSync47(transcriptPath)) return result;
|
|
37698
37924
|
try {
|
|
37699
37925
|
const stat = statSync6(transcriptPath);
|
|
37700
37926
|
if (stat.size === 0 || stat.size > MAX_TRANSCRIPT_BYTES) return result;
|
|
37701
|
-
const content =
|
|
37927
|
+
const content = readFileSync36(transcriptPath, "utf-8");
|
|
37702
37928
|
const lines = content.split("\n").filter((l) => l.trim());
|
|
37703
37929
|
for (const line of lines) {
|
|
37704
37930
|
let entry;
|
|
@@ -37882,7 +38108,7 @@ function registerTranscriptCommand(program2) {
|
|
|
37882
38108
|
error(`No transcript path for session: ${sessionId}`);
|
|
37883
38109
|
return;
|
|
37884
38110
|
}
|
|
37885
|
-
if (!
|
|
38111
|
+
if (!existsSync47(session.transcript_path)) {
|
|
37886
38112
|
error(`Transcript file not found: ${session.transcript_path}`);
|
|
37887
38113
|
return;
|
|
37888
38114
|
}
|
|
@@ -38059,8 +38285,8 @@ var init_recall_synonyms = __esm({
|
|
|
38059
38285
|
});
|
|
38060
38286
|
|
|
38061
38287
|
// src/lib/recall.ts
|
|
38062
|
-
import { existsSync as
|
|
38063
|
-
import { join as
|
|
38288
|
+
import { existsSync as existsSync48, readFileSync as readFileSync37 } from "fs";
|
|
38289
|
+
import { join as join47, basename as basename13, dirname as dirname24, relative as relative3 } from "path";
|
|
38064
38290
|
function isFederated(doc) {
|
|
38065
38291
|
return doc.federated === true;
|
|
38066
38292
|
}
|
|
@@ -38149,7 +38375,7 @@ function productFromRelPath(relPath) {
|
|
|
38149
38375
|
return m ? m[1] : void 0;
|
|
38150
38376
|
}
|
|
38151
38377
|
function loadMarkdownDocs(dir, type, contextRoot) {
|
|
38152
|
-
if (!
|
|
38378
|
+
if (!existsSync48(dir)) return [];
|
|
38153
38379
|
const files = import_fast_glob12.default.sync("**/*.md", { cwd: dir, absolute: true });
|
|
38154
38380
|
const boardDirs = diagramFolderDirs(files);
|
|
38155
38381
|
const out = [];
|
|
@@ -38192,11 +38418,11 @@ function loadMarkdownDocs(dir, type, contextRoot) {
|
|
|
38192
38418
|
return out;
|
|
38193
38419
|
}
|
|
38194
38420
|
function loadChangelogEntries(contextRoot) {
|
|
38195
|
-
const path2 =
|
|
38196
|
-
if (!
|
|
38421
|
+
const path2 = join47(contextRoot, "core", "CHANGELOG.json");
|
|
38422
|
+
if (!existsSync48(path2)) return [];
|
|
38197
38423
|
let entries = [];
|
|
38198
38424
|
try {
|
|
38199
|
-
const raw =
|
|
38425
|
+
const raw = readFileSync37(path2, "utf-8");
|
|
38200
38426
|
const parsed = JSON.parse(raw);
|
|
38201
38427
|
if (Array.isArray(parsed)) entries = parsed;
|
|
38202
38428
|
} catch {
|
|
@@ -38244,9 +38470,9 @@ function loadChangelogEntries(contextRoot) {
|
|
|
38244
38470
|
return out;
|
|
38245
38471
|
}
|
|
38246
38472
|
function loadMemoryFile(contextRoot) {
|
|
38247
|
-
const path2 =
|
|
38248
|
-
if (!
|
|
38249
|
-
const raw =
|
|
38473
|
+
const path2 = join47(contextRoot, "core", "2.memory.md");
|
|
38474
|
+
if (!existsSync48(path2)) return [];
|
|
38475
|
+
const raw = readFileSync37(path2, "utf-8");
|
|
38250
38476
|
const sections = raw.split(/^##\s+/m).slice(1);
|
|
38251
38477
|
const out = [];
|
|
38252
38478
|
for (let i = 0; i < sections.length; i++) {
|
|
@@ -38278,11 +38504,11 @@ function loadMemoryFile(contextRoot) {
|
|
|
38278
38504
|
return out;
|
|
38279
38505
|
}
|
|
38280
38506
|
function loadBookmarkDocs(contextRoot) {
|
|
38281
|
-
const path2 =
|
|
38282
|
-
if (!
|
|
38507
|
+
const path2 = join47(contextRoot, "state", ".sleep.json");
|
|
38508
|
+
if (!existsSync48(path2)) return [];
|
|
38283
38509
|
let bookmarks = [];
|
|
38284
38510
|
try {
|
|
38285
|
-
const parsed = JSON.parse(
|
|
38511
|
+
const parsed = JSON.parse(readFileSync37(path2, "utf-8"));
|
|
38286
38512
|
if (parsed && typeof parsed === "object" && Array.isArray(parsed.bookmarks)) {
|
|
38287
38513
|
bookmarks = parsed.bookmarks;
|
|
38288
38514
|
}
|
|
@@ -38324,14 +38550,14 @@ function loadBookmarkDocs(contextRoot) {
|
|
|
38324
38550
|
return out;
|
|
38325
38551
|
}
|
|
38326
38552
|
function loadSkillDocs(skillsRoot) {
|
|
38327
|
-
if (!
|
|
38553
|
+
if (!existsSync48(skillsRoot)) return [];
|
|
38328
38554
|
const files = import_fast_glob12.default.sync("*/SKILL.md", { cwd: skillsRoot, absolute: true });
|
|
38329
38555
|
const out = [];
|
|
38330
38556
|
for (const file of files) {
|
|
38331
38557
|
try {
|
|
38332
38558
|
const { data, content } = readFrontmatter(file);
|
|
38333
38559
|
if (data.alwaysApply === true) continue;
|
|
38334
|
-
const slug = typeof data.name === "string" && data.name ? data.name : basename13(
|
|
38560
|
+
const slug = typeof data.name === "string" && data.name ? data.name : basename13(dirname24(file));
|
|
38335
38561
|
const title = slug;
|
|
38336
38562
|
const description = typeof data.description === "string" ? data.description : "";
|
|
38337
38563
|
const tags = Array.isArray(data.tags) ? data.tags.map(String) : [];
|
|
@@ -38363,13 +38589,13 @@ function buildCorpus(contextRoot, opts = {}) {
|
|
|
38363
38589
|
const types = new Set(opts.types ?? ["knowledge", "feature", "task", "memory", "changelog"]);
|
|
38364
38590
|
const docs = [];
|
|
38365
38591
|
if (types.has("knowledge")) {
|
|
38366
|
-
docs.push(...loadMarkdownDocs(
|
|
38592
|
+
docs.push(...loadMarkdownDocs(join47(contextRoot, "knowledge"), "knowledge", contextRoot));
|
|
38367
38593
|
}
|
|
38368
38594
|
if (types.has("feature")) {
|
|
38369
|
-
docs.push(...loadMarkdownDocs(
|
|
38595
|
+
docs.push(...loadMarkdownDocs(join47(contextRoot, "core", "features"), "feature", contextRoot));
|
|
38370
38596
|
}
|
|
38371
38597
|
if (types.has("task")) {
|
|
38372
|
-
docs.push(...loadMarkdownDocs(
|
|
38598
|
+
docs.push(...loadMarkdownDocs(join47(contextRoot, "state"), "task", contextRoot));
|
|
38373
38599
|
docs.push(...loadDigestDocs(contextRoot));
|
|
38374
38600
|
}
|
|
38375
38601
|
if (types.has("memory")) {
|
|
@@ -38719,8 +38945,8 @@ var init_recall = __esm({
|
|
|
38719
38945
|
});
|
|
38720
38946
|
|
|
38721
38947
|
// src/lib/session-digest.ts
|
|
38722
|
-
import { existsSync as
|
|
38723
|
-
import { join as
|
|
38948
|
+
import { existsSync as existsSync49, mkdirSync as mkdirSync23, writeFileSync as writeFileSync30 } from "fs";
|
|
38949
|
+
import { join as join48 } from "path";
|
|
38724
38950
|
function coerceCreatedAt(value) {
|
|
38725
38951
|
if (typeof value === "string" && value.trim()) return value.trim();
|
|
38726
38952
|
if (value instanceof Date && !Number.isNaN(value.getTime())) return value.toISOString();
|
|
@@ -38778,18 +39004,18 @@ function enforceByteCap(lines, maxBytes) {
|
|
|
38778
39004
|
return out.trimEnd() + "\n";
|
|
38779
39005
|
}
|
|
38780
39006
|
function digestsDir(root) {
|
|
38781
|
-
return
|
|
39007
|
+
return join48(root, "state", DIGESTS_DIRNAME);
|
|
38782
39008
|
}
|
|
38783
39009
|
function digestPath(root, sessionId) {
|
|
38784
39010
|
const safe = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
38785
|
-
return
|
|
39011
|
+
return join48(digestsDir(root), `${safe}.md`);
|
|
38786
39012
|
}
|
|
38787
39013
|
function digestExists(root, sessionId) {
|
|
38788
|
-
return
|
|
39014
|
+
return existsSync49(digestPath(root, sessionId));
|
|
38789
39015
|
}
|
|
38790
39016
|
function digestIsPartial(root, sessionId) {
|
|
38791
39017
|
const file = digestPath(root, sessionId);
|
|
38792
|
-
if (!
|
|
39018
|
+
if (!existsSync49(file)) return false;
|
|
38793
39019
|
try {
|
|
38794
39020
|
const { data } = readFrontmatter(file);
|
|
38795
39021
|
return data.partial === true;
|
|
@@ -38799,7 +39025,7 @@ function digestIsPartial(root, sessionId) {
|
|
|
38799
39025
|
}
|
|
38800
39026
|
function writeDigest(root, sessionId, md, opts = {}) {
|
|
38801
39027
|
const dir = digestsDir(root);
|
|
38802
|
-
|
|
39028
|
+
mkdirSync23(dir, { recursive: true });
|
|
38803
39029
|
const file = digestPath(root, sessionId);
|
|
38804
39030
|
const safeId = sessionId.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
38805
39031
|
const frontmatter = [
|
|
@@ -38811,12 +39037,12 @@ function writeDigest(root, sessionId, md, opts = {}) {
|
|
|
38811
39037
|
"---",
|
|
38812
39038
|
""
|
|
38813
39039
|
].join("\n");
|
|
38814
|
-
|
|
39040
|
+
writeFileSync30(file, frontmatter + md, "utf-8");
|
|
38815
39041
|
return file;
|
|
38816
39042
|
}
|
|
38817
39043
|
function loadDigestDocs(root) {
|
|
38818
39044
|
const dir = digestsDir(root);
|
|
38819
|
-
if (!
|
|
39045
|
+
if (!existsSync49(dir)) return [];
|
|
38820
39046
|
const files = import_fast_glob13.default.sync("*.md", { cwd: dir, absolute: true });
|
|
38821
39047
|
const parsed = [];
|
|
38822
39048
|
for (const file of files) {
|
|
@@ -38827,7 +39053,7 @@ function loadDigestDocs(root) {
|
|
|
38827
39053
|
const title = `Session digest ${sessionId}`;
|
|
38828
39054
|
const body = content.trim();
|
|
38829
39055
|
if (!body) continue;
|
|
38830
|
-
const relPath =
|
|
39056
|
+
const relPath = join48("state", DIGESTS_DIRNAME, `${sessionId}.md`);
|
|
38831
39057
|
const createdAt = coerceCreatedAt(data.created_at);
|
|
38832
39058
|
const fields = buildFields({ slug, title, description: "", tags: [], body });
|
|
38833
39059
|
const ms = createdAt ? Date.parse(createdAt) : NaN;
|
|
@@ -38878,56 +39104,9 @@ var init_session_digest = __esm({
|
|
|
38878
39104
|
}
|
|
38879
39105
|
});
|
|
38880
39106
|
|
|
38881
|
-
// src/lib/salience.ts
|
|
38882
|
-
function clamp(text) {
|
|
38883
|
-
const oneLine = text.replace(/\s+/g, " ").trim();
|
|
38884
|
-
return oneLine.length <= MAX_MESSAGE_CHARS ? oneLine : oneLine.slice(0, MAX_MESSAGE_CHARS - 1) + "\u2026";
|
|
38885
|
-
}
|
|
38886
|
-
function detectSalience(distilled) {
|
|
38887
|
-
const moments = [];
|
|
38888
|
-
const seen = /* @__PURE__ */ new Set();
|
|
38889
|
-
const push = (message, salience) => {
|
|
38890
|
-
const clamped = clamp(message);
|
|
38891
|
-
if (!clamped) return;
|
|
38892
|
-
const key = `${salience}::${clamped.toLowerCase()}`;
|
|
38893
|
-
if (seen.has(key)) return;
|
|
38894
|
-
seen.add(key);
|
|
38895
|
-
moments.push({ message: clamped, salience });
|
|
38896
|
-
};
|
|
38897
|
-
for (const msg of distilled.userMessages) {
|
|
38898
|
-
if (CORRECTION_RE.test(msg)) {
|
|
38899
|
-
push(`User correction: ${msg}`, 2);
|
|
38900
|
-
}
|
|
38901
|
-
}
|
|
38902
|
-
if (distilled.errors.length > 0 && distilled.codeChanges.length > 0) {
|
|
38903
|
-
const firstError = distilled.errors[0];
|
|
38904
|
-
push(`Error resolved by code change: ${firstError}`, 1);
|
|
38905
|
-
}
|
|
38906
|
-
const decisionSources = [
|
|
38907
|
-
...distilled.agentDecisions.filter((d) => !d.startsWith("[thinking]")),
|
|
38908
|
-
...distilled.userMessages
|
|
38909
|
-
];
|
|
38910
|
-
for (const src of decisionSources) {
|
|
38911
|
-
if (DECISION_RE.test(src)) {
|
|
38912
|
-
push(`Decision: ${src}`, 2);
|
|
38913
|
-
}
|
|
38914
|
-
}
|
|
38915
|
-
return moments.slice(0, MAX_MOMENTS);
|
|
38916
|
-
}
|
|
38917
|
-
var CORRECTION_RE, DECISION_RE, MAX_MOMENTS, MAX_MESSAGE_CHARS;
|
|
38918
|
-
var init_salience = __esm({
|
|
38919
|
-
"src/lib/salience.ts"() {
|
|
38920
|
-
"use strict";
|
|
38921
|
-
CORRECTION_RE = /\b(no|actually|wrong|instead|hayır|yanlış|değil)\b/i;
|
|
38922
|
-
DECISION_RE = /\b(decided|chose|switched to|will use|karar|seçtik)\b/i;
|
|
38923
|
-
MAX_MOMENTS = 5;
|
|
38924
|
-
MAX_MESSAGE_CHARS = 200;
|
|
38925
|
-
}
|
|
38926
|
-
});
|
|
38927
|
-
|
|
38928
39107
|
// src/lib/marketing/path-guards.ts
|
|
38929
|
-
import { existsSync as
|
|
38930
|
-
import { basename as basename14, dirname as
|
|
39108
|
+
import { existsSync as existsSync50, realpathSync } from "fs";
|
|
39109
|
+
import { basename as basename14, dirname as dirname25, resolve as resolve8, sep as sep5 } from "path";
|
|
38931
39110
|
function isMarketingEnvPath(filePath, from) {
|
|
38932
39111
|
if (!filePath) return false;
|
|
38933
39112
|
const root = resolveContextRoot(from);
|
|
@@ -38941,7 +39120,7 @@ function isMarketingEnvPath(filePath, from) {
|
|
|
38941
39120
|
}
|
|
38942
39121
|
function realpathOrSelf(p) {
|
|
38943
39122
|
try {
|
|
38944
|
-
return
|
|
39123
|
+
return existsSync50(p) ? realpathSync(p) : p;
|
|
38945
39124
|
} catch {
|
|
38946
39125
|
return p;
|
|
38947
39126
|
}
|
|
@@ -38949,9 +39128,9 @@ function realpathOrSelf(p) {
|
|
|
38949
39128
|
function realpathOfNearestAncestor(p) {
|
|
38950
39129
|
let current = p;
|
|
38951
39130
|
const tail = [];
|
|
38952
|
-
while (current && current !== sep5 && !
|
|
39131
|
+
while (current && current !== sep5 && !existsSync50(current)) {
|
|
38953
39132
|
tail.unshift(basename14(current));
|
|
38954
|
-
current =
|
|
39133
|
+
current = dirname25(current);
|
|
38955
39134
|
}
|
|
38956
39135
|
if (!current || current === sep5) return p;
|
|
38957
39136
|
try {
|
|
@@ -39093,17 +39272,17 @@ If pure greeting: {"skip":true}`;
|
|
|
39093
39272
|
// src/cli/commands/app.ts
|
|
39094
39273
|
import { execFileSync as execFileSync3, spawn as spawnProcess } from "child_process";
|
|
39095
39274
|
import {
|
|
39096
|
-
existsSync as
|
|
39097
|
-
mkdirSync as
|
|
39275
|
+
existsSync as existsSync51,
|
|
39276
|
+
mkdirSync as mkdirSync24,
|
|
39098
39277
|
mkdtempSync,
|
|
39099
|
-
readFileSync as
|
|
39100
|
-
writeFileSync as
|
|
39278
|
+
readFileSync as readFileSync39,
|
|
39279
|
+
writeFileSync as writeFileSync31,
|
|
39101
39280
|
rmSync as rmSync6,
|
|
39102
39281
|
renameSync as renameSync7,
|
|
39103
39282
|
readdirSync as readdirSync12
|
|
39104
39283
|
} from "fs";
|
|
39105
39284
|
import { homedir as homedir2, tmpdir } from "os";
|
|
39106
|
-
import { join as
|
|
39285
|
+
import { join as join49, resolve as resolve9, dirname as dirname26 } from "path";
|
|
39107
39286
|
import { createHash as createHash2 } from "crypto";
|
|
39108
39287
|
function detectPlatform(platform2 = process.platform, arch2 = process.arch) {
|
|
39109
39288
|
const os3 = platform2 === "darwin" ? "darwin" : platform2 === "win32" ? "win32" : platform2 === "linux" ? "linux" : "other";
|
|
@@ -39116,16 +39295,16 @@ function pickAssetForArch(assetNames, arch2) {
|
|
|
39116
39295
|
return exact ?? null;
|
|
39117
39296
|
}
|
|
39118
39297
|
function defaultInstallDir(home = homedir2()) {
|
|
39119
|
-
return
|
|
39298
|
+
return join49(home, "Applications");
|
|
39120
39299
|
}
|
|
39121
39300
|
function appManifestPath(home = homedir2()) {
|
|
39122
|
-
return
|
|
39301
|
+
return join49(home, ".dreamcontext", "app.json");
|
|
39123
39302
|
}
|
|
39124
39303
|
function readAppManifest(home = homedir2()) {
|
|
39125
39304
|
const p = appManifestPath(home);
|
|
39126
|
-
if (!
|
|
39305
|
+
if (!existsSync51(p)) return null;
|
|
39127
39306
|
try {
|
|
39128
|
-
const parsed = JSON.parse(
|
|
39307
|
+
const parsed = JSON.parse(readFileSync39(p, "utf-8"));
|
|
39129
39308
|
if (!parsed || typeof parsed.version !== "string" || typeof parsed.path !== "string") return null;
|
|
39130
39309
|
return {
|
|
39131
39310
|
version: parsed.version,
|
|
@@ -39139,8 +39318,8 @@ function readAppManifest(home = homedir2()) {
|
|
|
39139
39318
|
}
|
|
39140
39319
|
function writeAppManifest(manifest, home = homedir2()) {
|
|
39141
39320
|
const p = appManifestPath(home);
|
|
39142
|
-
|
|
39143
|
-
|
|
39321
|
+
mkdirSync24(dirname26(p), { recursive: true });
|
|
39322
|
+
writeFileSync31(p, JSON.stringify(manifest, null, 2) + "\n", "utf-8");
|
|
39144
39323
|
}
|
|
39145
39324
|
function run(cmd, args) {
|
|
39146
39325
|
execFileSync3(cmd, args, { stdio: ["ignore", "ignore", "pipe"] });
|
|
@@ -39149,17 +39328,17 @@ function runCapture(cmd, args) {
|
|
|
39149
39328
|
return execFileSync3(cmd, args, { encoding: "utf-8" }).toString().trim();
|
|
39150
39329
|
}
|
|
39151
39330
|
function validateAppBundle(appDir) {
|
|
39152
|
-
if (!appDir.endsWith(".app") || !
|
|
39331
|
+
if (!appDir.endsWith(".app") || !existsSync51(appDir)) {
|
|
39153
39332
|
throw new Error(`Not a .app bundle: ${appDir}`);
|
|
39154
39333
|
}
|
|
39155
|
-
const macos =
|
|
39156
|
-
const plist =
|
|
39157
|
-
if (!
|
|
39334
|
+
const macos = join49(appDir, "Contents", "MacOS");
|
|
39335
|
+
const plist = join49(appDir, "Contents", "Info.plist");
|
|
39336
|
+
if (!existsSync51(macos) || !existsSync51(plist)) {
|
|
39158
39337
|
throw new Error(`Malformed .app (missing Contents/MacOS or Info.plist): ${appDir}`);
|
|
39159
39338
|
}
|
|
39160
39339
|
}
|
|
39161
39340
|
function readBundleVersion(appDir) {
|
|
39162
|
-
const plist =
|
|
39341
|
+
const plist = join49(appDir, "Contents", "Info.plist");
|
|
39163
39342
|
try {
|
|
39164
39343
|
return runCapture("plutil", ["-extract", "CFBundleShortVersionString", "raw", "-o", "-", plist]) || null;
|
|
39165
39344
|
} catch {
|
|
@@ -39168,11 +39347,11 @@ function readBundleVersion(appDir) {
|
|
|
39168
39347
|
}
|
|
39169
39348
|
function findAppInDir(dir) {
|
|
39170
39349
|
const entries = readdirSync12(dir).filter((e) => e.endsWith(".app"));
|
|
39171
|
-
return entries.length > 0 ?
|
|
39350
|
+
return entries.length > 0 ? join49(dir, entries[0]) : null;
|
|
39172
39351
|
}
|
|
39173
39352
|
function materializeAppBundle(source, workDir) {
|
|
39174
39353
|
const src = resolve9(source);
|
|
39175
|
-
if (!
|
|
39354
|
+
if (!existsSync51(src)) throw new Error(`Source not found: ${src}`);
|
|
39176
39355
|
if (src.endsWith(".app")) {
|
|
39177
39356
|
return src;
|
|
39178
39357
|
}
|
|
@@ -39209,14 +39388,14 @@ function installAppBundle(source, opts = {}) {
|
|
|
39209
39388
|
}
|
|
39210
39389
|
const home = opts.home ?? homedir2();
|
|
39211
39390
|
const installDir = opts.installDir ?? defaultInstallDir(home);
|
|
39212
|
-
|
|
39213
|
-
const workDir = mkdtempSync(
|
|
39391
|
+
mkdirSync24(installDir, { recursive: true });
|
|
39392
|
+
const workDir = mkdtempSync(join49(tmpdir(), "dc-app-"));
|
|
39214
39393
|
try {
|
|
39215
39394
|
const appDir = materializeAppBundle(source, workDir);
|
|
39216
39395
|
validateAppBundle(appDir);
|
|
39217
|
-
const target =
|
|
39218
|
-
const staging =
|
|
39219
|
-
const backup =
|
|
39396
|
+
const target = join49(installDir, APP_BUNDLE_NAME);
|
|
39397
|
+
const staging = join49(installDir, `.${APP_BUNDLE_NAME}.new-${process.pid}`);
|
|
39398
|
+
const backup = join49(installDir, `.${APP_BUNDLE_NAME}.old-${process.pid}`);
|
|
39220
39399
|
rmSync6(staging, { recursive: true, force: true });
|
|
39221
39400
|
rmSync6(backup, { recursive: true, force: true });
|
|
39222
39401
|
let wasRunning;
|
|
@@ -39228,11 +39407,11 @@ function installAppBundle(source, opts = {}) {
|
|
|
39228
39407
|
} catch {
|
|
39229
39408
|
}
|
|
39230
39409
|
wasRunning = isAppRunning();
|
|
39231
|
-
replaced =
|
|
39410
|
+
replaced = existsSync51(target);
|
|
39232
39411
|
if (replaced) renameSync7(target, backup);
|
|
39233
39412
|
renameSync7(staging, target);
|
|
39234
39413
|
} catch (e) {
|
|
39235
|
-
if (
|
|
39414
|
+
if (existsSync51(target) === false && existsSync51(backup)) {
|
|
39236
39415
|
try {
|
|
39237
39416
|
renameSync7(backup, target);
|
|
39238
39417
|
} catch {
|
|
@@ -39278,10 +39457,10 @@ async function downloadTo(url, destFile, fetchImpl = fetch) {
|
|
|
39278
39457
|
const res = await fetchImpl(url, { headers: { "User-Agent": "dreamcontext-cli" } });
|
|
39279
39458
|
if (!res.ok) throw new Error(`Download failed (${res.status}): ${url}`);
|
|
39280
39459
|
const buf = Buffer.from(await res.arrayBuffer());
|
|
39281
|
-
|
|
39460
|
+
writeFileSync31(destFile, buf);
|
|
39282
39461
|
}
|
|
39283
39462
|
function sha256File(file) {
|
|
39284
|
-
return createHash2("sha256").update(
|
|
39463
|
+
return createHash2("sha256").update(readFileSync39(file)).digest("hex");
|
|
39285
39464
|
}
|
|
39286
39465
|
async function downloadLatestArtifact(repo = APP_RELEASE_REPO, fetchImpl = fetch) {
|
|
39287
39466
|
const plat = detectPlatform();
|
|
@@ -39297,13 +39476,13 @@ async function downloadLatestArtifact(repo = APP_RELEASE_REPO, fetchImpl = fetch
|
|
|
39297
39476
|
`Release ${release2.tag_name} is missing ${assetName}.sha256 \u2014 refusing to install an unverified binary.`
|
|
39298
39477
|
);
|
|
39299
39478
|
}
|
|
39300
|
-
const workDir = mkdtempSync(
|
|
39479
|
+
const workDir = mkdtempSync(join49(tmpdir(), "dc-app-dl-"));
|
|
39301
39480
|
try {
|
|
39302
|
-
const archivePath =
|
|
39481
|
+
const archivePath = join49(workDir, assetName);
|
|
39303
39482
|
await downloadTo(asset.browser_download_url, archivePath, fetchImpl);
|
|
39304
|
-
const sumFile =
|
|
39483
|
+
const sumFile = join49(workDir, `${assetName}.sha256`);
|
|
39305
39484
|
await downloadTo(sumAsset.browser_download_url, sumFile, fetchImpl);
|
|
39306
|
-
const expected =
|
|
39485
|
+
const expected = readFileSync39(sumFile, "utf-8").trim().split(/\s+/)[0].toLowerCase();
|
|
39307
39486
|
const actual = sha256File(archivePath).toLowerCase();
|
|
39308
39487
|
if (!expected || expected !== actual) {
|
|
39309
39488
|
throw new Error(`Checksum mismatch for ${assetName}: expected ${expected || "(empty)"}, got ${actual}`);
|
|
@@ -39365,7 +39544,7 @@ async function doInstall(from, dir) {
|
|
|
39365
39544
|
}
|
|
39366
39545
|
source = dl.archivePath;
|
|
39367
39546
|
sourceLabel = "github";
|
|
39368
|
-
tempToClean =
|
|
39547
|
+
tempToClean = dirname26(dl.archivePath);
|
|
39369
39548
|
}
|
|
39370
39549
|
try {
|
|
39371
39550
|
const res = installAppBundle(source, { installDir: dir, sourceLabel });
|
|
@@ -39417,7 +39596,7 @@ async function doUpdate(from, dir) {
|
|
|
39417
39596
|
console.log(source_default.green(`\u2713 Updated dreamcontext-beta ${installed.version} \u2192 ${res.version ?? dl.version}`));
|
|
39418
39597
|
if (res.wasRunning) console.log(source_default.yellow("Restart the app to apply the update."));
|
|
39419
39598
|
} finally {
|
|
39420
|
-
rmSync6(
|
|
39599
|
+
rmSync6(dirname26(dl.archivePath), { recursive: true, force: true });
|
|
39421
39600
|
}
|
|
39422
39601
|
}
|
|
39423
39602
|
function doStatus() {
|
|
@@ -39426,7 +39605,7 @@ function doStatus() {
|
|
|
39426
39605
|
console.log("Desktop app: not installed (run `dreamcontext app install`).");
|
|
39427
39606
|
return;
|
|
39428
39607
|
}
|
|
39429
|
-
const onDisk =
|
|
39608
|
+
const onDisk = existsSync51(installed.path);
|
|
39430
39609
|
console.log(`Desktop app: ${installed.version}`);
|
|
39431
39610
|
console.log(` path: ${installed.path}${onDisk ? "" : source_default.red(" (missing!)")}`);
|
|
39432
39611
|
console.log(` source: ${installed.source}`);
|
|
@@ -39455,15 +39634,82 @@ var init_app = __esm({
|
|
|
39455
39634
|
}
|
|
39456
39635
|
});
|
|
39457
39636
|
|
|
39637
|
+
// src/cli/commands/asset-drift.ts
|
|
39638
|
+
import { mkdtempSync as mkdtempSync2, rmSync as rmSync7, existsSync as existsSync52, readFileSync as readFileSync40, readdirSync as readdirSync13 } from "fs";
|
|
39639
|
+
import { tmpdir as tmpdir2 } from "os";
|
|
39640
|
+
import { join as join50, dirname as dirname27 } from "path";
|
|
39641
|
+
function walkFiles(dir, base, out) {
|
|
39642
|
+
for (const entry of readdirSync13(dir, { withFileTypes: true })) {
|
|
39643
|
+
const abs = join50(dir, entry.name);
|
|
39644
|
+
if (entry.isDirectory()) walkFiles(abs, base, out);
|
|
39645
|
+
else if (entry.isFile()) out.push(abs.slice(base.length + 1));
|
|
39646
|
+
}
|
|
39647
|
+
}
|
|
39648
|
+
async function computeUsedAssetsChanged(projectRoot, config) {
|
|
39649
|
+
const tmp = mkdtempSync2(join50(tmpdir2(), "dc-assetdrift-"));
|
|
39650
|
+
try {
|
|
39651
|
+
for (const platform2 of config.platforms) {
|
|
39652
|
+
await installCoreForPlatform(platform2, tmp);
|
|
39653
|
+
}
|
|
39654
|
+
if (config.packs.length > 0) {
|
|
39655
|
+
directPackInstall(config.packs, tmp, config.platforms, emptyManifest());
|
|
39656
|
+
}
|
|
39657
|
+
const produced = [];
|
|
39658
|
+
walkFiles(tmp, tmp, produced);
|
|
39659
|
+
for (const rel of produced) {
|
|
39660
|
+
if (rel.endsWith("settings.json")) continue;
|
|
39661
|
+
if (rel.startsWith("_dream_context/")) continue;
|
|
39662
|
+
const onDisk = join50(projectRoot, rel);
|
|
39663
|
+
if (!existsSync52(onDisk)) return true;
|
|
39664
|
+
if (!readFileSync40(join50(tmp, rel)).equals(readFileSync40(onDisk))) return true;
|
|
39665
|
+
}
|
|
39666
|
+
return false;
|
|
39667
|
+
} finally {
|
|
39668
|
+
try {
|
|
39669
|
+
rmSync7(tmp, { recursive: true, force: true });
|
|
39670
|
+
} catch {
|
|
39671
|
+
}
|
|
39672
|
+
}
|
|
39673
|
+
}
|
|
39674
|
+
async function runAssetDriftRefresh(contextRoot) {
|
|
39675
|
+
const projectRoot = dirname27(contextRoot);
|
|
39676
|
+
const config = readSetupConfig(projectRoot);
|
|
39677
|
+
if (!config) return;
|
|
39678
|
+
const cliVersion = dreamcontextVersion();
|
|
39679
|
+
const state = resolveDriftState({
|
|
39680
|
+
cliVersion,
|
|
39681
|
+
setupVersion: config.setupVersion,
|
|
39682
|
+
driftCheckEnv: process.env.DREAMCONTEXT_DRIFT_CHECK
|
|
39683
|
+
});
|
|
39684
|
+
if (state !== "stale" && state !== "bootstrap") return;
|
|
39685
|
+
const usedAssetsChanged = await computeUsedAssetsChanged(projectRoot, config);
|
|
39686
|
+
writeAssetDriftCache(contextRoot, {
|
|
39687
|
+
cliVersion,
|
|
39688
|
+
setupVersion: config.setupVersion,
|
|
39689
|
+
usedAssetsChanged,
|
|
39690
|
+
checkedAt: Date.now()
|
|
39691
|
+
});
|
|
39692
|
+
}
|
|
39693
|
+
var init_asset_drift = __esm({
|
|
39694
|
+
"src/cli/commands/asset-drift.ts"() {
|
|
39695
|
+
"use strict";
|
|
39696
|
+
init_setup_config();
|
|
39697
|
+
init_manifest();
|
|
39698
|
+
init_setup_drift();
|
|
39699
|
+
init_asset_drift_cache();
|
|
39700
|
+
init_install_skill();
|
|
39701
|
+
}
|
|
39702
|
+
});
|
|
39703
|
+
|
|
39458
39704
|
// src/cli/commands/hook.ts
|
|
39459
|
-
import { readFileSync as
|
|
39705
|
+
import { readFileSync as readFileSync41, existsSync as existsSync53, statSync as statSync7 } from "fs";
|
|
39460
39706
|
import { execFileSync as execFileSync4, spawn as spawn3 } from "child_process";
|
|
39461
39707
|
import { get as httpGet } from "http";
|
|
39462
|
-
import { dirname as
|
|
39708
|
+
import { dirname as dirname28, resolve as resolve10, join as join51, extname as extname2, basename as basename15, relative as relative4 } from "path";
|
|
39463
39709
|
function readStdin() {
|
|
39464
39710
|
if (process.stdin.isTTY) return null;
|
|
39465
39711
|
try {
|
|
39466
|
-
const raw =
|
|
39712
|
+
const raw = readFileSync41(0, "utf-8");
|
|
39467
39713
|
if (!raw.trim()) return null;
|
|
39468
39714
|
const parsed = JSON.parse(raw);
|
|
39469
39715
|
if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) return null;
|
|
@@ -39473,11 +39719,11 @@ function readStdin() {
|
|
|
39473
39719
|
}
|
|
39474
39720
|
}
|
|
39475
39721
|
function analyzeTranscript(transcriptPath) {
|
|
39476
|
-
if (!
|
|
39722
|
+
if (!existsSync53(transcriptPath)) return ZERO_ANALYSIS;
|
|
39477
39723
|
try {
|
|
39478
39724
|
const stat = statSync7(transcriptPath);
|
|
39479
39725
|
if (stat.size === 0 || stat.size > MAX_TRANSCRIPT_BYTES2) return ZERO_ANALYSIS;
|
|
39480
|
-
const content =
|
|
39726
|
+
const content = readFileSync41(transcriptPath, "utf-8");
|
|
39481
39727
|
const changeMatches = content.match(/"name"\s*:\s*"(?:Write|Edit)"/g);
|
|
39482
39728
|
const toolMatches = content.match(/"name"\s*:\s*"[A-Za-z_]+"/g);
|
|
39483
39729
|
const slugs = /* @__PURE__ */ new Set();
|
|
@@ -39487,15 +39733,76 @@ function analyzeTranscript(transcriptPath) {
|
|
|
39487
39733
|
for (const m of content.matchAll(/"file_path"\s*:\s*"[^"]*_dream_context\/state\/([a-z0-9][a-z0-9-]*)\.md"/g)) {
|
|
39488
39734
|
slugs.add(m[1]);
|
|
39489
39735
|
}
|
|
39736
|
+
let userTurns = 0;
|
|
39737
|
+
let assistantChars = 0;
|
|
39738
|
+
let decisionMarkers = 0;
|
|
39739
|
+
for (const line of content.split("\n")) {
|
|
39740
|
+
const trimmed = line.trim();
|
|
39741
|
+
if (!trimmed) continue;
|
|
39742
|
+
if (DECISION_RE.test(trimmed) || CORRECTION_RE.test(trimmed)) {
|
|
39743
|
+
decisionMarkers++;
|
|
39744
|
+
}
|
|
39745
|
+
let rec;
|
|
39746
|
+
try {
|
|
39747
|
+
rec = JSON.parse(trimmed);
|
|
39748
|
+
} catch {
|
|
39749
|
+
continue;
|
|
39750
|
+
}
|
|
39751
|
+
if (!rec || typeof rec !== "object") continue;
|
|
39752
|
+
const role = recordRole(rec);
|
|
39753
|
+
if (role === "user") {
|
|
39754
|
+
userTurns++;
|
|
39755
|
+
} else if (role === "assistant") {
|
|
39756
|
+
assistantChars += sumAssistantTextChars(rec);
|
|
39757
|
+
}
|
|
39758
|
+
}
|
|
39490
39759
|
return {
|
|
39491
39760
|
changeCount: changeMatches ? changeMatches.length : 0,
|
|
39492
39761
|
toolCount: toolMatches ? toolMatches.length : 0,
|
|
39493
|
-
taskSlugs: [...slugs]
|
|
39762
|
+
taskSlugs: [...slugs],
|
|
39763
|
+
userTurns,
|
|
39764
|
+
assistantChars,
|
|
39765
|
+
decisionMarkers
|
|
39494
39766
|
};
|
|
39495
39767
|
} catch {
|
|
39496
39768
|
return ZERO_ANALYSIS;
|
|
39497
39769
|
}
|
|
39498
39770
|
}
|
|
39771
|
+
function recordRole(rec) {
|
|
39772
|
+
const r = rec;
|
|
39773
|
+
if (typeof r.role === "string") return r.role;
|
|
39774
|
+
if (r.message && typeof r.message === "object" && typeof r.message.role === "string") {
|
|
39775
|
+
return r.message.role;
|
|
39776
|
+
}
|
|
39777
|
+
return null;
|
|
39778
|
+
}
|
|
39779
|
+
function sumAssistantTextChars(rec) {
|
|
39780
|
+
const r = rec;
|
|
39781
|
+
const content = (r.message && typeof r.message === "object" ? r.message.content : void 0) ?? r.content;
|
|
39782
|
+
let total = 0;
|
|
39783
|
+
if (typeof content === "string") {
|
|
39784
|
+
return Math.min(MAX_TEXT_BLOCK_CHARS, content.length);
|
|
39785
|
+
}
|
|
39786
|
+
if (Array.isArray(content)) {
|
|
39787
|
+
for (const block of content) {
|
|
39788
|
+
if (block && typeof block === "object") {
|
|
39789
|
+
const b = block;
|
|
39790
|
+
if (b.type === "text" && typeof b.text === "string") {
|
|
39791
|
+
total += Math.min(MAX_TEXT_BLOCK_CHARS, b.text.length);
|
|
39792
|
+
}
|
|
39793
|
+
}
|
|
39794
|
+
}
|
|
39795
|
+
}
|
|
39796
|
+
return total;
|
|
39797
|
+
}
|
|
39798
|
+
function scoreFromSubstance(signals2) {
|
|
39799
|
+
let pts = 0;
|
|
39800
|
+
if (signals2.userTurns >= 6) pts++;
|
|
39801
|
+
if (signals2.assistantChars >= 6e3) pts++;
|
|
39802
|
+
if (signals2.decisionMarkers >= 1) pts++;
|
|
39803
|
+
if (signals2.taskSlugs.length >= 2) pts++;
|
|
39804
|
+
return Math.min(3, pts);
|
|
39805
|
+
}
|
|
39499
39806
|
function scoreFromChangeCount(count) {
|
|
39500
39807
|
if (count <= 0) return 0;
|
|
39501
39808
|
if (count <= 3) return 1;
|
|
@@ -39512,39 +39819,39 @@ function isJsTsFile(filePath) {
|
|
|
39512
39819
|
return JS_TS_EXTENSIONS.has(extname2(filePath).toLowerCase());
|
|
39513
39820
|
}
|
|
39514
39821
|
function findProjectConfig(filePath) {
|
|
39515
|
-
let dir =
|
|
39822
|
+
let dir = dirname28(resolve10(filePath));
|
|
39516
39823
|
let formatter = null;
|
|
39517
39824
|
let tsconfig = null;
|
|
39518
39825
|
for (let i = 0; i <= MAX_WALK_LEVELS; i++) {
|
|
39519
39826
|
if (!formatter) {
|
|
39520
39827
|
for (const name of BIOME_CONFIGS) {
|
|
39521
|
-
if (
|
|
39522
|
-
formatter = { type: "biome", configPath:
|
|
39828
|
+
if (existsSync53(join51(dir, name))) {
|
|
39829
|
+
formatter = { type: "biome", configPath: join51(dir, name), projectRoot: dir };
|
|
39523
39830
|
break;
|
|
39524
39831
|
}
|
|
39525
39832
|
}
|
|
39526
39833
|
if (!formatter) {
|
|
39527
39834
|
for (const name of PRETTIER_CONFIGS) {
|
|
39528
|
-
if (
|
|
39529
|
-
formatter = { type: "prettier", configPath:
|
|
39835
|
+
if (existsSync53(join51(dir, name))) {
|
|
39836
|
+
formatter = { type: "prettier", configPath: join51(dir, name), projectRoot: dir };
|
|
39530
39837
|
break;
|
|
39531
39838
|
}
|
|
39532
39839
|
}
|
|
39533
39840
|
}
|
|
39534
39841
|
}
|
|
39535
|
-
if (!tsconfig &&
|
|
39536
|
-
tsconfig =
|
|
39842
|
+
if (!tsconfig && existsSync53(join51(dir, "tsconfig.json"))) {
|
|
39843
|
+
tsconfig = join51(dir, "tsconfig.json");
|
|
39537
39844
|
}
|
|
39538
39845
|
if (formatter && tsconfig) break;
|
|
39539
|
-
const parent =
|
|
39846
|
+
const parent = dirname28(dir);
|
|
39540
39847
|
if (parent === dir) break;
|
|
39541
39848
|
dir = parent;
|
|
39542
39849
|
}
|
|
39543
39850
|
return { formatter, tsconfig };
|
|
39544
39851
|
}
|
|
39545
39852
|
function resolveLocalBin(binName, projectRoot) {
|
|
39546
|
-
const localBin =
|
|
39547
|
-
return
|
|
39853
|
+
const localBin = join51(projectRoot, "node_modules", ".bin", binName);
|
|
39854
|
+
return existsSync53(localBin) ? localBin : null;
|
|
39548
39855
|
}
|
|
39549
39856
|
function runFormatter(detection, filePath) {
|
|
39550
39857
|
try {
|
|
@@ -39586,7 +39893,7 @@ function runFormatter(detection, filePath) {
|
|
|
39586
39893
|
}
|
|
39587
39894
|
}
|
|
39588
39895
|
function runTscCheckWithConfig(filePath, tsconfigPath) {
|
|
39589
|
-
const projectRoot =
|
|
39896
|
+
const projectRoot = dirname28(tsconfigPath);
|
|
39590
39897
|
let tscOutput;
|
|
39591
39898
|
try {
|
|
39592
39899
|
const localBin = resolveLocalBin("tsc", projectRoot);
|
|
@@ -39687,6 +39994,29 @@ function getConsolidationDirective(state) {
|
|
|
39687
39994
|
}
|
|
39688
39995
|
return null;
|
|
39689
39996
|
}
|
|
39997
|
+
function userPromptReminder(state) {
|
|
39998
|
+
const { debt, bookmarks, sleep_started_at } = state;
|
|
39999
|
+
if (sleep_started_at) {
|
|
40000
|
+
if (debt >= 4) {
|
|
40001
|
+
return `Consolidation already in progress (started: ${sleep_started_at}). Do NOT dispatch another sleep agent.`;
|
|
40002
|
+
}
|
|
40003
|
+
return null;
|
|
40004
|
+
}
|
|
40005
|
+
const criticalBookmarks = bookmarks.filter((b) => b.salience === 3);
|
|
40006
|
+
if (debt >= 10) {
|
|
40007
|
+
return `Sleep debt is ${debt}. CONSOLIDATION REQUIRED. Run sleep flow per SKILL.md (parallel specialist fan-out) NOW.`;
|
|
40008
|
+
}
|
|
40009
|
+
if (criticalBookmarks.length > 0) {
|
|
40010
|
+
return `${criticalBookmarks.length} critical bookmark(s) need consolidation. Run sleep flow per SKILL.md.`;
|
|
40011
|
+
}
|
|
40012
|
+
if (debt >= 7) {
|
|
40013
|
+
return `Sleep debt is ${debt}. Consolidation recommended before starting new work.`;
|
|
40014
|
+
}
|
|
40015
|
+
if (debt >= 4) {
|
|
40016
|
+
return `Sleep debt is ${debt}. After completing the current task, offer to consolidate.`;
|
|
40017
|
+
}
|
|
40018
|
+
return null;
|
|
40019
|
+
}
|
|
39690
40020
|
function resolveDashboardPort() {
|
|
39691
40021
|
const raw = process.env.DREAMCONTEXT_DASHBOARD_PORT;
|
|
39692
40022
|
if (raw) {
|
|
@@ -39728,6 +40058,16 @@ function spawnDashboard(port) {
|
|
|
39728
40058
|
});
|
|
39729
40059
|
child.unref();
|
|
39730
40060
|
}
|
|
40061
|
+
function spawnAssetDriftRefresh() {
|
|
40062
|
+
const cliEntry = process.argv[1];
|
|
40063
|
+
if (!cliEntry) return;
|
|
40064
|
+
const child = spawn3(process.execPath, [cliEntry, "hook", "refresh-asset-drift"], {
|
|
40065
|
+
detached: true,
|
|
40066
|
+
stdio: "ignore",
|
|
40067
|
+
cwd: process.cwd()
|
|
40068
|
+
});
|
|
40069
|
+
child.unref();
|
|
40070
|
+
}
|
|
39731
40071
|
function registerHookCommand(program2) {
|
|
39732
40072
|
const hook = program2.command("hook").description("Hook handlers for Claude Code (stop, session-start, subagent-start, pre-tool-use, user-prompt-submit, post-tool-use, pre-compact)");
|
|
39733
40073
|
hook.command("stop").description("Record session metadata (called by Claude Code Stop hook)").action(() => {
|
|
@@ -39749,7 +40089,11 @@ function registerHookCommand(program2) {
|
|
|
39749
40089
|
const stoppedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
39750
40090
|
const analysis = transcriptPath ? analyzeTranscript(transcriptPath) : ZERO_ANALYSIS;
|
|
39751
40091
|
const { changeCount, toolCount } = analysis;
|
|
39752
|
-
const score = Math.max(
|
|
40092
|
+
const score = Math.max(
|
|
40093
|
+
scoreFromChangeCount(changeCount),
|
|
40094
|
+
scoreFromToolCount(toolCount),
|
|
40095
|
+
scoreFromSubstance(analysis)
|
|
40096
|
+
);
|
|
39753
40097
|
for (const bookmark of state.bookmarks) {
|
|
39754
40098
|
if (!bookmark.session_id) {
|
|
39755
40099
|
bookmark.session_id = sessionId;
|
|
@@ -39758,35 +40102,18 @@ function registerHookCommand(program2) {
|
|
|
39758
40102
|
const bookmarkTaskSlugs = state.bookmarks.filter((b) => b.session_id === sessionId && b.task_slug).map((b) => b.task_slug);
|
|
39759
40103
|
const transcriptTaskSlugs = analysis.taskSlugs;
|
|
39760
40104
|
const taskSlugs = [.../* @__PURE__ */ new Set([...transcriptTaskSlugs, ...bookmarkTaskSlugs])];
|
|
39761
|
-
const
|
|
39762
|
-
|
|
39763
|
-
|
|
39764
|
-
|
|
39765
|
-
|
|
39766
|
-
|
|
39767
|
-
|
|
39768
|
-
|
|
39769
|
-
|
|
39770
|
-
|
|
39771
|
-
|
|
39772
|
-
|
|
39773
|
-
} else {
|
|
39774
|
-
state.sessions.unshift({
|
|
39775
|
-
session_id: sessionId,
|
|
39776
|
-
transcript_path: transcriptPath,
|
|
39777
|
-
stopped_at: stoppedAt,
|
|
39778
|
-
last_assistant_message: lastAssistantMessage,
|
|
39779
|
-
change_count: changeCount,
|
|
39780
|
-
tool_count: toolCount,
|
|
39781
|
-
score,
|
|
39782
|
-
task_slugs: taskSlugs
|
|
39783
|
-
});
|
|
39784
|
-
}
|
|
39785
|
-
state.debt += score;
|
|
39786
|
-
if (existing < 0) {
|
|
39787
|
-
state.sessions_since_last_sleep = (state.sessions_since_last_sleep || 0) + 1;
|
|
39788
|
-
}
|
|
39789
|
-
writeSleepState(root, state);
|
|
40105
|
+
const upsertInput = {
|
|
40106
|
+
session_id: sessionId,
|
|
40107
|
+
transcript_path: transcriptPath,
|
|
40108
|
+
stopped_at: stoppedAt,
|
|
40109
|
+
last_assistant_message: lastAssistantMessage,
|
|
40110
|
+
change_count: changeCount,
|
|
40111
|
+
tool_count: toolCount,
|
|
40112
|
+
score,
|
|
40113
|
+
task_slugs: taskSlugs
|
|
40114
|
+
};
|
|
40115
|
+
const nextState = upsertSessionOnStop(state, upsertInput);
|
|
40116
|
+
writeSleepState(root, nextState);
|
|
39790
40117
|
});
|
|
39791
40118
|
hook.command("session-start").description("Analyze previous session + output context snapshot (called by Claude Code SessionStart hook)").action(() => {
|
|
39792
40119
|
const input2 = readStdin();
|
|
@@ -39808,7 +40135,11 @@ function registerHookCommand(program2) {
|
|
|
39808
40135
|
continue;
|
|
39809
40136
|
}
|
|
39810
40137
|
const analysis = analyzeTranscript(session.transcript_path);
|
|
39811
|
-
const score = Math.max(
|
|
40138
|
+
const score = Math.max(
|
|
40139
|
+
scoreFromChangeCount(analysis.changeCount),
|
|
40140
|
+
scoreFromToolCount(analysis.toolCount),
|
|
40141
|
+
scoreFromSubstance(analysis)
|
|
40142
|
+
);
|
|
39812
40143
|
session.change_count = analysis.changeCount;
|
|
39813
40144
|
session.tool_count = analysis.toolCount;
|
|
39814
40145
|
session.score = score;
|
|
@@ -39913,23 +40244,12 @@ function registerHookCommand(program2) {
|
|
|
39913
40244
|
const root = resolveContextRoot();
|
|
39914
40245
|
if (!root) process.exit(0);
|
|
39915
40246
|
const state = readSleepState(root);
|
|
39916
|
-
const
|
|
39917
|
-
if (sleep_started_at) {
|
|
39918
|
-
if (
|
|
39919
|
-
console.log(`Consolidation already in progress (started: ${sleep_started_at}). Do NOT dispatch another sleep agent.`);
|
|
39920
|
-
}
|
|
40247
|
+
const reminder = userPromptReminder(state);
|
|
40248
|
+
if (state.sleep_started_at) {
|
|
40249
|
+
if (reminder) console.log(reminder);
|
|
39921
40250
|
return;
|
|
39922
40251
|
}
|
|
39923
|
-
|
|
39924
|
-
if (debt >= 10) {
|
|
39925
|
-
console.log(`Sleep debt is ${debt}. CONSOLIDATION REQUIRED. Run sleep flow per SKILL.md (parallel specialist fan-out) NOW.`);
|
|
39926
|
-
} else if (criticalBookmarks.length > 0) {
|
|
39927
|
-
console.log(`${criticalBookmarks.length} critical bookmark(s) need consolidation. Run sleep flow per SKILL.md.`);
|
|
39928
|
-
} else if (debt >= 7) {
|
|
39929
|
-
console.log(`Sleep debt is ${debt}. Consolidation recommended before starting new work.`);
|
|
39930
|
-
} else if (debt >= 4) {
|
|
39931
|
-
console.log(`Sleep debt is ${debt}. After completing the current task, offer to consolidate.`);
|
|
39932
|
-
}
|
|
40252
|
+
if (reminder) console.log(reminder);
|
|
39933
40253
|
try {
|
|
39934
40254
|
const stale = listStaleRecs(24);
|
|
39935
40255
|
if (stale.length > 0) {
|
|
@@ -39943,7 +40263,7 @@ function registerHookCommand(program2) {
|
|
|
39943
40263
|
}
|
|
39944
40264
|
if (process.env.DREAMCONTEXT_VERSION_CHECK !== "0") {
|
|
39945
40265
|
try {
|
|
39946
|
-
const projectRoot =
|
|
40266
|
+
const projectRoot = dirname28(root);
|
|
39947
40267
|
let vcache = readVersionCache(projectRoot);
|
|
39948
40268
|
if (!isCacheFresh(vcache)) {
|
|
39949
40269
|
const loaded = loadCatalog();
|
|
@@ -39954,6 +40274,7 @@ function registerHookCommand(program2) {
|
|
|
39954
40274
|
refreshVersionCache(projectRoot, { catalogPackNames: packNames });
|
|
39955
40275
|
vcache = readVersionCache(projectRoot);
|
|
39956
40276
|
maybeTriggerAppUpdate();
|
|
40277
|
+
spawnAssetDriftRefresh();
|
|
39957
40278
|
}
|
|
39958
40279
|
const notice = maybeAutoUpgrade(projectRoot, dreamcontextVersion(), vcache);
|
|
39959
40280
|
if (notice) console.log(notice);
|
|
@@ -40018,7 +40339,7 @@ function registerHookCommand(program2) {
|
|
|
40018
40339
|
try {
|
|
40019
40340
|
const prompt = String(input2.prompt ?? "");
|
|
40020
40341
|
if (prompt.trim().length >= 8) {
|
|
40021
|
-
const skillsRoot =
|
|
40342
|
+
const skillsRoot = join51(process.cwd(), ".claude", "skills");
|
|
40022
40343
|
const docs = loadSkillDocs(skillsRoot);
|
|
40023
40344
|
if (docs.length > 0 && bm25Search(prompt, docs, 5).some((h) => h.score >= SKILL_SCORE_THRESHOLD)) {
|
|
40024
40345
|
gatedSkills = true;
|
|
@@ -40079,30 +40400,37 @@ function registerHookCommand(program2) {
|
|
|
40079
40400
|
if (!root) process.exit(0);
|
|
40080
40401
|
const state = readSleepState(root);
|
|
40081
40402
|
const trigger = input2 && typeof input2.trigger === "string" ? input2.trigger : "unknown";
|
|
40082
|
-
state
|
|
40403
|
+
const nextState = appendCompactionRecord(state, {
|
|
40083
40404
|
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
40084
40405
|
trigger,
|
|
40085
40406
|
debt_at_compaction: state.debt,
|
|
40086
40407
|
sessions_count: state.sessions.length,
|
|
40087
40408
|
bookmarks_count: state.bookmarks.length
|
|
40088
40409
|
});
|
|
40089
|
-
|
|
40090
|
-
state.compaction_log = state.compaction_log.slice(0, 20);
|
|
40091
|
-
}
|
|
40092
|
-
writeSleepState(root, state);
|
|
40410
|
+
writeSleepState(root, nextState);
|
|
40093
40411
|
try {
|
|
40094
40412
|
const sessionId = input2 && typeof input2.session_id === "string" ? input2.session_id : "";
|
|
40095
40413
|
const transcriptPath = input2 && typeof input2.transcript_path === "string" ? input2.transcript_path : "";
|
|
40096
|
-
if (sessionId && transcriptPath &&
|
|
40414
|
+
if (sessionId && transcriptPath && existsSync53(transcriptPath)) {
|
|
40097
40415
|
const distilled = distillTranscript(transcriptPath);
|
|
40098
40416
|
writeDigest(root, sessionId, buildDigest(distilled), { partial: true });
|
|
40099
40417
|
}
|
|
40100
40418
|
} catch {
|
|
40101
40419
|
}
|
|
40102
40420
|
});
|
|
40421
|
+
hook.command("refresh-asset-drift").description("Recompute whether `dreamcontext update` would change any asset this project uses (detached cache refresh)").action(async () => {
|
|
40422
|
+
readStdin();
|
|
40423
|
+
try {
|
|
40424
|
+
const root = resolveContextRoot();
|
|
40425
|
+
if (root) await runAssetDriftRefresh(root);
|
|
40426
|
+
} catch {
|
|
40427
|
+
}
|
|
40428
|
+
process.exit(0);
|
|
40429
|
+
});
|
|
40103
40430
|
hook.command("ensure-dashboard").description("Open the web dashboard if it is not already running (called by Claude Code SessionStart hook)").action(async () => {
|
|
40104
40431
|
readStdin();
|
|
40105
40432
|
if (process.env.DREAMCONTEXT_AUTO_DASHBOARD === "0") process.exit(0);
|
|
40433
|
+
if (readAppManifest() !== null) process.exit(0);
|
|
40106
40434
|
const root = resolveContextRoot();
|
|
40107
40435
|
if (!root) process.exit(0);
|
|
40108
40436
|
const port = resolveDashboardPort();
|
|
@@ -40118,12 +40446,14 @@ function registerHookCommand(program2) {
|
|
|
40118
40446
|
process.exit(0);
|
|
40119
40447
|
});
|
|
40120
40448
|
}
|
|
40121
|
-
var MAX_TRANSCRIPT_BYTES2, SKILL_SCORE_THRESHOLD, ZERO_ANALYSIS, JS_TS_EXTENSIONS, MAX_WALK_LEVELS, BIOME_CONFIGS, PRETTIER_CONFIGS, DEFAULT_DASHBOARD_PORT;
|
|
40449
|
+
var MAX_TRANSCRIPT_BYTES2, SKILL_SCORE_THRESHOLD, ZERO_ANALYSIS, MAX_TEXT_BLOCK_CHARS, JS_TS_EXTENSIONS, MAX_WALK_LEVELS, BIOME_CONFIGS, PRETTIER_CONFIGS, DEFAULT_DASHBOARD_PORT;
|
|
40122
40450
|
var init_hook = __esm({
|
|
40123
40451
|
"src/cli/commands/hook.ts"() {
|
|
40124
40452
|
"use strict";
|
|
40125
40453
|
init_context_path();
|
|
40126
40454
|
init_sleep();
|
|
40455
|
+
init_sleep_consolidation();
|
|
40456
|
+
init_salience();
|
|
40127
40457
|
init_transcript();
|
|
40128
40458
|
init_session_digest();
|
|
40129
40459
|
init_salience();
|
|
@@ -40137,10 +40467,19 @@ var init_hook = __esm({
|
|
|
40137
40467
|
init_version_check();
|
|
40138
40468
|
init_manifest();
|
|
40139
40469
|
init_app();
|
|
40470
|
+
init_asset_drift();
|
|
40140
40471
|
init_install_skill();
|
|
40141
40472
|
MAX_TRANSCRIPT_BYTES2 = 50 * 1024 * 1024;
|
|
40142
40473
|
SKILL_SCORE_THRESHOLD = 1;
|
|
40143
|
-
ZERO_ANALYSIS = {
|
|
40474
|
+
ZERO_ANALYSIS = {
|
|
40475
|
+
changeCount: 0,
|
|
40476
|
+
toolCount: 0,
|
|
40477
|
+
taskSlugs: [],
|
|
40478
|
+
userTurns: 0,
|
|
40479
|
+
assistantChars: 0,
|
|
40480
|
+
decisionMarkers: 0
|
|
40481
|
+
};
|
|
40482
|
+
MAX_TEXT_BLOCK_CHARS = 2e4;
|
|
40144
40483
|
JS_TS_EXTENSIONS = /* @__PURE__ */ new Set([".js", ".jsx", ".ts", ".tsx", ".mjs", ".cjs", ".mts", ".cts"]);
|
|
40145
40484
|
MAX_WALK_LEVELS = 10;
|
|
40146
40485
|
BIOME_CONFIGS = ["biome.json", "biome.jsonc"];
|
|
@@ -40159,11 +40498,11 @@ var init_hook = __esm({
|
|
|
40159
40498
|
});
|
|
40160
40499
|
|
|
40161
40500
|
// src/cli/commands/doctor.ts
|
|
40162
|
-
import { existsSync as
|
|
40163
|
-
import { join as
|
|
40501
|
+
import { existsSync as existsSync54, readFileSync as readFileSync42, readdirSync as readdirSync14, statSync as statSync8 } from "fs";
|
|
40502
|
+
import { join as join52 } from "path";
|
|
40164
40503
|
function checkFile(root, relPath, label, required) {
|
|
40165
|
-
const fullPath =
|
|
40166
|
-
if (!
|
|
40504
|
+
const fullPath = join52(root, relPath);
|
|
40505
|
+
if (!existsSync54(fullPath)) {
|
|
40167
40506
|
return {
|
|
40168
40507
|
name: label,
|
|
40169
40508
|
status: required ? "error" : "warn",
|
|
@@ -40179,7 +40518,7 @@ function checkFile(root, relPath, label, required) {
|
|
|
40179
40518
|
};
|
|
40180
40519
|
}
|
|
40181
40520
|
if (relPath.endsWith(".md")) {
|
|
40182
|
-
const content =
|
|
40521
|
+
const content = readFileSync42(fullPath, "utf-8");
|
|
40183
40522
|
if (content.includes("(Add your") || content.includes("{{") || content.includes("(To be defined)")) {
|
|
40184
40523
|
return {
|
|
40185
40524
|
name: label,
|
|
@@ -40191,12 +40530,12 @@ function checkFile(root, relPath, label, required) {
|
|
|
40191
40530
|
return { name: label, status: "ok", message: relPath };
|
|
40192
40531
|
}
|
|
40193
40532
|
function checkJson(root, relPath, label) {
|
|
40194
|
-
const fullPath =
|
|
40195
|
-
if (!
|
|
40533
|
+
const fullPath = join52(root, relPath);
|
|
40534
|
+
if (!existsSync54(fullPath)) {
|
|
40196
40535
|
return { name: label, status: "error", message: `Missing: ${relPath}` };
|
|
40197
40536
|
}
|
|
40198
40537
|
try {
|
|
40199
|
-
const content =
|
|
40538
|
+
const content = readFileSync42(fullPath, "utf-8");
|
|
40200
40539
|
JSON.parse(content);
|
|
40201
40540
|
return { name: label, status: "ok", message: relPath };
|
|
40202
40541
|
} catch {
|
|
@@ -40204,8 +40543,8 @@ function checkJson(root, relPath, label) {
|
|
|
40204
40543
|
}
|
|
40205
40544
|
}
|
|
40206
40545
|
function checkDirectory(root, relPath, label) {
|
|
40207
|
-
const fullPath =
|
|
40208
|
-
if (!
|
|
40546
|
+
const fullPath = join52(root, relPath);
|
|
40547
|
+
if (!existsSync54(fullPath)) {
|
|
40209
40548
|
return { name: label, status: "error", message: `Missing directory: ${relPath}` };
|
|
40210
40549
|
}
|
|
40211
40550
|
return { name: label, status: "ok", message: relPath };
|
|
@@ -40213,13 +40552,13 @@ function checkDirectory(root, relPath, label) {
|
|
|
40213
40552
|
function checkDataStructures(root) {
|
|
40214
40553
|
const results = [];
|
|
40215
40554
|
const dirRel = "knowledge/data-structures";
|
|
40216
|
-
const dirAbs =
|
|
40555
|
+
const dirAbs = join52(root, dirRel);
|
|
40217
40556
|
const oldRel = "core/data-structures";
|
|
40218
|
-
const oldAbs =
|
|
40219
|
-
const oldExists =
|
|
40557
|
+
const oldAbs = join52(root, oldRel);
|
|
40558
|
+
const oldExists = existsSync54(oldAbs);
|
|
40220
40559
|
const legacyRel = "core/5.data_structures.sql";
|
|
40221
|
-
const legacyExists =
|
|
40222
|
-
if (!
|
|
40560
|
+
const legacyExists = existsSync54(join52(root, legacyRel));
|
|
40561
|
+
if (!existsSync54(dirAbs)) {
|
|
40223
40562
|
if (oldExists) {
|
|
40224
40563
|
results.push({
|
|
40225
40564
|
name: "Data structures",
|
|
@@ -40243,7 +40582,7 @@ function checkDataStructures(root) {
|
|
|
40243
40582
|
}
|
|
40244
40583
|
let mdCount = 0;
|
|
40245
40584
|
try {
|
|
40246
|
-
mdCount =
|
|
40585
|
+
mdCount = readdirSync14(dirAbs).filter((f) => f.endsWith(".md")).length;
|
|
40247
40586
|
} catch {
|
|
40248
40587
|
results.push({
|
|
40249
40588
|
name: "Data structures",
|
|
@@ -40315,19 +40654,19 @@ function registerDoctorCommand(program2) {
|
|
|
40315
40654
|
checkFile(root, "core/4.tech_stack.md", "Tech stack", false),
|
|
40316
40655
|
...checkDataStructures(root),
|
|
40317
40656
|
// Taxonomy vocabulary (non-fatal: absent means DEFAULT_VOCABULARY used)
|
|
40318
|
-
...!
|
|
40657
|
+
...!existsSync54(join52(root, "core", "taxonomy.json")) ? [{
|
|
40319
40658
|
name: "Taxonomy vocabulary",
|
|
40320
40659
|
status: "warn",
|
|
40321
40660
|
message: "core/taxonomy.json not found \u2014 run `dreamcontext taxonomy init` to scaffold it"
|
|
40322
40661
|
}] : [checkJson(root, "core/taxonomy.json", "Taxonomy vocabulary")],
|
|
40323
40662
|
// Sleep state (optional — created on first Stop hook)
|
|
40324
|
-
...
|
|
40325
|
-
...
|
|
40663
|
+
...existsSync54(join52(root, "state", ".sleep.json")) ? [checkJson(root, "state/.sleep.json", "Sleep state")] : [],
|
|
40664
|
+
...existsSync54(join52(root, "state", ".platforms.json")) ? [checkJson(root, "state/.platforms.json", "Platform defaults")] : []
|
|
40326
40665
|
];
|
|
40327
|
-
const sleepPath =
|
|
40328
|
-
if (
|
|
40666
|
+
const sleepPath = join52(root, "state", ".sleep.json");
|
|
40667
|
+
if (existsSync54(sleepPath)) {
|
|
40329
40668
|
try {
|
|
40330
|
-
const parsed = JSON.parse(
|
|
40669
|
+
const parsed = JSON.parse(readFileSync42(sleepPath, "utf-8"));
|
|
40331
40670
|
if (typeof parsed.debt !== "number" || parsed.debt < 0) {
|
|
40332
40671
|
results.push({ name: "Sleep debt", status: "warn", message: "Invalid debt value in .sleep.json" });
|
|
40333
40672
|
}
|
|
@@ -40490,23 +40829,23 @@ var init_middleware = __esm({
|
|
|
40490
40829
|
});
|
|
40491
40830
|
|
|
40492
40831
|
// src/server/static.ts
|
|
40493
|
-
import { existsSync as
|
|
40494
|
-
import { join as
|
|
40832
|
+
import { existsSync as existsSync55, readFileSync as readFileSync43, statSync as statSync9 } from "fs";
|
|
40833
|
+
import { join as join53, extname as extname3 } from "path";
|
|
40495
40834
|
function serveStatic(req, res, staticDir) {
|
|
40496
40835
|
const url = new URL(req.url || "/", `http://${req.headers.host}`);
|
|
40497
|
-
let filePath =
|
|
40836
|
+
let filePath = join53(staticDir, url.pathname);
|
|
40498
40837
|
if (!filePath.startsWith(staticDir)) {
|
|
40499
40838
|
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
40500
40839
|
res.end("Forbidden");
|
|
40501
40840
|
return;
|
|
40502
40841
|
}
|
|
40503
|
-
if (
|
|
40504
|
-
filePath =
|
|
40842
|
+
if (existsSync55(filePath) && statSync9(filePath).isDirectory()) {
|
|
40843
|
+
filePath = join53(filePath, "index.html");
|
|
40505
40844
|
}
|
|
40506
|
-
if (
|
|
40845
|
+
if (existsSync55(filePath) && statSync9(filePath).isFile()) {
|
|
40507
40846
|
const ext = extname3(filePath);
|
|
40508
40847
|
const contentType = MIME_TYPES[ext] || "application/octet-stream";
|
|
40509
|
-
const content =
|
|
40848
|
+
const content = readFileSync43(filePath);
|
|
40510
40849
|
res.writeHead(200, {
|
|
40511
40850
|
"Content-Type": contentType,
|
|
40512
40851
|
"Content-Length": content.length,
|
|
@@ -40515,9 +40854,9 @@ function serveStatic(req, res, staticDir) {
|
|
|
40515
40854
|
res.end(content);
|
|
40516
40855
|
return;
|
|
40517
40856
|
}
|
|
40518
|
-
const indexPath2 =
|
|
40519
|
-
if (
|
|
40520
|
-
const content =
|
|
40857
|
+
const indexPath2 = join53(staticDir, "index.html");
|
|
40858
|
+
if (existsSync55(indexPath2)) {
|
|
40859
|
+
const content = readFileSync43(indexPath2);
|
|
40521
40860
|
res.writeHead(200, {
|
|
40522
40861
|
"Content-Type": "text/html; charset=utf-8",
|
|
40523
40862
|
"Content-Length": content.length,
|
|
@@ -41038,20 +41377,20 @@ var init_sleep2 = __esm({
|
|
|
41038
41377
|
});
|
|
41039
41378
|
|
|
41040
41379
|
// src/server/routes/core.ts
|
|
41041
|
-
import { existsSync as
|
|
41042
|
-
import { join as
|
|
41380
|
+
import { existsSync as existsSync56, readdirSync as readdirSync15 } from "fs";
|
|
41381
|
+
import { join as join54 } from "path";
|
|
41043
41382
|
function getCoreDir(contextRoot) {
|
|
41044
|
-
return
|
|
41383
|
+
return join54(contextRoot, "core");
|
|
41045
41384
|
}
|
|
41046
41385
|
async function handleCoreList(_req, res, _params, contextRoot) {
|
|
41047
41386
|
const coreDir = getCoreDir(contextRoot);
|
|
41048
|
-
if (!
|
|
41387
|
+
if (!existsSync56(coreDir)) {
|
|
41049
41388
|
sendJson(res, 200, { files: [] });
|
|
41050
41389
|
return;
|
|
41051
41390
|
}
|
|
41052
|
-
const entries =
|
|
41391
|
+
const entries = readdirSync15(coreDir, { withFileTypes: true });
|
|
41053
41392
|
const files = entries.filter((e) => e.isFile() && (e.name.endsWith(".md") || e.name.endsWith(".sql") || e.name.endsWith(".json"))).map((e) => {
|
|
41054
|
-
const filePath =
|
|
41393
|
+
const filePath = join54(coreDir, e.name);
|
|
41055
41394
|
let frontmatter = {};
|
|
41056
41395
|
if (e.name.endsWith(".md")) {
|
|
41057
41396
|
try {
|
|
@@ -41075,13 +41414,13 @@ async function handleCoreGet(_req, res, params, contextRoot) {
|
|
|
41075
41414
|
sendError(res, 400, "invalid_path", "Invalid filename.");
|
|
41076
41415
|
return;
|
|
41077
41416
|
}
|
|
41078
|
-
if (!
|
|
41417
|
+
if (!existsSync56(filePath)) {
|
|
41079
41418
|
sendError(res, 404, "not_found", `Core file not found: ${filename}`);
|
|
41080
41419
|
return;
|
|
41081
41420
|
}
|
|
41082
41421
|
if (filename.endsWith(".json")) {
|
|
41083
|
-
const { readFileSync:
|
|
41084
|
-
const raw2 =
|
|
41422
|
+
const { readFileSync: readFileSync69 } = await import("fs");
|
|
41423
|
+
const raw2 = readFileSync69(filePath, "utf-8");
|
|
41085
41424
|
try {
|
|
41086
41425
|
const data = JSON.parse(raw2);
|
|
41087
41426
|
sendJson(res, 200, { filename, type: "json", data });
|
|
@@ -41115,8 +41454,8 @@ async function handleCoreGet(_req, res, params, contextRoot) {
|
|
|
41115
41454
|
});
|
|
41116
41455
|
return;
|
|
41117
41456
|
}
|
|
41118
|
-
const { readFileSync:
|
|
41119
|
-
const raw =
|
|
41457
|
+
const { readFileSync: readFileSync68 } = await import("fs");
|
|
41458
|
+
const raw = readFileSync68(filePath, "utf-8");
|
|
41120
41459
|
sendJson(res, 200, { filename, type: "text", content: raw });
|
|
41121
41460
|
}
|
|
41122
41461
|
async function handleCoreUpdate(req, res, params, contextRoot) {
|
|
@@ -41126,7 +41465,7 @@ async function handleCoreUpdate(req, res, params, contextRoot) {
|
|
|
41126
41465
|
sendError(res, 400, "invalid_path", "Invalid filename.");
|
|
41127
41466
|
return;
|
|
41128
41467
|
}
|
|
41129
|
-
if (!
|
|
41468
|
+
if (!existsSync56(filePath)) {
|
|
41130
41469
|
sendError(res, 404, "not_found", `Core file not found: ${filename}`);
|
|
41131
41470
|
return;
|
|
41132
41471
|
}
|
|
@@ -41166,8 +41505,8 @@ async function handleCoreUpdate(req, res, params, contextRoot) {
|
|
|
41166
41505
|
return;
|
|
41167
41506
|
}
|
|
41168
41507
|
changedParts.push("content");
|
|
41169
|
-
const { writeFileSync:
|
|
41170
|
-
|
|
41508
|
+
const { writeFileSync: writeFileSync46 } = await import("fs");
|
|
41509
|
+
writeFileSync46(filePath, body.content, "utf-8");
|
|
41171
41510
|
}
|
|
41172
41511
|
const what = changedParts.length > 0 ? changedParts.join(" and ") : "file";
|
|
41173
41512
|
recordDashboardChange(contextRoot, {
|
|
@@ -41190,10 +41529,10 @@ var init_core2 = __esm({
|
|
|
41190
41529
|
});
|
|
41191
41530
|
|
|
41192
41531
|
// src/server/routes/knowledge.ts
|
|
41193
|
-
import { existsSync as
|
|
41194
|
-
import { join as
|
|
41532
|
+
import { existsSync as existsSync57 } from "fs";
|
|
41533
|
+
import { join as join55 } from "path";
|
|
41195
41534
|
function getKnowledgeDir2(contextRoot) {
|
|
41196
|
-
return
|
|
41535
|
+
return join55(contextRoot, "knowledge");
|
|
41197
41536
|
}
|
|
41198
41537
|
async function handleKnowledgeList(_req, res, _params, contextRoot) {
|
|
41199
41538
|
const entries = buildKnowledgeIndex(contextRoot);
|
|
@@ -41206,7 +41545,7 @@ async function handleKnowledgeGet(_req, res, params, contextRoot) {
|
|
|
41206
41545
|
sendError(res, 400, "invalid_path", `Invalid knowledge slug: ${slug}`);
|
|
41207
41546
|
return;
|
|
41208
41547
|
}
|
|
41209
|
-
if (!
|
|
41548
|
+
if (!existsSync57(filePath)) {
|
|
41210
41549
|
sendError(res, 404, "not_found", `Knowledge file not found: ${slug}`);
|
|
41211
41550
|
return;
|
|
41212
41551
|
}
|
|
@@ -41230,7 +41569,7 @@ async function handleKnowledgeUpdate(req, res, params, contextRoot) {
|
|
|
41230
41569
|
sendError(res, 400, "invalid_path", `Invalid knowledge slug: ${slug}`);
|
|
41231
41570
|
return;
|
|
41232
41571
|
}
|
|
41233
|
-
if (!
|
|
41572
|
+
if (!existsSync57(filePath)) {
|
|
41234
41573
|
sendError(res, 404, "not_found", `Knowledge file not found: ${slug}`);
|
|
41235
41574
|
return;
|
|
41236
41575
|
}
|
|
@@ -41287,14 +41626,14 @@ var init_knowledge2 = __esm({
|
|
|
41287
41626
|
});
|
|
41288
41627
|
|
|
41289
41628
|
// src/server/routes/features.ts
|
|
41290
|
-
import { existsSync as
|
|
41291
|
-
import { join as
|
|
41629
|
+
import { existsSync as existsSync58 } from "fs";
|
|
41630
|
+
import { join as join56, basename as basename16 } from "path";
|
|
41292
41631
|
function getFeaturesDir2(contextRoot) {
|
|
41293
|
-
return
|
|
41632
|
+
return join56(contextRoot, "core", "features");
|
|
41294
41633
|
}
|
|
41295
41634
|
async function handleFeaturesList(_req, res, _params, contextRoot) {
|
|
41296
41635
|
const featuresDir = getFeaturesDir2(contextRoot);
|
|
41297
|
-
if (!
|
|
41636
|
+
if (!existsSync58(featuresDir)) {
|
|
41298
41637
|
sendJson(res, 200, { features: [] });
|
|
41299
41638
|
return;
|
|
41300
41639
|
}
|
|
@@ -41325,7 +41664,7 @@ async function handleFeaturesGet(_req, res, params, contextRoot) {
|
|
|
41325
41664
|
sendError(res, 400, "invalid_path", `Invalid feature slug: ${slug}`);
|
|
41326
41665
|
return;
|
|
41327
41666
|
}
|
|
41328
|
-
if (!
|
|
41667
|
+
if (!existsSync58(filePath)) {
|
|
41329
41668
|
sendError(res, 404, "not_found", `Feature not found: ${slug}`);
|
|
41330
41669
|
return;
|
|
41331
41670
|
}
|
|
@@ -41367,11 +41706,11 @@ var init_features2 = __esm({
|
|
|
41367
41706
|
});
|
|
41368
41707
|
|
|
41369
41708
|
// src/server/routes/changelog.ts
|
|
41370
|
-
import { existsSync as
|
|
41371
|
-
import { join as
|
|
41709
|
+
import { existsSync as existsSync59 } from "fs";
|
|
41710
|
+
import { join as join57 } from "path";
|
|
41372
41711
|
async function handleChangelogGet(_req, res, _params, contextRoot) {
|
|
41373
|
-
const filePath =
|
|
41374
|
-
if (!
|
|
41712
|
+
const filePath = join57(contextRoot, "core", "CHANGELOG.json");
|
|
41713
|
+
if (!existsSync59(filePath)) {
|
|
41375
41714
|
sendJson(res, 200, { entries: [] });
|
|
41376
41715
|
return;
|
|
41377
41716
|
}
|
|
@@ -41383,8 +41722,8 @@ async function handleChangelogGet(_req, res, _params, contextRoot) {
|
|
|
41383
41722
|
}
|
|
41384
41723
|
}
|
|
41385
41724
|
async function handleReleasesGet(_req, res, _params, contextRoot) {
|
|
41386
|
-
const filePath =
|
|
41387
|
-
if (!
|
|
41725
|
+
const filePath = join57(contextRoot, "core", "RELEASES.json");
|
|
41726
|
+
if (!existsSync59(filePath)) {
|
|
41388
41727
|
sendJson(res, 200, { entries: [] });
|
|
41389
41728
|
return;
|
|
41390
41729
|
}
|
|
@@ -41438,7 +41777,7 @@ async function handleReleasesCreate(req, res, _params, contextRoot) {
|
|
|
41438
41777
|
tasks: Array.isArray(body.tasks) ? body.tasks : [],
|
|
41439
41778
|
changelog: Array.isArray(body.changelog) ? body.changelog : []
|
|
41440
41779
|
};
|
|
41441
|
-
const filePath =
|
|
41780
|
+
const filePath = join57(contextRoot, "core", "RELEASES.json");
|
|
41442
41781
|
insertToJsonArray(filePath, release2);
|
|
41443
41782
|
if (release2.features.length > 0) {
|
|
41444
41783
|
backPopulateFeatures(contextRoot, release2.features, release2.version);
|
|
@@ -41457,8 +41796,8 @@ async function handleReleasesUpdate(req, res, params, contextRoot) {
|
|
|
41457
41796
|
sendError(res, 400, "invalid_body", "Request body must be JSON.");
|
|
41458
41797
|
return;
|
|
41459
41798
|
}
|
|
41460
|
-
const filePath =
|
|
41461
|
-
if (!
|
|
41799
|
+
const filePath = join57(contextRoot, "core", "RELEASES.json");
|
|
41800
|
+
if (!existsSync59(filePath)) {
|
|
41462
41801
|
sendError(res, 404, "not_found", `Release not found: ${params.version}`);
|
|
41463
41802
|
return;
|
|
41464
41803
|
}
|
|
@@ -41512,8 +41851,8 @@ var init_changelog = __esm({
|
|
|
41512
41851
|
});
|
|
41513
41852
|
|
|
41514
41853
|
// src/lib/graph.ts
|
|
41515
|
-
import { existsSync as
|
|
41516
|
-
import { join as
|
|
41854
|
+
import { existsSync as existsSync60, readFileSync as readFileSync44 } from "fs";
|
|
41855
|
+
import { join as join58, basename as basename17 } from "path";
|
|
41517
41856
|
function buildGraph(contextRoot) {
|
|
41518
41857
|
const nodes = [];
|
|
41519
41858
|
const links = [];
|
|
@@ -41527,14 +41866,14 @@ function buildGraph(contextRoot) {
|
|
|
41527
41866
|
byId.set(node.id, node);
|
|
41528
41867
|
if (slug) bySlug.set(slug, node);
|
|
41529
41868
|
};
|
|
41530
|
-
const coreDir =
|
|
41869
|
+
const coreDir = join58(contextRoot, "core");
|
|
41531
41870
|
const foundational = [
|
|
41532
41871
|
{ prefix: "0", group: "soul" },
|
|
41533
41872
|
{ prefix: "1", group: "user" },
|
|
41534
41873
|
{ prefix: "2", group: "memory" }
|
|
41535
41874
|
];
|
|
41536
41875
|
for (const { prefix, group } of foundational) {
|
|
41537
|
-
if (!
|
|
41876
|
+
if (!existsSync60(coreDir)) continue;
|
|
41538
41877
|
const matches = import_fast_glob15.default.sync(`${prefix}.*.md`, { cwd: coreDir, absolute: true });
|
|
41539
41878
|
for (const file of matches) {
|
|
41540
41879
|
try {
|
|
@@ -41554,7 +41893,7 @@ function buildGraph(contextRoot) {
|
|
|
41554
41893
|
}
|
|
41555
41894
|
}
|
|
41556
41895
|
}
|
|
41557
|
-
if (
|
|
41896
|
+
if (existsSync60(coreDir)) {
|
|
41558
41897
|
const others = import_fast_glob15.default.sync("[3-9]*.md", { cwd: coreDir, absolute: true });
|
|
41559
41898
|
for (const file of others) {
|
|
41560
41899
|
const filename = basename17(file);
|
|
@@ -41574,8 +41913,8 @@ function buildGraph(contextRoot) {
|
|
|
41574
41913
|
}
|
|
41575
41914
|
}
|
|
41576
41915
|
}
|
|
41577
|
-
const featuresDir =
|
|
41578
|
-
if (
|
|
41916
|
+
const featuresDir = join58(coreDir, "features");
|
|
41917
|
+
if (existsSync60(featuresDir)) {
|
|
41579
41918
|
const files = import_fast_glob15.default.sync("*.md", { cwd: featuresDir, absolute: true });
|
|
41580
41919
|
for (const file of files) {
|
|
41581
41920
|
const fileSlug = basename17(file, ".md");
|
|
@@ -41605,8 +41944,8 @@ function buildGraph(contextRoot) {
|
|
|
41605
41944
|
}
|
|
41606
41945
|
}
|
|
41607
41946
|
}
|
|
41608
|
-
const stateDir =
|
|
41609
|
-
if (
|
|
41947
|
+
const stateDir = join58(contextRoot, "state");
|
|
41948
|
+
if (existsSync60(stateDir)) {
|
|
41610
41949
|
const files = import_fast_glob15.default.sync("*.md", { cwd: stateDir, absolute: true });
|
|
41611
41950
|
for (const file of files) {
|
|
41612
41951
|
const fileSlug = basename17(file, ".md");
|
|
@@ -41657,8 +41996,8 @@ function buildGraph(contextRoot) {
|
|
|
41657
41996
|
entry.slug
|
|
41658
41997
|
);
|
|
41659
41998
|
}
|
|
41660
|
-
const inboxDir2 =
|
|
41661
|
-
if (
|
|
41999
|
+
const inboxDir2 = join58(contextRoot, "inbox");
|
|
42000
|
+
if (existsSync60(inboxDir2)) {
|
|
41662
42001
|
const files = import_fast_glob15.default.sync("*.md", { cwd: inboxDir2, absolute: true });
|
|
41663
42002
|
for (const file of files) {
|
|
41664
42003
|
const slug = basename17(file, ".md");
|
|
@@ -41679,11 +42018,11 @@ function buildGraph(contextRoot) {
|
|
|
41679
42018
|
});
|
|
41680
42019
|
}
|
|
41681
42020
|
}
|
|
41682
|
-
const releasesPath =
|
|
42021
|
+
const releasesPath = join58(coreDir, "RELEASES.json");
|
|
41683
42022
|
let releases = [];
|
|
41684
|
-
if (
|
|
42023
|
+
if (existsSync60(releasesPath)) {
|
|
41685
42024
|
try {
|
|
41686
|
-
const parsed = JSON.parse(
|
|
42025
|
+
const parsed = JSON.parse(readFileSync44(releasesPath, "utf-8"));
|
|
41687
42026
|
if (Array.isArray(parsed)) releases = parsed;
|
|
41688
42027
|
} catch {
|
|
41689
42028
|
}
|
|
@@ -41779,7 +42118,7 @@ var init_graph = __esm({
|
|
|
41779
42118
|
});
|
|
41780
42119
|
|
|
41781
42120
|
// src/server/routes/graph.ts
|
|
41782
|
-
import { existsSync as
|
|
42121
|
+
import { existsSync as existsSync61, readFileSync as readFileSync45 } from "fs";
|
|
41783
42122
|
import { normalize, resolve as resolve11, sep as sep6 } from "path";
|
|
41784
42123
|
async function handleGraphGet(_req, res, _params, contextRoot) {
|
|
41785
42124
|
try {
|
|
@@ -41803,7 +42142,7 @@ async function handleGraphContentGet(req, res, _params, contextRoot) {
|
|
|
41803
42142
|
sendError(res, 400, "invalid_path", "Path escapes context root.");
|
|
41804
42143
|
return;
|
|
41805
42144
|
}
|
|
41806
|
-
if (!
|
|
42145
|
+
if (!existsSync61(absTarget)) {
|
|
41807
42146
|
sendError(res, 404, "not_found", `Path not found: ${rawPath}`);
|
|
41808
42147
|
return;
|
|
41809
42148
|
}
|
|
@@ -41824,7 +42163,7 @@ async function handleGraphContentGet(req, res, _params, contextRoot) {
|
|
|
41824
42163
|
}
|
|
41825
42164
|
if (absTarget.endsWith(".json")) {
|
|
41826
42165
|
try {
|
|
41827
|
-
const raw =
|
|
42166
|
+
const raw = readFileSync45(absTarget, "utf-8");
|
|
41828
42167
|
try {
|
|
41829
42168
|
sendJson(res, 200, { path: rawPath, type: "json", data: JSON.parse(raw) });
|
|
41830
42169
|
} catch {
|
|
@@ -41837,7 +42176,7 @@ async function handleGraphContentGet(req, res, _params, contextRoot) {
|
|
|
41837
42176
|
return;
|
|
41838
42177
|
}
|
|
41839
42178
|
try {
|
|
41840
|
-
const content =
|
|
42179
|
+
const content = readFileSync45(absTarget, "utf-8");
|
|
41841
42180
|
sendJson(res, 200, { path: rawPath, type: "text", content });
|
|
41842
42181
|
} catch (err) {
|
|
41843
42182
|
const message = err instanceof Error ? err.message : "Failed to read file";
|
|
@@ -41854,12 +42193,12 @@ var init_graph2 = __esm({
|
|
|
41854
42193
|
});
|
|
41855
42194
|
|
|
41856
42195
|
// src/lib/council.ts
|
|
41857
|
-
import { existsSync as
|
|
41858
|
-
import { join as
|
|
42196
|
+
import { existsSync as existsSync62, mkdirSync as mkdirSync25, readFileSync as readFileSync46 } from "fs";
|
|
42197
|
+
import { join as join59, resolve as resolve12, sep as sep7 } from "path";
|
|
41859
42198
|
import { fileURLToPath as fileURLToPath6 } from "url";
|
|
41860
42199
|
function getCouncilDir() {
|
|
41861
42200
|
const root = ensureContextRoot();
|
|
41862
|
-
return
|
|
42201
|
+
return join59(root, "council");
|
|
41863
42202
|
}
|
|
41864
42203
|
function assertSafeSegment(kind, id) {
|
|
41865
42204
|
if (!id || typeof id !== "string") {
|
|
@@ -41882,29 +42221,29 @@ function assertWithinCouncil(target) {
|
|
|
41882
42221
|
}
|
|
41883
42222
|
function getDebateDir(debateId) {
|
|
41884
42223
|
assertSafeSegment("debate_id", debateId);
|
|
41885
|
-
const target =
|
|
42224
|
+
const target = join59(getCouncilDir(), debateId);
|
|
41886
42225
|
return assertWithinCouncil(target);
|
|
41887
42226
|
}
|
|
41888
42227
|
function getPersonaDir(debateId, personaSlug) {
|
|
41889
42228
|
assertSafeSegment("persona_slug", personaSlug);
|
|
41890
|
-
const target =
|
|
42229
|
+
const target = join59(getDebateDir(debateId), personaSlug);
|
|
41891
42230
|
return assertWithinCouncil(target);
|
|
41892
42231
|
}
|
|
41893
42232
|
function getCouncilIndexPath() {
|
|
41894
|
-
return
|
|
42233
|
+
return join59(getCouncilDir(), "index.json");
|
|
41895
42234
|
}
|
|
41896
42235
|
function ensureCouncilDir() {
|
|
41897
42236
|
const dir = getCouncilDir();
|
|
41898
|
-
|
|
42237
|
+
mkdirSync25(dir, { recursive: true });
|
|
41899
42238
|
const indexPath2 = getCouncilIndexPath();
|
|
41900
|
-
if (!
|
|
42239
|
+
if (!existsSync62(indexPath2)) {
|
|
41901
42240
|
writeJsonArray(indexPath2, []);
|
|
41902
42241
|
}
|
|
41903
42242
|
return dir;
|
|
41904
42243
|
}
|
|
41905
42244
|
function ensureDebateExists(debateId) {
|
|
41906
42245
|
const dir = getDebateDir(debateId);
|
|
41907
|
-
if (!
|
|
42246
|
+
if (!existsSync62(dir)) {
|
|
41908
42247
|
throw new Error(`Debate not found: ${debateId}`);
|
|
41909
42248
|
}
|
|
41910
42249
|
return dir;
|
|
@@ -41912,19 +42251,19 @@ function ensureDebateExists(debateId) {
|
|
|
41912
42251
|
function ensurePersonaExists(debateId, personaSlug) {
|
|
41913
42252
|
ensureDebateExists(debateId);
|
|
41914
42253
|
const dir = getPersonaDir(debateId, personaSlug);
|
|
41915
|
-
if (!
|
|
42254
|
+
if (!existsSync62(dir)) {
|
|
41916
42255
|
throw new Error(`Persona not found in ${debateId}: ${personaSlug}`);
|
|
41917
42256
|
}
|
|
41918
42257
|
return dir;
|
|
41919
42258
|
}
|
|
41920
42259
|
function readDebateFrontmatter(debateId) {
|
|
41921
42260
|
ensureDebateExists(debateId);
|
|
41922
|
-
const { data } = readFrontmatter(
|
|
42261
|
+
const { data } = readFrontmatter(join59(getDebateDir(debateId), "debate.md"));
|
|
41923
42262
|
return data;
|
|
41924
42263
|
}
|
|
41925
42264
|
function loadCouncilIndex() {
|
|
41926
42265
|
const indexPath2 = getCouncilIndexPath();
|
|
41927
|
-
if (!
|
|
42266
|
+
if (!existsSync62(indexPath2)) return [];
|
|
41928
42267
|
return readJsonArray(indexPath2);
|
|
41929
42268
|
}
|
|
41930
42269
|
function saveCouncilIndex(entries) {
|
|
@@ -41942,17 +42281,17 @@ function upsertCouncilIndex(entry) {
|
|
|
41942
42281
|
}
|
|
41943
42282
|
function loadTemplate(filename) {
|
|
41944
42283
|
const candidates = [
|
|
41945
|
-
|
|
42284
|
+
join59(__dirname6, "templates", filename),
|
|
41946
42285
|
// bundled: dist/templates/
|
|
41947
|
-
|
|
42286
|
+
join59(__dirname6, "..", "templates", filename),
|
|
41948
42287
|
// alt layout
|
|
41949
|
-
|
|
42288
|
+
join59(__dirname6, "..", "src", "templates", filename),
|
|
41950
42289
|
// dev fallback
|
|
41951
|
-
|
|
42290
|
+
join59(__dirname6, "..", "..", "src", "templates", filename)
|
|
41952
42291
|
];
|
|
41953
42292
|
for (const path2 of candidates) {
|
|
41954
|
-
if (
|
|
41955
|
-
return
|
|
42293
|
+
if (existsSync62(path2)) {
|
|
42294
|
+
return readFileSync46(path2, "utf-8");
|
|
41956
42295
|
}
|
|
41957
42296
|
}
|
|
41958
42297
|
throw new Error(`Template not found: ${filename}`);
|
|
@@ -42026,8 +42365,8 @@ function parseReportRounds(reportContent) {
|
|
|
42026
42365
|
return entries;
|
|
42027
42366
|
}
|
|
42028
42367
|
function getPersonaRoundSummary(debateId, personaSlug, round) {
|
|
42029
|
-
const reportPath =
|
|
42030
|
-
if (!
|
|
42368
|
+
const reportPath = join59(getPersonaDir(debateId, personaSlug), "report.md");
|
|
42369
|
+
if (!existsSync62(reportPath)) return null;
|
|
42031
42370
|
const { content } = readFrontmatter(reportPath);
|
|
42032
42371
|
const entries = parseReportRounds(content);
|
|
42033
42372
|
const entry = entries.find((e) => e.round === round);
|
|
@@ -42061,10 +42400,10 @@ var init_council = __esm({
|
|
|
42061
42400
|
});
|
|
42062
42401
|
|
|
42063
42402
|
// src/server/routes/council.ts
|
|
42064
|
-
import { existsSync as
|
|
42065
|
-
import { join as
|
|
42403
|
+
import { existsSync as existsSync63 } from "fs";
|
|
42404
|
+
import { join as join60, resolve as resolve13, sep as sep8 } from "path";
|
|
42066
42405
|
function getCouncilDir2(contextRoot) {
|
|
42067
|
-
return
|
|
42406
|
+
return join60(contextRoot, "council");
|
|
42068
42407
|
}
|
|
42069
42408
|
function assertSafeSegment2(id) {
|
|
42070
42409
|
if (!id || typeof id !== "string") return false;
|
|
@@ -42117,14 +42456,14 @@ function toParsedRound(entry) {
|
|
|
42117
42456
|
};
|
|
42118
42457
|
}
|
|
42119
42458
|
function loadPersonaDetail(debateDir, slug) {
|
|
42120
|
-
const personaDir =
|
|
42121
|
-
if (!
|
|
42122
|
-
const personaFile =
|
|
42123
|
-
const reportFile =
|
|
42459
|
+
const personaDir = join60(debateDir, slug);
|
|
42460
|
+
if (!existsSync63(personaDir)) return null;
|
|
42461
|
+
const personaFile = join60(personaDir, "context-and-persona.md");
|
|
42462
|
+
const reportFile = join60(personaDir, "report.md");
|
|
42124
42463
|
let fm = { name: slug, model: "unknown", aspects: [], round_entries: 0 };
|
|
42125
42464
|
let persona = "";
|
|
42126
42465
|
let crossContext = {};
|
|
42127
|
-
if (
|
|
42466
|
+
if (existsSync63(personaFile)) {
|
|
42128
42467
|
const parsed = readFrontmatter(personaFile);
|
|
42129
42468
|
fm = {
|
|
42130
42469
|
name: parsed.data.name ?? slug,
|
|
@@ -42137,13 +42476,13 @@ function loadPersonaDetail(debateDir, slug) {
|
|
|
42137
42476
|
crossContext = split.crossContext;
|
|
42138
42477
|
}
|
|
42139
42478
|
let rounds = [];
|
|
42140
|
-
if (
|
|
42479
|
+
if (existsSync63(reportFile)) {
|
|
42141
42480
|
const { content } = readFrontmatter(reportFile);
|
|
42142
42481
|
rounds = parseReportRounds(content).map(toParsedRound);
|
|
42143
42482
|
}
|
|
42144
|
-
const researchIndex =
|
|
42483
|
+
const researchIndex = join60(personaDir, "researches", "index.json");
|
|
42145
42484
|
let researches = [];
|
|
42146
|
-
if (
|
|
42485
|
+
if (existsSync63(researchIndex)) {
|
|
42147
42486
|
try {
|
|
42148
42487
|
researches = readJsonArray(researchIndex);
|
|
42149
42488
|
} catch {
|
|
@@ -42153,17 +42492,17 @@ function loadPersonaDetail(debateDir, slug) {
|
|
|
42153
42492
|
return { slug, frontmatter: fm, persona, crossContext, rounds, researches };
|
|
42154
42493
|
}
|
|
42155
42494
|
async function handleCouncilList(_req, res, _params, contextRoot) {
|
|
42156
|
-
const indexPath2 =
|
|
42157
|
-
if (!
|
|
42495
|
+
const indexPath2 = join60(getCouncilDir2(contextRoot), "index.json");
|
|
42496
|
+
if (!existsSync63(indexPath2)) {
|
|
42158
42497
|
sendJson(res, 200, { debates: [] });
|
|
42159
42498
|
return;
|
|
42160
42499
|
}
|
|
42161
42500
|
try {
|
|
42162
42501
|
const debates = readJsonArray(indexPath2);
|
|
42163
42502
|
const enriched = debates.map((d) => {
|
|
42164
|
-
const debateFile =
|
|
42503
|
+
const debateFile = join60(getCouncilDir2(contextRoot), d.id, "debate.md");
|
|
42165
42504
|
let personaSlugs = [];
|
|
42166
|
-
if (
|
|
42505
|
+
if (existsSync63(debateFile)) {
|
|
42167
42506
|
try {
|
|
42168
42507
|
const fm = readFrontmatter(debateFile).data;
|
|
42169
42508
|
if (Array.isArray(fm.personas)) personaSlugs = fm.personas;
|
|
@@ -42186,14 +42525,14 @@ async function handleCouncilGet(_req, res, params, contextRoot) {
|
|
|
42186
42525
|
return;
|
|
42187
42526
|
}
|
|
42188
42527
|
const councilDir = getCouncilDir2(contextRoot);
|
|
42189
|
-
const debateDirUnchecked =
|
|
42528
|
+
const debateDirUnchecked = join60(councilDir, debateId);
|
|
42190
42529
|
const debateDir = assertWithin(councilDir, debateDirUnchecked);
|
|
42191
|
-
if (!debateDir || !
|
|
42530
|
+
if (!debateDir || !existsSync63(debateDir)) {
|
|
42192
42531
|
sendError(res, 404, "not_found", `Debate not found: ${debateId}`);
|
|
42193
42532
|
return;
|
|
42194
42533
|
}
|
|
42195
|
-
const debateFile =
|
|
42196
|
-
if (!
|
|
42534
|
+
const debateFile = join60(debateDir, "debate.md");
|
|
42535
|
+
if (!existsSync63(debateFile)) {
|
|
42197
42536
|
sendError(res, 404, "not_found", `Debate metadata missing: ${debateId}`);
|
|
42198
42537
|
return;
|
|
42199
42538
|
}
|
|
@@ -42210,11 +42549,11 @@ async function handleCouncilGet(_req, res, params, contextRoot) {
|
|
|
42210
42549
|
created_at: String(fmRaw.created_at ?? ""),
|
|
42211
42550
|
updated_at: String(fmRaw.updated_at ?? "")
|
|
42212
42551
|
};
|
|
42213
|
-
const roundLogFile =
|
|
42214
|
-
const roundLog =
|
|
42215
|
-
const finalReportFile =
|
|
42552
|
+
const roundLogFile = join60(debateDir, "round-log.md");
|
|
42553
|
+
const roundLog = existsSync63(roundLogFile) ? readFrontmatter(roundLogFile).content : null;
|
|
42554
|
+
const finalReportFile = join60(debateDir, "final-report.md");
|
|
42216
42555
|
let finalReport = null;
|
|
42217
|
-
if (
|
|
42556
|
+
if (existsSync63(finalReportFile)) {
|
|
42218
42557
|
const parsed = readFrontmatter(finalReportFile);
|
|
42219
42558
|
finalReport = { frontmatter: parsed.data, content: parsed.content };
|
|
42220
42559
|
}
|
|
@@ -42242,9 +42581,9 @@ async function handleCouncilResearchGet(_req, res, params, contextRoot) {
|
|
|
42242
42581
|
const councilDir = getCouncilDir2(contextRoot);
|
|
42243
42582
|
const researchFile = assertWithin(
|
|
42244
42583
|
councilDir,
|
|
42245
|
-
|
|
42584
|
+
join60(councilDir, debateId, personaSlug, "researches", `${researchSlug}.md`)
|
|
42246
42585
|
);
|
|
42247
|
-
if (!researchFile || !
|
|
42586
|
+
if (!researchFile || !existsSync63(researchFile)) {
|
|
42248
42587
|
sendError(res, 404, "not_found", `Research not found: ${researchSlug}`);
|
|
42249
42588
|
return;
|
|
42250
42589
|
}
|
|
@@ -42262,9 +42601,9 @@ var init_council2 = __esm({
|
|
|
42262
42601
|
});
|
|
42263
42602
|
|
|
42264
42603
|
// src/server/routes/config.ts
|
|
42265
|
-
import { dirname as
|
|
42604
|
+
import { dirname as dirname29 } from "path";
|
|
42266
42605
|
async function handleConfigGet(_req, res, _params, contextRoot) {
|
|
42267
|
-
const config = readSetupConfig(
|
|
42606
|
+
const config = readSetupConfig(dirname29(contextRoot));
|
|
42268
42607
|
sendJson(res, 200, { config });
|
|
42269
42608
|
}
|
|
42270
42609
|
async function handleConfigUpdate(req, res, _params, contextRoot) {
|
|
@@ -42348,14 +42687,14 @@ async function handleConfigUpdate(req, res, _params, contextRoot) {
|
|
|
42348
42687
|
}
|
|
42349
42688
|
picked.changelogTarget = "comments";
|
|
42350
42689
|
}
|
|
42351
|
-
const existing = readSetupConfig(
|
|
42690
|
+
const existing = readSetupConfig(dirname29(contextRoot))?.clickup ?? {};
|
|
42352
42691
|
patch.clickup = { ...existing, ...picked };
|
|
42353
42692
|
}
|
|
42354
42693
|
if (patch.platforms === void 0 && patch.packs === void 0 && patch.disableNativeMemory === void 0 && patch.taskBackend === void 0 && patch.cloudTaskManagement === void 0 && patch.clickup === void 0 && patch.shareable === void 0) {
|
|
42355
42694
|
sendError(res, 400, "no_changes", "Provide at least one of: platforms, packs, disableNativeMemory, taskBackend, cloudTaskManagement, clickup, shareable.");
|
|
42356
42695
|
return;
|
|
42357
42696
|
}
|
|
42358
|
-
const projectRoot =
|
|
42697
|
+
const projectRoot = dirname29(contextRoot);
|
|
42359
42698
|
if (patch.taskBackend === "clickup") {
|
|
42360
42699
|
try {
|
|
42361
42700
|
ensureRemoteBackendGitignore(projectRoot);
|
|
@@ -42382,11 +42721,11 @@ var init_config = __esm({
|
|
|
42382
42721
|
});
|
|
42383
42722
|
|
|
42384
42723
|
// src/server/routes/vaults.ts
|
|
42385
|
-
import { dirname as
|
|
42386
|
-
import { existsSync as
|
|
42724
|
+
import { dirname as dirname30, resolve as resolve14 } from "path";
|
|
42725
|
+
import { existsSync as existsSync64 } from "fs";
|
|
42387
42726
|
async function handleVaultsGet(_req, res, _params, contextRoot) {
|
|
42388
|
-
const vaults = listVaults().map((v) => ({ ...v, exists:
|
|
42389
|
-
const current = contextRoot ? vaults.find((v) => resolve14(v.path) === resolve14(
|
|
42727
|
+
const vaults = listVaults().map((v) => ({ ...v, exists: existsSync64(resolve14(v.path)) }));
|
|
42728
|
+
const current = contextRoot ? vaults.find((v) => resolve14(v.path) === resolve14(dirname30(contextRoot)))?.name ?? null : null;
|
|
42390
42729
|
sendJson(res, 200, { vaults, current });
|
|
42391
42730
|
}
|
|
42392
42731
|
var init_vaults2 = __esm({
|
|
@@ -42398,7 +42737,7 @@ var init_vaults2 = __esm({
|
|
|
42398
42737
|
});
|
|
42399
42738
|
|
|
42400
42739
|
// src/lib/vault-discovery.ts
|
|
42401
|
-
import { dirname as
|
|
42740
|
+
import { dirname as dirname31 } from "path";
|
|
42402
42741
|
function discoverVaults(root) {
|
|
42403
42742
|
const matches = import_fast_glob16.default.sync("**/_dream_context", {
|
|
42404
42743
|
cwd: root,
|
|
@@ -42409,7 +42748,7 @@ function discoverVaults(root) {
|
|
|
42409
42748
|
suppressErrors: true
|
|
42410
42749
|
});
|
|
42411
42750
|
const projects = /* @__PURE__ */ new Set();
|
|
42412
|
-
for (const ctx of matches) projects.add(
|
|
42751
|
+
for (const ctx of matches) projects.add(dirname31(ctx));
|
|
42413
42752
|
return Array.from(projects).sort();
|
|
42414
42753
|
}
|
|
42415
42754
|
async function discoverVaultsAsync(root) {
|
|
@@ -42422,7 +42761,7 @@ async function discoverVaultsAsync(root) {
|
|
|
42422
42761
|
suppressErrors: true
|
|
42423
42762
|
});
|
|
42424
42763
|
const projects = /* @__PURE__ */ new Set();
|
|
42425
|
-
for (const ctx of matches) projects.add(
|
|
42764
|
+
for (const ctx of matches) projects.add(dirname31(ctx));
|
|
42426
42765
|
return Array.from(projects).sort();
|
|
42427
42766
|
}
|
|
42428
42767
|
var import_fast_glob16;
|
|
@@ -42480,8 +42819,8 @@ var init_ensure_cli = __esm({
|
|
|
42480
42819
|
});
|
|
42481
42820
|
|
|
42482
42821
|
// src/server/routes/launcher.ts
|
|
42483
|
-
import { basename as basename18, isAbsolute, join as
|
|
42484
|
-
import { existsSync as
|
|
42822
|
+
import { basename as basename18, isAbsolute, join as join61, resolve as resolve15, sep as sep9 } from "path";
|
|
42823
|
+
import { existsSync as existsSync65, mkdirSync as mkdirSync26, readdirSync as readdirSync16, statSync as statSync10, createReadStream, readFileSync as readFileSync47, writeFileSync as writeFileSync33 } from "fs";
|
|
42485
42824
|
import { homedir as homedir3 } from "os";
|
|
42486
42825
|
import { execFile as execFile2, spawn as spawn4 } from "child_process";
|
|
42487
42826
|
import { promisify as promisify2 } from "util";
|
|
@@ -42505,7 +42844,7 @@ async function handleLauncherDiscover(req, res, _params, _contextRoot) {
|
|
|
42505
42844
|
return;
|
|
42506
42845
|
}
|
|
42507
42846
|
const resolvedRoot = resolve15(root);
|
|
42508
|
-
if (!
|
|
42847
|
+
if (!existsSync65(resolvedRoot)) {
|
|
42509
42848
|
sendError(res, 400, "invalid_root", `Path does not exist: ${resolvedRoot}`);
|
|
42510
42849
|
return;
|
|
42511
42850
|
}
|
|
@@ -42548,7 +42887,7 @@ async function handleLauncherRegister(req, res, _params, _contextRoot) {
|
|
|
42548
42887
|
}
|
|
42549
42888
|
function isNonEmptyDir(dir) {
|
|
42550
42889
|
try {
|
|
42551
|
-
return statSync10(dir).isDirectory() &&
|
|
42890
|
+
return statSync10(dir).isDirectory() && readdirSync16(dir).length > 0;
|
|
42552
42891
|
} catch {
|
|
42553
42892
|
return false;
|
|
42554
42893
|
}
|
|
@@ -42573,30 +42912,30 @@ async function scaffoldProject(a, runner = defaultCliRunner, home) {
|
|
|
42573
42912
|
throw new ScaffoldError("parentDir must be an absolute path.");
|
|
42574
42913
|
}
|
|
42575
42914
|
const resolvedParent = resolve15(parentDir);
|
|
42576
|
-
if (!
|
|
42915
|
+
if (!existsSync65(resolvedParent) || !statSync10(resolvedParent).isDirectory()) {
|
|
42577
42916
|
throw new ScaffoldError(`Parent directory does not exist: ${resolvedParent}`);
|
|
42578
42917
|
}
|
|
42579
42918
|
target = resolve15(resolvedParent, name);
|
|
42580
|
-
if (target !==
|
|
42919
|
+
if (target !== join61(resolvedParent, name) || !target.startsWith(resolvedParent + sep9)) {
|
|
42581
42920
|
throw new ScaffoldError("Resolved project path escapes the parent directory.");
|
|
42582
42921
|
}
|
|
42583
|
-
if (isNonEmptyDir(target) && !
|
|
42922
|
+
if (isNonEmptyDir(target) && !existsSync65(join61(target, "_dream_context"))) {
|
|
42584
42923
|
throw new ScaffoldError(`A non-empty folder already exists at ${target}.`);
|
|
42585
42924
|
}
|
|
42586
|
-
|
|
42925
|
+
mkdirSync26(target, { recursive: true });
|
|
42587
42926
|
} else if (a.mode === "existing") {
|
|
42588
42927
|
const projectPath = (a.projectPath ?? "").trim();
|
|
42589
42928
|
if (!projectPath || !isAbsolute(projectPath)) {
|
|
42590
42929
|
throw new ScaffoldError("projectPath must be an absolute path.");
|
|
42591
42930
|
}
|
|
42592
42931
|
target = resolve15(projectPath);
|
|
42593
|
-
if (!
|
|
42932
|
+
if (!existsSync65(target) || !statSync10(target).isDirectory()) {
|
|
42594
42933
|
throw new ScaffoldError(`Folder does not exist: ${target}`);
|
|
42595
42934
|
}
|
|
42596
42935
|
} else {
|
|
42597
42936
|
throw new ScaffoldError("mode must be 'new' or 'existing'.");
|
|
42598
42937
|
}
|
|
42599
|
-
const alreadyProject =
|
|
42938
|
+
const alreadyProject = existsSync65(join61(target, "_dream_context"));
|
|
42600
42939
|
if (!alreadyProject) {
|
|
42601
42940
|
const initArgs = ["init", "--yes", "--platforms", platformArg, "--name", name];
|
|
42602
42941
|
if (a.description?.trim()) initArgs.push("--description", a.description.trim());
|
|
@@ -42651,13 +42990,13 @@ async function handleLauncherDetect(req, res, _params, _contextRoot) {
|
|
|
42651
42990
|
return;
|
|
42652
42991
|
}
|
|
42653
42992
|
const resolved = resolve15(path2);
|
|
42654
|
-
if (!
|
|
42993
|
+
if (!existsSync65(resolved)) {
|
|
42655
42994
|
sendError(res, 400, "invalid_path", `Path does not exist: ${resolved}`);
|
|
42656
42995
|
return;
|
|
42657
42996
|
}
|
|
42658
42997
|
sendJson(res, 200, {
|
|
42659
42998
|
stack: detectTechStack(resolved) ?? "",
|
|
42660
|
-
hasContext:
|
|
42999
|
+
hasContext: existsSync65(join61(resolved, "_dream_context")),
|
|
42661
43000
|
name: basename18(resolved)
|
|
42662
43001
|
});
|
|
42663
43002
|
}
|
|
@@ -42677,15 +43016,15 @@ async function handleLauncherCatalog(_req, res, _params, _contextRoot) {
|
|
|
42677
43016
|
sendJson(res, 200, { platforms, packs });
|
|
42678
43017
|
}
|
|
42679
43018
|
function sleepyConfigPath() {
|
|
42680
|
-
return
|
|
43019
|
+
return join61(homedir3(), ".dreamcontext", "sleepy.json");
|
|
42681
43020
|
}
|
|
42682
43021
|
async function handleSleepyConfigGet(_req, res, _params, _contextRoot) {
|
|
42683
43022
|
let enabled = false;
|
|
42684
43023
|
let hotkey = "Alt+Cmd+S";
|
|
42685
43024
|
try {
|
|
42686
43025
|
const p = sleepyConfigPath();
|
|
42687
|
-
if (
|
|
42688
|
-
const raw = JSON.parse(
|
|
43026
|
+
if (existsSync65(p)) {
|
|
43027
|
+
const raw = JSON.parse(readFileSync47(p, "utf-8"));
|
|
42689
43028
|
enabled = raw.enabled === true;
|
|
42690
43029
|
if (typeof raw.hotkey === "string" && raw.hotkey.trim()) hotkey = raw.hotkey;
|
|
42691
43030
|
}
|
|
@@ -42703,8 +43042,8 @@ async function handleSleepyConfigSet(req, res, _params, _contextRoot) {
|
|
|
42703
43042
|
const hotkey = typeof body.hotkey === "string" && body.hotkey.trim() ? body.hotkey.trim() : "Alt+Cmd+S";
|
|
42704
43043
|
try {
|
|
42705
43044
|
const p = sleepyConfigPath();
|
|
42706
|
-
|
|
42707
|
-
|
|
43045
|
+
mkdirSync26(join61(homedir3(), ".dreamcontext"), { recursive: true });
|
|
43046
|
+
writeFileSync33(p, JSON.stringify({ enabled, hotkey }, null, 2) + "\n", "utf-8");
|
|
42708
43047
|
sendJson(res, 200, { enabled, hotkey });
|
|
42709
43048
|
} catch (err) {
|
|
42710
43049
|
console.error("[launcher] sleepy-config write failed:", err);
|
|
@@ -42724,8 +43063,8 @@ async function handleSleepyVideo(req, res, _params, _contextRoot) {
|
|
|
42724
43063
|
res.end();
|
|
42725
43064
|
return;
|
|
42726
43065
|
}
|
|
42727
|
-
const file =
|
|
42728
|
-
if (!
|
|
43066
|
+
const file = join61(dir, `${mode}.mp4`);
|
|
43067
|
+
if (!existsSync65(file)) {
|
|
42729
43068
|
res.writeHead(404);
|
|
42730
43069
|
res.end();
|
|
42731
43070
|
return;
|
|
@@ -42756,8 +43095,8 @@ async function handleSleepyAnim(req, res, _params, _contextRoot) {
|
|
|
42756
43095
|
return;
|
|
42757
43096
|
}
|
|
42758
43097
|
const dir = process.env.DREAMCONTEXT_SLEEPY_DIR;
|
|
42759
|
-
const file = dir ?
|
|
42760
|
-
if (!file || !
|
|
43098
|
+
const file = dir ? join61(dir, `${mode}.webp`) : "";
|
|
43099
|
+
if (!file || !existsSync65(file)) {
|
|
42761
43100
|
res.writeHead(404);
|
|
42762
43101
|
res.end();
|
|
42763
43102
|
return;
|
|
@@ -42782,8 +43121,9 @@ function buildAskPrompt(question) {
|
|
|
42782
43121
|
|
|
42783
43122
|
Question: "${question}"`;
|
|
42784
43123
|
}
|
|
42785
|
-
function buildSleepPrompt() {
|
|
42786
|
-
|
|
43124
|
+
function buildSleepPrompt(depth) {
|
|
43125
|
+
const depthLine = isDestructiveAllowed(depth) ? `This is a DEEP consolidation: you ARE authorized to perform destructive/expensive knowledge ops (merge-with-delete, summarize-and-replace still-valid detail, archive/delete stale files) \u2014 but first copy any file you will merge/replace/delete to \`_dream_context/knowledge/.archive/<slug>-<YYYYMMDD>.md\` (create the dir if absent).` : `This is a ${depth.toUpperCase()} consolidation: do NOT merge, summarize-and-replace, or delete any knowledge. Only create/extend/retag/tick. If you spot merge or deletion candidates, FLAG them in your report instead of acting on them.`;
|
|
43126
|
+
return `Think hard. Run a dreamcontext memory consolidation ("sleep") for THIS project now, fully autonomously \u2014 do NOT ask any questions. Follow the project's dreamcontext sleep/consolidation flow: pin the epoch with \`dreamcontext sleep start\`, reconcile the task/changelog/knowledge/feature files to current truth as warranted (prefer updating existing entities over creating new ones), then close the cycle with \`dreamcontext sleep done "<one-paragraph summary>"\` to reset the debt. ${depthLine} When finished, reply with a SHORT GitHub-flavored Markdown summary (a few bullets) of what was consolidated. Keep it concise.`;
|
|
42787
43127
|
}
|
|
42788
43128
|
async function handleLauncherCapture(req, res, _params, _contextRoot) {
|
|
42789
43129
|
const body = await parseJsonBody(req);
|
|
@@ -42808,14 +43148,14 @@ async function handleLauncherCapture(req, res, _params, _contextRoot) {
|
|
|
42808
43148
|
return;
|
|
42809
43149
|
}
|
|
42810
43150
|
const cwd = resolve15(vault.path);
|
|
42811
|
-
if (!
|
|
43151
|
+
if (!existsSync65(cwd)) {
|
|
42812
43152
|
sendError(res, 400, "missing_vault", `Vault path no longer exists: ${cwd}`);
|
|
42813
43153
|
return;
|
|
42814
43154
|
}
|
|
42815
43155
|
if (mode === "learn") {
|
|
42816
43156
|
try {
|
|
42817
|
-
const changelogPath =
|
|
42818
|
-
if (!
|
|
43157
|
+
const changelogPath = join61(cwd, "_dream_context", "core", "CHANGELOG.json");
|
|
43158
|
+
if (!existsSync65(changelogPath)) {
|
|
42819
43159
|
sendError(res, 400, "not_initialized", `"${vaultName}" has no _dream_context \u2014 run init first.`);
|
|
42820
43160
|
return;
|
|
42821
43161
|
}
|
|
@@ -42841,7 +43181,18 @@ async function handleLauncherCapture(req, res, _params, _contextRoot) {
|
|
|
42841
43181
|
captureRuns.set(captureId, run2);
|
|
42842
43182
|
try {
|
|
42843
43183
|
const shell = process.env.SHELL || "/bin/zsh";
|
|
42844
|
-
|
|
43184
|
+
let sleepDepth = "deep";
|
|
43185
|
+
if (mode === "sleep") {
|
|
43186
|
+
try {
|
|
43187
|
+
sleepDepth = consolidationDepth(readSleepState(cwd).debt, {
|
|
43188
|
+
userRequestedDeep: true
|
|
43189
|
+
}).depth;
|
|
43190
|
+
} catch (err) {
|
|
43191
|
+
console.error("[launcher] could not read sleep state for depth:", err);
|
|
43192
|
+
sleepDepth = "deep";
|
|
43193
|
+
}
|
|
43194
|
+
}
|
|
43195
|
+
const prompt = mode === "sleep" ? buildSleepPrompt(sleepDepth) : mode === "ask" ? buildAskPrompt(text) : buildCapturePrompt(text);
|
|
42845
43196
|
const child = spawn4(shell, ["-ilc", 'exec claude --model sonnet -p "$0"', prompt], {
|
|
42846
43197
|
cwd,
|
|
42847
43198
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -42886,21 +43237,275 @@ async function handleLauncherCaptureStatus(req, res, _params, _contextRoot) {
|
|
|
42886
43237
|
}
|
|
42887
43238
|
async function handleLauncherDefaults(_req, res, _params, _contextRoot) {
|
|
42888
43239
|
const home = homedir3();
|
|
42889
|
-
sendJson(res, 200, { home, defaultParent:
|
|
43240
|
+
sendJson(res, 200, { home, defaultParent: join61(home, "projects") });
|
|
43241
|
+
}
|
|
43242
|
+
function computeVaultStatus(v, latest) {
|
|
43243
|
+
const exists = existsSync65(resolve15(v.path));
|
|
43244
|
+
let setupVersion = "0.0.0";
|
|
43245
|
+
let shareable = false;
|
|
43246
|
+
if (exists) {
|
|
43247
|
+
try {
|
|
43248
|
+
const cfg = readSetupConfig(resolve15(v.path));
|
|
43249
|
+
if (cfg) {
|
|
43250
|
+
setupVersion = cfg.setupVersion || "0.0.0";
|
|
43251
|
+
shareable = cfg.shareable === true;
|
|
43252
|
+
}
|
|
43253
|
+
} catch {
|
|
43254
|
+
}
|
|
43255
|
+
}
|
|
43256
|
+
const needsUpdate = exists && compareVersions(setupVersion, latest) < 0;
|
|
43257
|
+
return { name: v.name, path: v.path, exists, setupVersion, latestVersion: latest, needsUpdate, shareable };
|
|
43258
|
+
}
|
|
43259
|
+
async function handleLauncherStatus(_req, res, _params, _contextRoot) {
|
|
43260
|
+
const latest = dreamcontextVersion();
|
|
43261
|
+
const vaults = listVaults().map((v) => computeVaultStatus(v, latest));
|
|
43262
|
+
sendJson(res, 200, { vaults, latestVersion: latest });
|
|
43263
|
+
}
|
|
43264
|
+
async function handleLauncherUnregister(req, res, _params, _contextRoot) {
|
|
43265
|
+
const body = await parseJsonBody(req);
|
|
43266
|
+
if (!body) {
|
|
43267
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43268
|
+
return;
|
|
43269
|
+
}
|
|
43270
|
+
const name = typeof body.name === "string" ? body.name.trim() : "";
|
|
43271
|
+
if (!name) {
|
|
43272
|
+
sendError(res, 400, "invalid_name", "name must be a non-empty string.");
|
|
43273
|
+
return;
|
|
43274
|
+
}
|
|
43275
|
+
const removed = removeVault(name);
|
|
43276
|
+
sendJson(res, 200, { removed, vaults: listVaults() });
|
|
43277
|
+
}
|
|
43278
|
+
async function handleLauncherUpdate(req, res, _params, _contextRoot) {
|
|
43279
|
+
const body = await parseJsonBody(req);
|
|
43280
|
+
if (!body) {
|
|
43281
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43282
|
+
return;
|
|
43283
|
+
}
|
|
43284
|
+
const name = typeof body.name === "string" ? body.name.trim() : "";
|
|
43285
|
+
if (!name) {
|
|
43286
|
+
sendError(res, 400, "invalid_name", "name must be a non-empty string.");
|
|
43287
|
+
return;
|
|
43288
|
+
}
|
|
43289
|
+
const vault = listVaults().find((v) => v.name === name);
|
|
43290
|
+
if (!vault) {
|
|
43291
|
+
sendError(res, 400, "unknown_vault", `No registered vault named "${name}".`);
|
|
43292
|
+
return;
|
|
43293
|
+
}
|
|
43294
|
+
const target = resolve15(vault.path);
|
|
43295
|
+
if (!existsSync65(target)) {
|
|
43296
|
+
sendError(res, 400, "missing_vault", `Vault path no longer exists: ${target}`);
|
|
43297
|
+
return;
|
|
43298
|
+
}
|
|
43299
|
+
try {
|
|
43300
|
+
await defaultCliRunner(["update"], target);
|
|
43301
|
+
const latest = dreamcontextVersion();
|
|
43302
|
+
sendJson(res, 200, { ok: true, status: computeVaultStatus(vault, latest) });
|
|
43303
|
+
} catch (err) {
|
|
43304
|
+
console.error("[launcher] update failed:", err);
|
|
43305
|
+
const detail = err instanceof Error ? err.message : "unknown error";
|
|
43306
|
+
sendError(res, 500, "update_failed", `Update failed: ${detail}`);
|
|
43307
|
+
}
|
|
43308
|
+
}
|
|
43309
|
+
async function handleLauncherFederationGraph(_req, res, _params, _contextRoot) {
|
|
43310
|
+
const latest = dreamcontextVersion();
|
|
43311
|
+
const vaults = listVaults();
|
|
43312
|
+
const nodes = vaults.map((v) => computeVaultStatus(v, latest));
|
|
43313
|
+
const shareableByName = new Map(nodes.map((n) => [n.name, n.shareable]));
|
|
43314
|
+
const known = new Set(vaults.map((v) => v.name));
|
|
43315
|
+
const edges = [];
|
|
43316
|
+
const connections = [];
|
|
43317
|
+
const seen = /* @__PURE__ */ new Set();
|
|
43318
|
+
for (const v of vaults) {
|
|
43319
|
+
if (!existsSync65(resolve15(v.path))) continue;
|
|
43320
|
+
const conns = listConnections(join61(resolve15(v.path), "_dream_context"));
|
|
43321
|
+
for (const c of conns) {
|
|
43322
|
+
if (!known.has(c.vault)) continue;
|
|
43323
|
+
if (c.status === "stale") continue;
|
|
43324
|
+
connections.push({ from: v.name, to: c.vault, direction: c.direction });
|
|
43325
|
+
if (c.direction !== "out" && c.direction !== "both") continue;
|
|
43326
|
+
const key = `${v.name} ${c.vault}`;
|
|
43327
|
+
if (seen.has(key)) continue;
|
|
43328
|
+
seen.add(key);
|
|
43329
|
+
edges.push({ source: v.name, target: c.vault, active: shareableByName.get(c.vault) === true });
|
|
43330
|
+
}
|
|
43331
|
+
}
|
|
43332
|
+
sendJson(res, 200, { nodes, edges, connections, latestVersion: latest });
|
|
43333
|
+
}
|
|
43334
|
+
async function handleLauncherConnectionCreate(req, res, _params, _contextRoot) {
|
|
43335
|
+
const body = await parseJsonBody(req);
|
|
43336
|
+
if (!body) {
|
|
43337
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43338
|
+
return;
|
|
43339
|
+
}
|
|
43340
|
+
const from = typeof body.from === "string" ? body.from.trim() : "";
|
|
43341
|
+
const to = typeof body.to === "string" ? body.to.trim() : "";
|
|
43342
|
+
if (!from || !to) {
|
|
43343
|
+
sendError(res, 400, "invalid_body", "from and to must be non-empty strings.");
|
|
43344
|
+
return;
|
|
43345
|
+
}
|
|
43346
|
+
const fromVault = listVaults().find((v) => v.name === from);
|
|
43347
|
+
if (!fromVault) {
|
|
43348
|
+
sendError(res, 400, "unknown_vault", `No registered vault named "${from}".`);
|
|
43349
|
+
return;
|
|
43350
|
+
}
|
|
43351
|
+
const fromRoot = join61(resolve15(fromVault.path), "_dream_context");
|
|
43352
|
+
try {
|
|
43353
|
+
const cur = dirToward(fromRoot, to);
|
|
43354
|
+
addConnection(fromRoot, from, to, addOut(cur?.dir ?? null), cur?.topics ?? null);
|
|
43355
|
+
sendJson(res, 200, { ok: true });
|
|
43356
|
+
} catch (err) {
|
|
43357
|
+
if (err instanceof VaultError) {
|
|
43358
|
+
sendError(res, 400, "invalid_connection", err.message);
|
|
43359
|
+
return;
|
|
43360
|
+
}
|
|
43361
|
+
console.error("[launcher] connection create failed:", err);
|
|
43362
|
+
sendError(res, 500, "connection_failed", "Failed to create connection.");
|
|
43363
|
+
}
|
|
42890
43364
|
}
|
|
42891
|
-
|
|
43365
|
+
async function handleLauncherConnectionRemove(req, res, _params, _contextRoot) {
|
|
43366
|
+
const body = await parseJsonBody(req);
|
|
43367
|
+
if (!body) {
|
|
43368
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43369
|
+
return;
|
|
43370
|
+
}
|
|
43371
|
+
const from = typeof body.from === "string" ? body.from.trim() : "";
|
|
43372
|
+
const to = typeof body.to === "string" ? body.to.trim() : "";
|
|
43373
|
+
if (!from || !to) {
|
|
43374
|
+
sendError(res, 400, "invalid_body", "from and to must be non-empty strings.");
|
|
43375
|
+
return;
|
|
43376
|
+
}
|
|
43377
|
+
const fromVault = listVaults().find((v) => v.name === from);
|
|
43378
|
+
if (!fromVault) {
|
|
43379
|
+
sendError(res, 400, "unknown_vault", `No registered vault named "${from}".`);
|
|
43380
|
+
return;
|
|
43381
|
+
}
|
|
43382
|
+
const fromRoot = join61(resolve15(fromVault.path), "_dream_context");
|
|
43383
|
+
const a = dirToward(fromRoot, to);
|
|
43384
|
+
if (a) applyDir(fromRoot, from, to, dropOut(a.dir), a.topics);
|
|
43385
|
+
const toRoot = vaultRoot(to);
|
|
43386
|
+
if (toRoot) {
|
|
43387
|
+
const b = dirToward(toRoot, from);
|
|
43388
|
+
if (b) applyDir(toRoot, to, from, dropIn(b.dir), b.topics);
|
|
43389
|
+
}
|
|
43390
|
+
sendJson(res, 200, { ok: true, removed: true });
|
|
43391
|
+
}
|
|
43392
|
+
function dirToward(root, peer) {
|
|
43393
|
+
const c = listConnections(root).find((x) => x.vault === peer);
|
|
43394
|
+
return c ? { dir: c.direction, topics: c.topics } : null;
|
|
43395
|
+
}
|
|
43396
|
+
function vaultRoot(name) {
|
|
43397
|
+
const v = listVaults().find((x) => x.name === name);
|
|
43398
|
+
return v ? join61(resolve15(v.path), "_dream_context") : null;
|
|
43399
|
+
}
|
|
43400
|
+
function applyDir(fromRoot, fromName, peer, next, topics) {
|
|
43401
|
+
if (next === null) removeConnection(fromRoot, peer);
|
|
43402
|
+
else addConnection(fromRoot, fromName, peer, next, topics);
|
|
43403
|
+
}
|
|
43404
|
+
async function handleLauncherSyncCreate(req, res, _params, _contextRoot) {
|
|
43405
|
+
const body = await parseJsonBody(req);
|
|
43406
|
+
if (!body) {
|
|
43407
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43408
|
+
return;
|
|
43409
|
+
}
|
|
43410
|
+
const from = typeof body.from === "string" ? body.from.trim() : "";
|
|
43411
|
+
const to = typeof body.to === "string" ? body.to.trim() : "";
|
|
43412
|
+
if (!from || !to) {
|
|
43413
|
+
sendError(res, 400, "invalid_body", "from and to must be non-empty strings.");
|
|
43414
|
+
return;
|
|
43415
|
+
}
|
|
43416
|
+
const fromRoot = vaultRoot(from);
|
|
43417
|
+
const toRoot = vaultRoot(to);
|
|
43418
|
+
if (!fromRoot) {
|
|
43419
|
+
sendError(res, 400, "unknown_vault", `No registered vault named "${from}".`);
|
|
43420
|
+
return;
|
|
43421
|
+
}
|
|
43422
|
+
if (!toRoot) {
|
|
43423
|
+
sendError(res, 400, "unknown_vault", `No registered vault named "${to}".`);
|
|
43424
|
+
return;
|
|
43425
|
+
}
|
|
43426
|
+
try {
|
|
43427
|
+
const a = dirToward(fromRoot, to);
|
|
43428
|
+
addConnection(fromRoot, from, to, addOut(a?.dir ?? null), a?.topics ?? null);
|
|
43429
|
+
const b = dirToward(toRoot, from);
|
|
43430
|
+
addConnection(toRoot, to, from, addIn(b?.dir ?? null), b?.topics ?? null);
|
|
43431
|
+
sendJson(res, 200, { ok: true });
|
|
43432
|
+
} catch (err) {
|
|
43433
|
+
if (err instanceof VaultError) {
|
|
43434
|
+
sendError(res, 400, "invalid_connection", err.message);
|
|
43435
|
+
return;
|
|
43436
|
+
}
|
|
43437
|
+
console.error("[launcher] sync create failed:", err);
|
|
43438
|
+
sendError(res, 500, "sync_failed", "Failed to enable sync.");
|
|
43439
|
+
}
|
|
43440
|
+
}
|
|
43441
|
+
async function handleLauncherSyncRemove(req, res, _params, _contextRoot) {
|
|
43442
|
+
const body = await parseJsonBody(req);
|
|
43443
|
+
if (!body) {
|
|
43444
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43445
|
+
return;
|
|
43446
|
+
}
|
|
43447
|
+
const from = typeof body.from === "string" ? body.from.trim() : "";
|
|
43448
|
+
const to = typeof body.to === "string" ? body.to.trim() : "";
|
|
43449
|
+
if (!from || !to) {
|
|
43450
|
+
sendError(res, 400, "invalid_body", "from and to must be non-empty strings.");
|
|
43451
|
+
return;
|
|
43452
|
+
}
|
|
43453
|
+
const toRoot = vaultRoot(to);
|
|
43454
|
+
if (toRoot) {
|
|
43455
|
+
const b = dirToward(toRoot, from);
|
|
43456
|
+
if (b) applyDir(toRoot, to, from, dropIn(b.dir), b.topics);
|
|
43457
|
+
}
|
|
43458
|
+
sendJson(res, 200, { ok: true });
|
|
43459
|
+
}
|
|
43460
|
+
async function handleLauncherShareable(req, res, _params, _contextRoot) {
|
|
43461
|
+
const body = await parseJsonBody(req);
|
|
43462
|
+
if (!body) {
|
|
43463
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43464
|
+
return;
|
|
43465
|
+
}
|
|
43466
|
+
const name = typeof body.name === "string" ? body.name.trim() : "";
|
|
43467
|
+
const shareable = body.shareable === true;
|
|
43468
|
+
if (!name) {
|
|
43469
|
+
sendError(res, 400, "invalid_name", "name must be a non-empty string.");
|
|
43470
|
+
return;
|
|
43471
|
+
}
|
|
43472
|
+
const vault = listVaults().find((v) => v.name === name);
|
|
43473
|
+
if (!vault) {
|
|
43474
|
+
sendError(res, 400, "unknown_vault", `No registered vault named "${name}".`);
|
|
43475
|
+
return;
|
|
43476
|
+
}
|
|
43477
|
+
const root = resolve15(vault.path);
|
|
43478
|
+
if (!existsSync65(root)) {
|
|
43479
|
+
sendError(res, 400, "missing_vault", `Vault path no longer exists: ${root}`);
|
|
43480
|
+
return;
|
|
43481
|
+
}
|
|
43482
|
+
try {
|
|
43483
|
+
updateSetupConfig(root, { shareable });
|
|
43484
|
+
sendJson(res, 200, { ok: true, name, shareable });
|
|
43485
|
+
} catch (err) {
|
|
43486
|
+
console.error("[launcher] shareable toggle failed:", err);
|
|
43487
|
+
sendError(res, 500, "shareable_failed", "Failed to update sharing.");
|
|
43488
|
+
}
|
|
43489
|
+
}
|
|
43490
|
+
var execFileAsync2, captureRuns, CAPTURE_RUN_TTL_MS, CAPTURE_RUNS_MAX, ScaffoldError, defaultCliRunner, SAFE_NAME_RE, SLEEPY_MODES, addOut, addIn, dropOut, dropIn;
|
|
42892
43491
|
var init_launcher = __esm({
|
|
42893
43492
|
"src/server/routes/launcher.ts"() {
|
|
42894
43493
|
"use strict";
|
|
42895
43494
|
init_middleware();
|
|
42896
43495
|
init_vault_discovery();
|
|
42897
43496
|
init_vaults();
|
|
43497
|
+
init_connections();
|
|
43498
|
+
init_setup_config();
|
|
43499
|
+
init_manifest();
|
|
43500
|
+
init_version_check();
|
|
42898
43501
|
init_tech_stack();
|
|
42899
43502
|
init_ensure_cli();
|
|
42900
43503
|
init_platforms();
|
|
42901
43504
|
init_catalog();
|
|
42902
43505
|
init_json_file();
|
|
42903
43506
|
init_id();
|
|
43507
|
+
init_sleep();
|
|
43508
|
+
init_sleep_consolidation();
|
|
42904
43509
|
execFileAsync2 = promisify2(execFile2);
|
|
42905
43510
|
captureRuns = /* @__PURE__ */ new Map();
|
|
42906
43511
|
CAPTURE_RUN_TTL_MS = 10 * 60 * 1e3;
|
|
@@ -42926,6 +43531,66 @@ var init_launcher = __esm({
|
|
|
42926
43531
|
};
|
|
42927
43532
|
SAFE_NAME_RE = /^[^/\\]+$/;
|
|
42928
43533
|
SLEEPY_MODES = /* @__PURE__ */ new Set(["idle", "sleepy", "sleeps"]);
|
|
43534
|
+
addOut = (d) => d === "in" || d === "both" ? "both" : "out";
|
|
43535
|
+
addIn = (d) => d === "out" || d === "both" ? "both" : "in";
|
|
43536
|
+
dropOut = (d) => d === "both" ? "in" : d === "in" ? "in" : null;
|
|
43537
|
+
dropIn = (d) => d === "both" ? "out" : d === "out" ? "out" : null;
|
|
43538
|
+
}
|
|
43539
|
+
});
|
|
43540
|
+
|
|
43541
|
+
// src/server/routes/ui-settings.ts
|
|
43542
|
+
import { dirname as dirname32, join as join62 } from "path";
|
|
43543
|
+
import { existsSync as existsSync66, mkdirSync as mkdirSync27, readFileSync as readFileSync48, writeFileSync as writeFileSync34 } from "fs";
|
|
43544
|
+
function settingsPath(contextRoot) {
|
|
43545
|
+
return join62(contextRoot, BRAIN_SETTINGS_REL_PATH);
|
|
43546
|
+
}
|
|
43547
|
+
async function handleBrainSettingsGet(_req, res, _params, contextRoot) {
|
|
43548
|
+
const path2 = settingsPath(contextRoot);
|
|
43549
|
+
if (!existsSync66(path2)) {
|
|
43550
|
+
sendJson(res, 200, { settings: {} });
|
|
43551
|
+
return;
|
|
43552
|
+
}
|
|
43553
|
+
try {
|
|
43554
|
+
const raw = JSON.parse(readFileSync48(path2, "utf-8"));
|
|
43555
|
+
const settings = raw && typeof raw === "object" && !Array.isArray(raw) ? raw : {};
|
|
43556
|
+
sendJson(res, 200, { settings });
|
|
43557
|
+
} catch {
|
|
43558
|
+
sendJson(res, 200, { settings: {} });
|
|
43559
|
+
}
|
|
43560
|
+
}
|
|
43561
|
+
async function handleBrainSettingsPut(req, res, _params, contextRoot) {
|
|
43562
|
+
const body = await parseJsonBody(req);
|
|
43563
|
+
if (!body) {
|
|
43564
|
+
sendError(res, 400, "invalid_body", "Request body must be valid JSON.");
|
|
43565
|
+
return;
|
|
43566
|
+
}
|
|
43567
|
+
const settings = body.settings;
|
|
43568
|
+
if (settings === null || typeof settings !== "object" || Array.isArray(settings)) {
|
|
43569
|
+
sendError(res, 400, "invalid_settings", "settings must be a JSON object.");
|
|
43570
|
+
return;
|
|
43571
|
+
}
|
|
43572
|
+
const serialized = JSON.stringify(settings, null, 2);
|
|
43573
|
+
if (Buffer.byteLength(serialized, "utf-8") > MAX_BYTES) {
|
|
43574
|
+
sendError(res, 400, "too_large", "settings payload is too large.");
|
|
43575
|
+
return;
|
|
43576
|
+
}
|
|
43577
|
+
try {
|
|
43578
|
+
const path2 = settingsPath(contextRoot);
|
|
43579
|
+
mkdirSync27(dirname32(path2), { recursive: true });
|
|
43580
|
+
writeFileSync34(path2, serialized + "\n", "utf-8");
|
|
43581
|
+
sendJson(res, 200, { ok: true });
|
|
43582
|
+
} catch (err) {
|
|
43583
|
+
console.error("[ui-settings] brain-settings write failed:", err);
|
|
43584
|
+
sendError(res, 500, "write_failed", "Failed to persist brain settings.");
|
|
43585
|
+
}
|
|
43586
|
+
}
|
|
43587
|
+
var BRAIN_SETTINGS_REL_PATH, MAX_BYTES;
|
|
43588
|
+
var init_ui_settings = __esm({
|
|
43589
|
+
"src/server/routes/ui-settings.ts"() {
|
|
43590
|
+
"use strict";
|
|
43591
|
+
init_middleware();
|
|
43592
|
+
BRAIN_SETTINGS_REL_PATH = "state/.brain-settings.json";
|
|
43593
|
+
MAX_BYTES = 256 * 1024;
|
|
42929
43594
|
}
|
|
42930
43595
|
});
|
|
42931
43596
|
|
|
@@ -42942,7 +43607,7 @@ var init_federation_config = __esm({
|
|
|
42942
43607
|
});
|
|
42943
43608
|
|
|
42944
43609
|
// src/lib/federation-recall.ts
|
|
42945
|
-
import { basename as basename19, dirname as
|
|
43610
|
+
import { basename as basename19, dirname as dirname33 } from "path";
|
|
42946
43611
|
function namespacedKey(vault, type, slug) {
|
|
42947
43612
|
return `${vault}::${type}/${slug}`;
|
|
42948
43613
|
}
|
|
@@ -42967,7 +43632,7 @@ function crossVaultRecall(query, opts) {
|
|
|
42967
43632
|
}
|
|
42968
43633
|
const isCurrent = target.current === true;
|
|
42969
43634
|
if (!isCurrent) {
|
|
42970
|
-
const projectRoot =
|
|
43635
|
+
const projectRoot = dirname33(contextRoot);
|
|
42971
43636
|
if (!isShareable(projectRoot)) continue;
|
|
42972
43637
|
}
|
|
42973
43638
|
const corpus = buildCorpus(contextRoot, opts.types ? { types: opts.types } : {}).filter((doc) => !isFederated(doc));
|
|
@@ -43040,9 +43705,9 @@ var init_federation_recall = __esm({
|
|
|
43040
43705
|
});
|
|
43041
43706
|
|
|
43042
43707
|
// src/server/routes/connections.ts
|
|
43043
|
-
import { dirname as
|
|
43708
|
+
import { dirname as dirname34 } from "path";
|
|
43044
43709
|
function currentVaultName(contextRoot) {
|
|
43045
|
-
return currentVaultTarget(
|
|
43710
|
+
return currentVaultTarget(dirname34(contextRoot)).name;
|
|
43046
43711
|
}
|
|
43047
43712
|
async function handleConnectionsList(_req, res, _params, contextRoot) {
|
|
43048
43713
|
sendJson(res, 200, { connections: listConnections(contextRoot) });
|
|
@@ -43117,8 +43782,8 @@ var init_connections2 = __esm({
|
|
|
43117
43782
|
});
|
|
43118
43783
|
|
|
43119
43784
|
// src/lib/federation-digest.ts
|
|
43120
|
-
import { existsSync as
|
|
43121
|
-
import { join as
|
|
43785
|
+
import { existsSync as existsSync67 } from "fs";
|
|
43786
|
+
import { join as join63 } from "path";
|
|
43122
43787
|
function buildInterestProfile(peerRoot, topics) {
|
|
43123
43788
|
if (topics && topics.length > 0) {
|
|
43124
43789
|
const terms2 = Array.from(new Set(tokenize(topics.join(" "))));
|
|
@@ -43137,8 +43802,8 @@ function buildInterestProfile(peerRoot, topics) {
|
|
|
43137
43802
|
return { terms, query: terms.join(" ") };
|
|
43138
43803
|
}
|
|
43139
43804
|
function activeTaskTerms(peerRoot) {
|
|
43140
|
-
const stateDir =
|
|
43141
|
-
if (!
|
|
43805
|
+
const stateDir = join63(peerRoot, "state");
|
|
43806
|
+
if (!existsSync67(stateDir)) return [];
|
|
43142
43807
|
let files;
|
|
43143
43808
|
try {
|
|
43144
43809
|
files = import_fast_glob17.default.sync("*.md", { cwd: stateDir, absolute: true });
|
|
@@ -43239,7 +43904,7 @@ var init_federation_digest = __esm({
|
|
|
43239
43904
|
});
|
|
43240
43905
|
|
|
43241
43906
|
// src/server/routes/federation.ts
|
|
43242
|
-
import { dirname as
|
|
43907
|
+
import { dirname as dirname35 } from "path";
|
|
43243
43908
|
async function handleFederationInboxGet(_req, res, _params, contextRoot) {
|
|
43244
43909
|
const { entries, quarantined } = drainInbox(contextRoot);
|
|
43245
43910
|
const pending = entries.map((e) => e.entry);
|
|
@@ -43251,7 +43916,7 @@ async function handleFederationInboxGet(_req, res, _params, contextRoot) {
|
|
|
43251
43916
|
});
|
|
43252
43917
|
}
|
|
43253
43918
|
async function handleFederationSyncPost(_req, res, _params, contextRoot) {
|
|
43254
|
-
const senderName = currentVaultTarget(
|
|
43919
|
+
const senderName = currentVaultTarget(dirname35(contextRoot)).name;
|
|
43255
43920
|
const outbound = listConnections(contextRoot).filter(
|
|
43256
43921
|
(c) => (c.direction === "out" || c.direction === "both") && c.status !== "stale"
|
|
43257
43922
|
);
|
|
@@ -43299,14 +43964,14 @@ var init_federation = __esm({
|
|
|
43299
43964
|
});
|
|
43300
43965
|
|
|
43301
43966
|
// src/server/routes/packs.ts
|
|
43302
|
-
import { dirname as
|
|
43967
|
+
import { dirname as dirname36 } from "path";
|
|
43303
43968
|
async function handlePacksGet(_req, res, _params, contextRoot) {
|
|
43304
43969
|
const loaded = loadCatalog();
|
|
43305
43970
|
if (!loaded) {
|
|
43306
43971
|
sendJson(res, 200, { packs: [], standalone: [] });
|
|
43307
43972
|
return;
|
|
43308
43973
|
}
|
|
43309
|
-
const projectRoot =
|
|
43974
|
+
const projectRoot = dirname36(contextRoot);
|
|
43310
43975
|
const packs = loaded.catalog.packs.map((p) => ({ ...p, installed: isSkillInstalled(projectRoot, p.name) }));
|
|
43311
43976
|
const standalone = loaded.catalog.standalone.map((s) => ({ ...s, installed: isSkillInstalled(projectRoot, s.name) }));
|
|
43312
43977
|
sendJson(res, 200, { packs, standalone });
|
|
@@ -43320,7 +43985,7 @@ var init_packs = __esm({
|
|
|
43320
43985
|
});
|
|
43321
43986
|
|
|
43322
43987
|
// src/server/routes/packs-install.ts
|
|
43323
|
-
import { dirname as
|
|
43988
|
+
import { dirname as dirname37 } from "path";
|
|
43324
43989
|
function validatePackName(name, contextRoot) {
|
|
43325
43990
|
if (name.includes("/") || name.includes("\0") || safeChildPath2("/x", name) === null) {
|
|
43326
43991
|
return { ok: false, status: 400, code: "invalid_name", message: "Invalid pack name." };
|
|
@@ -43333,7 +43998,7 @@ function validatePackName(name, contextRoot) {
|
|
|
43333
43998
|
if (!known) {
|
|
43334
43999
|
return { ok: false, status: 404, code: "unknown_pack", message: `Pack "${name}" not found.` };
|
|
43335
44000
|
}
|
|
43336
|
-
const projectRoot =
|
|
44001
|
+
const projectRoot = dirname37(contextRoot);
|
|
43337
44002
|
const config = readSetupConfig(projectRoot);
|
|
43338
44003
|
const platforms = normalizePlatforms(config?.platforms ?? []);
|
|
43339
44004
|
const resolved = platforms.length > 0 ? platforms : [...DEFAULT_PLATFORMS];
|
|
@@ -43406,10 +44071,10 @@ var init_packs_install = __esm({
|
|
|
43406
44071
|
});
|
|
43407
44072
|
|
|
43408
44073
|
// src/server/routes/version-check.ts
|
|
43409
|
-
import { dirname as
|
|
44074
|
+
import { dirname as dirname38 } from "path";
|
|
43410
44075
|
async function handleVersionCheckGet(_req, res, _params, contextRoot) {
|
|
43411
44076
|
try {
|
|
43412
|
-
const projectRoot =
|
|
44077
|
+
const projectRoot = dirname38(contextRoot);
|
|
43413
44078
|
const cache = readVersionCache(projectRoot);
|
|
43414
44079
|
const fresh = isCacheFresh(cache);
|
|
43415
44080
|
const installedCli = dreamcontextVersion();
|
|
@@ -43464,7 +44129,7 @@ var init_taxonomy2 = __esm({
|
|
|
43464
44129
|
|
|
43465
44130
|
// src/server/index.ts
|
|
43466
44131
|
import { createServer } from "http";
|
|
43467
|
-
import { join as
|
|
44132
|
+
import { join as join64, resolve as resolve16 } from "path";
|
|
43468
44133
|
import { fileURLToPath as fileURLToPath7 } from "url";
|
|
43469
44134
|
import { exec } from "child_process";
|
|
43470
44135
|
function buildRouter() {
|
|
@@ -43510,6 +44175,15 @@ function buildRouter() {
|
|
|
43510
44175
|
router.get("/api/launcher/capture/status", handleLauncherCaptureStatus);
|
|
43511
44176
|
router.get("/api/launcher/sleepy-config", handleSleepyConfigGet);
|
|
43512
44177
|
router.post("/api/launcher/sleepy-config", handleSleepyConfigSet);
|
|
44178
|
+
router.get("/api/launcher/status", handleLauncherStatus);
|
|
44179
|
+
router.post("/api/launcher/unregister", handleLauncherUnregister);
|
|
44180
|
+
router.post("/api/launcher/update", handleLauncherUpdate);
|
|
44181
|
+
router.get("/api/launcher/federation-graph", handleLauncherFederationGraph);
|
|
44182
|
+
router.post("/api/launcher/connection", handleLauncherConnectionCreate);
|
|
44183
|
+
router.post("/api/launcher/connection/remove", handleLauncherConnectionRemove);
|
|
44184
|
+
router.post("/api/launcher/sync", handleLauncherSyncCreate);
|
|
44185
|
+
router.post("/api/launcher/sync/remove", handleLauncherSyncRemove);
|
|
44186
|
+
router.post("/api/launcher/shareable", handleLauncherShareable);
|
|
43513
44187
|
router.get("/api/sleepy/video", handleSleepyVideo);
|
|
43514
44188
|
router.get("/api/sleepy/anim", handleSleepyAnim);
|
|
43515
44189
|
router.get("/api/vaults", handleVaultsGet);
|
|
@@ -43521,6 +44195,8 @@ function buildRouter() {
|
|
|
43521
44195
|
router.get("/api/packs", handlePacksGet);
|
|
43522
44196
|
router.post("/api/packs/:name/install", handlePackInstall);
|
|
43523
44197
|
router.delete("/api/packs/:name", handlePackUninstall);
|
|
44198
|
+
router.get("/api/brain-settings", handleBrainSettingsGet);
|
|
44199
|
+
router.put("/api/brain-settings", handleBrainSettingsPut);
|
|
43524
44200
|
router.get("/api/version-check", handleVersionCheckGet);
|
|
43525
44201
|
router.get("/api/taxonomy", handleTaxonomyGet);
|
|
43526
44202
|
router.get("/api/changelog", handleChangelogGet);
|
|
@@ -43542,7 +44218,7 @@ function resolveRequestVault(req) {
|
|
|
43542
44218
|
if (/[/\\:.\x00]/.test(h)) return "INVALID";
|
|
43543
44219
|
const v = listVaults().find((x) => x.name === h);
|
|
43544
44220
|
if (!v) return "INVALID";
|
|
43545
|
-
return
|
|
44221
|
+
return join64(v.path, "_dream_context");
|
|
43546
44222
|
}
|
|
43547
44223
|
function getDashboardDir() {
|
|
43548
44224
|
const __dirname8 = fileURLToPath7(new URL(".", import.meta.url));
|
|
@@ -43642,6 +44318,7 @@ var init_server = __esm({
|
|
|
43642
44318
|
init_config();
|
|
43643
44319
|
init_vaults2();
|
|
43644
44320
|
init_launcher();
|
|
44321
|
+
init_ui_settings();
|
|
43645
44322
|
init_connections2();
|
|
43646
44323
|
init_federation();
|
|
43647
44324
|
init_packs();
|
|
@@ -43833,8 +44510,8 @@ var init_trigger = __esm({
|
|
|
43833
44510
|
});
|
|
43834
44511
|
|
|
43835
44512
|
// src/lib/reflection.ts
|
|
43836
|
-
import { existsSync as
|
|
43837
|
-
import { join as
|
|
44513
|
+
import { existsSync as existsSync68, mkdirSync as mkdirSync28, writeFileSync as writeFileSync35 } from "fs";
|
|
44514
|
+
import { join as join65, dirname as dirname39 } from "path";
|
|
43838
44515
|
function buildExclusionSet(corpus, excludedExtra) {
|
|
43839
44516
|
const excluded = new Set(excludedExtra);
|
|
43840
44517
|
for (const doc of corpus) {
|
|
@@ -44010,13 +44687,13 @@ function formatReflection(result) {
|
|
|
44010
44687
|
return capToBytes(lines, MAX_REFLECTION_BYTES);
|
|
44011
44688
|
}
|
|
44012
44689
|
function reflectionPath(root) {
|
|
44013
|
-
return
|
|
44690
|
+
return join65(root, "state", ".reflection.md");
|
|
44014
44691
|
}
|
|
44015
44692
|
function writeReflection(root, md) {
|
|
44016
44693
|
const outPath = reflectionPath(root);
|
|
44017
|
-
const dir =
|
|
44018
|
-
if (!
|
|
44019
|
-
|
|
44694
|
+
const dir = dirname39(outPath);
|
|
44695
|
+
if (!existsSync68(dir)) {
|
|
44696
|
+
mkdirSync28(dir, { recursive: true });
|
|
44020
44697
|
}
|
|
44021
44698
|
const tsMatch = md.match(/Generated: ([^\n]+)/);
|
|
44022
44699
|
const generatedAt = tsMatch ? tsMatch[1].trim() : (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -44027,7 +44704,7 @@ function writeReflection(root, md) {
|
|
|
44027
44704
|
"---",
|
|
44028
44705
|
""
|
|
44029
44706
|
].join("\n");
|
|
44030
|
-
|
|
44707
|
+
writeFileSync35(outPath, frontmatter + md, "utf-8");
|
|
44031
44708
|
return outPath;
|
|
44032
44709
|
}
|
|
44033
44710
|
var MAX_REFLECTION_BYTES, DEFAULT_MIN_SESSIONS, DEFAULT_MAX_CANDIDATES, REFLECTION_NOISE;
|
|
@@ -44191,14 +44868,14 @@ var init_reflection = __esm({
|
|
|
44191
44868
|
});
|
|
44192
44869
|
|
|
44193
44870
|
// src/cli/commands/reflect.ts
|
|
44194
|
-
import { existsSync as
|
|
44195
|
-
import { join as
|
|
44871
|
+
import { existsSync as existsSync69, readFileSync as readFileSync51 } from "fs";
|
|
44872
|
+
import { join as join66 } from "path";
|
|
44196
44873
|
function buildBookmarkSessions(root) {
|
|
44197
|
-
const sleepPath =
|
|
44874
|
+
const sleepPath = join66(root, "state", ".sleep.json");
|
|
44198
44875
|
const result = /* @__PURE__ */ new Map();
|
|
44199
|
-
if (!
|
|
44876
|
+
if (!existsSync69(sleepPath)) return result;
|
|
44200
44877
|
try {
|
|
44201
|
-
const parsed = JSON.parse(
|
|
44878
|
+
const parsed = JSON.parse(readFileSync51(sleepPath, "utf-8"));
|
|
44202
44879
|
const bookmarks = parsed.bookmarks ?? [];
|
|
44203
44880
|
for (const b of bookmarks) {
|
|
44204
44881
|
if (b.id && b.session_id) {
|
|
@@ -44212,13 +44889,13 @@ function buildBookmarkSessions(root) {
|
|
|
44212
44889
|
function buildExcludedExtra(root) {
|
|
44213
44890
|
const excluded = /* @__PURE__ */ new Set();
|
|
44214
44891
|
const coreFiles = [
|
|
44215
|
-
|
|
44216
|
-
|
|
44892
|
+
join66(root, "core", "0.soul.md"),
|
|
44893
|
+
join66(root, "core", "1.user.md")
|
|
44217
44894
|
];
|
|
44218
44895
|
for (const filePath of coreFiles) {
|
|
44219
|
-
if (!
|
|
44896
|
+
if (!existsSync69(filePath)) continue;
|
|
44220
44897
|
try {
|
|
44221
|
-
const content =
|
|
44898
|
+
const content = readFileSync51(filePath, "utf-8");
|
|
44222
44899
|
for (const tok of tokenize(content)) {
|
|
44223
44900
|
excluded.add(tok);
|
|
44224
44901
|
}
|
|
@@ -44269,8 +44946,8 @@ var init_reflect = __esm({
|
|
|
44269
44946
|
});
|
|
44270
44947
|
|
|
44271
44948
|
// src/cli/commands/council.ts
|
|
44272
|
-
import { existsSync as
|
|
44273
|
-
import { join as
|
|
44949
|
+
import { existsSync as existsSync70, mkdirSync as mkdirSync29, readFileSync as readFileSync52, writeFileSync as writeFileSync36 } from "fs";
|
|
44950
|
+
import { join as join67 } from "path";
|
|
44274
44951
|
function roundRunningStatus(n) {
|
|
44275
44952
|
return `round_${n}_running`;
|
|
44276
44953
|
}
|
|
@@ -44312,12 +44989,12 @@ function registerCreate(council) {
|
|
|
44312
44989
|
}
|
|
44313
44990
|
const id = generateId("council");
|
|
44314
44991
|
const dir = getDebateDir(id);
|
|
44315
|
-
|
|
44992
|
+
mkdirSync29(dir, { recursive: true });
|
|
44316
44993
|
const template = loadTemplate("council-debate.md");
|
|
44317
44994
|
const content = template.replaceAll("{{ID}}", id).replaceAll("{{TOPIC}}", topic.replace(/"/g, '\\"')).replaceAll("{{ROUNDS}}", String(rounds)).replaceAll("{{INTERRUPT}}", opts.interrupt ? "true" : "false").replaceAll("{{DATE}}", today());
|
|
44318
|
-
|
|
44319
|
-
|
|
44320
|
-
|
|
44995
|
+
writeFileSync36(join67(dir, "debate.md"), content, "utf-8");
|
|
44996
|
+
writeFileSync36(
|
|
44997
|
+
join67(dir, "round-log.md"),
|
|
44321
44998
|
`# Round log \u2014 ${id}
|
|
44322
44999
|
|
|
44323
45000
|
(Main agent appends timeline entries here.)
|
|
@@ -44359,8 +45036,8 @@ function registerAgent(council) {
|
|
|
44359
45036
|
process.exit(1);
|
|
44360
45037
|
}
|
|
44361
45038
|
const personaDir = getPersonaDir(debateId, slug);
|
|
44362
|
-
const personaFile =
|
|
44363
|
-
if (
|
|
45039
|
+
const personaFile = join67(personaDir, "context-and-persona.md");
|
|
45040
|
+
if (existsSync70(personaFile) && !opts.force) {
|
|
44364
45041
|
error(`Persona already exists: ${slug}`, "Use --force to overwrite.");
|
|
44365
45042
|
process.exit(1);
|
|
44366
45043
|
}
|
|
@@ -44370,14 +45047,14 @@ function registerAgent(council) {
|
|
|
44370
45047
|
process.exit(1);
|
|
44371
45048
|
}
|
|
44372
45049
|
const aspects = opts.aspects ? opts.aspects.split(",").map((a) => a.trim()).filter(Boolean) : [];
|
|
44373
|
-
|
|
45050
|
+
mkdirSync29(personaDir, { recursive: true });
|
|
44374
45051
|
const template = loadTemplate("council-persona.md");
|
|
44375
45052
|
const personaContent = template.replaceAll("{{SLUG}}", slug).replaceAll("{{MODEL}}", opts.model).replaceAll("{{ASPECTS}}", JSON.stringify(aspects)).replaceAll("{{PERSONA_BODY}}", body.trim());
|
|
44376
|
-
|
|
45053
|
+
writeFileSync36(personaFile, personaContent, "utf-8");
|
|
44377
45054
|
const reportTemplate = loadTemplate("council-report.md");
|
|
44378
45055
|
const reportContent = reportTemplate.replaceAll("{{SLUG}}", slug);
|
|
44379
|
-
|
|
44380
|
-
const debateFile =
|
|
45056
|
+
writeFileSync36(join67(personaDir, "report.md"), reportContent, "utf-8");
|
|
45057
|
+
const debateFile = join67(getDebateDir(debateId), "debate.md");
|
|
44381
45058
|
const { data } = readFrontmatter(debateFile);
|
|
44382
45059
|
const personas = Array.isArray(data.personas) ? data.personas.slice() : [];
|
|
44383
45060
|
if (!personas.includes(slug)) personas.push(slug);
|
|
@@ -44406,7 +45083,7 @@ function registerRound(council) {
|
|
|
44406
45083
|
error(`Round ${n} exceeds planned rounds (${data.rounds_planned}).`);
|
|
44407
45084
|
process.exit(1);
|
|
44408
45085
|
}
|
|
44409
|
-
const debateFile =
|
|
45086
|
+
const debateFile = join67(getDebateDir(debateId), "debate.md");
|
|
44410
45087
|
const personas = data.personas ?? [];
|
|
44411
45088
|
if (personas.length === 0) {
|
|
44412
45089
|
error("No personas registered. Run `council agent create` first.");
|
|
@@ -44415,9 +45092,9 @@ function registerRound(council) {
|
|
|
44415
45092
|
const crossContextHeader = `## Round ${n} \u2014 Cross-context loaded`;
|
|
44416
45093
|
if (n >= 2) {
|
|
44417
45094
|
for (const persona of personas) {
|
|
44418
|
-
const personaFile =
|
|
44419
|
-
if (!
|
|
44420
|
-
const existing =
|
|
45095
|
+
const personaFile = join67(getPersonaDir(debateId, persona), "context-and-persona.md");
|
|
45096
|
+
if (!existsSync70(personaFile)) continue;
|
|
45097
|
+
const existing = readFileSync52(personaFile, "utf-8");
|
|
44421
45098
|
if (existing.includes(crossContextHeader)) {
|
|
44422
45099
|
continue;
|
|
44423
45100
|
}
|
|
@@ -44439,7 +45116,7 @@ _(no round ${n - 1} report submitted)_`);
|
|
|
44439
45116
|
|
|
44440
45117
|
${peerLines.join("\n\n")}`;
|
|
44441
45118
|
const updated = existing.trimEnd() + "\n\n" + newSection + "\n";
|
|
44442
|
-
|
|
45119
|
+
writeFileSync36(personaFile, updated, "utf-8");
|
|
44443
45120
|
}
|
|
44444
45121
|
}
|
|
44445
45122
|
updateFrontmatterFields(debateFile, {
|
|
@@ -44447,13 +45124,13 @@ ${peerLines.join("\n\n")}`;
|
|
|
44447
45124
|
current_round: n,
|
|
44448
45125
|
updated_at: today()
|
|
44449
45126
|
});
|
|
44450
|
-
const logFile =
|
|
44451
|
-
const logExisting =
|
|
45127
|
+
const logFile = join67(getDebateDir(debateId), "round-log.md");
|
|
45128
|
+
const logExisting = existsSync70(logFile) ? readFileSync52(logFile, "utf-8") : "";
|
|
44452
45129
|
const logEntry = `
|
|
44453
45130
|
## Round ${n} started \u2014 ${today()}
|
|
44454
45131
|
- Personas: ${formatPersonaList(personas)}
|
|
44455
45132
|
`;
|
|
44456
|
-
|
|
45133
|
+
writeFileSync36(logFile, logExisting.trimEnd() + "\n" + logEntry + "\n", "utf-8");
|
|
44457
45134
|
upsertCouncilIndex({
|
|
44458
45135
|
id: debateId,
|
|
44459
45136
|
topic: data.topic,
|
|
@@ -44487,18 +45164,18 @@ ${peerLines.join("\n\n")}`;
|
|
|
44487
45164
|
error(`Round ${n} incomplete. Missing reports from: ${missing.join(", ")}`);
|
|
44488
45165
|
process.exit(1);
|
|
44489
45166
|
}
|
|
44490
|
-
const debateFile =
|
|
45167
|
+
const debateFile = join67(getDebateDir(debateId), "debate.md");
|
|
44491
45168
|
updateFrontmatterFields(debateFile, {
|
|
44492
45169
|
status: roundCompleteStatus(n),
|
|
44493
45170
|
updated_at: today()
|
|
44494
45171
|
});
|
|
44495
|
-
const logFile =
|
|
44496
|
-
const logExisting =
|
|
45172
|
+
const logFile = join67(getDebateDir(debateId), "round-log.md");
|
|
45173
|
+
const logExisting = existsSync70(logFile) ? readFileSync52(logFile, "utf-8") : "";
|
|
44497
45174
|
const logEntry = `
|
|
44498
45175
|
## Round ${n} complete \u2014 ${today()}
|
|
44499
45176
|
- All ${personas.length} personas submitted reports.
|
|
44500
45177
|
`;
|
|
44501
|
-
|
|
45178
|
+
writeFileSync36(logFile, logExisting.trimEnd() + "\n" + logEntry + "\n", "utf-8");
|
|
44502
45179
|
upsertCouncilIndex({
|
|
44503
45180
|
id: debateId,
|
|
44504
45181
|
topic: data.topic,
|
|
@@ -44521,8 +45198,8 @@ function registerRoundContext(council) {
|
|
|
44521
45198
|
try {
|
|
44522
45199
|
const data = readDebateFrontmatter(debateId);
|
|
44523
45200
|
ensurePersonaExists(debateId, personaSlug);
|
|
44524
|
-
const personaFile =
|
|
44525
|
-
const personaContent =
|
|
45201
|
+
const personaFile = join67(getPersonaDir(debateId, personaSlug), "context-and-persona.md");
|
|
45202
|
+
const personaContent = readFileSync52(personaFile, "utf-8");
|
|
44526
45203
|
console.log(`# Council debate: ${data.topic}`);
|
|
44527
45204
|
console.log(`Debate ID: ${debateId}`);
|
|
44528
45205
|
console.log(`Current round: ${data.current_round}/${data.rounds_planned}`);
|
|
@@ -44531,8 +45208,8 @@ function registerRoundContext(council) {
|
|
|
44531
45208
|
console.log("---");
|
|
44532
45209
|
console.log("");
|
|
44533
45210
|
console.log(personaContent);
|
|
44534
|
-
const debateFile =
|
|
44535
|
-
const debateRaw =
|
|
45211
|
+
const debateFile = join67(getDebateDir(debateId), "debate.md");
|
|
45212
|
+
const debateRaw = readFileSync52(debateFile, "utf-8");
|
|
44536
45213
|
const questionMatch = debateRaw.match(/##\s+Question\s*\n([\s\S]*?)(?=\n##\s|\Z)/);
|
|
44537
45214
|
const constraintsMatch = debateRaw.match(/##\s+Constraints & Known Facts\s*\n([\s\S]*?)(?=\n##\s|\Z)/);
|
|
44538
45215
|
if (questionMatch) {
|
|
@@ -44575,7 +45252,7 @@ function registerReport(council) {
|
|
|
44575
45252
|
process.exit(1);
|
|
44576
45253
|
}
|
|
44577
45254
|
for (const w of validation.warnings) warn(w);
|
|
44578
|
-
const reportFile =
|
|
45255
|
+
const reportFile = join67(getPersonaDir(debateId, personaSlug), "report.md");
|
|
44579
45256
|
const { data: reportData, content } = readFrontmatter(reportFile);
|
|
44580
45257
|
const existingRounds = parseReportRounds(content);
|
|
44581
45258
|
if (existingRounds.find((r) => r.round === round)) {
|
|
@@ -44597,7 +45274,7 @@ ${otherSerialized}
|
|
|
44597
45274
|
persona: personaSlug,
|
|
44598
45275
|
rounds_completed: Math.max(reportData.rounds_completed ?? 0, round)
|
|
44599
45276
|
}, "\n" + merged);
|
|
44600
|
-
const personaFile =
|
|
45277
|
+
const personaFile = join67(getPersonaDir(debateId, personaSlug), "context-and-persona.md");
|
|
44601
45278
|
const { data: pData } = readFrontmatter(personaFile);
|
|
44602
45279
|
updateFrontmatterFields(personaFile, {
|
|
44603
45280
|
round_entries: Math.max(pData.round_entries ?? 0, round)
|
|
@@ -44640,13 +45317,13 @@ function registerResearch(council) {
|
|
|
44640
45317
|
error("Research topic is required.");
|
|
44641
45318
|
process.exit(1);
|
|
44642
45319
|
}
|
|
44643
|
-
const researchesDir =
|
|
44644
|
-
|
|
44645
|
-
const indexPath2 =
|
|
44646
|
-
if (!
|
|
45320
|
+
const researchesDir = join67(getPersonaDir(debateId, personaSlug), "researches");
|
|
45321
|
+
mkdirSync29(researchesDir, { recursive: true });
|
|
45322
|
+
const indexPath2 = join67(researchesDir, "index.json");
|
|
45323
|
+
if (!existsSync70(indexPath2)) writeJsonArray(indexPath2, []);
|
|
44647
45324
|
const slug = slugify(topic);
|
|
44648
|
-
const file =
|
|
44649
|
-
if (
|
|
45325
|
+
const file = join67(researchesDir, `${slug}.md`);
|
|
45326
|
+
if (existsSync70(file)) {
|
|
44650
45327
|
error(`Research note already exists: ${slug}.md`);
|
|
44651
45328
|
process.exit(1);
|
|
44652
45329
|
}
|
|
@@ -44661,7 +45338,7 @@ _Added ${today()} by ${personaSlug}_
|
|
|
44661
45338
|
|
|
44662
45339
|
${body.trim()}
|
|
44663
45340
|
`;
|
|
44664
|
-
|
|
45341
|
+
writeFileSync36(file, noteContent, "utf-8");
|
|
44665
45342
|
insertToJsonArray(indexPath2, {
|
|
44666
45343
|
slug,
|
|
44667
45344
|
topic,
|
|
@@ -44676,9 +45353,9 @@ ${body.trim()}
|
|
|
44676
45353
|
research.command("list").argument("<debate_id>").argument("<persona_slug>").description("List this persona's prior research notes.").action((debateId, personaSlug) => {
|
|
44677
45354
|
try {
|
|
44678
45355
|
ensurePersonaExists(debateId, personaSlug);
|
|
44679
|
-
const researchesDir =
|
|
44680
|
-
const indexPath2 =
|
|
44681
|
-
if (!
|
|
45356
|
+
const researchesDir = join67(getPersonaDir(debateId, personaSlug), "researches");
|
|
45357
|
+
const indexPath2 = join67(researchesDir, "index.json");
|
|
45358
|
+
if (!existsSync70(indexPath2)) {
|
|
44682
45359
|
console.log(source_default.dim("(no researches)"));
|
|
44683
45360
|
return;
|
|
44684
45361
|
}
|
|
@@ -44700,7 +45377,7 @@ function registerSynthesize(council) {
|
|
|
44700
45377
|
council.command("synthesize").argument("<debate_id>").description("Mark status=synthesizing; print manifest of files synthesizer should read.").action((debateId) => {
|
|
44701
45378
|
try {
|
|
44702
45379
|
const data = readDebateFrontmatter(debateId);
|
|
44703
|
-
const debateFile =
|
|
45380
|
+
const debateFile = join67(getDebateDir(debateId), "debate.md");
|
|
44704
45381
|
updateFrontmatterFields(debateFile, {
|
|
44705
45382
|
status: "synthesizing",
|
|
44706
45383
|
updated_at: today()
|
|
@@ -44722,8 +45399,8 @@ function registerSynthesize(council) {
|
|
|
44722
45399
|
const personaDir = getPersonaDir(debateId, persona);
|
|
44723
45400
|
manifest.push(`_dream_context/council/${debateId}/${persona}/context-and-persona.md`);
|
|
44724
45401
|
manifest.push(`_dream_context/council/${debateId}/${persona}/report.md`);
|
|
44725
|
-
const researchesIndex =
|
|
44726
|
-
if (
|
|
45402
|
+
const researchesIndex = join67(personaDir, "researches", "index.json");
|
|
45403
|
+
if (existsSync70(researchesIndex)) {
|
|
44727
45404
|
manifest.push(`_dream_context/council/${debateId}/${persona}/researches/`);
|
|
44728
45405
|
}
|
|
44729
45406
|
}
|
|
@@ -44741,12 +45418,12 @@ function registerComplete(council) {
|
|
|
44741
45418
|
council.command("complete").argument("<debate_id>").description("Mark status=complete after final-report.md is written.").action((debateId) => {
|
|
44742
45419
|
try {
|
|
44743
45420
|
const data = readDebateFrontmatter(debateId);
|
|
44744
|
-
const finalReport =
|
|
44745
|
-
if (!
|
|
45421
|
+
const finalReport = join67(getDebateDir(debateId), "final-report.md");
|
|
45422
|
+
if (!existsSync70(finalReport)) {
|
|
44746
45423
|
error("final-report.md not found.", "Synthesizer must write it before calling `council complete`.");
|
|
44747
45424
|
process.exit(1);
|
|
44748
45425
|
}
|
|
44749
|
-
const debateFile =
|
|
45426
|
+
const debateFile = join67(getDebateDir(debateId), "debate.md");
|
|
44750
45427
|
updateFrontmatterFields(debateFile, {
|
|
44751
45428
|
status: "complete",
|
|
44752
45429
|
updated_at: today()
|
|
@@ -44778,8 +45455,8 @@ function registerPromote(council) {
|
|
|
44778
45455
|
error(`Cannot promote: debate status is "${data.status}", expected "complete".`);
|
|
44779
45456
|
process.exit(1);
|
|
44780
45457
|
}
|
|
44781
|
-
const finalReport =
|
|
44782
|
-
if (!
|
|
45458
|
+
const finalReport = join67(getDebateDir(debateId), "final-report.md");
|
|
45459
|
+
if (!existsSync70(finalReport)) {
|
|
44783
45460
|
error("final-report.md not found.");
|
|
44784
45461
|
process.exit(1);
|
|
44785
45462
|
}
|
|
@@ -44792,12 +45469,12 @@ function registerPromote(council) {
|
|
|
44792
45469
|
|
|
44793
45470
|
${sec.body.trim()}` : null;
|
|
44794
45471
|
}).filter(Boolean).join("\n\n");
|
|
44795
|
-
const knowledgeDir =
|
|
44796
|
-
|
|
45472
|
+
const knowledgeDir = join67(root, "knowledge");
|
|
45473
|
+
mkdirSync29(knowledgeDir, { recursive: true });
|
|
44797
45474
|
const slug = slugify(data.topic).slice(0, 80) || debateId;
|
|
44798
45475
|
const filename = `decision-${slug}.md`;
|
|
44799
|
-
const target =
|
|
44800
|
-
if (
|
|
45476
|
+
const target = join67(knowledgeDir, filename);
|
|
45477
|
+
if (existsSync70(target) && !opts.force) {
|
|
44801
45478
|
error(`Knowledge file exists: ${filename}`, "Use --force to overwrite.");
|
|
44802
45479
|
process.exit(1);
|
|
44803
45480
|
}
|
|
@@ -44821,7 +45498,7 @@ ${kept}
|
|
|
44821
45498
|
_Promoted from council debate \`${debateId}\` on ${today()}. See \`_dream_context/council/${debateId}/final-report.md\` for the full record._
|
|
44822
45499
|
`;
|
|
44823
45500
|
writeFrontmatter(target, knowledgeFrontmatter, body);
|
|
44824
|
-
updateFrontmatterFields(
|
|
45501
|
+
updateFrontmatterFields(join67(getDebateDir(debateId), "debate.md"), {
|
|
44825
45502
|
promoted_to_knowledge: `knowledge/${filename}`,
|
|
44826
45503
|
updated_at: today()
|
|
44827
45504
|
});
|
|
@@ -44883,10 +45560,10 @@ function registerShow(council) {
|
|
|
44883
45560
|
console.log(` promoted: ${data.promoted_to_knowledge ?? source_default.dim("(no)")}`);
|
|
44884
45561
|
console.log(` created: ${data.created_at}`);
|
|
44885
45562
|
console.log(` updated: ${data.updated_at}`);
|
|
44886
|
-
const logFile =
|
|
44887
|
-
if (
|
|
45563
|
+
const logFile = join67(getDebateDir(debateId), "round-log.md");
|
|
45564
|
+
if (existsSync70(logFile)) {
|
|
44888
45565
|
console.log("\n" + source_default.dim("\u2500\u2500\u2500 Round log \u2500\u2500\u2500"));
|
|
44889
|
-
console.log(
|
|
45566
|
+
console.log(readFileSync52(logFile, "utf-8"));
|
|
44890
45567
|
}
|
|
44891
45568
|
} catch (err) {
|
|
44892
45569
|
error(err.message);
|
|
@@ -45078,12 +45755,12 @@ var init_env_loader = __esm({
|
|
|
45078
45755
|
});
|
|
45079
45756
|
|
|
45080
45757
|
// src/lib/marketing/config.ts
|
|
45081
|
-
import { existsSync as
|
|
45082
|
-
import { dirname as
|
|
45758
|
+
import { existsSync as existsSync71, readFileSync as readFileSync53, writeFileSync as writeFileSync37, mkdirSync as mkdirSync30 } from "fs";
|
|
45759
|
+
import { dirname as dirname40 } from "path";
|
|
45083
45760
|
function readEnvFile() {
|
|
45084
45761
|
const path2 = MARKETING_PATHS.envFile();
|
|
45085
|
-
if (!
|
|
45086
|
-
const raw =
|
|
45762
|
+
if (!existsSync71(path2)) return {};
|
|
45763
|
+
const raw = readFileSync53(path2, "utf8");
|
|
45087
45764
|
const parsed = parseEnv(raw);
|
|
45088
45765
|
if (parsed.errors.length > 0) {
|
|
45089
45766
|
for (const e of parsed.errors) {
|
|
@@ -45127,9 +45804,9 @@ function requireEnv(keys = REQUIRED_KEYS) {
|
|
|
45127
45804
|
}
|
|
45128
45805
|
function loadConfig() {
|
|
45129
45806
|
const path2 = MARKETING_PATHS.configFile();
|
|
45130
|
-
if (!
|
|
45807
|
+
if (!existsSync71(path2)) return { ...EMPTY_CONFIG, feature_flags: { ...EMPTY_CONFIG.feature_flags } };
|
|
45131
45808
|
try {
|
|
45132
|
-
const raw =
|
|
45809
|
+
const raw = readFileSync53(path2, "utf8");
|
|
45133
45810
|
const parsed = JSON.parse(raw);
|
|
45134
45811
|
return {
|
|
45135
45812
|
default_profile: parsed.default_profile ?? null,
|
|
@@ -45144,21 +45821,21 @@ function loadConfig() {
|
|
|
45144
45821
|
}
|
|
45145
45822
|
function writeConfig(cfg) {
|
|
45146
45823
|
const path2 = MARKETING_PATHS.configFile();
|
|
45147
|
-
|
|
45148
|
-
|
|
45824
|
+
mkdirSync30(dirname40(path2), { recursive: true });
|
|
45825
|
+
writeFileSync37(path2, JSON.stringify(cfg, null, 2) + "\n", "utf8");
|
|
45149
45826
|
}
|
|
45150
45827
|
function ensureConfigFile() {
|
|
45151
45828
|
const path2 = MARKETING_PATHS.configFile();
|
|
45152
|
-
if (
|
|
45829
|
+
if (existsSync71(path2)) return loadConfig();
|
|
45153
45830
|
const cfg = { ...EMPTY_CONFIG, feature_flags: { ...EMPTY_CONFIG.feature_flags } };
|
|
45154
45831
|
writeConfig(cfg);
|
|
45155
45832
|
return cfg;
|
|
45156
45833
|
}
|
|
45157
45834
|
function ensureEnvFile() {
|
|
45158
45835
|
const path2 = MARKETING_PATHS.envFile();
|
|
45159
|
-
if (
|
|
45160
|
-
|
|
45161
|
-
|
|
45836
|
+
if (existsSync71(path2)) return;
|
|
45837
|
+
mkdirSync30(marketingRoot(), { recursive: true });
|
|
45838
|
+
writeFileSync37(path2, ENV_TEMPLATE, { encoding: "utf8", mode: 384 });
|
|
45162
45839
|
}
|
|
45163
45840
|
var DEFAULT_API_VERSION, EMPTY_CONFIG, REQUIRED_KEYS, OPTIONAL_KEYS, ENV_TEMPLATE;
|
|
45164
45841
|
var init_config2 = __esm({
|
|
@@ -45199,9 +45876,9 @@ REINFLUENCE_BIN= # optional override; default uses .venv
|
|
|
45199
45876
|
|
|
45200
45877
|
// src/lib/marketing/bootstrap.ts
|
|
45201
45878
|
import { spawn as spawn5, spawnSync as spawnSync2 } from "child_process";
|
|
45202
|
-
import { existsSync as
|
|
45879
|
+
import { existsSync as existsSync72, mkdirSync as mkdirSync31, cpSync as cpSync3 } from "fs";
|
|
45203
45880
|
import { fileURLToPath as fileURLToPath8 } from "url";
|
|
45204
|
-
import { dirname as
|
|
45881
|
+
import { dirname as dirname41, resolve as resolve17, join as join68 } from "path";
|
|
45205
45882
|
function findBundledReinfluence() {
|
|
45206
45883
|
const candidates = [
|
|
45207
45884
|
// Installed npm package: dist/<chunk>.js -> ../tools/reinfluence
|
|
@@ -45211,7 +45888,7 @@ function findBundledReinfluence() {
|
|
|
45211
45888
|
resolve17(__dirname7, "..", "..", "..", "tools", "reinfluence")
|
|
45212
45889
|
];
|
|
45213
45890
|
for (const c of candidates) {
|
|
45214
|
-
if (
|
|
45891
|
+
if (existsSync72(join68(c, "__main__.py"))) return c;
|
|
45215
45892
|
}
|
|
45216
45893
|
throw new Error(
|
|
45217
45894
|
"Bundled reinfluence not found. Reinstall dreamcontext or set REINFLUENCE_BIN."
|
|
@@ -45242,18 +45919,18 @@ async function bootstrapMarketing(opts = {}) {
|
|
|
45242
45919
|
if (verbose) process.stderr.write(`[mk init] ${msg}
|
|
45243
45920
|
`);
|
|
45244
45921
|
};
|
|
45245
|
-
|
|
45922
|
+
mkdirSync31(marketingRoot(), { recursive: true });
|
|
45246
45923
|
const bundled = findBundledReinfluence();
|
|
45247
45924
|
const target = MARKETING_PATHS.reinfluenceDir();
|
|
45248
45925
|
log(`copying tools \u2192 ${target}`);
|
|
45249
|
-
|
|
45926
|
+
mkdirSync31(MARKETING_PATHS.toolsDir(), { recursive: true });
|
|
45250
45927
|
cpSync3(bundled, target, { recursive: true });
|
|
45251
45928
|
const py = findPython3();
|
|
45252
45929
|
if (!py) {
|
|
45253
45930
|
throw new Error("python3 not found on PATH. Install Python 3.10+ and retry.");
|
|
45254
45931
|
}
|
|
45255
45932
|
const venv = MARKETING_PATHS.venvDir();
|
|
45256
|
-
if (!
|
|
45933
|
+
if (!existsSync72(MARKETING_PATHS.venvPython())) {
|
|
45257
45934
|
log(`creating venv \u2192 ${venv}`);
|
|
45258
45935
|
const r2 = runBlocking(py, ["-m", "venv", venv]);
|
|
45259
45936
|
if (r2.code !== 0) {
|
|
@@ -45266,7 +45943,7 @@ async function bootstrapMarketing(opts = {}) {
|
|
|
45266
45943
|
log("upgrading pip");
|
|
45267
45944
|
let r = runBlocking(venvPy, ["-m", "pip", "install", "--upgrade", "pip", "--quiet"]);
|
|
45268
45945
|
if (r.code !== 0) log(`pip upgrade warning: ${r.stderr.trim().slice(0, 200)}`);
|
|
45269
|
-
const reqs =
|
|
45946
|
+
const reqs = join68(target, "requirements.txt");
|
|
45270
45947
|
log("installing python deps (whisper / yt-dlp / instaloader) \u2014 first run can take several minutes");
|
|
45271
45948
|
r = runBlocking(venvPy, ["-m", "pip", "install", "-r", reqs, "--quiet"]);
|
|
45272
45949
|
if (r.code !== 0) {
|
|
@@ -45276,7 +45953,7 @@ ${r.stderr.trim() || r.stdout.trim()}`);
|
|
|
45276
45953
|
let whisperPrimed = false;
|
|
45277
45954
|
if (whisperModel) {
|
|
45278
45955
|
log(`pre-pulling whisper model "${whisperModel}" into ${MARKETING_PATHS.whisperCacheDir()}`);
|
|
45279
|
-
|
|
45956
|
+
mkdirSync31(MARKETING_PATHS.whisperCacheDir(), { recursive: true });
|
|
45280
45957
|
whisperPrimed = await primeWhisper(whisperModel);
|
|
45281
45958
|
if (!whisperPrimed) log("whisper pre-pull failed (will retry on first ingest)");
|
|
45282
45959
|
}
|
|
@@ -45316,15 +45993,15 @@ function subprocessEnv() {
|
|
|
45316
45993
|
return {
|
|
45317
45994
|
...process.env,
|
|
45318
45995
|
XDG_CACHE_HOME: cache,
|
|
45319
|
-
HF_HOME:
|
|
45320
|
-
TRANSFORMERS_CACHE:
|
|
45996
|
+
HF_HOME: join68(cache, "hf"),
|
|
45997
|
+
TRANSFORMERS_CACHE: join68(cache, "hf", "transformers"),
|
|
45321
45998
|
WHISPER_CACHE_DIR: MARKETING_PATHS.whisperCacheDir(),
|
|
45322
45999
|
PYTHONUNBUFFERED: "1",
|
|
45323
46000
|
PYTHONPATH: MARKETING_PATHS.toolsDir()
|
|
45324
46001
|
};
|
|
45325
46002
|
}
|
|
45326
46003
|
function isBootstrapped() {
|
|
45327
|
-
return
|
|
46004
|
+
return existsSync72(MARKETING_PATHS.venvPython()) && existsSync72(join68(MARKETING_PATHS.reinfluenceDir(), "__main__.py"));
|
|
45328
46005
|
}
|
|
45329
46006
|
var __filename, __dirname7;
|
|
45330
46007
|
var init_bootstrap = __esm({
|
|
@@ -45332,12 +46009,12 @@ var init_bootstrap = __esm({
|
|
|
45332
46009
|
"use strict";
|
|
45333
46010
|
init_paths2();
|
|
45334
46011
|
__filename = fileURLToPath8(import.meta.url);
|
|
45335
|
-
__dirname7 =
|
|
46012
|
+
__dirname7 = dirname41(__filename);
|
|
45336
46013
|
}
|
|
45337
46014
|
});
|
|
45338
46015
|
|
|
45339
46016
|
// src/cli/commands/marketing/init.ts
|
|
45340
|
-
import { mkdirSync as
|
|
46017
|
+
import { mkdirSync as mkdirSync32 } from "fs";
|
|
45341
46018
|
function registerMarketingInit(parent) {
|
|
45342
46019
|
parent.command("init").description("Bootstrap _dream_context/marketing/ (folders, .env, venv, reinfluence tools, whisper cache)").option("--skip-bootstrap", "Only create folders + .env template; skip venv + pip install", false).option("--whisper-model <model>", "Whisper model to pre-pull (default: medium)", "medium").option("--no-whisper", "Skip Whisper model pre-pull").action(async (opts) => {
|
|
45343
46020
|
try {
|
|
@@ -45348,7 +46025,7 @@ function registerMarketingInit(parent) {
|
|
|
45348
46025
|
}
|
|
45349
46026
|
console.log(header("Marketing init"));
|
|
45350
46027
|
const root = marketingRoot();
|
|
45351
|
-
|
|
46028
|
+
mkdirSync32(root, { recursive: true });
|
|
45352
46029
|
for (const dir of [
|
|
45353
46030
|
MARKETING_PATHS.cohortsDir(),
|
|
45354
46031
|
MARKETING_PATHS.campaignsDir(),
|
|
@@ -45361,7 +46038,7 @@ function registerMarketingInit(parent) {
|
|
|
45361
46038
|
MARKETING_PATHS.byIdemDir(),
|
|
45362
46039
|
MARKETING_PATHS.cacheDir()
|
|
45363
46040
|
]) {
|
|
45364
|
-
|
|
46041
|
+
mkdirSync32(dir, { recursive: true });
|
|
45365
46042
|
}
|
|
45366
46043
|
info(`folders ready under ${source_default.dim(root)}`);
|
|
45367
46044
|
ensureEnvFile();
|
|
@@ -45401,8 +46078,8 @@ var init_init2 = __esm({
|
|
|
45401
46078
|
});
|
|
45402
46079
|
|
|
45403
46080
|
// src/lib/marketing/vision.ts
|
|
45404
|
-
import { existsSync as
|
|
45405
|
-
import { dirname as
|
|
46081
|
+
import { existsSync as existsSync73, readFileSync as readFileSync54, writeFileSync as writeFileSync38 } from "fs";
|
|
46082
|
+
import { dirname as dirname42, join as join69 } from "path";
|
|
45406
46083
|
function pickVisionProvider(env2 = process.env) {
|
|
45407
46084
|
const oai = env2.OPENAI_VISION_API_KEY;
|
|
45408
46085
|
if (oai && oai.trim().length > 0) return { provider: "openai", apiKey: oai.trim() };
|
|
@@ -45441,11 +46118,11 @@ function parseLabelsFromText(text, allowlist = LABEL_ALLOWLIST) {
|
|
|
45441
46118
|
return out;
|
|
45442
46119
|
}
|
|
45443
46120
|
async function readImageAsBase64(framePath) {
|
|
45444
|
-
const buf =
|
|
46121
|
+
const buf = readFileSync54(framePath);
|
|
45445
46122
|
return buf.toString("base64");
|
|
45446
46123
|
}
|
|
45447
46124
|
async function labelHookFrame(framePath, opts) {
|
|
45448
|
-
if (!
|
|
46125
|
+
if (!existsSync73(framePath)) return [];
|
|
45449
46126
|
const fetcher = opts.fetcher ?? defaultFetcher;
|
|
45450
46127
|
const prompt = opts.promptOverride ?? PROMPT;
|
|
45451
46128
|
const b64 = await readImageAsBase64(framePath);
|
|
@@ -45495,7 +46172,7 @@ async function labelHookFrame(framePath, opts) {
|
|
|
45495
46172
|
return parseLabelsFromText(text);
|
|
45496
46173
|
}
|
|
45497
46174
|
async function runVisionPassOnPost(postJsonPath, opts = {}) {
|
|
45498
|
-
const raw =
|
|
46175
|
+
const raw = readFileSync54(postJsonPath, "utf-8");
|
|
45499
46176
|
const post = JSON.parse(raw);
|
|
45500
46177
|
const shortcode = post.shortcode ?? "?";
|
|
45501
46178
|
const provider = opts.provider && opts.apiKey ? { provider: opts.provider, apiKey: opts.apiKey } : pickVisionProvider();
|
|
@@ -45534,15 +46211,15 @@ async function runVisionPassOnPost(postJsonPath, opts = {}) {
|
|
|
45534
46211
|
post.pattern_tags = [...aggregated].sort();
|
|
45535
46212
|
post.vision_summary = post.pattern_tags.length > 0 ? `Vision-tagged ${framesLabeled}/${hookFrames.length} hook frames; patterns: ${post.pattern_tags.join(", ")}.` : `Vision pass found no allowlisted patterns across ${hookFrames.length} hook frames.`;
|
|
45536
46213
|
const tmp = postJsonPath + ".tmp";
|
|
45537
|
-
|
|
46214
|
+
writeFileSync38(tmp, JSON.stringify(post, null, 2) + "\n", "utf-8");
|
|
45538
46215
|
const fs = await import("fs");
|
|
45539
46216
|
fs.renameSync(tmp, postJsonPath);
|
|
45540
|
-
const mdPath =
|
|
45541
|
-
if (
|
|
46217
|
+
const mdPath = join69(dirname42(postJsonPath), `${shortcode}.md`);
|
|
46218
|
+
if (existsSync73(mdPath)) {
|
|
45542
46219
|
try {
|
|
45543
|
-
const md =
|
|
46220
|
+
const md = readFileSync54(mdPath, "utf-8");
|
|
45544
46221
|
const refreshed = updatePatternTagsInBridge(md, post.pattern_tags);
|
|
45545
|
-
|
|
46222
|
+
writeFileSync38(mdPath, refreshed, "utf-8");
|
|
45546
46223
|
} catch {
|
|
45547
46224
|
}
|
|
45548
46225
|
}
|
|
@@ -45617,8 +46294,8 @@ Example output: ["talking-head","prop-driven"]`;
|
|
|
45617
46294
|
// src/lib/marketing/competitors.ts
|
|
45618
46295
|
import { spawn as spawn6 } from "child_process";
|
|
45619
46296
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
45620
|
-
import { existsSync as
|
|
45621
|
-
import { dirname as
|
|
46297
|
+
import { existsSync as existsSync74, mkdirSync as mkdirSync33, statfsSync } from "fs";
|
|
46298
|
+
import { dirname as dirname43, join as join70, basename as basename20, extname as extname4 } from "path";
|
|
45622
46299
|
function which(cmd) {
|
|
45623
46300
|
const r = spawnSync3(process.platform === "win32" ? "where" : "which", [cmd], { encoding: "utf8" });
|
|
45624
46301
|
if (r.status === 0) return (r.stdout || "").trim().split("\n")[0] || null;
|
|
@@ -45695,8 +46372,8 @@ ${h.installHints.join("\n")}`);
|
|
|
45695
46372
|
skip_transcripts: !!opts.skipTranscripts,
|
|
45696
46373
|
skip_frames: !!opts.skipFrames
|
|
45697
46374
|
});
|
|
45698
|
-
const outDir =
|
|
45699
|
-
|
|
46375
|
+
const outDir = join70(MARKETING_PATHS.competitorsDir(), "_ingest-tmp", run2.id);
|
|
46376
|
+
mkdirSync33(outDir, { recursive: true });
|
|
45700
46377
|
const args = [
|
|
45701
46378
|
"-m",
|
|
45702
46379
|
"reinfluence",
|
|
@@ -45796,15 +46473,15 @@ stderr: ${stderrBuf.slice(0, 1e3)}`));
|
|
|
45796
46473
|
return { runId: run2.id, postsIngested, warnings, errors };
|
|
45797
46474
|
}
|
|
45798
46475
|
function persistPost(evt) {
|
|
45799
|
-
const handleDir =
|
|
45800
|
-
const postsDir =
|
|
45801
|
-
const mediaDir =
|
|
45802
|
-
|
|
45803
|
-
|
|
45804
|
-
const finalVideoPath = evt.video_path ? moveAsset(evt.video_path,
|
|
46476
|
+
const handleDir = join70(MARKETING_PATHS.competitorsDir(), evt.handle);
|
|
46477
|
+
const postsDir = join70(handleDir, "posts");
|
|
46478
|
+
const mediaDir = join70(handleDir, "_media", evt.shortcode);
|
|
46479
|
+
mkdirSync33(postsDir, { recursive: true });
|
|
46480
|
+
mkdirSync33(mediaDir, { recursive: true });
|
|
46481
|
+
const finalVideoPath = evt.video_path ? moveAsset(evt.video_path, join70(mediaDir, basename20(evt.video_path))) : null;
|
|
45805
46482
|
const finalFramePaths = [];
|
|
45806
46483
|
for (const fr of evt.frames) {
|
|
45807
|
-
const finalP = moveAsset(fr.path,
|
|
46484
|
+
const finalP = moveAsset(fr.path, join70(mediaDir, "frames", basename20(fr.path)));
|
|
45808
46485
|
finalFramePaths.push(finalP);
|
|
45809
46486
|
}
|
|
45810
46487
|
const id = `${evt.handle}__${evt.shortcode}`;
|
|
@@ -45824,14 +46501,14 @@ function persistPost(evt) {
|
|
|
45824
46501
|
ingested_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
45825
46502
|
asset_paths: { video: finalVideoPath, frames: finalFramePaths }
|
|
45826
46503
|
};
|
|
45827
|
-
const jsonPath =
|
|
45828
|
-
const bridgePath =
|
|
46504
|
+
const jsonPath = join70(postsDir, `${evt.shortcode}.json`);
|
|
46505
|
+
const bridgePath = join70(postsDir, `${evt.shortcode}.md`);
|
|
45829
46506
|
writeJsonWithBridge(jsonPath, bridgePath, json, renderPostBridge(json));
|
|
45830
|
-
const metaPath =
|
|
45831
|
-
if (!
|
|
46507
|
+
const metaPath = join70(handleDir, "meta.json");
|
|
46508
|
+
if (!existsSync74(metaPath)) {
|
|
45832
46509
|
writeJsonWithBridge(
|
|
45833
46510
|
metaPath,
|
|
45834
|
-
|
|
46511
|
+
join70(handleDir, "meta.md"),
|
|
45835
46512
|
{ handle: evt.handle, first_seen_at: (/* @__PURE__ */ new Date()).toISOString() },
|
|
45836
46513
|
`---
|
|
45837
46514
|
id: competitor_${evt.handle}
|
|
@@ -45848,8 +46525,8 @@ First seen: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
|
45848
46525
|
return jsonPath;
|
|
45849
46526
|
}
|
|
45850
46527
|
function moveAsset(src, dest) {
|
|
45851
|
-
if (!
|
|
45852
|
-
|
|
46528
|
+
if (!existsSync74(src)) return dest;
|
|
46529
|
+
mkdirSync33(dirname43(dest), { recursive: true });
|
|
45853
46530
|
const fs = __require("fs");
|
|
45854
46531
|
try {
|
|
45855
46532
|
fs.renameSync(src, dest);
|
|
@@ -45910,8 +46587,8 @@ var init_competitors = __esm({
|
|
|
45910
46587
|
});
|
|
45911
46588
|
|
|
45912
46589
|
// src/cli/commands/marketing/competitor.ts
|
|
45913
|
-
import { existsSync as
|
|
45914
|
-
import { join as
|
|
46590
|
+
import { existsSync as existsSync75, readdirSync as readdirSync17, statSync as statSync11 } from "fs";
|
|
46591
|
+
import { join as join71 } from "path";
|
|
45915
46592
|
function registerMarketingCompetitor(parent) {
|
|
45916
46593
|
const cmd = parent.command("competitor").description("Ingest competitor IG / YouTube content (Reinfluence pipeline).");
|
|
45917
46594
|
cmd.command("ingest <target>").description("Ingest a single URL or an IG handle. Outputs land under _dream_context/marketing/competitors/<handle>/.").option("--model <name>", "Whisper model size (tiny|base|small|medium|large)", "medium").option("--max <n>", "Max reels for IG handle ingest (0 = all)", "0").option("--skip-transcripts", "Skip Whisper transcription", false).option("--skip-frames", "Skip frame extraction", false).option("--timeout <seconds>", "Wall-clock kill", "600").action(async (target, opts) => {
|
|
@@ -45961,13 +46638,13 @@ function registerMarketingCompetitor(parent) {
|
|
|
45961
46638
|
});
|
|
45962
46639
|
cmd.command("list").description("List ingested competitor handles.").action(() => {
|
|
45963
46640
|
const dir = MARKETING_PATHS.competitorsDir();
|
|
45964
|
-
if (!
|
|
46641
|
+
if (!existsSync75(dir)) {
|
|
45965
46642
|
info("No competitors ingested yet.");
|
|
45966
46643
|
return;
|
|
45967
46644
|
}
|
|
45968
|
-
const handles =
|
|
46645
|
+
const handles = readdirSync17(dir).filter((name) => {
|
|
45969
46646
|
if (name.startsWith("_") || name.startsWith(".")) return false;
|
|
45970
|
-
const full =
|
|
46647
|
+
const full = join71(dir, name);
|
|
45971
46648
|
try {
|
|
45972
46649
|
return statSync11(full).isDirectory();
|
|
45973
46650
|
} catch {
|
|
@@ -45980,8 +46657,8 @@ function registerMarketingCompetitor(parent) {
|
|
|
45980
46657
|
}
|
|
45981
46658
|
console.log(header("Competitors"));
|
|
45982
46659
|
for (const handle of handles) {
|
|
45983
|
-
const postsDir =
|
|
45984
|
-
const postCount =
|
|
46660
|
+
const postsDir = join71(dir, handle, "posts");
|
|
46661
|
+
const postCount = existsSync75(postsDir) ? readdirSync17(postsDir).filter((f) => f.endsWith(".json")).length : 0;
|
|
45985
46662
|
console.log(` ${source_default.cyan("@" + handle)} ${source_default.dim(`${postCount} post(s)`)}`);
|
|
45986
46663
|
}
|
|
45987
46664
|
});
|
|
@@ -45994,11 +46671,11 @@ function registerMarketingCompetitor(parent) {
|
|
|
45994
46671
|
}
|
|
45995
46672
|
info(`Provider: ${provider.provider}`);
|
|
45996
46673
|
const competitorsDir = MARKETING_PATHS.competitorsDir();
|
|
45997
|
-
const handles = opts.handle ? [opts.handle] :
|
|
46674
|
+
const handles = opts.handle ? [opts.handle] : existsSync75(competitorsDir) ? readdirSync17(competitorsDir).filter((h) => !h.startsWith("_") && statSync11(join71(competitorsDir, h)).isDirectory()) : [];
|
|
45998
46675
|
const matches = [];
|
|
45999
46676
|
for (const h of handles) {
|
|
46000
|
-
const candidate =
|
|
46001
|
-
if (
|
|
46677
|
+
const candidate = join71(competitorsDir, h, "posts", `${shortcode}.json`);
|
|
46678
|
+
if (existsSync75(candidate)) matches.push(candidate);
|
|
46002
46679
|
}
|
|
46003
46680
|
if (matches.length === 0) {
|
|
46004
46681
|
error(`No post JSON found for shortcode "${shortcode}".`);
|
|
@@ -46033,18 +46710,18 @@ function registerMarketingCompetitor(parent) {
|
|
|
46033
46710
|
process.exit(1);
|
|
46034
46711
|
}
|
|
46035
46712
|
const competitorsDir = MARKETING_PATHS.competitorsDir();
|
|
46036
|
-
if (!
|
|
46713
|
+
if (!existsSync75(competitorsDir)) {
|
|
46037
46714
|
warn("No competitors directory yet \u2014 nothing to relabel.");
|
|
46038
46715
|
return;
|
|
46039
46716
|
}
|
|
46040
|
-
const handles =
|
|
46717
|
+
const handles = readdirSync17(competitorsDir).filter((h) => !h.startsWith("_") && statSync11(join71(competitorsDir, h)).isDirectory());
|
|
46041
46718
|
let labeled = 0;
|
|
46042
46719
|
let skipped = 0;
|
|
46043
46720
|
for (const h of handles) {
|
|
46044
|
-
const postsDir =
|
|
46045
|
-
if (!
|
|
46046
|
-
for (const f of
|
|
46047
|
-
const path2 =
|
|
46721
|
+
const postsDir = join71(competitorsDir, h, "posts");
|
|
46722
|
+
if (!existsSync75(postsDir)) continue;
|
|
46723
|
+
for (const f of readdirSync17(postsDir).filter((n) => n.endsWith(".json"))) {
|
|
46724
|
+
const path2 = join71(postsDir, f);
|
|
46048
46725
|
if (opts.dryRun) {
|
|
46049
46726
|
info(`would relabel: ${path2}`);
|
|
46050
46727
|
continue;
|
|
@@ -46091,8 +46768,8 @@ var init_competitor = __esm({
|
|
|
46091
46768
|
});
|
|
46092
46769
|
|
|
46093
46770
|
// src/lib/marketing/meta-fetch.ts
|
|
46094
|
-
import { existsSync as
|
|
46095
|
-
import { dirname as
|
|
46771
|
+
import { existsSync as existsSync76, mkdirSync as mkdirSync34, readFileSync as readFileSync55, writeFileSync as writeFileSync39, statSync as statSync12, openSync as openSync2, readSync, closeSync as closeSync2 } from "fs";
|
|
46772
|
+
import { dirname as dirname44, basename as basename21 } from "path";
|
|
46096
46773
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
46097
46774
|
function getQueue(accountId) {
|
|
46098
46775
|
let q = writeQueues.get(accountId);
|
|
@@ -46142,17 +46819,17 @@ function idemCachePath(key) {
|
|
|
46142
46819
|
}
|
|
46143
46820
|
function readIdem(key) {
|
|
46144
46821
|
const p = idemCachePath(key);
|
|
46145
|
-
if (!
|
|
46822
|
+
if (!existsSync76(p)) return null;
|
|
46146
46823
|
try {
|
|
46147
|
-
return JSON.parse(
|
|
46824
|
+
return JSON.parse(readFileSync55(p, "utf8"));
|
|
46148
46825
|
} catch {
|
|
46149
46826
|
return null;
|
|
46150
46827
|
}
|
|
46151
46828
|
}
|
|
46152
46829
|
function writeIdem(rec) {
|
|
46153
46830
|
const p = idemCachePath(rec.key);
|
|
46154
|
-
|
|
46155
|
-
|
|
46831
|
+
mkdirSync34(dirname44(p), { recursive: true });
|
|
46832
|
+
writeFileSync39(p, JSON.stringify(rec, null, 2) + "\n", "utf8");
|
|
46156
46833
|
}
|
|
46157
46834
|
function backoffMs(attempt, hintSec) {
|
|
46158
46835
|
if (hintSec != null && Number.isFinite(hintSec) && hintSec > 0) {
|
|
@@ -46420,7 +47097,7 @@ async function singleShotVideoUpload(ctx, filepath, fields) {
|
|
|
46420
47097
|
if (fields.name) form.set("name", fields.name);
|
|
46421
47098
|
if (fields.title) form.set("title", fields.title);
|
|
46422
47099
|
if (fields.description) form.set("description", fields.description);
|
|
46423
|
-
const buffer =
|
|
47100
|
+
const buffer = readFileSync55(filepath);
|
|
46424
47101
|
const blob = new Blob([new Uint8Array(buffer)], { type: "video/mp4" });
|
|
46425
47102
|
form.set("source", blob, basename21(filepath));
|
|
46426
47103
|
const resp = await fetch(url, {
|
|
@@ -46469,7 +47146,7 @@ async function uploadImageFile(ctx, filepath) {
|
|
|
46469
47146
|
return withWriteSlot(ctx.adAccountId, async () => {
|
|
46470
47147
|
const url = buildUrl(ctx, { method: "POST", path: `${ctx.adAccountId}/adimages` });
|
|
46471
47148
|
const form = new FormData();
|
|
46472
|
-
const buffer =
|
|
47149
|
+
const buffer = readFileSync55(filepath);
|
|
46473
47150
|
const blob = new Blob([new Uint8Array(buffer)], { type: "image/png" });
|
|
46474
47151
|
form.set("filename", blob, basename21(filepath));
|
|
46475
47152
|
const resp = await fetch(url, {
|
|
@@ -46888,7 +47565,7 @@ var init_account = __esm({
|
|
|
46888
47565
|
});
|
|
46889
47566
|
|
|
46890
47567
|
// src/lib/marketing/hypothesis.ts
|
|
46891
|
-
import { existsSync as
|
|
47568
|
+
import { existsSync as existsSync77, readFileSync as readFileSync56 } from "fs";
|
|
46892
47569
|
function validateHypothesis(raw, options2 = {}) {
|
|
46893
47570
|
const errors = [];
|
|
46894
47571
|
const fieldErrors = {};
|
|
@@ -46955,12 +47632,12 @@ function validateHypothesis(raw, options2 = {}) {
|
|
|
46955
47632
|
};
|
|
46956
47633
|
}
|
|
46957
47634
|
function loadHypothesisFile(path2, options2 = {}) {
|
|
46958
|
-
if (!
|
|
47635
|
+
if (!existsSync77(path2)) {
|
|
46959
47636
|
return { ok: false, errors: [`Hypothesis file not found: ${path2}`] };
|
|
46960
47637
|
}
|
|
46961
47638
|
let parsed;
|
|
46962
47639
|
try {
|
|
46963
|
-
parsed = JSON.parse(
|
|
47640
|
+
parsed = JSON.parse(readFileSync56(path2, "utf8"));
|
|
46964
47641
|
} catch (e) {
|
|
46965
47642
|
return { ok: false, errors: [`Failed to parse JSON at ${path2}: ${e.message}`] };
|
|
46966
47643
|
}
|
|
@@ -47148,8 +47825,8 @@ var init_cohort2 = __esm({
|
|
|
47148
47825
|
});
|
|
47149
47826
|
|
|
47150
47827
|
// src/lib/marketing/insights-cache.ts
|
|
47151
|
-
import { existsSync as
|
|
47152
|
-
import { join as
|
|
47828
|
+
import { existsSync as existsSync78, readFileSync as readFileSync57, mkdirSync as mkdirSync35, writeFileSync as writeFileSync40, readdirSync as readdirSync18, statSync as statSync13 } from "fs";
|
|
47829
|
+
import { join as join72 } from "path";
|
|
47153
47830
|
import { randomBytes as randomBytes3 } from "crypto";
|
|
47154
47831
|
function snapshotFilename(entityId, pulledAt) {
|
|
47155
47832
|
const yyyy = pulledAt.getUTCFullYear();
|
|
@@ -47160,30 +47837,30 @@ function snapshotFilename(entityId, pulledAt) {
|
|
|
47160
47837
|
return `${safe}__${yyyy}-${mm}-${dd}-${hh}.json`;
|
|
47161
47838
|
}
|
|
47162
47839
|
function indexPath() {
|
|
47163
|
-
return
|
|
47840
|
+
return join72(MARKETING_PATHS.insightsDir(), "_index.json");
|
|
47164
47841
|
}
|
|
47165
47842
|
function readIndex() {
|
|
47166
47843
|
const p = indexPath();
|
|
47167
|
-
if (!
|
|
47844
|
+
if (!existsSync78(p)) return { latest: {}, updated_at: "1970-01-01T00:00:00Z" };
|
|
47168
47845
|
try {
|
|
47169
|
-
return JSON.parse(
|
|
47846
|
+
return JSON.parse(readFileSync57(p, "utf8"));
|
|
47170
47847
|
} catch {
|
|
47171
47848
|
return { latest: {}, updated_at: "1970-01-01T00:00:00Z" };
|
|
47172
47849
|
}
|
|
47173
47850
|
}
|
|
47174
47851
|
function writeIndex(idx) {
|
|
47175
47852
|
const p = indexPath();
|
|
47176
|
-
|
|
47853
|
+
mkdirSync35(MARKETING_PATHS.insightsDir(), { recursive: true });
|
|
47177
47854
|
const tmp = `${p}.tmp.${process.pid}.${randomBytes3(4).toString("hex")}`;
|
|
47178
|
-
|
|
47855
|
+
writeFileSync40(tmp, JSON.stringify(idx, null, 2) + "\n", "utf8");
|
|
47179
47856
|
__require("fs").renameSync(tmp, p);
|
|
47180
47857
|
}
|
|
47181
47858
|
function saveInsightsSnapshot(snap) {
|
|
47182
|
-
|
|
47859
|
+
mkdirSync35(MARKETING_PATHS.insightsDir(), { recursive: true });
|
|
47183
47860
|
const filename = snapshotFilename(snap.entity_id, new Date(snap.pulled_at));
|
|
47184
|
-
const fullPath =
|
|
47861
|
+
const fullPath = join72(MARKETING_PATHS.insightsDir(), filename);
|
|
47185
47862
|
const tmp = `${fullPath}.tmp.${process.pid}.${randomBytes3(4).toString("hex")}`;
|
|
47186
|
-
|
|
47863
|
+
writeFileSync40(tmp, JSON.stringify(snap, null, 2) + "\n", "utf8");
|
|
47187
47864
|
__require("fs").renameSync(tmp, fullPath);
|
|
47188
47865
|
const idx = readIndex();
|
|
47189
47866
|
idx.latest[snap.entity_id] = filename;
|
|
@@ -47195,10 +47872,10 @@ function getCachedInsights(entityId) {
|
|
|
47195
47872
|
const idx = readIndex();
|
|
47196
47873
|
const filename = idx.latest[entityId];
|
|
47197
47874
|
if (!filename) return null;
|
|
47198
|
-
const fullPath =
|
|
47199
|
-
if (!
|
|
47875
|
+
const fullPath = join72(MARKETING_PATHS.insightsDir(), filename);
|
|
47876
|
+
if (!existsSync78(fullPath)) return null;
|
|
47200
47877
|
try {
|
|
47201
|
-
const snap = JSON.parse(
|
|
47878
|
+
const snap = JSON.parse(readFileSync57(fullPath, "utf8"));
|
|
47202
47879
|
const ageMs = Date.now() - new Date(snap.pulled_at).getTime();
|
|
47203
47880
|
if (ageMs > INSIGHTS_TTL_MS) return null;
|
|
47204
47881
|
return snap;
|
|
@@ -47210,20 +47887,20 @@ function getLatestSnapshot(entityId) {
|
|
|
47210
47887
|
const idx = readIndex();
|
|
47211
47888
|
const filename = idx.latest[entityId];
|
|
47212
47889
|
if (!filename) return null;
|
|
47213
|
-
const fullPath =
|
|
47214
|
-
if (!
|
|
47890
|
+
const fullPath = join72(MARKETING_PATHS.insightsDir(), filename);
|
|
47891
|
+
if (!existsSync78(fullPath)) return null;
|
|
47215
47892
|
try {
|
|
47216
|
-
return JSON.parse(
|
|
47893
|
+
return JSON.parse(readFileSync57(fullPath, "utf8"));
|
|
47217
47894
|
} catch {
|
|
47218
47895
|
return null;
|
|
47219
47896
|
}
|
|
47220
47897
|
}
|
|
47221
47898
|
function getPriorSnapshot(entityId, beforeMs) {
|
|
47222
47899
|
const dir = MARKETING_PATHS.insightsDir();
|
|
47223
|
-
if (!
|
|
47900
|
+
if (!existsSync78(dir)) return null;
|
|
47224
47901
|
const safe = entityId.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
47225
|
-
const candidates =
|
|
47226
|
-
const p =
|
|
47902
|
+
const candidates = readdirSync18(dir).filter((f) => f.startsWith(`${safe}__`) && f.endsWith(".json")).map((f) => {
|
|
47903
|
+
const p = join72(dir, f);
|
|
47227
47904
|
const stat = statSync13(p);
|
|
47228
47905
|
return { f, p, mtimeMs: stat.mtimeMs };
|
|
47229
47906
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
@@ -47231,7 +47908,7 @@ function getPriorSnapshot(entityId, beforeMs) {
|
|
|
47231
47908
|
for (const c of candidates) {
|
|
47232
47909
|
if (c.mtimeMs <= cutoff) {
|
|
47233
47910
|
try {
|
|
47234
|
-
return JSON.parse(
|
|
47911
|
+
return JSON.parse(readFileSync57(c.p, "utf8"));
|
|
47235
47912
|
} catch {
|
|
47236
47913
|
continue;
|
|
47237
47914
|
}
|
|
@@ -47867,8 +48544,8 @@ var init_kill = __esm({
|
|
|
47867
48544
|
});
|
|
47868
48545
|
|
|
47869
48546
|
// src/cli/commands/marketing/doctor.ts
|
|
47870
|
-
import { readFileSync as
|
|
47871
|
-
import { join as
|
|
48547
|
+
import { readFileSync as readFileSync58, readdirSync as readdirSync19, statSync as statSync14 } from "fs";
|
|
48548
|
+
import { join as join73 } from "path";
|
|
47872
48549
|
function registerMarketingDoctor(parent) {
|
|
47873
48550
|
parent.command("doctor").description("Run diagnostics: env, FK integrity, retroactive secret scan, Reinfluence health.").option("--scan", "Run retroactive secret scan over the entire _dream_context/ tree", false).action(async (opts) => {
|
|
47874
48551
|
console.log(header("Marketing doctor"));
|
|
@@ -47949,7 +48626,7 @@ function scanForSecrets(root) {
|
|
|
47949
48626
|
for (const file of walkText(root)) {
|
|
47950
48627
|
let txt;
|
|
47951
48628
|
try {
|
|
47952
|
-
txt =
|
|
48629
|
+
txt = readFileSync58(file, "utf8");
|
|
47953
48630
|
} catch {
|
|
47954
48631
|
continue;
|
|
47955
48632
|
}
|
|
@@ -47970,13 +48647,13 @@ function scanForSecrets(root) {
|
|
|
47970
48647
|
function* walkText(dir) {
|
|
47971
48648
|
let entries;
|
|
47972
48649
|
try {
|
|
47973
|
-
entries =
|
|
48650
|
+
entries = readdirSync19(dir);
|
|
47974
48651
|
} catch {
|
|
47975
48652
|
return;
|
|
47976
48653
|
}
|
|
47977
48654
|
for (const e of entries) {
|
|
47978
48655
|
if (e.startsWith(".") && (e === ".env" || e === ".env.local")) continue;
|
|
47979
|
-
const full =
|
|
48656
|
+
const full = join73(dir, e);
|
|
47980
48657
|
let stat;
|
|
47981
48658
|
try {
|
|
47982
48659
|
stat = statSync14(full);
|
|
@@ -48014,8 +48691,8 @@ var init_doctor2 = __esm({
|
|
|
48014
48691
|
});
|
|
48015
48692
|
|
|
48016
48693
|
// src/lib/marketing/entity-store.ts
|
|
48017
|
-
import { existsSync as
|
|
48018
|
-
import { join as
|
|
48694
|
+
import { existsSync as existsSync80, readFileSync as readFileSync59, readdirSync as readdirSync20 } from "fs";
|
|
48695
|
+
import { join as join74 } from "path";
|
|
48019
48696
|
function dirFor(kind) {
|
|
48020
48697
|
switch (kind) {
|
|
48021
48698
|
case "campaign":
|
|
@@ -48034,24 +48711,24 @@ function newEntityId(kind) {
|
|
|
48034
48711
|
}
|
|
48035
48712
|
function entityPaths(kind, id) {
|
|
48036
48713
|
const d = dirFor(kind);
|
|
48037
|
-
return { json:
|
|
48714
|
+
return { json: join74(d, `${id}.json`), md: join74(d, `${id}.md`) };
|
|
48038
48715
|
}
|
|
48039
48716
|
function loadEntity(kind, id) {
|
|
48040
48717
|
const { json } = entityPaths(kind, id);
|
|
48041
|
-
if (!
|
|
48718
|
+
if (!existsSync80(json)) return null;
|
|
48042
48719
|
try {
|
|
48043
|
-
return JSON.parse(
|
|
48720
|
+
return JSON.parse(readFileSync59(json, "utf8"));
|
|
48044
48721
|
} catch {
|
|
48045
48722
|
return null;
|
|
48046
48723
|
}
|
|
48047
48724
|
}
|
|
48048
48725
|
function listEntities(kind) {
|
|
48049
48726
|
const d = dirFor(kind);
|
|
48050
|
-
if (!
|
|
48727
|
+
if (!existsSync80(d)) return [];
|
|
48051
48728
|
const out = [];
|
|
48052
|
-
for (const f of
|
|
48729
|
+
for (const f of readdirSync20(d).filter((x) => x.endsWith(".json"))) {
|
|
48053
48730
|
try {
|
|
48054
|
-
out.push(JSON.parse(
|
|
48731
|
+
out.push(JSON.parse(readFileSync59(join74(d, f), "utf8")));
|
|
48055
48732
|
} catch {
|
|
48056
48733
|
}
|
|
48057
48734
|
}
|
|
@@ -48245,7 +48922,7 @@ var init_campaign = __esm({
|
|
|
48245
48922
|
});
|
|
48246
48923
|
|
|
48247
48924
|
// src/cli/commands/marketing/adset.ts
|
|
48248
|
-
import { existsSync as
|
|
48925
|
+
import { existsSync as existsSync81, readFileSync as readFileSync60 } from "fs";
|
|
48249
48926
|
function registerMarketingAdSet(parent) {
|
|
48250
48927
|
const cmd = parent.command("adset").description("Manage adsets.");
|
|
48251
48928
|
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) => {
|
|
@@ -48265,13 +48942,13 @@ function registerMarketingAdSet(parent) {
|
|
|
48265
48942
|
}
|
|
48266
48943
|
throw e;
|
|
48267
48944
|
}
|
|
48268
|
-
if (!
|
|
48945
|
+
if (!existsSync81(opts.targeting)) {
|
|
48269
48946
|
error(`Targeting file not found: ${opts.targeting}`);
|
|
48270
48947
|
process.exit(1);
|
|
48271
48948
|
}
|
|
48272
48949
|
let targeting;
|
|
48273
48950
|
try {
|
|
48274
|
-
targeting = JSON.parse(
|
|
48951
|
+
targeting = JSON.parse(readFileSync60(opts.targeting, "utf8"));
|
|
48275
48952
|
} catch (e) {
|
|
48276
48953
|
error(`Failed to parse targeting JSON: ${e.message}`);
|
|
48277
48954
|
process.exit(1);
|
|
@@ -48528,12 +49205,12 @@ var init_creative = __esm({
|
|
|
48528
49205
|
});
|
|
48529
49206
|
|
|
48530
49207
|
// src/cli/commands/marketing/asset.ts
|
|
48531
|
-
import { existsSync as
|
|
49208
|
+
import { existsSync as existsSync82, statSync as statSync15 } from "fs";
|
|
48532
49209
|
import { extname as extname5 } from "path";
|
|
48533
49210
|
function registerMarketingAsset(parent) {
|
|
48534
49211
|
const cmd = parent.command("asset").description("Upload creative assets to Meta.");
|
|
48535
49212
|
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) => {
|
|
48536
|
-
if (!
|
|
49213
|
+
if (!existsSync82(path2)) {
|
|
48537
49214
|
error(`File not found: ${path2}`);
|
|
48538
49215
|
process.exit(1);
|
|
48539
49216
|
}
|
|
@@ -48701,8 +49378,8 @@ var init_ad = __esm({
|
|
|
48701
49378
|
});
|
|
48702
49379
|
|
|
48703
49380
|
// src/lib/marketing/launch.ts
|
|
48704
|
-
import { existsSync as
|
|
48705
|
-
import { dirname as
|
|
49381
|
+
import { existsSync as existsSync83, readFileSync as readFileSync61, writeFileSync as writeFileSync41, mkdirSync as mkdirSync36, renameSync as renameSync8, readdirSync as readdirSync21 } from "fs";
|
|
49382
|
+
import { dirname as dirname45, join as join75, basename as basename22 } from "path";
|
|
48706
49383
|
import { randomBytes as randomBytes4 } from "crypto";
|
|
48707
49384
|
function buildLaunchSummary(cohortId) {
|
|
48708
49385
|
const cohort = loadCohort(cohortId);
|
|
@@ -48746,15 +49423,15 @@ function isoTs2() {
|
|
|
48746
49423
|
return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
48747
49424
|
}
|
|
48748
49425
|
function atomicWriteFile3(path2, data) {
|
|
48749
|
-
|
|
49426
|
+
mkdirSync36(dirname45(path2), { recursive: true });
|
|
48750
49427
|
const tmp = `${path2}.tmp.${process.pid}.${randomBytes4(4).toString("hex")}`;
|
|
48751
|
-
|
|
49428
|
+
writeFileSync41(tmp, data, "utf8");
|
|
48752
49429
|
renameSync8(tmp, path2);
|
|
48753
49430
|
}
|
|
48754
49431
|
function readWal(path2) {
|
|
48755
|
-
if (!
|
|
49432
|
+
if (!existsSync83(path2)) return null;
|
|
48756
49433
|
try {
|
|
48757
|
-
return JSON.parse(
|
|
49434
|
+
return JSON.parse(readFileSync61(path2, "utf8"));
|
|
48758
49435
|
} catch {
|
|
48759
49436
|
return null;
|
|
48760
49437
|
}
|
|
@@ -48764,13 +49441,13 @@ function writeWal(path2, wal) {
|
|
|
48764
49441
|
}
|
|
48765
49442
|
function findWalByRunId(runId) {
|
|
48766
49443
|
const dir = MARKETING_PATHS.runsDir();
|
|
48767
|
-
if (!
|
|
48768
|
-
for (const f of
|
|
49444
|
+
if (!existsSync83(dir)) return null;
|
|
49445
|
+
for (const f of readdirSync21(dir)) {
|
|
48769
49446
|
if (!f.endsWith(".json")) continue;
|
|
48770
49447
|
if (f.startsWith("by-idem")) continue;
|
|
48771
49448
|
const stem = f.replace(/\.json$/, "");
|
|
48772
49449
|
if (stem === runId || f === runId || basename22(f, ".json") === runId) {
|
|
48773
|
-
return
|
|
49450
|
+
return join75(dir, f);
|
|
48774
49451
|
}
|
|
48775
49452
|
}
|
|
48776
49453
|
return null;
|
|
@@ -48810,7 +49487,7 @@ function createLaunchWal(args) {
|
|
|
48810
49487
|
flipped_count: 0,
|
|
48811
49488
|
error: null
|
|
48812
49489
|
};
|
|
48813
|
-
const walPath =
|
|
49490
|
+
const walPath = join75(MARKETING_PATHS.runsDir(), `${id}.json`);
|
|
48814
49491
|
writeWal(walPath, wal);
|
|
48815
49492
|
return { walPath, wal };
|
|
48816
49493
|
}
|
|
@@ -49041,7 +49718,7 @@ var init_launch2 = __esm({
|
|
|
49041
49718
|
});
|
|
49042
49719
|
|
|
49043
49720
|
// src/cli/commands/marketing/learnings.ts
|
|
49044
|
-
import { existsSync as
|
|
49721
|
+
import { existsSync as existsSync84, readFileSync as readFileSync62 } from "fs";
|
|
49045
49722
|
function registerMarketingLearnings(parent) {
|
|
49046
49723
|
const cmd = parent.command("learnings").description("Performance Monitor learnings ledger (per-day .md + index).");
|
|
49047
49724
|
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) => {
|
|
@@ -49184,8 +49861,8 @@ async function resolveBody(body, bodyFile) {
|
|
|
49184
49861
|
if (body) return body;
|
|
49185
49862
|
if (bodyFile === "-") return readStdin3();
|
|
49186
49863
|
if (bodyFile) {
|
|
49187
|
-
if (!
|
|
49188
|
-
return
|
|
49864
|
+
if (!existsSync84(bodyFile)) throw new Error(`Body file not found: ${bodyFile}`);
|
|
49865
|
+
return readFileSync62(bodyFile, "utf8");
|
|
49189
49866
|
}
|
|
49190
49867
|
return null;
|
|
49191
49868
|
}
|
|
@@ -49215,29 +49892,29 @@ var init_learnings2 = __esm({
|
|
|
49215
49892
|
|
|
49216
49893
|
// src/lib/marketing/rem-sleep.ts
|
|
49217
49894
|
import {
|
|
49218
|
-
existsSync as
|
|
49219
|
-
mkdirSync as
|
|
49220
|
-
readFileSync as
|
|
49221
|
-
writeFileSync as
|
|
49222
|
-
readdirSync as
|
|
49895
|
+
existsSync as existsSync85,
|
|
49896
|
+
mkdirSync as mkdirSync37,
|
|
49897
|
+
readFileSync as readFileSync63,
|
|
49898
|
+
writeFileSync as writeFileSync42,
|
|
49899
|
+
readdirSync as readdirSync22,
|
|
49223
49900
|
statSync as statSync16,
|
|
49224
49901
|
unlinkSync as unlinkSync3,
|
|
49225
49902
|
renameSync as renameSync9
|
|
49226
49903
|
} from "fs";
|
|
49227
|
-
import { dirname as
|
|
49904
|
+
import { dirname as dirname46, join as join76 } from "path";
|
|
49228
49905
|
import { randomBytes as randomBytes5 } from "crypto";
|
|
49229
49906
|
function atomicWriteFile4(path2, data) {
|
|
49230
|
-
|
|
49907
|
+
mkdirSync37(dirname46(path2), { recursive: true });
|
|
49231
49908
|
const tmp = `${path2}.tmp.${process.pid}.${randomBytes5(4).toString("hex")}`;
|
|
49232
|
-
|
|
49909
|
+
writeFileSync42(tmp, data, "utf8");
|
|
49233
49910
|
renameSync9(tmp, path2);
|
|
49234
49911
|
}
|
|
49235
49912
|
function pruneRuns(opts = {}) {
|
|
49236
49913
|
const keepLast = opts.keepLast ?? 100;
|
|
49237
49914
|
const dir = MARKETING_PATHS.runsDir();
|
|
49238
|
-
if (!
|
|
49239
|
-
const files =
|
|
49240
|
-
const p =
|
|
49915
|
+
if (!existsSync85(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
|
|
49916
|
+
const files = readdirSync22(dir).filter((f) => f.endsWith(".json")).map((f) => {
|
|
49917
|
+
const p = join76(dir, f);
|
|
49241
49918
|
try {
|
|
49242
49919
|
return { f, p, mtimeMs: statSync16(p).mtimeMs };
|
|
49243
49920
|
} catch {
|
|
@@ -49271,13 +49948,13 @@ function compactInsights(opts = {}) {
|
|
|
49271
49948
|
const weeklyAfterDays = opts.weeklyAfterDays ?? 14;
|
|
49272
49949
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
49273
49950
|
const dir = MARKETING_PATHS.insightsDir();
|
|
49274
|
-
if (!
|
|
49951
|
+
if (!existsSync85(dir)) return { scanned: 0, kept: 0, deleted: 0, deletedFiles: [] };
|
|
49275
49952
|
const files = [];
|
|
49276
|
-
for (const f of
|
|
49953
|
+
for (const f of readdirSync22(dir)) {
|
|
49277
49954
|
if (!f.endsWith(".json") || f.startsWith("_")) continue;
|
|
49278
49955
|
const m = f.match(SNAP_RE);
|
|
49279
49956
|
if (!m) continue;
|
|
49280
|
-
const p =
|
|
49957
|
+
const p = join76(dir, f);
|
|
49281
49958
|
try {
|
|
49282
49959
|
const stat = statSync16(p);
|
|
49283
49960
|
files.push({ f, p, mtimeMs: stat.mtimeMs, entityId: m[1], bucket: m[2] });
|
|
@@ -49343,18 +50020,18 @@ function mergeDailyLearnings(opts = {}) {
|
|
|
49343
50020
|
const retainDays = opts.retainDays ?? 7;
|
|
49344
50021
|
const now = opts.now ?? /* @__PURE__ */ new Date();
|
|
49345
50022
|
const dir = MARKETING_PATHS.learningsDir();
|
|
49346
|
-
if (!
|
|
50023
|
+
if (!existsSync85(dir)) {
|
|
49347
50024
|
return { scanned: 0, merged: 0, archivePath: null, droppedRejected: 0, mergedFiles: [] };
|
|
49348
50025
|
}
|
|
49349
50026
|
const dayMs = 24 * 60 * 60 * 1e3;
|
|
49350
50027
|
const cutoff = now.getTime() - retainDays * dayMs;
|
|
49351
50028
|
const candidates = [];
|
|
49352
|
-
for (const f of
|
|
50029
|
+
for (const f of readdirSync22(dir)) {
|
|
49353
50030
|
const m = f.match(/^(\d{4}-\d{2}-\d{2})\.md$/);
|
|
49354
50031
|
if (!m) continue;
|
|
49355
50032
|
const date = m[1];
|
|
49356
50033
|
const dateMs = (/* @__PURE__ */ new Date(`${date}T00:00:00Z`)).getTime();
|
|
49357
|
-
if (dateMs < cutoff) candidates.push({ f, p:
|
|
50034
|
+
if (dateMs < cutoff) candidates.push({ f, p: join76(dir, f), date });
|
|
49358
50035
|
}
|
|
49359
50036
|
if (candidates.length === 0) {
|
|
49360
50037
|
return { scanned: 0, merged: 0, archivePath: null, droppedRejected: 0, mergedFiles: [] };
|
|
@@ -49368,10 +50045,10 @@ function mergeDailyLearnings(opts = {}) {
|
|
|
49368
50045
|
const mergedFiles = [];
|
|
49369
50046
|
let lastArchivePath = null;
|
|
49370
50047
|
for (const [q, list] of byQuarter) {
|
|
49371
|
-
const archivePath =
|
|
50048
|
+
const archivePath = join76(dir, `_archive-${q}.md`);
|
|
49372
50049
|
list.sort((a, b) => a.date.localeCompare(b.date));
|
|
49373
50050
|
for (const c of list) {
|
|
49374
|
-
const existingArchive =
|
|
50051
|
+
const existingArchive = existsSync85(archivePath) ? readFileSync63(archivePath, "utf8") : `# Marketing learnings archive \u2014 ${q}
|
|
49375
50052
|
`;
|
|
49376
50053
|
const dateMarker = `# Marketing learnings \u2014 ${c.date}`;
|
|
49377
50054
|
const alreadyMerged = existingArchive.includes(dateMarker);
|
|
@@ -49380,7 +50057,7 @@ function mergeDailyLearnings(opts = {}) {
|
|
|
49380
50057
|
continue;
|
|
49381
50058
|
}
|
|
49382
50059
|
if (!alreadyMerged) {
|
|
49383
|
-
const body =
|
|
50060
|
+
const body = readFileSync63(c.p, "utf8").trimEnd();
|
|
49384
50061
|
const next2 = existingArchive.trimEnd() + "\n\n" + body + "\n";
|
|
49385
50062
|
atomicWriteFile4(archivePath, next2);
|
|
49386
50063
|
}
|
|
@@ -49423,14 +50100,14 @@ function quarterKey(yyyymmdd) {
|
|
|
49423
50100
|
}
|
|
49424
50101
|
function redactRunsSweep(opts = {}) {
|
|
49425
50102
|
const dir = MARKETING_PATHS.runsDir();
|
|
49426
|
-
if (!
|
|
49427
|
-
const files =
|
|
50103
|
+
if (!existsSync85(dir)) return { scanned: 0, rewritten: 0, rewrittenFiles: [] };
|
|
50104
|
+
const files = readdirSync22(dir).filter((f) => f.endsWith(".json"));
|
|
49428
50105
|
const rewrittenFiles = [];
|
|
49429
50106
|
for (const f of files) {
|
|
49430
|
-
const p =
|
|
50107
|
+
const p = join76(dir, f);
|
|
49431
50108
|
let raw;
|
|
49432
50109
|
try {
|
|
49433
|
-
raw =
|
|
50110
|
+
raw = readFileSync63(p, "utf8");
|
|
49434
50111
|
} catch {
|
|
49435
50112
|
continue;
|
|
49436
50113
|
}
|
|
@@ -49452,7 +50129,7 @@ function redactRunsSweep(opts = {}) {
|
|
|
49452
50129
|
function runRemSleep(opts = {}) {
|
|
49453
50130
|
const ranAt = (opts.now ?? /* @__PURE__ */ new Date()).toISOString();
|
|
49454
50131
|
const root = marketingRootIfExists();
|
|
49455
|
-
if (!root || !
|
|
50132
|
+
if (!root || !existsSync85(root)) {
|
|
49456
50133
|
return {
|
|
49457
50134
|
ranAt,
|
|
49458
50135
|
marketingPresent: false,
|
|
@@ -49474,7 +50151,7 @@ function runRemSleep(opts = {}) {
|
|
|
49474
50151
|
now: opts.now
|
|
49475
50152
|
});
|
|
49476
50153
|
const redaction = redactRunsSweep({ dryRun: opts.dryRun });
|
|
49477
|
-
void
|
|
50154
|
+
void mkdirSync37;
|
|
49478
50155
|
return { ranAt, marketingPresent: true, runs, insights, learnings, redaction };
|
|
49479
50156
|
}
|
|
49480
50157
|
var SNAP_RE;
|
|
@@ -49571,9 +50248,9 @@ var init_git_guard = __esm({
|
|
|
49571
50248
|
});
|
|
49572
50249
|
|
|
49573
50250
|
// src/cli/commands/marketing/hooks.ts
|
|
49574
|
-
import { existsSync as
|
|
50251
|
+
import { existsSync as existsSync86, readFileSync as readFileSync64, writeFileSync as writeFileSync43, chmodSync as chmodSync3, mkdirSync as mkdirSync38, statSync as statSync17 } from "fs";
|
|
49575
50252
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
49576
|
-
import { join as
|
|
50253
|
+
import { join as join77 } from "path";
|
|
49577
50254
|
function findGitDir(cwd = process.cwd()) {
|
|
49578
50255
|
try {
|
|
49579
50256
|
const out = execFileSync6("git", ["rev-parse", "--git-dir"], {
|
|
@@ -49582,7 +50259,7 @@ function findGitDir(cwd = process.cwd()) {
|
|
|
49582
50259
|
stdio: ["ignore", "pipe", "ignore"]
|
|
49583
50260
|
}).trim();
|
|
49584
50261
|
if (!out) return null;
|
|
49585
|
-
return out.startsWith("/") ? out :
|
|
50262
|
+
return out.startsWith("/") ? out : join77(cwd, out);
|
|
49586
50263
|
} catch {
|
|
49587
50264
|
return null;
|
|
49588
50265
|
}
|
|
@@ -49613,11 +50290,11 @@ function registerMarketingHooks(parent) {
|
|
|
49613
50290
|
error("Not inside a git repository (or `git` is not on PATH).");
|
|
49614
50291
|
process.exit(1);
|
|
49615
50292
|
}
|
|
49616
|
-
const hooksDir =
|
|
49617
|
-
|
|
49618
|
-
const target =
|
|
49619
|
-
if (
|
|
49620
|
-
const existing =
|
|
50293
|
+
const hooksDir = join77(gitDir, "hooks");
|
|
50294
|
+
mkdirSync38(hooksDir, { recursive: true });
|
|
50295
|
+
const target = join77(hooksDir, "pre-commit");
|
|
50296
|
+
if (existsSync86(target)) {
|
|
50297
|
+
const existing = readFileSync64(target, "utf-8");
|
|
49621
50298
|
if (existing.includes(MANAGED_MARKER)) {
|
|
49622
50299
|
info("pre-commit hook already managed by dreamcontext \u2014 refreshing.");
|
|
49623
50300
|
} else if (!opts.force) {
|
|
@@ -49629,7 +50306,7 @@ function registerMarketingHooks(parent) {
|
|
|
49629
50306
|
warn("Overwriting existing pre-commit hook (--force).");
|
|
49630
50307
|
}
|
|
49631
50308
|
}
|
|
49632
|
-
|
|
50309
|
+
writeFileSync43(target, HOOK_LAUNCHER, "utf-8");
|
|
49633
50310
|
try {
|
|
49634
50311
|
chmodSync3(target, 493);
|
|
49635
50312
|
} catch {
|
|
@@ -49668,26 +50345,26 @@ exec dreamcontext mk hooks check-staged
|
|
|
49668
50345
|
});
|
|
49669
50346
|
|
|
49670
50347
|
// src/lib/marketing/council-personas.ts
|
|
49671
|
-
import { existsSync as
|
|
50348
|
+
import { existsSync as existsSync87, readFileSync as readFileSync65, readdirSync as readdirSync23 } from "fs";
|
|
49672
50349
|
import { fileURLToPath as fileURLToPath9 } from "url";
|
|
49673
|
-
import { join as
|
|
50350
|
+
import { join as join78, dirname as dirname47 } from "path";
|
|
49674
50351
|
function findPersonasDir() {
|
|
49675
50352
|
const candidates = [
|
|
49676
50353
|
// dev: src/lib/marketing/council-personas.ts → ../../../skill-packs/...
|
|
49677
|
-
|
|
50354
|
+
join78(__dirname_local, "..", "..", "..", PERSONA_SUBPATH),
|
|
49678
50355
|
// built: dist/index.js → ./skill-packs/...
|
|
49679
|
-
|
|
50356
|
+
join78(__dirname_local, PERSONA_SUBPATH),
|
|
49680
50357
|
// tsup-bundled (deeper nesting if ever): ../skill-packs/...
|
|
49681
|
-
|
|
49682
|
-
|
|
50358
|
+
join78(__dirname_local, "..", PERSONA_SUBPATH),
|
|
50359
|
+
join78(__dirname_local, "..", "..", PERSONA_SUBPATH)
|
|
49683
50360
|
];
|
|
49684
50361
|
for (const candidate of candidates) {
|
|
49685
|
-
if (
|
|
50362
|
+
if (existsSync87(candidate)) return candidate;
|
|
49686
50363
|
}
|
|
49687
50364
|
return null;
|
|
49688
50365
|
}
|
|
49689
50366
|
function parsePersonaFile(filePath) {
|
|
49690
|
-
const raw =
|
|
50367
|
+
const raw = readFileSync65(filePath, "utf-8");
|
|
49691
50368
|
const parsed = (0, import_gray_matter5.default)(raw);
|
|
49692
50369
|
const data = parsed.data;
|
|
49693
50370
|
const slug = typeof data.slug === "string" ? data.slug.trim() : "";
|
|
@@ -49707,9 +50384,9 @@ function parsePersonaFile(filePath) {
|
|
|
49707
50384
|
}
|
|
49708
50385
|
function loadAllPersonas(personasDir) {
|
|
49709
50386
|
const dir = personasDir ?? findPersonasDir();
|
|
49710
|
-
if (!dir || !
|
|
49711
|
-
const files =
|
|
49712
|
-
return files.map((name) => parsePersonaFile(
|
|
50387
|
+
if (!dir || !existsSync87(dir)) return [];
|
|
50388
|
+
const files = readdirSync23(dir).filter((n) => n.endsWith(".md")).sort();
|
|
50389
|
+
return files.map((name) => parsePersonaFile(join78(dir, name)));
|
|
49713
50390
|
}
|
|
49714
50391
|
function selectPersonas(all, requested) {
|
|
49715
50392
|
if (requested.length === 0) return [...all];
|
|
@@ -49728,23 +50405,23 @@ var init_council_personas = __esm({
|
|
|
49728
50405
|
import_gray_matter5 = __toESM(require_gray_matter(), 1);
|
|
49729
50406
|
__dirname_local = (() => {
|
|
49730
50407
|
try {
|
|
49731
|
-
return
|
|
50408
|
+
return dirname47(fileURLToPath9(import.meta.url));
|
|
49732
50409
|
} catch {
|
|
49733
50410
|
return process.cwd();
|
|
49734
50411
|
}
|
|
49735
50412
|
})();
|
|
49736
50413
|
VALID_MODELS2 = /* @__PURE__ */ new Set(["opus", "sonnet", "haiku"]);
|
|
49737
|
-
PERSONA_SUBPATH =
|
|
50414
|
+
PERSONA_SUBPATH = join78("skill-packs", "meta-marketing", "council-personas");
|
|
49738
50415
|
}
|
|
49739
50416
|
});
|
|
49740
50417
|
|
|
49741
50418
|
// src/cli/commands/marketing/council.ts
|
|
49742
50419
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
49743
|
-
import { existsSync as
|
|
50420
|
+
import { existsSync as existsSync88 } from "fs";
|
|
49744
50421
|
function resolveDreamcontextEntry() {
|
|
49745
50422
|
const node = process.argv[0];
|
|
49746
50423
|
const script = process.argv[1];
|
|
49747
|
-
if (script &&
|
|
50424
|
+
if (script && existsSync88(script)) {
|
|
49748
50425
|
return { node, script };
|
|
49749
50426
|
}
|
|
49750
50427
|
return { node, script: null };
|
|
@@ -49916,8 +50593,8 @@ var init_marketing = __esm({
|
|
|
49916
50593
|
});
|
|
49917
50594
|
|
|
49918
50595
|
// src/cli/commands/memory.ts
|
|
49919
|
-
import { existsSync as
|
|
49920
|
-
import { join as
|
|
50596
|
+
import { existsSync as existsSync89, unlinkSync as unlinkSync4 } from "fs";
|
|
50597
|
+
import { join as join79, dirname as dirname48 } from "path";
|
|
49921
50598
|
function collectVault(value, previous) {
|
|
49922
50599
|
return [...previous, value];
|
|
49923
50600
|
}
|
|
@@ -49929,7 +50606,7 @@ function parseTypes(value) {
|
|
|
49929
50606
|
return filtered.length > 0 ? filtered : void 0;
|
|
49930
50607
|
}
|
|
49931
50608
|
function recallFederated(contextRoot, query, topK, types, opts) {
|
|
49932
|
-
const projectRoot =
|
|
50609
|
+
const projectRoot = dirname48(contextRoot);
|
|
49933
50610
|
const { target: currentTarget } = currentVaultTarget(projectRoot);
|
|
49934
50611
|
const byName = /* @__PURE__ */ new Map();
|
|
49935
50612
|
const add = (t) => {
|
|
@@ -50082,7 +50759,7 @@ function registerMemoryCommand(program2) {
|
|
|
50082
50759
|
const summary = opts.summary ?? (text.length > 200 ? text.slice(0, 197) + "..." : text);
|
|
50083
50760
|
const references = opts.references ? opts.references.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
50084
50761
|
const authors = opts.person ? opts.person.split(",").map((s) => s.trim()).filter(Boolean) : void 0;
|
|
50085
|
-
const changelogPath =
|
|
50762
|
+
const changelogPath = join79(root, "core", "CHANGELOG.json");
|
|
50086
50763
|
const entry = {
|
|
50087
50764
|
date: today(),
|
|
50088
50765
|
type: opts.type ?? "note",
|
|
@@ -50100,8 +50777,8 @@ function registerMemoryCommand(program2) {
|
|
|
50100
50777
|
memory.command("update").argument("<slug>", "Knowledge file slug (without .md)").option("-d, --description <desc>", "New description (replaces existing)").option("-t, --tags <tags>", "New tags (comma-separated, replaces existing)").option("-c, --content <content>", "New body content (replaces existing)").option("--append <text>", "Append text to body (preserves existing content)").option("--pin", "Set pinned: true").option("--unpin", "Set pinned: false").description("Update a knowledge file (frontmatter and/or body)").action(
|
|
50101
50778
|
async (slug, opts) => {
|
|
50102
50779
|
const root = ensureContextRoot();
|
|
50103
|
-
const filePath =
|
|
50104
|
-
if (!
|
|
50780
|
+
const filePath = join79(root, "knowledge", `${slug}.md`);
|
|
50781
|
+
if (!existsSync89(filePath)) {
|
|
50105
50782
|
error(`Knowledge file not found: ${slug}.md`);
|
|
50106
50783
|
return;
|
|
50107
50784
|
}
|
|
@@ -50148,8 +50825,8 @@ ${opts.append}
|
|
|
50148
50825
|
);
|
|
50149
50826
|
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) => {
|
|
50150
50827
|
const root = ensureContextRoot();
|
|
50151
|
-
const filePath =
|
|
50152
|
-
if (!
|
|
50828
|
+
const filePath = join79(root, "knowledge", `${slug}.md`);
|
|
50829
|
+
if (!existsSync89(filePath)) {
|
|
50153
50830
|
error(`Knowledge file not found: ${slug}.md`);
|
|
50154
50831
|
return;
|
|
50155
50832
|
}
|
|
@@ -50257,13 +50934,13 @@ var init_memory = __esm({
|
|
|
50257
50934
|
|
|
50258
50935
|
// src/cli/commands/upgrade.ts
|
|
50259
50936
|
import { execFileSync as execFileSync8 } from "child_process";
|
|
50260
|
-
import { dirname as
|
|
50937
|
+
import { dirname as dirname49 } from "path";
|
|
50261
50938
|
function defaultInstaller(args) {
|
|
50262
50939
|
execFileSync8("npm", args, { stdio: "inherit" });
|
|
50263
50940
|
}
|
|
50264
50941
|
function projectRootForCache() {
|
|
50265
50942
|
const contextDir = resolveContextRoot();
|
|
50266
|
-
return contextDir ?
|
|
50943
|
+
return contextDir ? dirname49(contextDir) : process.cwd();
|
|
50267
50944
|
}
|
|
50268
50945
|
function defaultLiveLatest() {
|
|
50269
50946
|
let latest = null;
|
|
@@ -50586,9 +51263,9 @@ var init_vaults3 = __esm({
|
|
|
50586
51263
|
});
|
|
50587
51264
|
|
|
50588
51265
|
// src/cli/commands/connections.ts
|
|
50589
|
-
import { dirname as
|
|
51266
|
+
import { dirname as dirname50 } from "path";
|
|
50590
51267
|
function currentVaultName2(contextRoot) {
|
|
50591
|
-
return currentVaultTarget(
|
|
51268
|
+
return currentVaultTarget(dirname50(contextRoot)).name;
|
|
50592
51269
|
}
|
|
50593
51270
|
function registerConnectionsCommand(program2) {
|
|
50594
51271
|
program2.command("connect <vault>").description("Connect this vault to a peer for federation (out|in|both)").option("-d, --direction <direction>", "Connection direction: out | in | both", "both").option("--topics <list>", "Comma-separated topic filter (default: all topics)").action((vault, opts) => {
|
|
@@ -50670,17 +51347,17 @@ var init_connections3 = __esm({
|
|
|
50670
51347
|
});
|
|
50671
51348
|
|
|
50672
51349
|
// src/lib/federation-ingest.ts
|
|
50673
|
-
import { existsSync as
|
|
50674
|
-
import { join as
|
|
51350
|
+
import { existsSync as existsSync90, mkdirSync as mkdirSync39 } from "fs";
|
|
51351
|
+
import { join as join80 } from "path";
|
|
50675
51352
|
function ingestEntry(contextRoot, entry) {
|
|
50676
|
-
const knowledgeDir =
|
|
50677
|
-
|
|
51353
|
+
const knowledgeDir = join80(contextRoot, "knowledge");
|
|
51354
|
+
mkdirSync39(knowledgeDir, { recursive: true });
|
|
50678
51355
|
const baseSlug = slugFromTitle(entry.title);
|
|
50679
|
-
const canonicalPath =
|
|
50680
|
-
const collided =
|
|
51356
|
+
const canonicalPath = join80(knowledgeDir, `${baseSlug}.md`);
|
|
51357
|
+
const collided = existsSync90(canonicalPath);
|
|
50681
51358
|
const slug = collided ? `${baseSlug}--from-${sanitizeVault(entry.origin.vault)}` : baseSlug;
|
|
50682
|
-
const targetPath =
|
|
50683
|
-
if (!
|
|
51359
|
+
const targetPath = join80(knowledgeDir, `${slug}.md`);
|
|
51360
|
+
if (!existsSync90(targetPath)) {
|
|
50684
51361
|
writeFrontmatter(
|
|
50685
51362
|
targetPath,
|
|
50686
51363
|
{
|
|
@@ -50756,9 +51433,9 @@ var init_federation_ingest = __esm({
|
|
|
50756
51433
|
});
|
|
50757
51434
|
|
|
50758
51435
|
// src/cli/commands/federation.ts
|
|
50759
|
-
import { dirname as
|
|
51436
|
+
import { dirname as dirname51 } from "path";
|
|
50760
51437
|
function currentVaultName3(contextRoot) {
|
|
50761
|
-
return currentVaultTarget(
|
|
51438
|
+
return currentVaultTarget(dirname51(contextRoot)).name;
|
|
50762
51439
|
}
|
|
50763
51440
|
function outboundConnections(contextRoot) {
|
|
50764
51441
|
return listConnections(contextRoot).filter(
|
|
@@ -50971,12 +51648,12 @@ var init_people = __esm({
|
|
|
50971
51648
|
});
|
|
50972
51649
|
|
|
50973
51650
|
// src/cli/commands/config.ts
|
|
50974
|
-
import { dirname as
|
|
50975
|
-
import { existsSync as
|
|
50976
|
-
import { join as
|
|
51651
|
+
import { dirname as dirname52 } from "path";
|
|
51652
|
+
import { existsSync as existsSync91, readFileSync as readFileSync67, writeFileSync as writeFileSync45 } from "fs";
|
|
51653
|
+
import { join as join81 } from "path";
|
|
50977
51654
|
function resolveProjectRoot() {
|
|
50978
51655
|
const contextRoot = resolveContextRoot();
|
|
50979
|
-
return contextRoot ?
|
|
51656
|
+
return contextRoot ? dirname52(contextRoot) : null;
|
|
50980
51657
|
}
|
|
50981
51658
|
function requireProjectRoot() {
|
|
50982
51659
|
const projectRoot = resolveProjectRoot();
|
|
@@ -51135,7 +51812,7 @@ function registerConfigCommand(program2) {
|
|
|
51135
51812
|
const liveToken = resolveClickUpToken(projectRoot);
|
|
51136
51813
|
let connected = false;
|
|
51137
51814
|
if (liveToken) {
|
|
51138
|
-
const contextRoot =
|
|
51815
|
+
const contextRoot = join81(projectRoot, "_dream_context");
|
|
51139
51816
|
const probe = createClickUpBackend(contextRoot, readSetupConfig(projectRoot));
|
|
51140
51817
|
const test = await probe.testConnection();
|
|
51141
51818
|
if (test.ok) {
|
|
@@ -51178,7 +51855,7 @@ function registerConfigCommand(program2) {
|
|
|
51178
51855
|
cfgNow = readSetupConfig(projectRoot);
|
|
51179
51856
|
}
|
|
51180
51857
|
if (connected && cfgNow?.clickup?.listId) {
|
|
51181
|
-
const contextRoot =
|
|
51858
|
+
const contextRoot = join81(projectRoot, "_dream_context");
|
|
51182
51859
|
const backend2 = createClickUpBackend(contextRoot, cfgNow);
|
|
51183
51860
|
if (await esm_default4({ message: "Create the recommended custom fields on the list (urgency, summary, RICE, \u2026)?", default: true })) {
|
|
51184
51861
|
const result = await backend2.provisionRemote();
|
|
@@ -51233,13 +51910,13 @@ function registerConfigCommand(program2) {
|
|
|
51233
51910
|
const contextRoot = resolveContextRoot();
|
|
51234
51911
|
let userMdSynced = false;
|
|
51235
51912
|
if (contextRoot) {
|
|
51236
|
-
const userMdPath =
|
|
51237
|
-
if (
|
|
51913
|
+
const userMdPath = join81(contextRoot, "core", "1.user.md");
|
|
51914
|
+
if (existsSync91(userMdPath)) {
|
|
51238
51915
|
try {
|
|
51239
|
-
const before =
|
|
51916
|
+
const before = readFileSync67(userMdPath, "utf-8");
|
|
51240
51917
|
const after = ensurePeopleSection(before, roster);
|
|
51241
51918
|
if (after !== before) {
|
|
51242
|
-
|
|
51919
|
+
writeFileSync45(userMdPath, after, "utf-8");
|
|
51243
51920
|
userMdSynced = true;
|
|
51244
51921
|
}
|
|
51245
51922
|
} catch (err) {
|
|
@@ -51283,7 +51960,7 @@ function registerConfigCommand(program2) {
|
|
|
51283
51960
|
config.command("clickup-list <teamId> <spaceId> <listId>").description("Set the ClickUp team/space/list the tasks sync against").option("--migrate", "When changing lists: reset the sync ledger so the next sync recreates every local task in the NEW list").option("--keep", "When changing lists: keep existing task mappings (tasks were moved in ClickUp itself)").action(async (teamId, spaceId, listId, opts) => {
|
|
51284
51961
|
const projectRoot = requireProjectRoot();
|
|
51285
51962
|
if (!projectRoot) return;
|
|
51286
|
-
const contextRoot =
|
|
51963
|
+
const contextRoot = join81(projectRoot, "_dream_context");
|
|
51287
51964
|
const existing = readSetupConfig(projectRoot)?.clickup ?? {};
|
|
51288
51965
|
const ledger = new SyncLedger(contextRoot);
|
|
51289
51966
|
const changingList = !!existing.listId && existing.listId !== listId && ledger.readMap().length > 0;
|
|
@@ -51324,8 +52001,8 @@ function registerConfigCommand(program2) {
|
|
|
51324
52001
|
if (!value) {
|
|
51325
52002
|
if (!process.stdin.isTTY) {
|
|
51326
52003
|
try {
|
|
51327
|
-
const { readFileSync:
|
|
51328
|
-
value =
|
|
52004
|
+
const { readFileSync: readFileSync68 } = await import("fs");
|
|
52005
|
+
value = readFileSync68(0, "utf-8").trim();
|
|
51329
52006
|
} catch {
|
|
51330
52007
|
value = "";
|
|
51331
52008
|
}
|
|
@@ -51684,12 +52361,12 @@ var init_feedback2 = __esm({
|
|
|
51684
52361
|
});
|
|
51685
52362
|
|
|
51686
52363
|
// src/cli/commands/migrations.ts
|
|
51687
|
-
import { dirname as
|
|
52364
|
+
import { dirname as dirname53 } from "path";
|
|
51688
52365
|
function registerMigrationsCommand(program2) {
|
|
51689
52366
|
const migrations = program2.command("migrations").description("Inspect and record brain structure migrations");
|
|
51690
52367
|
migrations.command("pending").description("Print pending agent task instructions for any unfinished migrations").action(() => {
|
|
51691
52368
|
const root = ensureContextRoot();
|
|
51692
|
-
const projectRoot =
|
|
52369
|
+
const projectRoot = dirname53(root);
|
|
51693
52370
|
const config = readSetupConfig(projectRoot);
|
|
51694
52371
|
const fromVersion = config?.setupVersion ?? "0.0.0";
|
|
51695
52372
|
const toVersion = dreamcontextVersion();
|