project-athena 0.3.0 → 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 (124) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +46 -4
  3. package/dist/{activity-P4UUFHWV.js → activity-BKW7G4I5.js} +4 -4
  4. package/dist/{agents-3HTSQGL2.js → agents-DFSNEOP5.js} +4 -4
  5. package/dist/{analyze-F3YOILNL.js → analyze-ZY3MXBOI.js} +7 -6
  6. package/dist/{chunk-PR53DT7I.js → chunk-3XSDI5WF.js} +5 -5
  7. package/dist/{chunk-S7T6VX56.js → chunk-7DZK6WSQ.js} +8 -4
  8. package/dist/{chunk-32PRS2MG.js → chunk-DZDI2HRT.js} +4 -4
  9. package/dist/{chunk-EF6GHOIN.js → chunk-FVCDMQUQ.js} +2 -2
  10. package/dist/{chunk-SJOOXO34.js → chunk-GGXPG6OE.js} +3 -3
  11. package/dist/{chunk-TGJUUB44.js → chunk-KHMBNT66.js} +4 -4
  12. package/dist/{chunk-PANVPNYF.js → chunk-MPG3IEGB.js} +37 -238
  13. package/dist/chunk-QCC4VJUH.js +217 -0
  14. package/dist/{chunk-JY6BFIJJ.js → chunk-QLW657NT.js} +2 -2
  15. package/dist/{chunk-XB66PZ6Z.js → chunk-RVTNSNGK.js} +2 -2
  16. package/dist/{chunk-LMOFZNTQ.js → chunk-SJ4DQFIJ.js} +2 -2
  17. package/dist/{chunk-PDFQ5BFG.js → chunk-SVTEJYMS.js} +4 -155
  18. package/dist/chunk-TDNZ2RYA.js +702 -0
  19. package/dist/chunk-UAZLPNVC.js +108 -0
  20. package/dist/chunk-WVQC2EGO.js +166 -0
  21. package/dist/{chunk-DOQMAZL5.js → chunk-XDCKZ5TV.js} +3 -3
  22. package/dist/{chunk-2RS6TA3D.js → chunk-YRIS7ZS6.js} +28 -17
  23. package/dist/{clean-S7PKCOLM.js → clean-MDBYH62P.js} +4 -4
  24. package/dist/cli.js +1 -1
  25. package/dist/{context-AH5MFHRG.js → context-PLPCAPCO.js} +23 -9
  26. package/dist/{doctor-RSJMLE2P.js → doctor-BX677KRE.js} +13 -6
  27. package/dist/{init-2V34DVRQ.js → init-WQCAOJ2R.js} +7 -6
  28. package/dist/{mcp-T2GRTEX5.js → mcp-U7EPH43L.js} +153 -15
  29. package/dist/memory-VSVNLEJC.js +393 -0
  30. package/dist/{open-2QSZKKUG.js → open-UJZRYF4E.js} +246 -55
  31. package/dist/{program-V2USHGXN.js → program-CWJNGCTZ.js} +37 -20
  32. package/dist/{review-R3R2J5BJ.js → review-OOKXSYMP.js} +10 -8
  33. package/dist/{security-PI4LXCOB.js → security-LME3XFL3.js} +6 -4
  34. package/dist/{staged-check-HHIBKKMR.js → staged-check-X24C3YRD.js} +9 -7
  35. package/dist/{status-6M73WX5I.js → status-RR57ZNGI.js} +8 -2
  36. package/dist/{sync-3ZNJDSSU.js → sync-KFJANRXF.js} +11 -9
  37. package/dist/{watch-USN5CQIV.js → watch-CY7QHIYN.js} +11 -9
  38. package/dist/web/assets/{Editor-BI56-HX5.js → Editor-Bnilgch0.js} +1 -1
  39. package/dist/web/assets/{abnfDiagram-O67JEVCF-y_9px2ob.js → abnfDiagram-O67JEVCF-DW9LWr8f.js} +1 -1
  40. package/dist/web/assets/architecture-7GRP2DOG-BWDZV2yn.js +1 -0
  41. package/dist/web/assets/{architectureDiagram-NJMV4G6O-lB6fcVzU.js → architectureDiagram-NJMV4G6O-0eKeQRhj.js} +1 -1
  42. package/dist/web/assets/{blockDiagram-BEXU5L5S-DcM5pEjM.js → blockDiagram-BEXU5L5S-D5i3-ogI.js} +1 -1
  43. package/dist/web/assets/{c4Diagram-YGBWAQC7-CJgqxTY2.js → c4Diagram-YGBWAQC7-BAWQZrEu.js} +1 -1
  44. package/dist/web/assets/channel-Bkh05NKd.js +1 -0
  45. package/dist/web/assets/{chunk-3FUC2YCW-B8l_VuWR.js → chunk-3FUC2YCW-fKRGOZF3.js} +1 -1
  46. package/dist/web/assets/{chunk-5DYCD2WN-CZecgNhf.js → chunk-5DYCD2WN-C5jOlx42.js} +1 -1
  47. package/dist/web/assets/{chunk-742MDFTN-BeZ7P5jB.js → chunk-742MDFTN-urY4RP_A.js} +1 -1
  48. package/dist/web/assets/{chunk-7INBJB4K-IKy0pr5m.js → chunk-7INBJB4K-nk48sKqZ.js} +1 -1
  49. package/dist/web/assets/{chunk-7M6MHVWA-Dg_QqJEX.js → chunk-7M6MHVWA-BfBD9X0F.js} +1 -1
  50. package/dist/web/assets/{chunk-7PRAP22T-DqQNS8oq.js → chunk-7PRAP22T-jYf59QlI.js} +1 -1
  51. package/dist/web/assets/{chunk-GTNCS2PH-x4sM51nJ.js → chunk-GTNCS2PH-BOCxryKf.js} +1 -1
  52. package/dist/web/assets/{chunk-GWA4HPMP-CE5GcwVN.js → chunk-GWA4HPMP-CFpaW0ru.js} +1 -1
  53. package/dist/web/assets/{chunk-MBY4JIJT-DA_D1hjF.js → chunk-MBY4JIJT-BIB8HctN.js} +1 -1
  54. package/dist/web/assets/{chunk-NETBCI7D-CeJ3XBZ2.js → chunk-NETBCI7D-CpUUK6rh.js} +1 -1
  55. package/dist/web/assets/{chunk-O7XYJQB3-BH2gESvO.js → chunk-O7XYJQB3-BNx_V4Oi.js} +1 -1
  56. package/dist/web/assets/{chunk-UA2S7LBM-BWr0xCux.js → chunk-UA2S7LBM-D3tMiIOY.js} +1 -1
  57. package/dist/web/assets/{chunk-WEXAMYUT-B4QwUZPM.js → chunk-WEXAMYUT-CC-3C32l.js} +1 -1
  58. package/dist/web/assets/{chunk-Z7XXMR3K-BxcA-y5B.js → chunk-Z7XXMR3K-BzhxKQUc.js} +1 -1
  59. package/dist/web/assets/{chunk-ZIGJFQKS-BZYvP63G.js → chunk-ZIGJFQKS-D4tBHzxg.js} +1 -1
  60. package/dist/web/assets/{classDiagram-v2-NBCMYWYE-BS3P_NXb.js → classDiagram-v2-NBCMYWYE-BbtyanXR.js} +1 -1
  61. package/dist/web/assets/{cynefin-OW5HDTMX-BALD4Pve.js → cynefin-OW5HDTMX-BIArb8W1.js} +1 -1
  62. package/dist/web/assets/{cynefinDiagram-VND7K2PF-BM2y4W6d.js → cynefinDiagram-VND7K2PF-BrAcfkXL.js} +1 -1
  63. package/dist/web/assets/{dagre-6A5THRUB-PTfOrIdF.js → dagre-6A5THRUB-BcHXRl4s.js} +1 -1
  64. package/dist/web/assets/{diagram-22UHCM2B-CpXEHhUl.js → diagram-22UHCM2B-Dx9tSCdE.js} +1 -1
  65. package/dist/web/assets/{diagram-3UASUU5V-DPHfXzr6.js → diagram-3UASUU5V-CLLDP9yH.js} +1 -1
  66. package/dist/web/assets/{diagram-ATOU4E4O-DMBNXvAC.js → diagram-ATOU4E4O-B46H9iPt.js} +1 -1
  67. package/dist/web/assets/{diagram-CDSNMT55-CDLe1M7G.js → diagram-CDSNMT55-CYtvB6aG.js} +1 -1
  68. package/dist/web/assets/{diagram-MLGK6HIB-D6L8oE7j.js → diagram-MLGK6HIB-Dar7ktoX.js} +1 -1
  69. package/dist/web/assets/{diagram-MPIPVDR6-CP-S7rrQ.js → diagram-MPIPVDR6-C-DljnYN.js} +1 -1
  70. package/dist/web/assets/{ebnfDiagram-ZINNZB2B-CkUc63TK.js → ebnfDiagram-ZINNZB2B-Dv_3jWnh.js} +1 -1
  71. package/dist/web/assets/{elk-276RUBZZ-C1CAJLH_.js → elk-276RUBZZ-DnHciE9k.js} +1 -1
  72. package/dist/web/assets/{erDiagram-OPXOYQCR-DXBnaTHm.js → erDiagram-OPXOYQCR-Bn46KrHz.js} +1 -1
  73. package/dist/web/assets/eventmodeling-NTZA5JFV-DYwoptMd.js +1 -0
  74. package/dist/web/assets/flowDiagram-KWPJA3E3-y4rS0gIB.js +1 -0
  75. package/dist/web/assets/{ganttDiagram-FUAMR5RP-BVm8SiGg.js → ganttDiagram-FUAMR5RP-DOjjJtqz.js} +1 -1
  76. package/dist/web/assets/{gitGraph-4MIJSDKK-Dm7xBrW0.js → gitGraph-4MIJSDKK-BIoMXJRQ.js} +1 -1
  77. package/dist/web/assets/{gitGraphDiagram-X574FWY7-D_PIKKhx.js → gitGraphDiagram-X574FWY7-BsJ01R0v.js} +1 -1
  78. package/dist/web/assets/{index-CeOIBpu2.js → index-Cen0jOXj.js} +5 -4
  79. package/dist/web/assets/{index-DKE3ojTe.css → index-WwRY6n68.css} +1 -1
  80. package/dist/web/assets/{info-A6RAGUB7-CLGrx8pn.js → info-A6RAGUB7-BmlXzRWj.js} +1 -1
  81. package/dist/web/assets/{infoDiagram-VRGFBTTK-BlBjaKm7.js → infoDiagram-VRGFBTTK-CYPJPmBP.js} +1 -1
  82. package/dist/web/assets/{ishikawaDiagram-OU5B5YK6-Kxe7GGS3.js → ishikawaDiagram-OU5B5YK6-YN96geky.js} +1 -1
  83. package/dist/web/assets/{journeyDiagram-ZHPQQLJL-wCMoHK4M.js → journeyDiagram-ZHPQQLJL-20juojKY.js} +1 -1
  84. package/dist/web/assets/{kanban-definition-PNTS6WVX-BxdCz9Ko.js → kanban-definition-PNTS6WVX-BhCKIEbP.js} +1 -1
  85. package/dist/web/assets/{line-Zf11FnWF.js → line-BERsMFG6.js} +1 -1
  86. package/dist/web/assets/{mermaid-parser.core-BvFFklev.js → mermaid-parser.core-Bis_wTB-.js} +3 -3
  87. package/dist/web/assets/{mermaid.core-Cd_Ssti9.js → mermaid.core-DMsM3ZX7.js} +4 -4
  88. package/dist/web/assets/{mindmap-definition-NLK3R4M7-BGPQl-GY.js → mindmap-definition-NLK3R4M7-BkcGdOfv.js} +1 -1
  89. package/dist/web/assets/{packet-AYTQ26CC-6lI3cEX_.js → packet-AYTQ26CC-Bh30-JJX.js} +1 -1
  90. package/dist/web/assets/{pegDiagram-GJSIUBJH-BPIjlSAj.js → pegDiagram-GJSIUBJH-DxnIo9RF.js} +1 -1
  91. package/dist/web/assets/{pie-WAS4IAKB-D6Dzj3Ja.js → pie-WAS4IAKB-ChaTr-GD.js} +1 -1
  92. package/dist/web/assets/{pieDiagram-5QR66LMP-DtA-vZmv.js → pieDiagram-5QR66LMP-CzAp78FM.js} +1 -1
  93. package/dist/web/assets/{quadrantDiagram-O4NWA36T-EettyqQn.js → quadrantDiagram-O4NWA36T-BDSE-cfY.js} +1 -1
  94. package/dist/web/assets/{radar-RG4KPBEZ-xmRc3Dl8.js → radar-RG4KPBEZ-DgJ-o_dq.js} +1 -1
  95. package/dist/web/assets/{railroad-74A4TZTK-BLB7dhOn.js → railroad-74A4TZTK-C8MmcBKz.js} +1 -1
  96. package/dist/web/assets/railroad-abnf-HS5TGJTU-CTLXjcdP.js +1 -0
  97. package/dist/web/assets/railroad-ebnf-LZEXJU2U-ggWsTTL0.js +1 -0
  98. package/dist/web/assets/railroad-peg-WCYAUIDC-D1mCX705.js +1 -0
  99. package/dist/web/assets/{railroadDiagram-XR7U4H2S-PBw4We6b.js → railroadDiagram-XR7U4H2S-DfbcWRNh.js} +1 -1
  100. package/dist/web/assets/{requirementDiagram-PLB6GJNP-DjQpaUFA.js → requirementDiagram-PLB6GJNP-DM3nksxs.js} +1 -1
  101. package/dist/web/assets/{sankeyDiagram-IPEJSGJF-CBW-_AoF.js → sankeyDiagram-IPEJSGJF-DthUpiiC.js} +1 -1
  102. package/dist/web/assets/{sequenceDiagram-PO4LG4MO-DEoPYqY9.js → sequenceDiagram-PO4LG4MO-DLA3nuvA.js} +1 -1
  103. package/dist/web/assets/{stateDiagram-v2-GCMORJYK-UZq5rPud.js → stateDiagram-v2-GCMORJYK-B0X6ihBW.js} +1 -1
  104. package/dist/web/assets/{swimlanes-2SLR337P-CACfuXJR.js → swimlanes-2SLR337P-B4qWe6vE.js} +1 -1
  105. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-ClIk3e7S.js +8 -0
  106. package/dist/web/assets/{timeline-definition-EJHVYXUP-CYJl7mP-.js → timeline-definition-EJHVYXUP-F-cDzYrj.js} +1 -1
  107. package/dist/web/assets/{treeView-Q6P3EWNA-DtZ5nkPQ.js → treeView-Q6P3EWNA-BaI30nLZ.js} +1 -1
  108. package/dist/web/assets/{treemap-WGGIJYW6-m49GDM-M.js → treemap-WGGIJYW6-D2jGGoMl.js} +1 -1
  109. package/dist/web/assets/{usecaseDiagram-POWQR4AR-C2Vg20UK.js → usecaseDiagram-POWQR4AR-B9qoAQCy.js} +1 -1
  110. package/dist/web/assets/{vennDiagram-UO4OBE2U-C07v5OGI.js → vennDiagram-UO4OBE2U-DGVNOaKO.js} +1 -1
  111. package/dist/web/assets/{wardley-WFR3VGLG-C9Z7EZtz.js → wardley-WFR3VGLG-DbKqhNAh.js} +1 -1
  112. package/dist/web/assets/{wardleyDiagram-VNRHLVJA-DdA8CcSC.js → wardleyDiagram-VNRHLVJA-BgZ1gprw.js} +1 -1
  113. package/dist/web/assets/{xychartDiagram-PMCCYNJV-C9EZw07b.js → xychartDiagram-PMCCYNJV-D73RYid1.js} +1 -1
  114. package/dist/web/index.html +2 -2
  115. package/package.json +1 -1
  116. package/dist/chunk-CXUTYCZX.js +0 -238
  117. package/dist/web/assets/architecture-7GRP2DOG-DyxkwYiW.js +0 -1
  118. package/dist/web/assets/channel-BvDD7AMO.js +0 -1
  119. package/dist/web/assets/eventmodeling-NTZA5JFV-cLIzvgDp.js +0 -1
  120. package/dist/web/assets/flowDiagram-KWPJA3E3-D7Zq63VQ.js +0 -1
  121. package/dist/web/assets/railroad-abnf-HS5TGJTU-DBFym6g8.js +0 -1
  122. package/dist/web/assets/railroad-ebnf-LZEXJU2U-CkG28ig8.js +0 -1
  123. package/dist/web/assets/railroad-peg-WCYAUIDC-Df_Ifaad.js +0 -1
  124. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-CDSrqdgx.js +0 -8
@@ -1,20 +1,39 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ contentHash,
4
+ docAtRevision,
5
+ docHistory,
6
+ getRules,
7
+ listDocs,
8
+ readDoc,
9
+ rulesAdd,
10
+ rulesRemove,
11
+ rulesUpdate,
12
+ saveDoc,
13
+ searchDocs
14
+ } from "./chunk-LEMPCNAY.js";
2
15
  import {
3
16
  configureAgents,
4
17
  listAgents,
5
18
  removeAgents
6
- } from "./chunk-JY6BFIJJ.js";
19
+ } from "./chunk-QLW657NT.js";
20
+ import {
21
+ watchProject
22
+ } from "./chunk-DZDI2HRT.js";
23
+ import {
24
+ AnalysisScheduler
25
+ } from "./chunk-RVTNSNGK.js";
7
26
  import {
8
27
  getRelevantContext,
9
28
  graphSummary,
10
29
  refreshGraph
11
- } from "./chunk-CXUTYCZX.js";
30
+ } from "./chunk-UAZLPNVC.js";
12
31
  import {
13
32
  runSecurityScan
14
- } from "./chunk-LMOFZNTQ.js";
33
+ } from "./chunk-SJ4DQFIJ.js";
15
34
  import {
16
35
  reviewChanges
17
- } from "./chunk-EF6GHOIN.js";
36
+ } from "./chunk-FVCDMQUQ.js";
18
37
  import {
19
38
  buildStatus
20
39
  } from "./chunk-ZB7LC6FP.js";
@@ -22,25 +41,11 @@ import {
22
41
  INSTANCE_FILE,
23
42
  findRunningInstance,
24
43
  runDoctor
25
- } from "./chunk-PR53DT7I.js";
44
+ } from "./chunk-3XSDI5WF.js";
26
45
  import {
27
46
  aiStatus
28
47
  } from "./chunk-RXNRMIZP.js";
29
48
  import "./chunk-VSYBC3VY.js";
30
- import {
31
- contentHash,
32
- docAtRevision,
33
- docHistory,
34
- getRules,
35
- listDocs,
36
- readDoc,
37
- rulesAdd,
38
- rulesRemove,
39
- rulesUpdate,
40
- saveDoc,
41
- searchDocs
42
- } from "./chunk-LEMPCNAY.js";
43
- import "./chunk-3IS2X2Z7.js";
44
49
  import {
45
50
  ACTIVITY_FILE,
46
51
  activityFile,
@@ -53,11 +58,20 @@ import {
53
58
  printHeader
54
59
  } from "./chunk-SHKXELUX.js";
55
60
  import {
56
- watchProject
57
- } from "./chunk-32PRS2MG.js";
58
- import {
59
- AnalysisScheduler
60
- } from "./chunk-XB66PZ6Z.js";
61
+ MEMORY_DIR,
62
+ MEMORY_FILES,
63
+ MEMORY_KINDS,
64
+ MEMORY_STATUSES,
65
+ addMemory,
66
+ confirmMemory,
67
+ forgetMemory,
68
+ getMemory,
69
+ listMemory,
70
+ memoryDir,
71
+ supersedeMemory,
72
+ updateMemory
73
+ } from "./chunk-TDNZ2RYA.js";
74
+ import "./chunk-3IS2X2Z7.js";
61
75
  import {
62
76
  c,
63
77
  dim,
@@ -76,28 +90,31 @@ import {
76
90
  applySync,
77
91
  ignorePlan,
78
92
  staleForCheck
79
- } from "./chunk-TGJUUB44.js";
93
+ } from "./chunk-KHMBNT66.js";
80
94
  import {
81
95
  projectSession,
82
96
  releaseProjectSession
83
- } from "./chunk-PDFQ5BFG.js";
97
+ } from "./chunk-WVQC2EGO.js";
84
98
  import "./chunk-GR4DL2VM.js";
85
99
  import {
86
100
  runPipeline
87
- } from "./chunk-SJOOXO34.js";
101
+ } from "./chunk-GGXPG6OE.js";
88
102
  import {
89
103
  SCAN_FILE,
90
104
  saveScan
91
- } from "./chunk-PANVPNYF.js";
105
+ } from "./chunk-MPG3IEGB.js";
92
106
  import "./chunk-ELKFRTZT.js";
93
107
  import {
94
108
  ATHENA_VERSION
95
109
  } from "./chunk-2R6PXY6Z.js";
96
110
  import "./chunk-PVCIGUIT.js";
97
111
  import "./chunk-OLPSEQS5.js";
112
+ import "./chunk-SVTEJYMS.js";
113
+ import "./chunk-QCC4VJUH.js";
98
114
  import "./chunk-JCGDR4UV.js";
99
- import "./chunk-2RS6TA3D.js";
115
+ import "./chunk-YRIS7ZS6.js";
100
116
  import "./chunk-GHFRQAYT.js";
117
+ import "./chunk-INT3IGMQ.js";
101
118
  import "./chunk-673EPYYH.js";
102
119
  import {
103
120
  KNOWLEDGE_DOCS,
@@ -113,7 +130,6 @@ import {
113
130
  AthenaError,
114
131
  notFound
115
132
  } from "./chunk-AD4OZCU2.js";
116
- import "./chunk-INT3IGMQ.js";
117
133
  import "./chunk-XW3MLHI2.js";
118
134
  import "./chunk-EUPETUWA.js";
119
135
 
@@ -121,8 +137,8 @@ import "./chunk-EUPETUWA.js";
121
137
  import { execFile } from "child_process";
122
138
 
123
139
  // src/server/instance.ts
124
- import { promises as fs6 } from "fs";
125
- import path4 from "path";
140
+ import { promises as fs7 } from "fs";
141
+ import path5 from "path";
126
142
  import { fileURLToPath } from "url";
127
143
 
128
144
  // src/server/app.ts
@@ -568,6 +584,111 @@ function registerGraphRoutes({ app, root, events, state }) {
568
584
  });
569
585
  }
570
586
 
587
+ // src/server/routes/memory.ts
588
+ import { promises as fs2 } from "fs";
589
+ import path from "path";
590
+ var memoryWriteKey = (file) => `memory/${file}`;
591
+ var ID = "^m-[a-z0-9]{4,16}$";
592
+ var idParams = { type: "object", required: ["id"], additionalProperties: false, properties: { id: { type: "string", pattern: ID } } };
593
+ var fields = {
594
+ title: { type: "string", maxLength: 1e3 },
595
+ details: { type: "string", maxLength: 1e4 },
596
+ files: { type: "array", maxItems: 50, items: { type: "string", maxLength: 500 } },
597
+ tags: { type: "array", maxItems: 30, items: { type: "string", maxLength: 100 } },
598
+ evidence: { type: "string", maxLength: 2e3 }
599
+ };
600
+ function memoryCounts(entries) {
601
+ return {
602
+ total: entries.length,
603
+ unreviewed: entries.filter((e) => e.status === "unreviewed").length,
604
+ confirmed: entries.filter((e) => e.status === "confirmed").length,
605
+ superseded: entries.filter((e) => e.status === "superseded").length,
606
+ stale: entries.filter((e) => e.stale).length,
607
+ flagged: entries.filter((e) => e.flags.length > 0).length
608
+ };
609
+ }
610
+ function registerMemoryRoutes({ app, root, events, recentWrites }) {
611
+ const recordWrites = async () => {
612
+ for (const file of Object.values(MEMORY_FILES)) {
613
+ const text = await fs2.readFile(path.join(memoryDir(root), file), "utf8").catch(() => null);
614
+ if (text !== null) recentWrites.set(memoryWriteKey(file), contentHash(text));
615
+ }
616
+ };
617
+ const changed = async (action, id, message) => {
618
+ await recordWrites();
619
+ events.emit({ source: "web-ui", type: "memory.changed", level: "success", message, data: { action, id } });
620
+ };
621
+ app.get(
622
+ "/api/memory",
623
+ {
624
+ schema: {
625
+ querystring: {
626
+ type: "object",
627
+ additionalProperties: false,
628
+ properties: { kind: { type: "string", enum: [...MEMORY_KINDS] }, status: { type: "string", enum: [...MEMORY_STATUSES] }, stale: { type: "string", enum: ["true", "false"] } }
629
+ }
630
+ }
631
+ },
632
+ async (req) => {
633
+ const all = await listMemory(root);
634
+ const { kind, status, stale } = req.query;
635
+ const entries = all.filter((e) => (!kind || e.kind === kind) && (!status || e.status === status) && (stale === void 0 || e.stale === (stale === "true")));
636
+ return { entries, counts: memoryCounts(all) };
637
+ }
638
+ );
639
+ app.get("/api/memory/:id", { schema: { params: idParams } }, async (req) => getMemory(root, req.params.id));
640
+ app.post(
641
+ "/api/memory",
642
+ {
643
+ schema: {
644
+ body: {
645
+ type: "object",
646
+ required: ["kind", "title"],
647
+ additionalProperties: false,
648
+ properties: { kind: { type: "string", enum: [...MEMORY_KINDS] }, ...fields, supersedes: { type: "string", pattern: ID } }
649
+ }
650
+ }
651
+ },
652
+ async (req, reply) => {
653
+ const entry = await addMemory(root, req.body, "developer");
654
+ await changed("add", entry.id, `Added memory: ${entry.title}`);
655
+ return reply.code(201).send(entry);
656
+ }
657
+ );
658
+ app.post("/api/memory/:id/confirm", { schema: { params: idParams } }, async (req) => {
659
+ const entry = await confirmMemory(root, req.params.id);
660
+ await changed("confirm", entry.id, `Confirmed memory: ${entry.title}`);
661
+ return entry;
662
+ });
663
+ app.post(
664
+ "/api/memory/:id/supersede",
665
+ { schema: { params: idParams, body: { type: "object", required: ["by"], additionalProperties: false, properties: { by: { type: "string", pattern: ID } } } } },
666
+ async (req) => {
667
+ const { id } = req.params;
668
+ const { by } = req.body;
669
+ await getMemory(root, id);
670
+ if (id !== by && !(await listMemory(root)).some((e) => e.id === by)) throw new AthenaError(`Cannot supersede ${id}: no memory with id ${by}.`);
671
+ const entry = await supersedeMemory(root, id, by);
672
+ await changed("supersede", entry.id, `Memory ${id} superseded by ${by}`);
673
+ return entry;
674
+ }
675
+ );
676
+ app.patch(
677
+ "/api/memory/:id",
678
+ { schema: { params: idParams, body: { type: "object", minProperties: 1, additionalProperties: false, properties: fields } } },
679
+ async (req) => {
680
+ const entry = await updateMemory(root, req.params.id, req.body);
681
+ await changed("edit", entry.id, `Edited memory: ${entry.title}`);
682
+ return entry;
683
+ }
684
+ );
685
+ app.delete("/api/memory/:id", { schema: { params: idParams } }, async (req) => {
686
+ await forgetMemory(root, req.params.id);
687
+ await changed("forget", req.params.id, `Forgot memory ${req.params.id}`);
688
+ return { ok: true };
689
+ });
690
+ }
691
+
571
692
  // src/server/routes/review.ts
572
693
  function registerReviewRoutes({ app, root, scheduler }) {
573
694
  app.get("/api/review", async (req) => {
@@ -711,11 +832,11 @@ function registerSessionRoutes({ app, root, instanceId, getStatus }) {
711
832
  }
712
833
 
713
834
  // src/server/routes/static.ts
714
- import { promises as fs3 } from "fs";
835
+ import { promises as fs4 } from "fs";
715
836
 
716
837
  // src/server/static.ts
717
- import { promises as fs2 } from "fs";
718
- import path from "path";
838
+ import { promises as fs3 } from "fs";
839
+ import path2 from "path";
719
840
  var TYPES = {
720
841
  ".html": "text/html; charset=utf-8",
721
842
  ".js": "text/javascript; charset=utf-8",
@@ -731,20 +852,20 @@ var TYPES = {
731
852
  };
732
853
  async function buildAssetMap(webDir) {
733
854
  try {
734
- await fs2.access(path.join(webDir, "index.html"));
855
+ await fs3.access(path2.join(webDir, "index.html"));
735
856
  } catch {
736
857
  return null;
737
858
  }
738
859
  const map = /* @__PURE__ */ new Map();
739
860
  async function walk(dir) {
740
- for (const ent of await fs2.readdir(dir, { withFileTypes: true })) {
741
- const abs = path.join(dir, ent.name);
861
+ for (const ent of await fs3.readdir(dir, { withFileTypes: true })) {
862
+ const abs = path2.join(dir, ent.name);
742
863
  if (ent.isDirectory()) await walk(abs);
743
864
  else if (ent.isFile()) {
744
- const ext = path.extname(ent.name).toLowerCase();
865
+ const ext = path2.extname(ent.name).toLowerCase();
745
866
  const type = TYPES[ext];
746
867
  if (!type) continue;
747
- const urlPath = `/${path.relative(webDir, abs).split(path.sep).join("/")}`;
868
+ const urlPath = `/${path2.relative(webDir, abs).split(path2.sep).join("/")}`;
748
869
  map.set(urlPath, { abs, type, immutable: urlPath.startsWith("/assets/") });
749
870
  }
750
871
  }
@@ -763,7 +884,7 @@ function registerStaticRoutes(app, assets) {
763
884
  const sendAsset = async (reply, urlPath) => {
764
885
  if (!assets) return reply.code(503).type("text/html; charset=utf-8").send(MISSING_UI_HTML);
765
886
  const asset = assets.get(urlPath) ?? assets.get("/index.html");
766
- const body = await fs3.readFile(asset.abs);
887
+ const body = await fs4.readFile(asset.abs);
767
888
  reply.header("Cache-Control", asset.immutable ? "public, max-age=31536000, immutable" : "no-cache");
768
889
  return reply.type(asset.type).send(body);
769
890
  };
@@ -785,8 +906,8 @@ function registerStaticRoutes(app, assets) {
785
906
  }
786
907
 
787
908
  // src/server/routes/sync.ts
788
- import { promises as fs4 } from "fs";
789
- import path2 from "path";
909
+ import { promises as fs5 } from "fs";
910
+ import path3 from "path";
790
911
  function summarizePlan(plan) {
791
912
  if (!plan) return null;
792
913
  return { ...plan, documents: plan.documents.map(({ diff: _diff, ...rest }) => rest) };
@@ -824,7 +945,7 @@ function registerSyncRoutes(ctx) {
824
945
  try {
825
946
  const result = await ctx.scheduler.exclusive(() => applySync(root, plan));
826
947
  for (const d of plan.documents) {
827
- const text = await fs4.readFile(path2.join(athenaDir(root), d.file), "utf8").catch(() => null);
948
+ const text = await fs5.readFile(path3.join(athenaDir(root), d.file), "utf8").catch(() => null);
828
949
  if (text !== null) ctx.recentWrites.set(d.file, contentHash(text));
829
950
  }
830
951
  state.currentPlan = null;
@@ -950,8 +1071,8 @@ var SseHub = class {
950
1071
  };
951
1072
 
952
1073
  // src/server/watchers.ts
953
- import { promises as fs5, watch } from "fs";
954
- import path3 from "path";
1074
+ import { promises as fs6, watch } from "fs";
1075
+ import path4 from "path";
955
1076
  function watchKnowledgeDir(ctx, feed) {
956
1077
  const { events, recentWrites } = ctx;
957
1078
  let docsWatcher = null;
@@ -974,7 +1095,7 @@ function watchKnowledgeDir(ctx, feed) {
974
1095
  name,
975
1096
  setTimeout(async () => {
976
1097
  pending.delete(name);
977
- const text = await fs5.readFile(path3.join(dir, name), "utf8").catch(() => null);
1098
+ const text = await fs6.readFile(path4.join(dir, name), "utf8").catch(() => null);
978
1099
  const hash = text === null ? null : contentHash(text);
979
1100
  if (hash && recentWrites.get(name) === hash) return;
980
1101
  ctx.invalidateStatus();
@@ -992,6 +1113,73 @@ function watchKnowledgeDir(ctx, feed) {
992
1113
  for (const t of pending.values()) clearTimeout(t);
993
1114
  };
994
1115
  }
1116
+ var MEMORY_FILE_NAMES = new Set(Object.values(MEMORY_FILES));
1117
+ function watchMemoryDir(ctx, debounceMs = 150) {
1118
+ const { events, recentWrites } = ctx;
1119
+ const dir = memoryDir(ctx.root);
1120
+ const pending = /* @__PURE__ */ new Map();
1121
+ let memWatcher = null;
1122
+ let parentWatcher = null;
1123
+ let stopped = false;
1124
+ const onChange = (name) => {
1125
+ clearTimeout(pending.get(name));
1126
+ pending.set(
1127
+ name,
1128
+ setTimeout(async () => {
1129
+ pending.delete(name);
1130
+ const text = await fs6.readFile(path4.join(dir, name), "utf8").catch(() => null);
1131
+ const hash = text === null ? null : contentHash(text);
1132
+ const key = memoryWriteKey(name);
1133
+ if ((recentWrites.get(key) ?? null) === hash) return;
1134
+ if (hash) recentWrites.set(key, hash);
1135
+ else recentWrites.delete(key);
1136
+ if (stopped) return;
1137
+ events.emit({ source: "filesystem", type: "memory.changed", level: "info", message: text === null ? `memory/${name} was deleted on disk` : `memory/${name} changed on disk`, data: { action: "external", file: name } });
1138
+ }, debounceMs)
1139
+ );
1140
+ };
1141
+ const attach = () => {
1142
+ if (memWatcher || stopped) return true;
1143
+ try {
1144
+ memWatcher = watch(dir, { persistent: false }, (_type, filename) => {
1145
+ const name = filename?.toString();
1146
+ if (name && MEMORY_FILE_NAMES.has(name)) onChange(name);
1147
+ });
1148
+ memWatcher.on("error", () => {
1149
+ });
1150
+ } catch {
1151
+ return false;
1152
+ }
1153
+ for (const name of MEMORY_FILE_NAMES) onChange(name);
1154
+ return true;
1155
+ };
1156
+ void Promise.all(
1157
+ [...MEMORY_FILE_NAMES].map(async (name) => {
1158
+ const text = await fs6.readFile(path4.join(dir, name), "utf8").catch(() => null);
1159
+ if (text !== null && !recentWrites.has(memoryWriteKey(name))) recentWrites.set(memoryWriteKey(name), contentHash(text));
1160
+ })
1161
+ ).then(() => {
1162
+ if (stopped || attach()) return;
1163
+ try {
1164
+ parentWatcher = watch(athenaDir(ctx.root), { persistent: false }, (_type, filename) => {
1165
+ if (filename?.toString() === MEMORY_DIR && attach()) {
1166
+ parentWatcher?.close();
1167
+ parentWatcher = null;
1168
+ }
1169
+ });
1170
+ parentWatcher.on("error", () => {
1171
+ });
1172
+ } catch {
1173
+ parentWatcher = null;
1174
+ }
1175
+ });
1176
+ return () => {
1177
+ stopped = true;
1178
+ memWatcher?.close();
1179
+ parentWatcher?.close();
1180
+ for (const t of pending.values()) clearTimeout(t);
1181
+ };
1182
+ }
995
1183
  async function watchProjectFiles(ctx, debounceMs) {
996
1184
  const { events, state } = ctx;
997
1185
  try {
@@ -1108,9 +1296,11 @@ async function createServer(opts) {
1108
1296
  registerContextRoutes(ctx);
1109
1297
  registerGraphRoutes(ctx);
1110
1298
  registerActivityRoutes(ctx);
1299
+ registerMemoryRoutes(ctx);
1111
1300
  registerEventRoutes(app, hub);
1112
1301
  registerStaticRoutes(app, assets);
1113
1302
  const stopDocsWatcher = watchKnowledgeDir(ctx, feed);
1303
+ const stopMemoryWatcher = watchMemoryDir(ctx, opts.watchDebounceMs === void 0 ? void 0 : Math.min(opts.watchDebounceMs, 150));
1114
1304
  await feed.seed();
1115
1305
  if (opts.watch) await watchProjectFiles(ctx, opts.watchDebounceMs);
1116
1306
  return {
@@ -1123,6 +1313,7 @@ async function createServer(opts) {
1123
1313
  ctx.state.watcher = null;
1124
1314
  ctx.scheduler.close();
1125
1315
  stopDocsWatcher();
1316
+ stopMemoryWatcher();
1126
1317
  events.close();
1127
1318
  await app.close();
1128
1319
  hub.close();
@@ -1151,8 +1342,8 @@ async function findAvailablePort(host, start = DEFAULT_PORT, attempts = 100) {
1151
1342
 
1152
1343
  // src/server/instance.ts
1153
1344
  function defaultWebDir() {
1154
- const here = path4.dirname(fileURLToPath(import.meta.url));
1155
- return path4.basename(here) === "dist" ? path4.join(here, "web") : path4.resolve(here, "../../dist/web");
1345
+ const here = path5.dirname(fileURLToPath(import.meta.url));
1346
+ return path5.basename(here) === "dist" ? path5.join(here, "web") : path5.resolve(here, "../../dist/web");
1156
1347
  }
1157
1348
  function browserUrl(info) {
1158
1349
  const host = info.host.includes(":") ? `[${info.host}]` : info.host;
@@ -1168,8 +1359,8 @@ async function startServer(opts) {
1168
1359
  const server = await createServer({ root: opts.root, token, host, port, webDir: opts.webDir ?? defaultWebDir(), allowRemote: opts.allowRemote, watch: opts.watch ?? true });
1169
1360
  await server.app.listen({ host, port });
1170
1361
  const info = { pid: process.pid, host, port, instanceId: server.instanceId, token, startedAt: (/* @__PURE__ */ new Date()).toISOString() };
1171
- const file = path4.join(athenaDir(opts.root), INSTANCE_FILE);
1172
- await fs6.writeFile(file, `${JSON.stringify(info, null, 2)}
1362
+ const file = path5.join(athenaDir(opts.root), INSTANCE_FILE);
1363
+ await fs7.writeFile(file, `${JSON.stringify(info, null, 2)}
1173
1364
  `, { mode: 384 });
1174
1365
  await ensureGitignored(opts.root, INSTANCE_FILE);
1175
1366
  return {
@@ -1178,16 +1369,16 @@ async function startServer(opts) {
1178
1369
  url: browserUrl(info),
1179
1370
  async close() {
1180
1371
  const current = await readTextIfExists(file);
1181
- if (current && current.includes(server.instanceId)) await fs6.rm(file, { force: true });
1372
+ if (current && current.includes(server.instanceId)) await fs7.rm(file, { force: true });
1182
1373
  await server.close();
1183
1374
  }
1184
1375
  };
1185
1376
  }
1186
1377
  async function ensureGitignored(root, entry) {
1187
- const file = path4.join(athenaDir(root), ".gitignore");
1378
+ const file = path5.join(athenaDir(root), ".gitignore");
1188
1379
  const text = await readTextIfExists(file) ?? "";
1189
1380
  if (text.split(/\r?\n/).includes(entry)) return;
1190
- await fs6.writeFile(file, `${text}${text.endsWith("\n") || !text ? "" : "\n"}${entry}
1381
+ await fs7.writeFile(file, `${text}${text.endsWith("\n") || !text ? "" : "\n"}${entry}
1191
1382
  `);
1192
1383
  }
1193
1384
 
@@ -1256,4 +1447,4 @@ export {
1256
1447
  openBrowser,
1257
1448
  openCommand
1258
1449
  };
1259
- //# sourceMappingURL=open-2QSZKKUG.js.map
1450
+ //# sourceMappingURL=open-UJZRYF4E.js.map
@@ -31,7 +31,10 @@ ${c.yellow("Interrupted.")} ${dim(getInterruptMessage())}
31
31
  `);
32
32
  }
33
33
  process.stdout.on("error", (err) => {
34
- if (err.code === "EPIPE") process.exit(0);
34
+ if (err.code === "EPIPE") {
35
+ if (process.env.ATHENA_DEBUG) process.stderr.write("athena: stdout was closed by the reader (EPIPE); exiting quietly\n");
36
+ process.exit(0);
37
+ }
35
38
  throw err;
36
39
  });
37
40
  process.on("SIGINT", onSignal);
@@ -55,23 +58,23 @@ function buildProgram() {
55
58
  program.command("init").description("Analyze the project and create .athena/ knowledge").option("--agents <list>", 'Agents to configure: comma-separated ids (claude-code, cursor, codex, copilot, gemini-cli, antigravity, windsurf, cline, agents-md), "all" or "none". Default: detected agents + AGENTS.md').option("--no-agents", "Do not configure any agent integration").option("--dry-run", "Analyze and show what would be written, without writing").action(
56
59
  run(async (cmdOpts, cmd) => {
57
60
  const g = globals(cmd);
58
- await (await import("./init-2V34DVRQ.js")).initCommand({ ...g, agents: typeof cmdOpts.agents === "string" ? cmdOpts.agents : void 0, noAgents: cmdOpts.agents === false, dryRun: cmdOpts.dryRun, signal: controller.signal });
61
+ await (await import("./init-WQCAOJ2R.js")).initCommand({ ...g, agents: typeof cmdOpts.agents === "string" ? cmdOpts.agents : void 0, noAgents: cmdOpts.agents === false, dryRun: cmdOpts.dryRun, signal: controller.signal });
59
62
  })
60
63
  );
61
- program.command("analyze").description("Re-analyze the project and refresh generated knowledge (developer edits are preserved)").option("--force", "Regenerate sections even if they were edited by hand").option("--agents <list>", "Reconfigure these agent integrations").action(run(async (o, cmd) => (await import("./analyze-F3YOILNL.js")).analyzeCommand({ ...globals(cmd), ...o, signal: controller.signal })));
62
- program.command("sync").description("Review and apply knowledge updates for changes since the last analysis").option("-y, --yes", "Apply without asking").option("--dry-run", "Show the plan without writing").option("--check", "Exit with code 1 if knowledge is out of date (for CI/hooks)").option("--staged", "With --check: check the staged knowledge against the staged code (the index), ignoring untracked and unstaged changes").option("--diff", "Print full diffs of proposed document changes").option("--force", "Also regenerate sections that were edited by hand").action(run(async (o, cmd) => (await import("./sync-3ZNJDSSU.js")).syncCommand({ ...globals(cmd), ...o, signal: controller.signal })));
63
- program.command("watch").description("Watch the project and propose knowledge updates as files change").option("--auto-apply", "Apply updates automatically instead of proposing them").option("--debounce <ms>", "Quiet period before checking changes (default 1500)").action(run(async (o, cmd) => (await import("./watch-USN5CQIV.js")).watchCommand({ ...globals(cmd), ...o, signal: controller.signal })));
64
- program.command("context <task>").description("Show which knowledge an agent should read for a task (deterministic)").option("--full", "Print the full context an agent would receive").option("--max-chars <n>", "Character budget for selected sections").action(run(async (task, o, cmd) => (await import("./context-AH5MFHRG.js")).contextCommand(task, { ...globals(cmd), ...o, signal: controller.signal })));
65
- program.command("graph").description("Inspect the project graph (packages, files, routes, entities and their relationships)").option("--build", "Rebuild the graph from the current code").option("--node <id>", "Show one node and its relationships").option("--kind <kind>", "Filter by node kind (package, file, route, entity, framework, command, infra)").option("--search <term>", "Filter nodes by name or path").action(run(async (o, cmd) => (await import("./context-AH5MFHRG.js")).graphCommand({ ...globals(cmd), ...o, signal: controller.signal })));
66
- program.command("architecture").description("Summarize the project graph").action(run(async (_o, cmd) => (await import("./context-AH5MFHRG.js")).architectureCommand({ ...globals(cmd), signal: controller.signal })));
67
- program.command("mcp").description("Serve Athena project intelligence over MCP (stdio) for AI agents").option("--allow-write", "Permit the update_knowledge tool to apply changes (read-only by default)").action(run(async (o, cmd) => (await import("./mcp-T2GRTEX5.js")).mcpCommand({ ...globals(cmd), ...o, signal: controller.signal })));
64
+ program.command("analyze").description("Re-analyze the project and refresh generated knowledge (developer edits are preserved)").option("--force", "Regenerate sections even if they were edited by hand").option("--agents <list>", "Reconfigure these agent integrations").action(run(async (o, cmd) => (await import("./analyze-ZY3MXBOI.js")).analyzeCommand({ ...globals(cmd), ...o, signal: controller.signal })));
65
+ program.command("sync").description("Review and apply knowledge updates for changes since the last analysis").option("-y, --yes", "Apply without asking").option("--dry-run", "Show the plan without writing").option("--check", "Exit with code 1 if knowledge is out of date (for CI/hooks)").option("--staged", "With --check: check the staged knowledge against the staged code (the index), ignoring untracked and unstaged changes").option("--diff", "Print full diffs of proposed document changes").option("--force", "Also regenerate sections that were edited by hand").action(run(async (o, cmd) => (await import("./sync-KFJANRXF.js")).syncCommand({ ...globals(cmd), ...o, signal: controller.signal })));
66
+ program.command("watch").description("Watch the project and propose knowledge updates as files change").option("--auto-apply", "Apply updates automatically instead of proposing them").option("--debounce <ms>", "Quiet period before checking changes (default 1500)").action(run(async (o, cmd) => (await import("./watch-CY7QHIYN.js")).watchCommand({ ...globals(cmd), ...o, signal: controller.signal })));
67
+ program.command("context <task>").description("Show which knowledge an agent should read for a task (deterministic)").option("--full", "Print the full context an agent would receive").option("--max-chars <n>", "Character budget for selected sections").action(run(async (task, o, cmd) => (await import("./context-PLPCAPCO.js")).contextCommand(task, { ...globals(cmd), ...o, signal: controller.signal })));
68
+ program.command("graph").description("Inspect the project graph (packages, files, routes, entities and their relationships)").option("--build", "Rebuild the graph from the current code").option("--node <id>", "Show one node and its relationships").option("--kind <kind>", "Filter by node kind (package, file, route, entity, framework, command, infra)").option("--search <term>", "Filter nodes by name or path").action(run(async (o, cmd) => (await import("./context-PLPCAPCO.js")).graphCommand({ ...globals(cmd), ...o, signal: controller.signal })));
69
+ program.command("architecture").description("Summarize the project graph").action(run(async (_o, cmd) => (await import("./context-PLPCAPCO.js")).architectureCommand({ ...globals(cmd), signal: controller.signal })));
70
+ program.command("mcp").description("Serve Athena project intelligence over MCP (stdio) for AI agents").option("--allow-write", "Permit the update_knowledge tool to apply changes (read-only by default)").option("--no-memory-write", "Disable the remember tool (agents cannot record unreviewed memories)").action(run(async (o, cmd) => (await import("./mcp-U7EPH43L.js")).mcpCommand({ ...globals(cmd), ...o, signal: controller.signal })));
68
71
  const ai = program.command("ai").description("Optional AI provider integration (never required)");
69
72
  ai.command("status", { isDefault: true }).description("Show configured and available AI providers").action(run(async (_o, cmd) => (await import("./ai-ASL4FFQ7.js")).aiStatusCommand(globals(cmd))));
70
73
  ai.command("enrich").description("Ask the configured provider for INFERRED suggestions based on your knowledge documents").option("--docs <list>", "Documents to send (default: project,architecture,database,api)").option("--consent", "Consent to sending redacted knowledge to a remote provider for this run").option("--dry-run", "Show exactly what would be sent, and send nothing").action(run(async (o, cmd) => (await import("./ai-ASL4FFQ7.js")).aiEnrichCommand({ ...globals(cmd), ...o, signal: controller.signal })));
71
- program.command("security").description("Scan dependencies with the audit tools installed for this project, and report secret findings").option("--no-audit", "Skip dependency audits (report secrets only)").option("--fail-on <severity>", "Exit 1 when a finding at or above this severity exists (critical, high, moderate, low)").option("--last", "Show the last scan instead of running a new one").option("--unrated <policy>", 'With --fail-on: "fail" (default) also fails on findings the tool did not rate (pip-audit, govulncheck); "warn" only reports them', "fail").action(run(async (o, cmd) => (await import("./security-PI4LXCOB.js")).securityCommand({ ...globals(cmd), noAudit: o.audit === false, failOn: o.failOn, unrated: o.unrated, last: o.last, signal: controller.signal })));
72
- program.command("review").description("Check the current diff for facts worth reviewing, and list the project rules and checklist").option("--base <ref>", "Compare against this Git ref instead of the working tree").option("--staged", "Review only what is staged for commit (used by the pre-commit hook)").option("--no-sync", "Skip the knowledge freshness check").option("--no-fail", "Always exit 0, even when blockers are found").action(run(async (o, cmd) => (await import("./review-R3R2J5BJ.js")).reviewCommand({ ...globals(cmd), base: o.base, staged: o.staged, noSync: o.sync === false, noFail: o.fail === false, signal: controller.signal })));
73
- program.command("status").description("Show knowledge health and changes since the last analysis").action(run(async (_o, cmd) => (await import("./status-6M73WX5I.js")).statusCommand({ ...globals(cmd), signal: controller.signal })));
74
- program.command("doctor").description("Check the Athena installation, project and integrations").action(run(async (_o, cmd) => (await import("./doctor-RSJMLE2P.js")).doctorCommand(globals(cmd))));
74
+ program.command("security").description("Scan dependencies with the audit tools installed for this project, and report secret findings").option("--no-audit", "Skip dependency audits (report secrets only)").option("--fail-on <severity>", "Exit 1 when a finding at or above this severity exists (critical, high, moderate, low)").option("--last", "Show the last scan instead of running a new one").option("--unrated <policy>", 'With --fail-on: "fail" (default) also fails on findings the tool did not rate (pip-audit, govulncheck); "warn" only reports them', "fail").action(run(async (o, cmd) => (await import("./security-LME3XFL3.js")).securityCommand({ ...globals(cmd), noAudit: o.audit === false, failOn: o.failOn, unrated: o.unrated, last: o.last, signal: controller.signal })));
75
+ program.command("review").description("Check the current diff for facts worth reviewing, and list the project rules and checklist").option("--base <ref>", "Compare against this Git ref instead of the working tree").option("--staged", "Review only what is staged for commit (used by the pre-commit hook)").option("--no-sync", "Skip the knowledge freshness check").option("--no-fail", "Always exit 0, even when blockers are found").action(run(async (o, cmd) => (await import("./review-OOKXSYMP.js")).reviewCommand({ ...globals(cmd), base: o.base, staged: o.staged, noSync: o.sync === false, noFail: o.fail === false, signal: controller.signal })));
76
+ program.command("status").description("Show knowledge health and changes since the last analysis").action(run(async (_o, cmd) => (await import("./status-RR57ZNGI.js")).statusCommand({ ...globals(cmd), signal: controller.signal })));
77
+ program.command("doctor").description("Check the Athena installation, project and integrations").action(run(async (_o, cmd) => (await import("./doctor-BX677KRE.js")).doctorCommand(globals(cmd))));
75
78
  const rules = program.command("rules").description("List and edit project rules (.athena/rules.md)");
76
79
  rules.command("list", { isDefault: true }).description("List rules with their numbers").action(run(async (_o, cmd) => (await import("./rules-4FXJUCXB.js")).rulesListCommand(globals(cmd))));
77
80
  rules.command("add <text>").description("Add a rule").option("-s, --section <name>", "Section heading", "General").action(run(async (text, o, cmd) => (await import("./rules-4FXJUCXB.js")).rulesAddCommand(text, { ...globals(cmd), ...o })));
@@ -79,23 +82,37 @@ function buildProgram() {
79
82
  rules.command("enable <number>").description("Enable a rule").action(run(async (n, _o, cmd) => (await import("./rules-4FXJUCXB.js")).rulesEnableCommand(n, globals(cmd))));
80
83
  rules.command("disable <number>").description("Disable a rule without deleting it").action(run(async (n, _o, cmd) => (await import("./rules-4FXJUCXB.js")).rulesDisableCommand(n, globals(cmd))));
81
84
  rules.command("remove <number>").description("Delete a rule").action(run(async (n, _o, cmd) => (await import("./rules-4FXJUCXB.js")).rulesRemoveCommand(n, globals(cmd))));
85
+ const repeat = (value, prev = []) => [...prev, ...value.split(",").map((s) => s.trim()).filter(Boolean)];
86
+ const mem = () => import("./memory-VSVNLEJC.js");
87
+ const memory = program.command("memory").description("Record, review and recall project memory (.athena/memory/)");
88
+ memory.command("list", { isDefault: true }).description("List memory entries with their label (FACT/INFERRED), status and staleness").option("--kind <kind>", "Only this kind (decision, gotcha, bug, convention, todo, fact)").option("--status <status>", "Only this status (unreviewed, confirmed, superseded)").option("--stale", "Only entries whose linked files changed since").action(run(async (o, cmd) => (await mem()).memoryListCommand({ ...globals(cmd), ...o })));
89
+ memory.command("show <id>").description("Show one entry in full: files, tags, evidence, staleness, warnings").action(run(async (id, _o, cmd) => (await mem()).memoryShowCommand(id, globals(cmd))));
90
+ memory.command("add").description("Record a memory as the developer (confirmed, FACT)").option("--kind <kind>", "decision, gotcha, bug, convention, todo or fact").option("--title <title>", "One-line summary").option("--details <text>", 'Longer explanation ("-" reads it from stdin)').option("--file <path>", "Linked project file (repeatable); the entry goes stale when it changes", repeat).option("--tag <tag>", "Tag (repeatable)", repeat).option("--evidence <text>", "Where this was observed (commit, issue, test, log)").option("--supersedes <id>", "Older memory this one replaces").action(run(async (o, cmd) => (await mem()).memoryAddCommand({ ...globals(cmd), ...o })));
91
+ memory.command("search <query>").description("Find entries whose title, details, tags or files contain the text").action(run(async (q, _o, cmd) => (await mem()).memorySearchCommand(q, globals(cmd))));
92
+ memory.command("recall <task...>").description("Rank the memory relevant to a task (what an agent would be given), with reasons").option("--file <path>", "File you are about to work on (repeatable)", repeat).option("--tag <tag>", "Tag to match (repeatable)", repeat).option("-n, --limit <count>", "Maximum entries (default 8)").action(run(async (task, o, cmd) => (await mem()).memoryRecallCommand(task, { ...globals(cmd), ...o })));
93
+ memory.command("confirm <ids...>").description("Confirm entries as FACT (and re-anchor them to the current files)").action(run(async (ids, _o, cmd) => (await mem()).memoryConfirmCommand(ids, globals(cmd))));
94
+ memory.command("supersede <id>").description("Mark an entry as replaced by a newer one (kept as history)").option("--by <id>", "The newer memory").action(run(async (id, o, cmd) => (await mem()).memorySupersedeCommand(id, { ...globals(cmd), ...o })));
95
+ memory.command("forget <ids...>").description("Delete entries").option("-y, --yes", "Skip confirmation").action(run(async (ids, o, cmd) => (await mem()).memoryForgetCommand(ids, { ...globals(cmd), ...o })));
96
+ memory.command("edit <id>").description("Change an entry (fields you pass replace the old values)").option("--title <title>", "New title").option("--details <text>", 'New details ("-" reads them from stdin)').option("--file <path>", "Linked files (repeatable; replaces the list)", repeat).option("--tag <tag>", "Tags (repeatable; replaces the list)", repeat).option("--evidence <text>", "New evidence").action(run(async (id, o, cmd) => (await mem()).memoryEditCommand(id, { ...globals(cmd), ...o })));
97
+ memory.command("stale").description("Entries whose linked files changed since they were recorded or confirmed").action(run(async (_o, cmd) => (await mem()).memoryStaleCommand(globals(cmd))));
98
+ memory.command("review").description("Walk through unreviewed (agent-written) entries: confirm, forget or skip").action(run(async (_o, cmd) => (await mem()).memoryReviewCommand(globals(cmd))));
82
99
  const agents = program.command("agents").description("Manage AI agent integrations");
83
- agents.command("list", { isDefault: true }).description("Show supported agents and integration status").action(run(async (_o, cmd) => (await import("./agents-3HTSQGL2.js")).agentsListCommand(globals(cmd))));
84
- agents.command("add <agents...>").description('Configure integrations (claude-code, cursor, codex, copilot, gemini-cli, antigravity, windsurf, cline, agents-md, or "all")').action(run(async (names, _o, cmd) => (await import("./agents-3HTSQGL2.js")).agentsAddCommand(names, globals(cmd))));
85
- agents.command("remove <agents...>").description("Remove Athena-managed integration files/blocks").action(run(async (names, _o, cmd) => (await import("./agents-3HTSQGL2.js")).agentsRemoveCommand(names, globals(cmd))));
100
+ agents.command("list", { isDefault: true }).description("Show supported agents and integration status").action(run(async (_o, cmd) => (await import("./agents-DFSNEOP5.js")).agentsListCommand(globals(cmd))));
101
+ agents.command("add <agents...>").description('Configure integrations (claude-code, cursor, codex, copilot, gemini-cli, antigravity, windsurf, cline, agents-md, or "all")').action(run(async (names, _o, cmd) => (await import("./agents-DFSNEOP5.js")).agentsAddCommand(names, globals(cmd))));
102
+ agents.command("remove <agents...>").description("Remove Athena-managed integration files/blocks").action(run(async (names, _o, cmd) => (await import("./agents-DFSNEOP5.js")).agentsRemoveCommand(names, globals(cmd))));
86
103
  const gitHook = program.command("git-hook").description("Install a Git pre-commit hook that blocks commits when knowledge is out of date");
87
104
  gitHook.command("status", { isDefault: true }).description("Show whether the Athena pre-commit hook is installed").action(run(async (_o, cmd) => (await import("./git-hook-YZNZGAAP.js")).gitHookStatusCommand(globals(cmd))));
88
105
  gitHook.command("install").description("Add the Athena pre-commit hook (existing hooks are kept; Athena adds a marked block)").option("--review", "Also run `athena review` and block commits with possible secrets or env files").action(run(async (o, cmd) => (await import("./git-hook-YZNZGAAP.js")).gitHookInstallCommand({ ...globals(cmd), review: o.review })));
89
106
  gitHook.command("uninstall").description("Remove Athena's pre-commit hook or block").action(run(async (_o, cmd) => (await import("./git-hook-YZNZGAAP.js")).gitHookUninstallCommand(globals(cmd))));
90
- program.command("open").description("Start (or reuse) the local web UI and open it in your browser").option("-p, --port <port>", "Port to bind (default: first free port from 7432)").option("--host <host>", "Interface to bind (default: 127.0.0.1)").option("--allow-remote", "Allow binding to a non-loopback interface").option("--no-open", "Do not launch a browser").option("--no-watch", "Do not watch the project for changes").action(run(async (o, cmd) => (await import("./open-2QSZKKUG.js")).openCommand({ ...globals(cmd), ...o, signal: controller.signal })));
91
- program.command("activity").description("Show AI agent activity observed through hooks").option("-n, --limit <count>", "Number of events to show (default 30)").option("--agent <id>", "Only show events from this agent").action(run(async (o, cmd) => (await import("./activity-P4UUFHWV.js")).activityCommand({ ...globals(cmd), ...o })));
107
+ program.command("open").description("Start (or reuse) the local web UI and open it in your browser").option("-p, --port <port>", "Port to bind (default: first free port from 7432)").option("--host <host>", "Interface to bind (default: 127.0.0.1)").option("--allow-remote", "Allow binding to a non-loopback interface").option("--no-open", "Do not launch a browser").option("--no-watch", "Do not watch the project for changes").action(run(async (o, cmd) => (await import("./open-UJZRYF4E.js")).openCommand({ ...globals(cmd), ...o, signal: controller.signal })));
108
+ program.command("activity").description("Show AI agent activity observed through hooks").option("-n, --limit <count>", "Number of events to show (default 30)").option("--agent <id>", "Only show events from this agent").action(run(async (o, cmd) => (await import("./activity-BKW7G4I5.js")).activityCommand({ ...globals(cmd), ...o })));
92
109
  program.command("event").description("Record an agent hook event (called by AI coding agents, reads JSON on stdin)").option("--agent <id>", "Agent that fired the hook").option("--hook <name>", "Hook event name").option("--athena-hook", "Marker used to identify Athena-managed hook entries").option("--verbose-errors", "Print errors to stderr (hooks stay silent by default)").action(
93
110
  run(async (o, cmd) => {
94
111
  const g = globals(cmd);
95
112
  await (await import("./event-TNT6CQZR.js")).eventCommand({ agent: o.agent, hook: o.hook, cwd: g.cwd, verbose: o.verboseErrors });
96
113
  })
97
114
  );
98
- program.command("clean").description("Remove .athena/ and Athena agent integrations").option("-y, --yes", "Skip confirmation").option("--keep-agents", "Keep agent integration files/blocks").action(run(async (o, cmd) => (await import("./clean-S7PKCOLM.js")).cleanCommand({ ...globals(cmd), ...o })));
115
+ program.command("clean").description("Remove .athena/ and Athena agent integrations").option("-y, --yes", "Skip confirmation").option("--keep-agents", "Keep agent integration files/blocks").action(run(async (o, cmd) => (await import("./clean-MDBYH62P.js")).cleanCommand({ ...globals(cmd), ...o })));
99
116
  program.command("version").description("Print the Athena version").action(run(async (_o, cmd) => {
100
117
  if (globals(cmd).json) json({ version: ATHENA_VERSION, node: process.versions.node, platform: process.platform });
101
118
  else line(ATHENA_VERSION);
@@ -145,4 +162,4 @@ export {
145
162
  buildProgram,
146
163
  main
147
164
  };
148
- //# sourceMappingURL=program-V2USHGXN.js.map
165
+ //# sourceMappingURL=program-CWJNGCTZ.js.map