project-athena 0.2.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (152) hide show
  1. package/CHANGELOG.md +63 -0
  2. package/README.md +61 -12
  3. package/dist/activity-BKW7G4I5.js +77 -0
  4. package/dist/agents-DFSNEOP5.js +69 -0
  5. package/dist/ai-ASL4FFQ7.js +96 -0
  6. package/dist/analyze-ZY3MXBOI.js +50 -0
  7. package/dist/chunk-2DY4PUR4.js +465 -0
  8. package/dist/chunk-2R6PXY6Z.js +33 -0
  9. package/dist/chunk-3IS2X2Z7.js +89 -0
  10. package/dist/chunk-3XSDI5WF.js +179 -0
  11. package/dist/chunk-65TSRDQ3.js +124 -0
  12. package/dist/chunk-673EPYYH.js +105 -0
  13. package/dist/chunk-7DZK6WSQ.js +65 -0
  14. package/dist/chunk-AD4OZCU2.js +34 -0
  15. package/dist/chunk-DZDI2HRT.js +169 -0
  16. package/dist/chunk-ELKFRTZT.js +221 -0
  17. package/dist/chunk-EUPETUWA.js +14 -0
  18. package/dist/chunk-FQEGEVLY.js +38 -0
  19. package/dist/chunk-FVCDMQUQ.js +343 -0
  20. package/dist/chunk-GGXPG6OE.js +904 -0
  21. package/dist/chunk-GHFRQAYT.js +112 -0
  22. package/dist/chunk-GR4DL2VM.js +47 -0
  23. package/dist/chunk-INT3IGMQ.js +111 -0
  24. package/dist/chunk-IQQBAWSM.js +90 -0
  25. package/dist/chunk-JCGDR4UV.js +182 -0
  26. package/dist/chunk-KBO7XRBW.js +26 -0
  27. package/dist/chunk-KHMBNT66.js +399 -0
  28. package/dist/chunk-LEMPCNAY.js +209 -0
  29. package/dist/chunk-MPG3IEGB.js +2691 -0
  30. package/dist/chunk-OLPSEQS5.js +264 -0
  31. package/dist/chunk-PVCIGUIT.js +64 -0
  32. package/dist/chunk-QCC4VJUH.js +217 -0
  33. package/dist/chunk-QLW657NT.js +95 -0
  34. package/dist/chunk-RVTNSNGK.js +182 -0
  35. package/dist/chunk-RXNRMIZP.js +390 -0
  36. package/dist/chunk-SHKXELUX.js +295 -0
  37. package/dist/chunk-SJ4DQFIJ.js +379 -0
  38. package/dist/chunk-SVTEJYMS.js +227 -0
  39. package/dist/chunk-TDNZ2RYA.js +702 -0
  40. package/dist/chunk-UAZLPNVC.js +108 -0
  41. package/dist/chunk-VSYBC3VY.js +28 -0
  42. package/dist/chunk-WVQC2EGO.js +166 -0
  43. package/dist/chunk-XDCKZ5TV.js +436 -0
  44. package/dist/chunk-XFN7UZCS.js +35 -0
  45. package/dist/chunk-XW3MLHI2.js +32 -0
  46. package/dist/chunk-YRIS7ZS6.js +919 -0
  47. package/dist/chunk-Z6QWMJLK.js +124 -0
  48. package/dist/chunk-ZB7LC6FP.js +221 -0
  49. package/dist/clean-MDBYH62P.js +23 -0
  50. package/dist/cli.js +18 -10716
  51. package/dist/context-PLPCAPCO.js +161 -0
  52. package/dist/doctor-BX677KRE.js +69 -0
  53. package/dist/event-TNT6CQZR.js +101 -0
  54. package/dist/git-hook-YZNZGAAP.js +252 -0
  55. package/dist/init-WQCAOJ2R.js +38 -0
  56. package/dist/mcp-U7EPH43L.js +393 -0
  57. package/dist/memory-VSVNLEJC.js +393 -0
  58. package/dist/open-UJZRYF4E.js +1450 -0
  59. package/dist/program-CWJNGCTZ.js +165 -0
  60. package/dist/review-OOKXSYMP.js +117 -0
  61. package/dist/rules-4FXJUCXB.js +83 -0
  62. package/dist/security-LME3XFL3.js +177 -0
  63. package/dist/staged-check-X24C3YRD.js +502 -0
  64. package/dist/status-RR57ZNGI.js +81 -0
  65. package/dist/sync-KFJANRXF.js +218 -0
  66. package/dist/watch-CY7QHIYN.js +123 -0
  67. package/dist/web/assets/{Editor-DAXvniWB.js → Editor-Bnilgch0.js} +1 -1
  68. package/dist/web/assets/{abnfDiagram-O67JEVCF-Az7EW1BC.js → abnfDiagram-O67JEVCF-DW9LWr8f.js} +1 -1
  69. package/dist/web/assets/architecture-7GRP2DOG-BWDZV2yn.js +1 -0
  70. package/dist/web/assets/{architectureDiagram-NJMV4G6O-BxeXqSTn.js → architectureDiagram-NJMV4G6O-0eKeQRhj.js} +1 -1
  71. package/dist/web/assets/{blockDiagram-BEXU5L5S-aeKZl9lJ.js → blockDiagram-BEXU5L5S-D5i3-ogI.js} +1 -1
  72. package/dist/web/assets/{c4Diagram-YGBWAQC7-CgmntYsG.js → c4Diagram-YGBWAQC7-BAWQZrEu.js} +1 -1
  73. package/dist/web/assets/channel-Bkh05NKd.js +1 -0
  74. package/dist/web/assets/{chunk-3FUC2YCW-BpmRD2yo.js → chunk-3FUC2YCW-fKRGOZF3.js} +1 -1
  75. package/dist/web/assets/{chunk-5DYCD2WN-CRIFDwod.js → chunk-5DYCD2WN-C5jOlx42.js} +1 -1
  76. package/dist/web/assets/{chunk-742MDFTN-hRW9VeNV.js → chunk-742MDFTN-urY4RP_A.js} +1 -1
  77. package/dist/web/assets/{chunk-7INBJB4K-C6VEpT0Y.js → chunk-7INBJB4K-nk48sKqZ.js} +1 -1
  78. package/dist/web/assets/{chunk-7M6MHVWA-Dnajov2w.js → chunk-7M6MHVWA-BfBD9X0F.js} +1 -1
  79. package/dist/web/assets/{chunk-7PRAP22T-DSAc0_CZ.js → chunk-7PRAP22T-jYf59QlI.js} +1 -1
  80. package/dist/web/assets/{chunk-GTNCS2PH-CefpYUjb.js → chunk-GTNCS2PH-BOCxryKf.js} +1 -1
  81. package/dist/web/assets/{chunk-GWA4HPMP-MLNflMmF.js → chunk-GWA4HPMP-CFpaW0ru.js} +1 -1
  82. package/dist/web/assets/{chunk-MBY4JIJT-D3GmmEiU.js → chunk-MBY4JIJT-BIB8HctN.js} +1 -1
  83. package/dist/web/assets/{chunk-NETBCI7D-DzTj6xVk.js → chunk-NETBCI7D-CpUUK6rh.js} +1 -1
  84. package/dist/web/assets/{chunk-O7XYJQB3-D1d0hCko.js → chunk-O7XYJQB3-BNx_V4Oi.js} +1 -1
  85. package/dist/web/assets/{chunk-UA2S7LBM-C9hIFeWR.js → chunk-UA2S7LBM-D3tMiIOY.js} +1 -1
  86. package/dist/web/assets/{chunk-WEXAMYUT-BFGtcjsi.js → chunk-WEXAMYUT-CC-3C32l.js} +1 -1
  87. package/dist/web/assets/{chunk-Z7XXMR3K-BRZ8_wtE.js → chunk-Z7XXMR3K-BzhxKQUc.js} +1 -1
  88. package/dist/web/assets/{chunk-ZIGJFQKS-CTKOioal.js → chunk-ZIGJFQKS-D4tBHzxg.js} +1 -1
  89. package/dist/web/assets/{classDiagram-v2-NBCMYWYE-DJGKtWJv.js → classDiagram-v2-NBCMYWYE-BbtyanXR.js} +1 -1
  90. package/dist/web/assets/{cynefin-OW5HDTMX-hNq1kGmA.js → cynefin-OW5HDTMX-BIArb8W1.js} +1 -1
  91. package/dist/web/assets/{cynefinDiagram-VND7K2PF-sODQM_ZZ.js → cynefinDiagram-VND7K2PF-BrAcfkXL.js} +1 -1
  92. package/dist/web/assets/{dagre-6A5THRUB-DEzTThIf.js → dagre-6A5THRUB-BcHXRl4s.js} +1 -1
  93. package/dist/web/assets/{diagram-22UHCM2B-s_eellsa.js → diagram-22UHCM2B-Dx9tSCdE.js} +1 -1
  94. package/dist/web/assets/{diagram-3UASUU5V-B2onY_Xw.js → diagram-3UASUU5V-CLLDP9yH.js} +1 -1
  95. package/dist/web/assets/{diagram-ATOU4E4O-B8V6s13s.js → diagram-ATOU4E4O-B46H9iPt.js} +1 -1
  96. package/dist/web/assets/{diagram-CDSNMT55-CJxiE6mf.js → diagram-CDSNMT55-CYtvB6aG.js} +1 -1
  97. package/dist/web/assets/{diagram-MLGK6HIB-m5OHPLAp.js → diagram-MLGK6HIB-Dar7ktoX.js} +1 -1
  98. package/dist/web/assets/{diagram-MPIPVDR6-Buvvrk_A.js → diagram-MPIPVDR6-C-DljnYN.js} +1 -1
  99. package/dist/web/assets/{ebnfDiagram-ZINNZB2B-CpL7Wt3R.js → ebnfDiagram-ZINNZB2B-Dv_3jWnh.js} +1 -1
  100. package/dist/web/assets/{elk-276RUBZZ-CwYhbsXa.js → elk-276RUBZZ-DnHciE9k.js} +1 -1
  101. package/dist/web/assets/{erDiagram-OPXOYQCR-DNikci2r.js → erDiagram-OPXOYQCR-Bn46KrHz.js} +1 -1
  102. package/dist/web/assets/eventmodeling-NTZA5JFV-DYwoptMd.js +1 -0
  103. package/dist/web/assets/flowDiagram-KWPJA3E3-y4rS0gIB.js +1 -0
  104. package/dist/web/assets/{ganttDiagram-FUAMR5RP-d-ynDlvJ.js → ganttDiagram-FUAMR5RP-DOjjJtqz.js} +1 -1
  105. package/dist/web/assets/{gitGraph-4MIJSDKK-DwIeBI91.js → gitGraph-4MIJSDKK-BIoMXJRQ.js} +1 -1
  106. package/dist/web/assets/{gitGraphDiagram-X574FWY7-04RZccu6.js → gitGraphDiagram-X574FWY7-BsJ01R0v.js} +1 -1
  107. package/dist/web/assets/{index-C3-8uYXr.js → index-Cen0jOXj.js} +5 -4
  108. package/dist/web/assets/{index-DKE3ojTe.css → index-WwRY6n68.css} +1 -1
  109. package/dist/web/assets/{info-A6RAGUB7-xf4Nzgv-.js → info-A6RAGUB7-BmlXzRWj.js} +1 -1
  110. package/dist/web/assets/{infoDiagram-VRGFBTTK-BYjw0eiK.js → infoDiagram-VRGFBTTK-CYPJPmBP.js} +1 -1
  111. package/dist/web/assets/{ishikawaDiagram-OU5B5YK6-Bx9s4nPM.js → ishikawaDiagram-OU5B5YK6-YN96geky.js} +1 -1
  112. package/dist/web/assets/{journeyDiagram-ZHPQQLJL-DrdHs7B-.js → journeyDiagram-ZHPQQLJL-20juojKY.js} +1 -1
  113. package/dist/web/assets/{kanban-definition-PNTS6WVX-CVd8v2Te.js → kanban-definition-PNTS6WVX-BhCKIEbP.js} +1 -1
  114. package/dist/web/assets/{line-V_WrJ-6y.js → line-BERsMFG6.js} +1 -1
  115. package/dist/web/assets/{mermaid-parser.core-B-ilyEpO.js → mermaid-parser.core-Bis_wTB-.js} +3 -3
  116. package/dist/web/assets/{mermaid.core-Bnyaa0nF.js → mermaid.core-DMsM3ZX7.js} +4 -4
  117. package/dist/web/assets/{mindmap-definition-NLK3R4M7-B3AbvHPR.js → mindmap-definition-NLK3R4M7-BkcGdOfv.js} +1 -1
  118. package/dist/web/assets/{packet-AYTQ26CC-CBAIUXIc.js → packet-AYTQ26CC-Bh30-JJX.js} +1 -1
  119. package/dist/web/assets/{pegDiagram-GJSIUBJH-DIdeELUM.js → pegDiagram-GJSIUBJH-DxnIo9RF.js} +1 -1
  120. package/dist/web/assets/{pie-WAS4IAKB-a1r3tzPR.js → pie-WAS4IAKB-ChaTr-GD.js} +1 -1
  121. package/dist/web/assets/{pieDiagram-5QR66LMP-pQBEio0x.js → pieDiagram-5QR66LMP-CzAp78FM.js} +1 -1
  122. package/dist/web/assets/{quadrantDiagram-O4NWA36T-CkJK5Y03.js → quadrantDiagram-O4NWA36T-BDSE-cfY.js} +1 -1
  123. package/dist/web/assets/{radar-RG4KPBEZ-BZfLYjx5.js → radar-RG4KPBEZ-DgJ-o_dq.js} +1 -1
  124. package/dist/web/assets/{railroad-74A4TZTK-CuIW1ZAU.js → railroad-74A4TZTK-C8MmcBKz.js} +1 -1
  125. package/dist/web/assets/railroad-abnf-HS5TGJTU-CTLXjcdP.js +1 -0
  126. package/dist/web/assets/railroad-ebnf-LZEXJU2U-ggWsTTL0.js +1 -0
  127. package/dist/web/assets/railroad-peg-WCYAUIDC-D1mCX705.js +1 -0
  128. package/dist/web/assets/{railroadDiagram-XR7U4H2S-_BpGE8aJ.js → railroadDiagram-XR7U4H2S-DfbcWRNh.js} +1 -1
  129. package/dist/web/assets/{requirementDiagram-PLB6GJNP-CnzF90GS.js → requirementDiagram-PLB6GJNP-DM3nksxs.js} +1 -1
  130. package/dist/web/assets/{sankeyDiagram-IPEJSGJF-DYeisDj_.js → sankeyDiagram-IPEJSGJF-DthUpiiC.js} +1 -1
  131. package/dist/web/assets/{sequenceDiagram-PO4LG4MO-ll9cBvca.js → sequenceDiagram-PO4LG4MO-DLA3nuvA.js} +1 -1
  132. package/dist/web/assets/{stateDiagram-v2-GCMORJYK-CdKcOIKQ.js → stateDiagram-v2-GCMORJYK-B0X6ihBW.js} +1 -1
  133. package/dist/web/assets/{swimlanes-2SLR337P-y6piTWEW.js → swimlanes-2SLR337P-B4qWe6vE.js} +1 -1
  134. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-ClIk3e7S.js +8 -0
  135. package/dist/web/assets/{timeline-definition-EJHVYXUP-DuC_4xK0.js → timeline-definition-EJHVYXUP-F-cDzYrj.js} +1 -1
  136. package/dist/web/assets/{treeView-Q6P3EWNA-gCQFmND0.js → treeView-Q6P3EWNA-BaI30nLZ.js} +1 -1
  137. package/dist/web/assets/{treemap-WGGIJYW6-BQ2010OY.js → treemap-WGGIJYW6-D2jGGoMl.js} +1 -1
  138. package/dist/web/assets/{usecaseDiagram-POWQR4AR-CCTqzHz6.js → usecaseDiagram-POWQR4AR-B9qoAQCy.js} +1 -1
  139. package/dist/web/assets/{vennDiagram-UO4OBE2U-0_O7guNq.js → vennDiagram-UO4OBE2U-DGVNOaKO.js} +1 -1
  140. package/dist/web/assets/{wardley-WFR3VGLG-SsX7uMDs.js → wardley-WFR3VGLG-DbKqhNAh.js} +1 -1
  141. package/dist/web/assets/{wardleyDiagram-VNRHLVJA-DlqH6Hox.js → wardleyDiagram-VNRHLVJA-BgZ1gprw.js} +1 -1
  142. package/dist/web/assets/{xychartDiagram-PMCCYNJV-nr4UYDtd.js → xychartDiagram-PMCCYNJV-D73RYid1.js} +1 -1
  143. package/dist/web/index.html +2 -2
  144. package/package.json +4 -2
  145. package/dist/web/assets/architecture-7GRP2DOG-blXBarB2.js +0 -1
  146. package/dist/web/assets/channel-f4QzewnN.js +0 -1
  147. package/dist/web/assets/eventmodeling-NTZA5JFV-CA_ZFPZ2.js +0 -1
  148. package/dist/web/assets/flowDiagram-KWPJA3E3-DObsBuWT.js +0 -1
  149. package/dist/web/assets/railroad-abnf-HS5TGJTU-6B4Ffbxn.js +0 -1
  150. package/dist/web/assets/railroad-ebnf-LZEXJU2U-BGL9lIQc.js +0 -1
  151. package/dist/web/assets/railroad-peg-WCYAUIDC-DcqxTem7.js +0 -1
  152. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-DFS8a3jO.js +0 -8
@@ -0,0 +1,179 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ committedAiWarning
4
+ } from "./chunk-RXNRMIZP.js";
5
+ import {
6
+ whichExecutable
7
+ } from "./chunk-VSYBC3VY.js";
8
+ import {
9
+ readRecentEvents
10
+ } from "./chunk-65TSRDQ3.js";
11
+ import {
12
+ listRules,
13
+ parseRules
14
+ } from "./chunk-3IS2X2Z7.js";
15
+ import {
16
+ findProjectRoot
17
+ } from "./chunk-KBO7XRBW.js";
18
+ import {
19
+ ATHENA_VERSION
20
+ } from "./chunk-2R6PXY6Z.js";
21
+ import {
22
+ gitAvailable,
23
+ isGitRepo
24
+ } from "./chunk-OLPSEQS5.js";
25
+ import {
26
+ ADAPTERS
27
+ } from "./chunk-YRIS7ZS6.js";
28
+ import {
29
+ hookCommand
30
+ } from "./chunk-GHFRQAYT.js";
31
+ import {
32
+ parseBlocks
33
+ } from "./chunk-673EPYYH.js";
34
+ import {
35
+ KNOWLEDGE_DOCS
36
+ } from "./chunk-FQEGEVLY.js";
37
+ import {
38
+ athenaDir,
39
+ loadConfig,
40
+ readState
41
+ } from "./chunk-2DY4PUR4.js";
42
+ import {
43
+ readTextIfExists
44
+ } from "./chunk-IQQBAWSM.js";
45
+
46
+ // src/services/instance.ts
47
+ import { promises as fs } from "fs";
48
+ import path from "path";
49
+ var INSTANCE_FILE = ".server.json";
50
+ async function findRunningInstance(root) {
51
+ const file = path.join(athenaDir(root), INSTANCE_FILE);
52
+ const raw = await readTextIfExists(file);
53
+ if (!raw) return null;
54
+ let info;
55
+ try {
56
+ info = JSON.parse(raw);
57
+ } catch {
58
+ return null;
59
+ }
60
+ if (typeof info.pid !== "number" || typeof info.port !== "number" || typeof info.token !== "string") return null;
61
+ try {
62
+ process.kill(info.pid, 0);
63
+ } catch {
64
+ await fs.rm(file, { force: true }).catch(() => {
65
+ });
66
+ return null;
67
+ }
68
+ try {
69
+ const host = info.host.includes(":") ? `[${info.host}]` : info.host;
70
+ const res = await fetch(`http://${host}:${info.port}/api/health`, { signal: AbortSignal.timeout(1500) });
71
+ const body = await res.json();
72
+ return body.instanceId === info.instanceId ? info : null;
73
+ } catch {
74
+ return null;
75
+ }
76
+ }
77
+
78
+ // src/services/doctor.ts
79
+ import { constants, promises as fs2 } from "fs";
80
+ import path2 from "path";
81
+
82
+ // src/services/time.ts
83
+ function relativeTime(iso, now = Date.now()) {
84
+ const ms = now - Date.parse(iso);
85
+ if (Number.isNaN(ms)) return "unknown";
86
+ const s = Math.round(ms / 1e3);
87
+ if (s < 60) return `${s}s ago`;
88
+ const m = Math.round(s / 60);
89
+ if (m < 60) return `${m} min ago`;
90
+ const h = Math.round(m / 60);
91
+ if (h < 48) return `${h} h ago`;
92
+ return `${Math.round(h / 24)} days ago`;
93
+ }
94
+
95
+ // src/services/doctor.ts
96
+ async function runDoctor(cwd) {
97
+ const checks = [];
98
+ const add = (c) => checks.push(c);
99
+ const [major, minor] = process.versions.node.split(".").map(Number);
100
+ const nodeOk = major > 22 || major === 22 && minor >= 12;
101
+ add({ area: "CLI", level: nodeOk ? "ok" : "error", message: `Athena ${ATHENA_VERSION} on Node.js ${process.versions.node} (${process.platform}/${process.arch})`, hint: nodeOk ? void 0 : "Athena requires Node.js >= 22.12" });
102
+ const root = await findProjectRoot(cwd);
103
+ const projectRoot = root ?? cwd;
104
+ if (await gitAvailable()) {
105
+ const repo = await isGitRepo(projectRoot);
106
+ add({ area: "Git", level: repo ? "ok" : "warn", message: repo ? "Git repository detected" : "Not a Git repository", hint: repo ? void 0 : "Change detection and knowledge history work best in a Git repository." });
107
+ } else {
108
+ add({ area: "Git", level: "warn", message: "git executable not found", hint: "Install Git to enable change detection and knowledge history." });
109
+ }
110
+ if (!root) {
111
+ add({ area: "Project", level: "error", message: "Athena is not initialized here", hint: "Run `athena init` in the project root." });
112
+ return { checks, root };
113
+ }
114
+ add({ area: "Project", level: "ok", message: root });
115
+ const dir = athenaDir(root);
116
+ try {
117
+ await fs2.access(dir, constants.R_OK | constants.W_OK);
118
+ add({ area: "Knowledge directory", level: "ok", message: ".athena/ is readable and writable" });
119
+ } catch {
120
+ add({ area: "Knowledge directory", level: "error", message: ".athena/ is not writable", hint: "Check file permissions." });
121
+ }
122
+ const cfg = await loadConfig(root);
123
+ if (cfg.warning) add({ area: "Configuration", level: "warn", message: cfg.warning });
124
+ const aiWarning = await committedAiWarning(root);
125
+ if (aiWarning) add({ area: "Configuration", level: "warn", message: aiWarning.split(": ")[0], hint: aiWarning.slice(aiWarning.indexOf(": ") + 2) });
126
+ const st = await readState(dir);
127
+ if (st.kind === "ok") add({ area: "State", level: "ok", message: `state.json valid (analyzed ${relativeTime(st.state.analyzedAt)})` });
128
+ else if (st.kind === "missing") add({ area: "State", level: "error", message: "state.json missing", hint: "Run `athena analyze`." });
129
+ else add({ area: "State", level: "error", message: `state.json corrupted: ${st.reason}`, hint: "Run `athena analyze` (the file is backed up and rebuilt)." });
130
+ const missing = [];
131
+ const malformed = [];
132
+ for (const d of KNOWLEDGE_DOCS) {
133
+ const text = await readTextIfExists(path2.join(dir, d.file));
134
+ if (text === null) missing.push(d.file);
135
+ else if (d.id !== "rules" && (text.match(/athena:generated:start/g)?.length ?? 0) !== parseBlocks(text).length) malformed.push(d.file);
136
+ }
137
+ add({ area: "Knowledge files", level: missing.length ? "error" : "ok", message: missing.length ? `Missing: ${missing.join(", ")}` : `${KNOWLEDGE_DOCS.length} knowledge files present`, hint: missing.length ? "Run `athena analyze` to regenerate missing files." : void 0 });
138
+ if (malformed.length) add({ area: "Knowledge files", level: "warn", message: `Unmatched generated-section markers in: ${malformed.join(", ")}`, hint: "Those sections are treated as developer content and will not be refreshed." });
139
+ const rulesText = await readTextIfExists(path2.join(dir, "rules.md"));
140
+ if (rulesText !== null) {
141
+ const rules = listRules(parseRules(rulesText));
142
+ const enabled = rules.filter((r) => r.enabled).length;
143
+ add({ area: "Rules", level: rules.length ? "ok" : "warn", message: `${enabled} enabled, ${rules.length - enabled} disabled`, hint: rules.length ? void 0 : "rules.md has no rules. Add some with `athena rules add`." });
144
+ }
145
+ const stateAgents = st.kind === "ok" ? st.state.agents : {};
146
+ for (const a of ADAPTERS) {
147
+ const configured = stateAgents[a.id]?.configured;
148
+ if (!configured) {
149
+ add({ area: a.displayName, level: "info", message: "Integration not configured", hint: `Enable with \`athena agents add ${a.id}\`.` });
150
+ continue;
151
+ }
152
+ for (const c of await a.check(root)) add({ area: a.displayName, level: c.level, message: c.message.replace(/^[^:]+:\s*/, "") });
153
+ }
154
+ const hooksConfigured = ADAPTERS.some((a) => a.capabilities.hooks && stateAgents[a.id]?.configured);
155
+ if (hooksConfigured) {
156
+ const cmd = hookCommand();
157
+ const resolved = await whichExecutable(cmd);
158
+ add(
159
+ resolved ? { area: "Agent hooks", level: "ok", message: `\`${cmd}\` resolves to ${resolved}` } : { area: "Agent hooks", level: "warn", message: `\`${cmd}\` is not on PATH \u2014 agent hooks cannot report activity`, hint: "Install globally (`npm i -g project-athena`) or set ATHENA_HOOK_COMMAND to an absolute path and re-run `athena agents add`." }
160
+ );
161
+ const events = await readRecentEvents(root, 1);
162
+ add({ area: "Agent hooks", level: "info", message: events.length ? `Last agent event: ${relativeTime(events[0].ts)}` : "No agent activity recorded yet (hooks fire when an agent runs)" });
163
+ }
164
+ const running = await findRunningInstance(root);
165
+ add(
166
+ running ? { area: "Local server", level: "ok", message: `Running on ${running.host}:${running.port} (pid ${running.pid})`, hint: "Run `athena open` to get the access link." } : { area: "Local server", level: "info", message: "Not running", hint: "Start the web UI with `athena open`." }
167
+ );
168
+ if (running && !["127.0.0.1", "::1", "localhost"].includes(running.host)) {
169
+ add({ area: "Local server", level: "warn", message: `Bound to ${running.host} \u2014 reachable beyond this machine` });
170
+ }
171
+ return { checks, root };
172
+ }
173
+
174
+ export {
175
+ INSTANCE_FILE,
176
+ findRunningInstance,
177
+ runDoctor
178
+ };
179
+ //# sourceMappingURL=chunk-3XSDI5WF.js.map
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ redact
4
+ } from "./chunk-JCGDR4UV.js";
5
+ import {
6
+ toPosix
7
+ } from "./chunk-XW3MLHI2.js";
8
+ import {
9
+ athenaDir
10
+ } from "./chunk-EUPETUWA.js";
11
+
12
+ // src/services/agent-activity.ts
13
+ import { promises as fs } from "fs";
14
+ import path from "path";
15
+ var ACTIVITY_FILE = ".agent-events.jsonl";
16
+ var ROTATED_ACTIVITY_FILE = ".agent-events.1.jsonl";
17
+ var ROTATE_LOCK = ".agent-events.rotate.lock";
18
+ var MAX_ACTIVITY_BYTES = 512 * 1024;
19
+ function activityFile(root) {
20
+ return path.join(athenaDir(root), ACTIVITY_FILE);
21
+ }
22
+ function rotatedActivityFile(root) {
23
+ return path.join(athenaDir(root), ROTATED_ACTIVITY_FILE);
24
+ }
25
+ var MASK = "<redacted>";
26
+ var COMMAND_SECRETS = [
27
+ // Authorization: Bearer <token> / Basic <b64> (headers, curl -H, etc.)
28
+ [/(\bauthorization\s*[:=]\s*["']?\s*(?:bearer|basic|token|digest)\s+)[^\s"',;]+/gi, `$1${MASK}`],
29
+ [/(\bbearer\s+)[A-Za-z0-9._~+/=-]{6,}/gi, `$1${MASK}`],
30
+ // --password=x, --password x, --passwd "x y"
31
+ [/(--(?:password|passwd|pass)(?:=|\s+))("[^"]*"|'[^']*'|[^\s"']+)/gi, `$1${MASK}`],
32
+ // mysql -psecret (attached value; `-p` alone prompts)
33
+ [/(\b(?:mysql|mysqldump|mysqladmin|mysqlimport|mariadb|mariadb-dump)\b[^|;&\n]*?\s-p)("[^"]*"|'[^']*'|[^\s"']+)/gi, `$1${MASK}`],
34
+ // scheme://user:password@host
35
+ [/(\b[a-z][a-z0-9+.-]*:\/\/[^\s:@/]*:)([^\s@/]+)(@)/gi, `$1${MASK}$3`]
36
+ ];
37
+ function redactCommandSecrets(text) {
38
+ let out = text;
39
+ for (const [re, rep] of COMMAND_SECRETS) out = out.replace(re, rep);
40
+ return redact(out);
41
+ }
42
+ function sanitizeEvent(root, event) {
43
+ const rel = (p) => {
44
+ const abs = path.isAbsolute(p) ? p : path.resolve(root, p);
45
+ const r = toPosix(path.relative(root, abs));
46
+ return !r || r.startsWith("..") ? toPosix(p) : r;
47
+ };
48
+ const stripRoot = (text) => text.split(`${root}${path.sep}`).join("").split(toPosix(root) + "/").join("");
49
+ return {
50
+ ...event,
51
+ message: redactCommandSecrets(stripRoot(event.message)),
52
+ command: event.command ? redactCommandSecrets(stripRoot(event.command)) : null,
53
+ files: event.files.map(rel)
54
+ };
55
+ }
56
+ async function appendEvent(root, event) {
57
+ const file = activityFile(root);
58
+ await fs.mkdir(path.dirname(file), { recursive: true });
59
+ await fs.appendFile(file, `${JSON.stringify(sanitizeEvent(root, event))}
60
+ `);
61
+ await rotateIfNeeded(file);
62
+ }
63
+ async function rotateIfNeeded(file, maxBytes = MAX_ACTIVITY_BYTES) {
64
+ try {
65
+ const st = await fs.stat(file);
66
+ if (st.size < maxBytes) return;
67
+ const dir = path.dirname(file);
68
+ const lock = path.join(dir, ROTATE_LOCK);
69
+ let handle;
70
+ try {
71
+ handle = await fs.open(lock, "wx");
72
+ } catch {
73
+ const age = await fs.stat(lock).then((l) => Date.now() - l.mtimeMs).catch(() => 0);
74
+ if (age > 1e4) await fs.rm(lock, { force: true });
75
+ return;
76
+ }
77
+ try {
78
+ const again = await fs.stat(file).catch(() => null);
79
+ if (again && again.size >= maxBytes) await fs.rename(file, path.join(dir, ROTATED_ACTIVITY_FILE));
80
+ } finally {
81
+ await handle.close();
82
+ await fs.rm(lock, { force: true });
83
+ }
84
+ } catch {
85
+ }
86
+ }
87
+ function parseEventLines(text) {
88
+ const out = [];
89
+ for (const line of text.split("\n")) {
90
+ if (!line.trim()) continue;
91
+ try {
92
+ const e = JSON.parse(line);
93
+ if (e && typeof e.id === "string" && typeof e.ts === "string" && typeof e.agent === "string") out.push(e);
94
+ } catch {
95
+ }
96
+ }
97
+ return out;
98
+ }
99
+ async function readRecentEvents(root, limit = 200) {
100
+ const current = parseEventLines(await fs.readFile(activityFile(root), "utf8").catch(() => ""));
101
+ if (current.length >= limit) return current.slice(-limit);
102
+ const previous = parseEventLines(await fs.readFile(rotatedActivityFile(root), "utf8").catch(() => ""));
103
+ return [...previous, ...current].slice(-limit);
104
+ }
105
+ function summarizeSessions(events) {
106
+ const byKey = /* @__PURE__ */ new Map();
107
+ for (const e of events) {
108
+ const key = `${e.agent}:${e.session ?? "-"}`;
109
+ const cur = byKey.get(key);
110
+ byKey.set(key, { agent: e.agent, session: e.session, lastEventAt: e.ts, lastMessage: e.message, events: (cur?.events ?? 0) + 1 });
111
+ }
112
+ return [...byKey.values()].sort((a, b) => b.lastEventAt.localeCompare(a.lastEventAt));
113
+ }
114
+
115
+ export {
116
+ ACTIVITY_FILE,
117
+ activityFile,
118
+ rotatedActivityFile,
119
+ appendEvent,
120
+ parseEventLines,
121
+ readRecentEvents,
122
+ summarizeSessions
123
+ };
124
+ //# sourceMappingURL=chunk-65TSRDQ3.js.map
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ sha256
4
+ } from "./chunk-IQQBAWSM.js";
5
+
6
+ // src/core/knowledge/managed-blocks.ts
7
+ var START_RE = /<!-- athena:generated:start id=([a-z0-9-]+) hash=([a-f0-9]*) -->\n?/g;
8
+ function blockHash(content) {
9
+ return sha256(content.trim()).slice(0, 12);
10
+ }
11
+ function renderBlock(section) {
12
+ const body = section.content.trim();
13
+ return `<!-- athena:generated:start id=${section.id} hash=${blockHash(body)} -->
14
+ ${body}
15
+ <!-- athena:generated:end id=${section.id} -->`;
16
+ }
17
+ function parseBlocks(text) {
18
+ const blocks = [];
19
+ START_RE.lastIndex = 0;
20
+ for (let m = START_RE.exec(text); m; m = START_RE.exec(text)) {
21
+ const id = m[1];
22
+ const endMarker = `<!-- athena:generated:end id=${id} -->`;
23
+ const endIdx = text.indexOf(endMarker, m.index + m[0].length);
24
+ if (endIdx === -1) continue;
25
+ blocks.push({ id, hash: m[2], content: text.slice(m.index + m[0].length, endIdx).trim(), start: m.index, end: endIdx + endMarker.length });
26
+ START_RE.lastIndex = endIdx + endMarker.length;
27
+ }
28
+ return blocks;
29
+ }
30
+ function isBlockModified(block) {
31
+ return blockHash(block.content) !== block.hash;
32
+ }
33
+ function mergeDocument(existing, sections, opts = {}) {
34
+ const blocks = parseBlocks(existing);
35
+ const byId = new Map(blocks.map((b) => [b.id, b]));
36
+ const result = { text: existing, changed: false, preservedModified: [], updated: [], added: [] };
37
+ const replacements = [];
38
+ for (const s of sections) {
39
+ const b = byId.get(s.id);
40
+ if (!b) continue;
41
+ if (isBlockModified(b) && !opts.force) {
42
+ result.preservedModified.push(s.id);
43
+ continue;
44
+ }
45
+ if (b.content === s.content.trim() && !isBlockModified(b)) continue;
46
+ replacements.push({ start: b.start, end: b.end, text: renderBlock(s) });
47
+ result.updated.push(s.id);
48
+ }
49
+ let text = existing;
50
+ for (const r of replacements.sort((a, b) => b.start - a.start)) text = text.slice(0, r.start) + r.text + text.slice(r.end);
51
+ const known = new Set(opts.previouslyKnown ?? []);
52
+ const toAdd = sections.filter((s) => !byId.has(s.id) && !known.has(s.id));
53
+ if (toAdd.length) {
54
+ const insert = toAdd.map((s) => renderBlock(s)).join("\n\n");
55
+ const marker = opts.insertBefore ? text.indexOf(opts.insertBefore) : -1;
56
+ text = marker >= 0 ? `${text.slice(0, marker)}${insert}
57
+
58
+ ${text.slice(marker)}` : `${text.replace(/\s*$/, "")}
59
+
60
+ ${insert}
61
+ `;
62
+ result.added.push(...toAdd.map((s) => s.id));
63
+ }
64
+ result.text = text;
65
+ result.changed = text !== existing;
66
+ return result;
67
+ }
68
+ var INTEGRATION_START = "<!-- athena:start -->";
69
+ var INTEGRATION_END = "<!-- athena:end -->";
70
+ function upsertIntegrationBlock(existing, body) {
71
+ const block = `${INTEGRATION_START}
72
+ ${body.trim()}
73
+ ${INTEGRATION_END}`;
74
+ if (!existing) return `${block}
75
+ `;
76
+ const s = existing.indexOf(INTEGRATION_START);
77
+ const e = existing.indexOf(INTEGRATION_END);
78
+ if (s !== -1 && e > s) return existing.slice(0, s) + block + existing.slice(e + INTEGRATION_END.length);
79
+ return `${existing.replace(/\s*$/, "")}
80
+
81
+ ${block}
82
+ `;
83
+ }
84
+ function removeIntegrationBlock(existing) {
85
+ const s = existing.indexOf(INTEGRATION_START);
86
+ const e = existing.indexOf(INTEGRATION_END);
87
+ if (s === -1 || e < s) return existing;
88
+ const before = existing.slice(0, s).replace(/\s*$/, "");
89
+ const after = existing.slice(e + INTEGRATION_END.length).replace(/^\s*/, "");
90
+ const joined = [before, after.replace(/\s*$/, "")].filter(Boolean).join("\n\n");
91
+ return joined ? `${joined}
92
+ ` : "";
93
+ }
94
+
95
+ export {
96
+ renderBlock,
97
+ parseBlocks,
98
+ isBlockModified,
99
+ mergeDocument,
100
+ INTEGRATION_START,
101
+ INTEGRATION_END,
102
+ upsertIntegrationBlock,
103
+ removeIntegrationBlock
104
+ };
105
+ //# sourceMappingURL=chunk-673EPYYH.js.map
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ c,
4
+ dim,
5
+ isJson,
6
+ json,
7
+ line,
8
+ ok,
9
+ sym
10
+ } from "./chunk-Z6QWMJLK.js";
11
+ import {
12
+ requireProjectRoot
13
+ } from "./chunk-XFN7UZCS.js";
14
+ import {
15
+ ADAPTERS
16
+ } from "./chunk-YRIS7ZS6.js";
17
+ import {
18
+ athenaDir
19
+ } from "./chunk-2DY4PUR4.js";
20
+ import {
21
+ AthenaError
22
+ } from "./chunk-AD4OZCU2.js";
23
+
24
+ // src/cli/commands/clean.ts
25
+ import { promises as fs } from "fs";
26
+ import { createInterface } from "readline/promises";
27
+ async function confirm(question) {
28
+ if (!process.stdin.isTTY) return false;
29
+ const rl = createInterface({ input: process.stdin, output: process.stdout });
30
+ try {
31
+ const answer = await rl.question(`${question} ${dim("[y/N]")} `);
32
+ return /^y(es)?$/i.test(answer.trim());
33
+ } finally {
34
+ rl.close();
35
+ }
36
+ }
37
+ async function cleanCommand(opts) {
38
+ const root = await requireProjectRoot(opts);
39
+ if (!opts.yes) {
40
+ const memory = (await (await import("./memory-VSVNLEJC.js")).memorySummary(root))?.total ?? 0;
41
+ const memoryNote = memory ? `${memory} project memory ${memory === 1 ? "entry" : "entries"} in .athena/memory/ (shared with your team)` : "";
42
+ if (!process.stdin.isTTY) throw new AthenaError(`Refusing to delete .athena/${memory ? `, including ${memoryNote},` : ""} without confirmation.`, "Re-run with --yes in non-interactive environments.");
43
+ line(`This removes ${c.bold(".athena/")} (including rules.md and your Developer Notes)${opts.keepAgents ? "" : " and Athena blocks/files in agent configurations"}.`);
44
+ if (memory) line(c.yellow(`${sym.warn} It also deletes ${memoryNote}.`));
45
+ line(dim("If .athena/ is committed to Git you can restore it from history."));
46
+ if (!await confirm("Continue?")) {
47
+ line("Cancelled.");
48
+ return;
49
+ }
50
+ }
51
+ const touched = [];
52
+ if (!opts.keepAgents) for (const a of ADAPTERS) touched.push(...await a.remove(root));
53
+ await fs.rm(athenaDir(root), { recursive: true, force: true });
54
+ if (isJson()) json({ ok: true, removed: [".athena/", ...touched] });
55
+ else {
56
+ ok("Removed .athena/");
57
+ for (const t of touched) ok(`Removed Athena integration from ${t}`);
58
+ }
59
+ }
60
+
61
+ export {
62
+ confirm,
63
+ cleanCommand
64
+ };
65
+ //# sourceMappingURL=chunk-7DZK6WSQ.js.map
@@ -0,0 +1,34 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/services/errors.ts
4
+ var EXIT = {
5
+ OK: 0,
6
+ ERROR: 1,
7
+ NOT_AVAILABLE: 2,
8
+ NOT_INITIALIZED: 3,
9
+ INTERRUPTED: 130
10
+ };
11
+ var AthenaError = class extends Error {
12
+ constructor(message, hint, exitCode = EXIT.ERROR, kind, details) {
13
+ super(message);
14
+ this.hint = hint;
15
+ this.exitCode = exitCode;
16
+ this.details = details;
17
+ this.name = "AthenaError";
18
+ this.kind = kind ?? (exitCode === EXIT.NOT_INITIALIZED ? "not-initialized" : "invalid");
19
+ }
20
+ hint;
21
+ exitCode;
22
+ details;
23
+ kind;
24
+ };
25
+ var notFound = (message) => new AthenaError(message, void 0, EXIT.ERROR, "not-found");
26
+ var conflict = (message, hint, details) => new AthenaError(message, hint, EXIT.ERROR, "conflict", details);
27
+
28
+ export {
29
+ EXIT,
30
+ AthenaError,
31
+ notFound,
32
+ conflict
33
+ };
34
+ //# sourceMappingURL=chunk-AD4OZCU2.js.map
@@ -0,0 +1,169 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ AnalysisScheduler
4
+ } from "./chunk-RVTNSNGK.js";
5
+ import {
6
+ applySync,
7
+ needsIndexRefreshOnly
8
+ } from "./chunk-KHMBNT66.js";
9
+ import {
10
+ readExclude
11
+ } from "./chunk-MPG3IEGB.js";
12
+ import {
13
+ IgnoreMatcher,
14
+ factsConfigHash
15
+ } from "./chunk-ELKFRTZT.js";
16
+ import {
17
+ git
18
+ } from "./chunk-OLPSEQS5.js";
19
+ import {
20
+ loadConfig
21
+ } from "./chunk-2DY4PUR4.js";
22
+ import {
23
+ toPosix
24
+ } from "./chunk-XW3MLHI2.js";
25
+
26
+ // src/services/watch.ts
27
+ import { promises as fs } from "fs";
28
+ import path from "path";
29
+ import { watch as chokidarWatch } from "chokidar";
30
+ async function gitDir(root) {
31
+ const r = await git(root, ["rev-parse", "--absolute-git-dir"]);
32
+ return r.ok ? r.stdout.trim() : null;
33
+ }
34
+ async function watchProject(root, opts) {
35
+ const debounceMs = opts.debounceMs ?? 1500;
36
+ const maxWaitMs = opts.maxWaitMs ?? 1e4;
37
+ const { config } = await loadConfig(root);
38
+ const [matcher, excludeText] = await Promise.all([IgnoreMatcher.load(root, config), readExclude(root)]);
39
+ const ownScheduler = !opts.scheduler;
40
+ const scheduler = opts.scheduler ?? new AnalysisScheduler(root);
41
+ let timer = null;
42
+ let firstChangeAt = 0;
43
+ let latest = null;
44
+ let closed = false;
45
+ const toRel = (abs) => toPosix(path.relative(root, abs));
46
+ scheduler.hooks.onStart = (run2) => {
47
+ if (!closed) opts.onEvent({ type: "planning", paths: run2.paths });
48
+ };
49
+ scheduler.hooks.onPlan = async (plan) => {
50
+ if (closed) return;
51
+ latest = plan;
52
+ if (plan.upToDate) {
53
+ latest = null;
54
+ if (needsIndexRefreshOnly(plan)) {
55
+ const result = await applySync(root, plan);
56
+ opts.onEvent({ type: "refreshed", plan, result });
57
+ } else {
58
+ opts.onEvent({ type: "plan", plan });
59
+ }
60
+ return;
61
+ }
62
+ if (opts.autoApply && !plan.ignored) {
63
+ const result = await applySync(root, plan);
64
+ latest = null;
65
+ opts.onEvent({ type: "applied", plan, result });
66
+ return;
67
+ }
68
+ opts.onEvent({ type: "plan", plan });
69
+ };
70
+ const run = async () => {
71
+ if (closed) return null;
72
+ firstChangeAt = 0;
73
+ try {
74
+ return await scheduler.request({ reason: "watch", supersede: true });
75
+ } catch (err) {
76
+ if (!closed && !opts.signal?.aborted && err?.name !== "AbortError") opts.onEvent({ type: "error", error: err });
77
+ return null;
78
+ }
79
+ };
80
+ const schedule = () => {
81
+ if (closed) return;
82
+ const now = Date.now();
83
+ if (!firstChangeAt) firstChangeAt = now;
84
+ if (timer) clearTimeout(timer);
85
+ const wait = Math.max(0, Math.min(debounceMs, firstChangeAt + maxWaitMs - now));
86
+ timer = setTimeout(() => {
87
+ timer = null;
88
+ void run();
89
+ }, wait);
90
+ };
91
+ const onPath = (abs) => {
92
+ const rel = toRel(abs);
93
+ if (!rel || rel.startsWith("..")) return;
94
+ if (rel === ".gitignore" || rel.endsWith("/.gitignore")) {
95
+ scheduler.setTracking(false);
96
+ const dir = rel === ".gitignore" ? "" : rel.slice(0, -"/.gitignore".length);
97
+ void fs.readFile(abs, "utf8").then((text) => matcher.setGitignore(dir, text)).catch(() => matcher.removeGitignore(dir));
98
+ }
99
+ scheduler.noteChanges([rel]);
100
+ opts.onEvent({ type: "changes", paths: [rel] });
101
+ schedule();
102
+ };
103
+ const watcher = chokidarWatch(root, {
104
+ ignoreInitial: true,
105
+ persistent: true,
106
+ followSymlinks: false,
107
+ ignored: (abs, stats) => {
108
+ const rel = toRel(abs);
109
+ if (!rel || rel === ".") return false;
110
+ if (rel.startsWith("..")) return true;
111
+ if (rel === ".git" || rel.startsWith(".git/")) return true;
112
+ if (stats) return matcher.ignores(rel, stats.isDirectory());
113
+ return matcher.ignores(rel, false) || matcher.ignores(rel, true);
114
+ }
115
+ });
116
+ const ready = new Promise((resolve) => watcher.once("ready", () => resolve()));
117
+ watcher.on("add", onPath).on("change", onPath).on("unlink", onPath).on("addDir", onPath).on("unlinkDir", onPath);
118
+ watcher.on("error", (err) => {
119
+ scheduler.resetBaseline();
120
+ opts.onEvent({ type: "error", error: err });
121
+ });
122
+ let headWatcher = null;
123
+ const gd = await gitDir(root);
124
+ let lastHead = null;
125
+ if (gd) {
126
+ lastHead = (await git(root, ["rev-parse", "HEAD"])).stdout.trim() || null;
127
+ headWatcher = chokidarWatch([path.join(gd, "HEAD"), path.join(gd, "refs", "heads")], { ignoreInitial: true, persistent: true, depth: 5 });
128
+ headWatcher.on("all", () => {
129
+ void git(root, ["rev-parse", "HEAD"]).then((r) => {
130
+ const head = r.ok ? r.stdout.trim() : null;
131
+ if (head && head !== lastHead) {
132
+ opts.onEvent({ type: "git-head", head: { from: lastHead, to: head } });
133
+ lastHead = head;
134
+ schedule();
135
+ }
136
+ });
137
+ });
138
+ headWatcher.on("error", () => {
139
+ });
140
+ }
141
+ await ready;
142
+ scheduler.setTracking(true, { configHash: factsConfigHash(config), excludeText });
143
+ opts.onEvent({ type: "ready" });
144
+ const close = async () => {
145
+ if (closed) return;
146
+ closed = true;
147
+ if (timer) clearTimeout(timer);
148
+ scheduler.setTracking(false);
149
+ scheduler.hooks.onStart = void 0;
150
+ scheduler.hooks.onPlan = void 0;
151
+ if (ownScheduler) scheduler.close();
152
+ await Promise.all([watcher.close(), headWatcher?.close()]);
153
+ };
154
+ opts.signal?.addEventListener("abort", () => void close(), { once: true });
155
+ return {
156
+ planNow: () => {
157
+ if (timer) clearTimeout(timer);
158
+ timer = null;
159
+ return run();
160
+ },
161
+ latestPlan: () => latest,
162
+ close
163
+ };
164
+ }
165
+
166
+ export {
167
+ watchProject
168
+ };
169
+ //# sourceMappingURL=chunk-DZDI2HRT.js.map