project-athena 0.3.0 → 0.5.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 (140) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +56 -4
  3. package/dist/{activity-P4UUFHWV.js → activity-XCHKBZTG.js} +6 -6
  4. package/dist/{agents-3HTSQGL2.js → agents-HUJ4JXIB.js} +6 -6
  5. package/dist/{ai-ASL4FFQ7.js → ai-LGTLQKL4.js} +3 -3
  6. package/dist/{analyze-F3YOILNL.js → analyze-AP4XJT7D.js} +10 -9
  7. package/dist/{chunk-ZB7LC6FP.js → chunk-3KFOI2X4.js} +2 -2
  8. package/dist/{chunk-PANVPNYF.js → chunk-44EGCEB2.js} +59 -251
  9. package/dist/{chunk-SJOOXO34.js → chunk-4FETKOY3.js} +9 -8
  10. package/dist/chunk-4IIBVTBS.js +76 -0
  11. package/dist/{chunk-LEMPCNAY.js → chunk-56EXAGTM.js} +3 -3
  12. package/dist/{chunk-32PRS2MG.js → chunk-6OSQMXUP.js} +5 -5
  13. package/dist/{chunk-OLPSEQS5.js → chunk-AKOI4VTD.js} +10 -1
  14. package/dist/{chunk-EF6GHOIN.js → chunk-C25FDXOO.js} +133 -23
  15. package/dist/{chunk-S7T6VX56.js → chunk-DH5AGULY.js} +8 -4
  16. package/dist/chunk-F65QINMR.js +702 -0
  17. package/dist/chunk-GU3ZX2J7.js +166 -0
  18. package/dist/chunk-GYQG4Q2N.js +108 -0
  19. package/dist/chunk-IDODPGTX.js +595 -0
  20. package/dist/chunk-KJYSNZXS.js +934 -0
  21. package/dist/{chunk-PR53DT7I.js → chunk-L2EHJCH4.js} +8 -8
  22. package/dist/{chunk-65TSRDQ3.js → chunk-P4TRQMES.js} +2 -2
  23. package/dist/{chunk-TGJUUB44.js → chunk-PZPMWCXS.js} +5 -5
  24. package/dist/chunk-QCC4VJUH.js +217 -0
  25. package/dist/{chunk-DOQMAZL5.js → chunk-R5AX7VST.js} +3 -3
  26. package/dist/{chunk-JY6BFIJJ.js → chunk-RQKGT2EK.js} +3 -3
  27. package/dist/{chunk-PDFQ5BFG.js → chunk-SVTEJYMS.js} +4 -155
  28. package/dist/{chunk-VSYBC3VY.js → chunk-UMWX4UTK.js} +2 -2
  29. package/dist/{chunk-RXNRMIZP.js → chunk-WUIC65QO.js} +2 -2
  30. package/dist/{chunk-JCGDR4UV.js → chunk-WWQ5NKEC.js} +3 -1
  31. package/dist/{chunk-XB66PZ6Z.js → chunk-X7EYOAEX.js} +2 -2
  32. package/dist/chunk-Y6SDMZET.js +278 -0
  33. package/dist/{chunk-2RS6TA3D.js → chunk-YRIS7ZS6.js} +28 -17
  34. package/dist/{clean-S7PKCOLM.js → clean-LQOG56AM.js} +4 -4
  35. package/dist/cli.js +2 -2
  36. package/dist/{context-AH5MFHRG.js → context-G5YHY3L2.js} +24 -10
  37. package/dist/{doctor-RSJMLE2P.js → doctor-L34QJ7WR.js} +17 -10
  38. package/dist/{event-TNT6CQZR.js → event-6YW6TGFI.js} +3 -3
  39. package/dist/{git-hook-YZNZGAAP.js → git-hook-Y7Y262F7.js} +2 -2
  40. package/dist/{init-2V34DVRQ.js → init-427QR5AS.js} +10 -9
  41. package/dist/{mcp-T2GRTEX5.js → mcp-DWNWRGJW.js} +196 -21
  42. package/dist/memory-XBZCYQLW.js +393 -0
  43. package/dist/{open-2QSZKKUG.js → open-LJMOB6U2.js} +262 -69
  44. package/dist/{program-V2USHGXN.js → program-DCP526LU.js} +63 -32
  45. package/dist/{review-R3R2J5BJ.js → review-VEJBPACX.js} +14 -11
  46. package/dist/{rules-4FXJUCXB.js → rules-M4DLLXBL.js} +4 -4
  47. package/dist/scan-JVKCVHPD.js +939 -0
  48. package/dist/{security-PI4LXCOB.js → security-JTJN3E7K.js} +15 -11
  49. package/dist/{staged-check-HHIBKKMR.js → staged-check-PQSLGQBW.js} +15 -13
  50. package/dist/{status-6M73WX5I.js → status-PO27BSOZ.js} +10 -4
  51. package/dist/{sync-3ZNJDSSU.js → sync-GVO2VHPI.js} +14 -12
  52. package/dist/{watch-USN5CQIV.js → watch-TEHFO47V.js} +14 -12
  53. package/dist/web/assets/{Editor-BI56-HX5.js → Editor-Bnilgch0.js} +1 -1
  54. package/dist/web/assets/{abnfDiagram-O67JEVCF-y_9px2ob.js → abnfDiagram-O67JEVCF-DW9LWr8f.js} +1 -1
  55. package/dist/web/assets/architecture-7GRP2DOG-BWDZV2yn.js +1 -0
  56. package/dist/web/assets/{architectureDiagram-NJMV4G6O-lB6fcVzU.js → architectureDiagram-NJMV4G6O-0eKeQRhj.js} +1 -1
  57. package/dist/web/assets/{blockDiagram-BEXU5L5S-DcM5pEjM.js → blockDiagram-BEXU5L5S-D5i3-ogI.js} +1 -1
  58. package/dist/web/assets/{c4Diagram-YGBWAQC7-CJgqxTY2.js → c4Diagram-YGBWAQC7-BAWQZrEu.js} +1 -1
  59. package/dist/web/assets/channel-Bkh05NKd.js +1 -0
  60. package/dist/web/assets/{chunk-3FUC2YCW-B8l_VuWR.js → chunk-3FUC2YCW-fKRGOZF3.js} +1 -1
  61. package/dist/web/assets/{chunk-5DYCD2WN-CZecgNhf.js → chunk-5DYCD2WN-C5jOlx42.js} +1 -1
  62. package/dist/web/assets/{chunk-742MDFTN-BeZ7P5jB.js → chunk-742MDFTN-urY4RP_A.js} +1 -1
  63. package/dist/web/assets/{chunk-7INBJB4K-IKy0pr5m.js → chunk-7INBJB4K-nk48sKqZ.js} +1 -1
  64. package/dist/web/assets/{chunk-7M6MHVWA-Dg_QqJEX.js → chunk-7M6MHVWA-BfBD9X0F.js} +1 -1
  65. package/dist/web/assets/{chunk-7PRAP22T-DqQNS8oq.js → chunk-7PRAP22T-jYf59QlI.js} +1 -1
  66. package/dist/web/assets/{chunk-GTNCS2PH-x4sM51nJ.js → chunk-GTNCS2PH-BOCxryKf.js} +1 -1
  67. package/dist/web/assets/{chunk-GWA4HPMP-CE5GcwVN.js → chunk-GWA4HPMP-CFpaW0ru.js} +1 -1
  68. package/dist/web/assets/{chunk-MBY4JIJT-DA_D1hjF.js → chunk-MBY4JIJT-BIB8HctN.js} +1 -1
  69. package/dist/web/assets/{chunk-NETBCI7D-CeJ3XBZ2.js → chunk-NETBCI7D-CpUUK6rh.js} +1 -1
  70. package/dist/web/assets/{chunk-O7XYJQB3-BH2gESvO.js → chunk-O7XYJQB3-BNx_V4Oi.js} +1 -1
  71. package/dist/web/assets/{chunk-UA2S7LBM-BWr0xCux.js → chunk-UA2S7LBM-D3tMiIOY.js} +1 -1
  72. package/dist/web/assets/{chunk-WEXAMYUT-B4QwUZPM.js → chunk-WEXAMYUT-CC-3C32l.js} +1 -1
  73. package/dist/web/assets/{chunk-Z7XXMR3K-BxcA-y5B.js → chunk-Z7XXMR3K-BzhxKQUc.js} +1 -1
  74. package/dist/web/assets/{chunk-ZIGJFQKS-BZYvP63G.js → chunk-ZIGJFQKS-D4tBHzxg.js} +1 -1
  75. package/dist/web/assets/{classDiagram-v2-NBCMYWYE-BS3P_NXb.js → classDiagram-v2-NBCMYWYE-BbtyanXR.js} +1 -1
  76. package/dist/web/assets/{cynefin-OW5HDTMX-BALD4Pve.js → cynefin-OW5HDTMX-BIArb8W1.js} +1 -1
  77. package/dist/web/assets/{cynefinDiagram-VND7K2PF-BM2y4W6d.js → cynefinDiagram-VND7K2PF-BrAcfkXL.js} +1 -1
  78. package/dist/web/assets/{dagre-6A5THRUB-PTfOrIdF.js → dagre-6A5THRUB-BcHXRl4s.js} +1 -1
  79. package/dist/web/assets/{diagram-22UHCM2B-CpXEHhUl.js → diagram-22UHCM2B-Dx9tSCdE.js} +1 -1
  80. package/dist/web/assets/{diagram-3UASUU5V-DPHfXzr6.js → diagram-3UASUU5V-CLLDP9yH.js} +1 -1
  81. package/dist/web/assets/{diagram-ATOU4E4O-DMBNXvAC.js → diagram-ATOU4E4O-B46H9iPt.js} +1 -1
  82. package/dist/web/assets/{diagram-CDSNMT55-CDLe1M7G.js → diagram-CDSNMT55-CYtvB6aG.js} +1 -1
  83. package/dist/web/assets/{diagram-MLGK6HIB-D6L8oE7j.js → diagram-MLGK6HIB-Dar7ktoX.js} +1 -1
  84. package/dist/web/assets/{diagram-MPIPVDR6-CP-S7rrQ.js → diagram-MPIPVDR6-C-DljnYN.js} +1 -1
  85. package/dist/web/assets/{ebnfDiagram-ZINNZB2B-CkUc63TK.js → ebnfDiagram-ZINNZB2B-Dv_3jWnh.js} +1 -1
  86. package/dist/web/assets/{elk-276RUBZZ-C1CAJLH_.js → elk-276RUBZZ-DnHciE9k.js} +1 -1
  87. package/dist/web/assets/{erDiagram-OPXOYQCR-DXBnaTHm.js → erDiagram-OPXOYQCR-Bn46KrHz.js} +1 -1
  88. package/dist/web/assets/eventmodeling-NTZA5JFV-DYwoptMd.js +1 -0
  89. package/dist/web/assets/flowDiagram-KWPJA3E3-y4rS0gIB.js +1 -0
  90. package/dist/web/assets/{ganttDiagram-FUAMR5RP-BVm8SiGg.js → ganttDiagram-FUAMR5RP-DOjjJtqz.js} +1 -1
  91. package/dist/web/assets/{gitGraph-4MIJSDKK-Dm7xBrW0.js → gitGraph-4MIJSDKK-BIoMXJRQ.js} +1 -1
  92. package/dist/web/assets/{gitGraphDiagram-X574FWY7-D_PIKKhx.js → gitGraphDiagram-X574FWY7-BsJ01R0v.js} +1 -1
  93. package/dist/web/assets/{index-CeOIBpu2.js → index-Cen0jOXj.js} +5 -4
  94. package/dist/web/assets/{index-DKE3ojTe.css → index-WwRY6n68.css} +1 -1
  95. package/dist/web/assets/{info-A6RAGUB7-CLGrx8pn.js → info-A6RAGUB7-BmlXzRWj.js} +1 -1
  96. package/dist/web/assets/{infoDiagram-VRGFBTTK-BlBjaKm7.js → infoDiagram-VRGFBTTK-CYPJPmBP.js} +1 -1
  97. package/dist/web/assets/{ishikawaDiagram-OU5B5YK6-Kxe7GGS3.js → ishikawaDiagram-OU5B5YK6-YN96geky.js} +1 -1
  98. package/dist/web/assets/{journeyDiagram-ZHPQQLJL-wCMoHK4M.js → journeyDiagram-ZHPQQLJL-20juojKY.js} +1 -1
  99. package/dist/web/assets/{kanban-definition-PNTS6WVX-BxdCz9Ko.js → kanban-definition-PNTS6WVX-BhCKIEbP.js} +1 -1
  100. package/dist/web/assets/{line-Zf11FnWF.js → line-BERsMFG6.js} +1 -1
  101. package/dist/web/assets/{mermaid-parser.core-BvFFklev.js → mermaid-parser.core-Bis_wTB-.js} +3 -3
  102. package/dist/web/assets/{mermaid.core-Cd_Ssti9.js → mermaid.core-DMsM3ZX7.js} +4 -4
  103. package/dist/web/assets/{mindmap-definition-NLK3R4M7-BGPQl-GY.js → mindmap-definition-NLK3R4M7-BkcGdOfv.js} +1 -1
  104. package/dist/web/assets/{packet-AYTQ26CC-6lI3cEX_.js → packet-AYTQ26CC-Bh30-JJX.js} +1 -1
  105. package/dist/web/assets/{pegDiagram-GJSIUBJH-BPIjlSAj.js → pegDiagram-GJSIUBJH-DxnIo9RF.js} +1 -1
  106. package/dist/web/assets/{pie-WAS4IAKB-D6Dzj3Ja.js → pie-WAS4IAKB-ChaTr-GD.js} +1 -1
  107. package/dist/web/assets/{pieDiagram-5QR66LMP-DtA-vZmv.js → pieDiagram-5QR66LMP-CzAp78FM.js} +1 -1
  108. package/dist/web/assets/{quadrantDiagram-O4NWA36T-EettyqQn.js → quadrantDiagram-O4NWA36T-BDSE-cfY.js} +1 -1
  109. package/dist/web/assets/{radar-RG4KPBEZ-xmRc3Dl8.js → radar-RG4KPBEZ-DgJ-o_dq.js} +1 -1
  110. package/dist/web/assets/{railroad-74A4TZTK-BLB7dhOn.js → railroad-74A4TZTK-C8MmcBKz.js} +1 -1
  111. package/dist/web/assets/railroad-abnf-HS5TGJTU-CTLXjcdP.js +1 -0
  112. package/dist/web/assets/railroad-ebnf-LZEXJU2U-ggWsTTL0.js +1 -0
  113. package/dist/web/assets/railroad-peg-WCYAUIDC-D1mCX705.js +1 -0
  114. package/dist/web/assets/{railroadDiagram-XR7U4H2S-PBw4We6b.js → railroadDiagram-XR7U4H2S-DfbcWRNh.js} +1 -1
  115. package/dist/web/assets/{requirementDiagram-PLB6GJNP-DjQpaUFA.js → requirementDiagram-PLB6GJNP-DM3nksxs.js} +1 -1
  116. package/dist/web/assets/{sankeyDiagram-IPEJSGJF-CBW-_AoF.js → sankeyDiagram-IPEJSGJF-DthUpiiC.js} +1 -1
  117. package/dist/web/assets/{sequenceDiagram-PO4LG4MO-DEoPYqY9.js → sequenceDiagram-PO4LG4MO-DLA3nuvA.js} +1 -1
  118. package/dist/web/assets/{stateDiagram-v2-GCMORJYK-UZq5rPud.js → stateDiagram-v2-GCMORJYK-B0X6ihBW.js} +1 -1
  119. package/dist/web/assets/{swimlanes-2SLR337P-CACfuXJR.js → swimlanes-2SLR337P-B4qWe6vE.js} +1 -1
  120. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-ClIk3e7S.js +8 -0
  121. package/dist/web/assets/{timeline-definition-EJHVYXUP-CYJl7mP-.js → timeline-definition-EJHVYXUP-F-cDzYrj.js} +1 -1
  122. package/dist/web/assets/{treeView-Q6P3EWNA-DtZ5nkPQ.js → treeView-Q6P3EWNA-BaI30nLZ.js} +1 -1
  123. package/dist/web/assets/{treemap-WGGIJYW6-m49GDM-M.js → treemap-WGGIJYW6-D2jGGoMl.js} +1 -1
  124. package/dist/web/assets/{usecaseDiagram-POWQR4AR-C2Vg20UK.js → usecaseDiagram-POWQR4AR-B9qoAQCy.js} +1 -1
  125. package/dist/web/assets/{vennDiagram-UO4OBE2U-C07v5OGI.js → vennDiagram-UO4OBE2U-DGVNOaKO.js} +1 -1
  126. package/dist/web/assets/{wardley-WFR3VGLG-C9Z7EZtz.js → wardley-WFR3VGLG-DbKqhNAh.js} +1 -1
  127. package/dist/web/assets/{wardleyDiagram-VNRHLVJA-DdA8CcSC.js → wardleyDiagram-VNRHLVJA-BgZ1gprw.js} +1 -1
  128. package/dist/web/assets/{xychartDiagram-PMCCYNJV-C9EZw07b.js → xychartDiagram-PMCCYNJV-D73RYid1.js} +1 -1
  129. package/dist/web/index.html +2 -2
  130. package/package.json +3 -1
  131. package/dist/chunk-CXUTYCZX.js +0 -238
  132. package/dist/chunk-LMOFZNTQ.js +0 -379
  133. package/dist/web/assets/architecture-7GRP2DOG-DyxkwYiW.js +0 -1
  134. package/dist/web/assets/channel-BvDD7AMO.js +0 -1
  135. package/dist/web/assets/eventmodeling-NTZA5JFV-cLIzvgDp.js +0 -1
  136. package/dist/web/assets/flowDiagram-KWPJA3E3-D7Zq63VQ.js +0 -1
  137. package/dist/web/assets/railroad-abnf-HS5TGJTU-DBFym6g8.js +0 -1
  138. package/dist/web/assets/railroad-ebnf-LZEXJU2U-CkG28ig8.js +0 -1
  139. package/dist/web/assets/railroad-peg-WCYAUIDC-Df_Ifaad.js +0 -1
  140. package/dist/web/assets/swimlanesDiagram-TC7HE7FX-CDSrqdgx.js +0 -8
@@ -1,4 +1,9 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ getOrCreateSalt,
4
+ keyedFingerprint,
5
+ readLocalConfig
6
+ } from "./chunk-PVCIGUIT.js";
2
7
  import {
3
8
  IgnoreMatcher,
4
9
  SOURCE_FILE,
@@ -8,20 +13,22 @@ import {
8
13
  sniffBinary,
9
14
  walkProject
10
15
  } from "./chunk-ELKFRTZT.js";
11
- import {
12
- getOrCreateSalt,
13
- keyedFingerprint,
14
- readLocalConfig
15
- } from "./chunk-PVCIGUIT.js";
16
16
  import {
17
17
  gitInfo
18
- } from "./chunk-OLPSEQS5.js";
18
+ } from "./chunk-AKOI4VTD.js";
19
+ import {
20
+ ProjectModel,
21
+ detected,
22
+ emptyModel,
23
+ fact,
24
+ inferred
25
+ } from "./chunk-QCC4VJUH.js";
19
26
  import {
20
27
  ephemeralFingerprint,
21
28
  isSecretLikeName,
22
29
  redact,
23
30
  scanText
24
- } from "./chunk-JCGDR4UV.js";
31
+ } from "./chunk-WWQ5NKEC.js";
25
32
  import {
26
33
  FactsCache,
27
34
  athenaDir,
@@ -122,213 +129,6 @@ var envDetector = {
122
129
  import path5 from "path";
123
130
  import { promises as fs5 } from "fs";
124
131
 
125
- // src/core/model/project-model.ts
126
- import { z as z2 } from "zod";
127
-
128
- // src/core/model/fact.ts
129
- import { z } from "zod";
130
- var FactStatus = z.enum(["FACT", "DETECTED", "INFERRED", "UNKNOWN"]);
131
- var Confidence = z.enum(["high", "medium", "low"]);
132
- var FactSource = z.enum(["code", "config", "filesystem", "git", "developer", "ai"]);
133
- var Evidence = z.object({
134
- /** Repo-relative POSIX path. */
135
- file: z.string(),
136
- line: z.number().int().positive().optional(),
137
- detail: z.string().optional()
138
- });
139
- var Provenance = z.object({
140
- status: FactStatus,
141
- confidence: Confidence,
142
- source: FactSource,
143
- evidence: z.array(Evidence)
144
- });
145
- function detected(source, evidence, confidence = "high") {
146
- return { status: "DETECTED", confidence, source, evidence };
147
- }
148
- function inferred(source, evidence, confidence = "medium") {
149
- return { status: "INFERRED", confidence, source, evidence };
150
- }
151
- function fact(source, evidence) {
152
- return { status: "FACT", confidence: "high", source, evidence };
153
- }
154
-
155
- // src/core/model/project-model.ts
156
- var Named = z2.object({ name: z2.string(), provenance: Provenance });
157
- var Language = z2.object({
158
- name: z2.string(),
159
- files: z2.number().int(),
160
- bytes: z2.number().int()
161
- });
162
- var Framework = Named.extend({
163
- category: z2.enum(["frontend", "backend", "fullstack", "mobile", "desktop", "orm", "testing", "other"]),
164
- version: z2.string().optional(),
165
- /** Workspace package root (repo-relative) this belongs to; "." for root. */
166
- root: z2.string()
167
- });
168
- var Manifest = z2.object({
169
- path: z2.string(),
170
- ecosystem: z2.string(),
171
- name: z2.string().optional(),
172
- version: z2.string().optional(),
173
- dependencies: z2.array(z2.string()),
174
- devDependencies: z2.array(z2.string())
175
- });
176
- var WorkspacePackage = z2.object({
177
- name: z2.string(),
178
- path: z2.string(),
179
- kind: z2.enum(["app", "package", "root", "unknown"]),
180
- ecosystem: z2.string(),
181
- /** Names of other workspace packages this one depends on. */
182
- internalDependencies: z2.array(z2.string())
183
- });
184
- var Command = z2.object({
185
- name: z2.string(),
186
- command: z2.string(),
187
- source: z2.string(),
188
- purpose: z2.enum(["dev", "build", "test", "lint", "format", "start", "migrate", "deploy", "other"])
189
- });
190
- var Route = z2.object({
191
- method: z2.string(),
192
- path: z2.string(),
193
- framework: z2.string(),
194
- file: z2.string(),
195
- line: z2.number().int().optional(),
196
- provenance: Provenance
197
- });
198
- var DbEntity = z2.object({
199
- name: z2.string(),
200
- kind: z2.enum(["table", "model", "collection"]),
201
- fields: z2.array(z2.object({ name: z2.string(), type: z2.string().optional(), attributes: z2.array(z2.string()) })),
202
- indexes: z2.array(z2.string()),
203
- relations: z2.array(z2.string()),
204
- file: z2.string(),
205
- provenance: Provenance
206
- });
207
- var Database = Named.extend({ kind: z2.enum(["engine", "orm", "driver", "service"]) });
208
- var EnvVar = z2.object({
209
- name: z2.string(),
210
- /** Where the name was seen. Values are NEVER recorded. */
211
- references: z2.array(z2.string()),
212
- secretLike: z2.boolean()
213
- });
214
- var SecretFinding = z2.object({
215
- type: z2.string(),
216
- file: z2.string(),
217
- line: z2.number().int(),
218
- /**
219
- * Keyed fingerprint (HMAC with the machine-local salt in .athena/local.json, or a
220
- * per-process key) — allows dedup without storing the secret. Never a plain hash
221
- * of the value, and never written to committed files.
222
- */
223
- fingerprint: z2.string()
224
- });
225
- var CiJob = z2.object({ system: z2.string(), file: z2.string(), name: z2.string(), commands: z2.array(z2.string()) });
226
- var ContainerService = z2.object({
227
- name: z2.string(),
228
- image: z2.string().optional(),
229
- ports: z2.array(z2.string()),
230
- dependsOn: z2.array(z2.string()),
231
- file: z2.string()
232
- });
233
- var TestInfo = z2.object({
234
- frameworks: z2.array(Named),
235
- testFileCount: z2.number().int(),
236
- testDirs: z2.array(z2.string()),
237
- coverageConfigs: z2.array(z2.string()),
238
- /** Workspace packages that contain source files but zero detected test files (structural, not coverage). */
239
- packagesWithoutTests: z2.array(z2.string())
240
- });
241
- var GitInfo = z2.object({
242
- available: z2.boolean(),
243
- isRepo: z2.boolean(),
244
- branch: z2.string().optional(),
245
- head: z2.string().optional(),
246
- lastCommitDate: z2.string().optional(),
247
- contributorCount: z2.number().int().optional(),
248
- hotspots: z2.array(z2.object({ path: z2.string(), commits: z2.number().int() }))
249
- });
250
- var ProjectModel = z2.object({
251
- schemaVersion: z2.literal(1),
252
- name: z2.string(),
253
- description: z2.string().optional(),
254
- root: z2.string(),
255
- stats: z2.object({
256
- filesScanned: z2.number().int(),
257
- skippedBinary: z2.number().int(),
258
- skippedLarge: z2.number().int(),
259
- skippedUnreadable: z2.number().int()
260
- }),
261
- topLevelDirs: z2.array(z2.string()),
262
- languages: z2.array(Language),
263
- manifests: z2.array(Manifest),
264
- packageManagers: z2.array(Named),
265
- buildSystems: z2.array(Named),
266
- workspace: z2.object({
267
- isMonorepo: z2.boolean(),
268
- tool: z2.string().optional(),
269
- packages: z2.array(WorkspacePackage)
270
- }),
271
- frameworks: z2.array(Framework),
272
- entryPoints: z2.array(z2.object({ path: z2.string(), provenance: Provenance })),
273
- commands: z2.array(Command),
274
- databases: z2.array(Database),
275
- dbEntities: z2.array(DbEntity),
276
- migrations: z2.array(z2.object({ path: z2.string(), tool: z2.string(), count: z2.number().int() })),
277
- routes: z2.array(Route),
278
- apiSpecs: z2.array(z2.object({ path: z2.string(), kind: z2.enum(["openapi", "graphql", "grpc"]) })),
279
- auth: z2.array(Named.extend({ kind: z2.enum(["library", "provider", "hashing", "middleware", "token"]) })),
280
- containers: z2.object({ dockerfiles: z2.array(z2.object({ path: z2.string(), baseImages: z2.array(z2.string()), exposedPorts: z2.array(z2.string()) })), services: z2.array(ContainerService) }),
281
- infrastructure: z2.array(Named.extend({ kind: z2.string(), file: z2.string() })),
282
- ci: z2.array(CiJob),
283
- tests: TestInfo,
284
- env: z2.object({ vars: z2.array(EnvVar), envFilesPresent: z2.array(z2.string()) }),
285
- security: z2.object({
286
- secrets: z2.array(SecretFinding),
287
- tooling: z2.array(Named),
288
- /** Libraries/middleware relevant to web security controls (helmet, cors, csrf...). */
289
- controls: z2.array(Named)
290
- }),
291
- caching: z2.array(Named),
292
- queues: z2.array(Named),
293
- observability: z2.array(Named),
294
- git: GitInfo,
295
- warnings: z2.array(z2.string())
296
- });
297
- function emptyModel(name, root) {
298
- return {
299
- schemaVersion: 1,
300
- name,
301
- root,
302
- stats: { filesScanned: 0, skippedBinary: 0, skippedLarge: 0, skippedUnreadable: 0 },
303
- topLevelDirs: [],
304
- languages: [],
305
- manifests: [],
306
- packageManagers: [],
307
- buildSystems: [],
308
- workspace: { isMonorepo: false, packages: [] },
309
- frameworks: [],
310
- entryPoints: [],
311
- commands: [],
312
- databases: [],
313
- dbEntities: [],
314
- migrations: [],
315
- routes: [],
316
- apiSpecs: [],
317
- auth: [],
318
- containers: { dockerfiles: [], services: [] },
319
- infrastructure: [],
320
- ci: [],
321
- tests: { frameworks: [], testFileCount: 0, testDirs: [], coverageConfigs: [], packagesWithoutTests: [] },
322
- env: { vars: [], envFilesPresent: [] },
323
- security: { secrets: [], tooling: [], controls: [] },
324
- caching: [],
325
- queues: [],
326
- observability: [],
327
- git: { available: false, isRepo: false, hotspots: [] },
328
- warnings: []
329
- };
330
- }
331
-
332
132
  // src/core/analyzer/context.ts
333
133
  function createContext(root, config, files, model, source, signal) {
334
134
  const byPath = new Map(files.map((f) => [f.path, f]));
@@ -2579,9 +2379,6 @@ import path4 from "path";
2579
2379
  import crypto2 from "crypto";
2580
2380
  var SKIP = /(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lock|poetry\.lock|uv\.lock|Cargo\.lock|go\.sum|composer\.lock|Gemfile\.lock|pubspec\.lock)$|\.(min\.js|map|svg|snap)$/;
2581
2381
  var MAX_SECRET_FINDINGS = 500;
2582
- async function secretFingerprinter(root) {
2583
- return (await secretFingerprintKey(root)).fingerprint;
2584
- }
2585
2382
  async function secretFingerprintKey(root, saltOverride) {
2586
2383
  try {
2587
2384
  let salt = saltOverride;
@@ -2598,12 +2395,20 @@ async function secretFingerprintKey(root, saltOverride) {
2598
2395
  }
2599
2396
  return { fingerprint: ephemeralFingerprint, fingerprintKeyId: null };
2600
2397
  }
2398
+ var MINIFIED = /\.(min\.js|map)$/;
2601
2399
  async function scanFilesForSecrets(files, read, opts) {
2602
2400
  const findings = opts.into ?? [];
2603
2401
  const max = opts.max ?? MAX_SECRET_FINDINGS;
2604
2402
  const stats = { skippedLongLines: 0 };
2403
+ const counts = { scanned: 0, binary: 0, tooLarge: 0, minified: 0, excluded: 0, unreadable: 0 };
2605
2404
  let truncated = false;
2606
2405
  for (const f of files) {
2406
+ if (f.binary) counts.binary++;
2407
+ else if (f.large) counts.tooLarge++;
2408
+ else if (SKIP.test(f.path)) {
2409
+ if (MINIFIED.test(f.path)) counts.minified++;
2410
+ else counts.excluded++;
2411
+ }
2607
2412
  if (f.binary || f.large || SKIP.test(f.path)) continue;
2608
2413
  if (findings.length >= max) {
2609
2414
  truncated = true;
@@ -2611,10 +2416,14 @@ async function scanFilesForSecrets(files, read, opts) {
2611
2416
  }
2612
2417
  opts.signal?.throwIfAborted();
2613
2418
  const text = await read(f.path);
2419
+ if (text === null) counts.unreadable++;
2420
+ else counts.scanned++;
2614
2421
  if (!text) continue;
2615
- for (const m of scanText(text, { fingerprint: opts.fingerprint, stats })) findings.push({ type: m.type, file: f.path, line: m.line, fingerprint: m.fingerprint });
2422
+ const matches = scanText(text, { fingerprint: opts.fingerprint, stats });
2423
+ for (const m of matches) findings.push({ type: m.type, file: f.path, line: m.line, fingerprint: m.fingerprint });
2424
+ if (matches.length) opts.onFile?.(f.path, text, matches);
2616
2425
  }
2617
- return { findings, truncated, skippedLongLines: stats.skippedLongLines };
2426
+ return { findings, truncated, skippedLongLines: stats.skippedLongLines, files: counts };
2618
2427
  }
2619
2428
  var secretsFact = {
2620
2429
  id: "secrets",
@@ -2790,54 +2599,54 @@ function redactDeep(value, memo = /* @__PURE__ */ new Map()) {
2790
2599
  }
2791
2600
 
2792
2601
  // src/core/model/security-scan.ts
2793
- import { z as z3 } from "zod";
2602
+ import { z } from "zod";
2794
2603
  import path6 from "path";
2795
2604
  var SCAN_FILE = "security-scan.json";
2796
2605
  var SEVERITIES = ["critical", "high", "moderate", "low", "unrated"];
2797
2606
  var SEVERITY_ORDER = [...SEVERITIES];
2798
2607
  var RATED_SEVERITIES = ["critical", "high", "moderate", "low"];
2799
2608
  var legacySeverity = (v) => v === "unknown" ? "unrated" : v;
2800
- var Severity = z3.preprocess(legacySeverity, z3.enum(SEVERITIES));
2801
- var Vulnerability = z3.object({
2802
- package: z3.string(),
2609
+ var Severity = z.preprocess(legacySeverity, z.enum(SEVERITIES));
2610
+ var Vulnerability = z.object({
2611
+ package: z.string(),
2803
2612
  severity: Severity,
2804
- title: z3.string(),
2805
- id: z3.string().optional(),
2806
- url: z3.string().optional(),
2807
- vulnerableRange: z3.string().optional(),
2808
- fixAvailable: z3.boolean().optional()
2613
+ title: z.string(),
2614
+ id: z.string().optional(),
2615
+ url: z.string().optional(),
2616
+ vulnerableRange: z.string().optional(),
2617
+ fixAvailable: z.boolean().optional()
2809
2618
  });
2810
- var ToolResult = z3.object({
2811
- tool: z3.string(),
2812
- ecosystem: z3.string(),
2619
+ var ToolResult = z.object({
2620
+ tool: z.string(),
2621
+ ecosystem: z.string(),
2813
2622
  /** What was audited when a tool runs once per input (e.g. a requirements file). */
2814
- target: z3.string().optional(),
2623
+ target: z.string().optional(),
2815
2624
  /** ok: ran and produced results · unavailable: not installed / nothing to audit · failed/timeout: ran but no usable output */
2816
- status: z3.enum(["ok", "unavailable", "failed", "timeout"]),
2817
- message: z3.string().optional(),
2818
- durationMs: z3.number(),
2819
- findings: z3.array(Vulnerability)
2625
+ status: z.enum(["ok", "unavailable", "failed", "timeout"]),
2626
+ message: z.string().optional(),
2627
+ durationMs: z.number(),
2628
+ findings: z.array(Vulnerability)
2820
2629
  });
2821
- var Counts = z3.preprocess(
2630
+ var Counts = z.preprocess(
2822
2631
  (v) => {
2823
2632
  if (!v || typeof v !== "object") return v;
2824
2633
  const { unknown, ...rest } = v;
2825
2634
  return { critical: 0, high: 0, moderate: 0, low: 0, unrated: 0, ...rest, ...typeof unknown === "number" ? { unrated: (rest.unrated ?? 0) + unknown } : {} };
2826
2635
  },
2827
- z3.object({ critical: z3.number(), high: z3.number(), moderate: z3.number(), low: z3.number(), unrated: z3.number() })
2636
+ z.object({ critical: z.number(), high: z.number(), moderate: z.number(), low: z.number(), unrated: z.number() })
2828
2637
  );
2829
- var SecurityScan = z3.object({
2830
- schemaVersion: z3.literal(1),
2831
- scannedAt: z3.string(),
2832
- durationMs: z3.number(),
2833
- tools: z3.array(ToolResult),
2638
+ var SecurityScan = z.object({
2639
+ schemaVersion: z.literal(1),
2640
+ scannedAt: z.string(),
2641
+ durationMs: z.number(),
2642
+ tools: z.array(ToolResult),
2834
2643
  counts: Counts,
2835
- secrets: z3.object({
2836
- count: z3.number(),
2837
- files: z3.array(z3.string()),
2644
+ secrets: z.object({
2645
+ count: z.number(),
2646
+ files: z.array(z.string()),
2838
2647
  /** Lines longer than 4096 chars on which generic keyword patterns were not applied. */
2839
- skippedLongLines: z3.number().optional(),
2840
- truncated: z3.boolean().optional()
2648
+ skippedLongLines: z.number().optional(),
2649
+ truncated: z.boolean().optional()
2841
2650
  })
2842
2651
  });
2843
2652
  var loadScan = (root) => loadScanFromDir(athenaDir(root));
@@ -2870,11 +2679,10 @@ function meetsThreshold(scan, level, opts = {}) {
2870
2679
  }
2871
2680
 
2872
2681
  export {
2873
- ProjectModel,
2874
2682
  readExclude,
2875
2683
  manifestDependencyNames,
2876
2684
  REAL_ENV_NAMES,
2877
- secretFingerprinter,
2685
+ MAX_SECRET_FINDINGS,
2878
2686
  scanFilesForSecrets,
2879
2687
  analyzeProject,
2880
2688
  persistAnalysisCache,
@@ -2889,4 +2697,4 @@ export {
2889
2697
  unratedFindings,
2890
2698
  meetsThreshold
2891
2699
  };
2892
- //# sourceMappingURL=chunk-PANVPNYF.js.map
2700
+ //# sourceMappingURL=chunk-44EGCEB2.js.map
@@ -1,22 +1,22 @@
1
1
  #!/usr/bin/env node
2
+ import {
3
+ ATHENA_VERSION
4
+ } from "./chunk-2R6PXY6Z.js";
2
5
  import {
3
6
  analyzeProject,
4
7
  loadScanFromDir,
5
8
  persistAnalysisCache
6
- } from "./chunk-PANVPNYF.js";
7
- import {
8
- ATHENA_VERSION
9
- } from "./chunk-2R6PXY6Z.js";
9
+ } from "./chunk-44EGCEB2.js";
10
10
  import {
11
11
  LOCAL_CONFIG_FILE
12
12
  } from "./chunk-PVCIGUIT.js";
13
13
  import {
14
14
  redact
15
- } from "./chunk-JCGDR4UV.js";
15
+ } from "./chunk-WWQ5NKEC.js";
16
16
  import {
17
17
  ADAPTERS,
18
18
  applyChanges
19
- } from "./chunk-2RS6TA3D.js";
19
+ } from "./chunk-YRIS7ZS6.js";
20
20
  import {
21
21
  mergeDocument,
22
22
  renderBlock
@@ -752,6 +752,7 @@ var ATHENA_GITIGNORE = [
752
752
  "model.json",
753
753
  "graph.json",
754
754
  "security-scan.json",
755
+ "findings.json",
755
756
  "ai-suggestions.md",
756
757
  ".backup/",
757
758
  ".server.json",
@@ -764,7 +765,7 @@ var ATHENA_GITIGNORE = [
764
765
  "local.json",
765
766
  ""
766
767
  ].join("\n");
767
- var GITIGNORE_ENTRIES = ["state.json", "model.json", "graph.json", "security-scan.json", "ai-suggestions.md", ".backup/", ".server.json", ".sync-ignore.json", ".agent-events.jsonl", ".agent-events.1.jsonl", ".agent-events.rotate.lock", "cache/", "local.json"];
768
+ var GITIGNORE_ENTRIES = ["state.json", "model.json", "graph.json", "security-scan.json", "findings.json", "ai-suggestions.md", ".backup/", ".server.json", ".sync-ignore.json", ".agent-events.jsonl", ".agent-events.1.jsonl", ".agent-events.rotate.lock", "cache/", "local.json"];
768
769
  async function ensureGitignoreEntries(file) {
769
770
  const existing = await readTextIfExists(file);
770
771
  if (existing === null) {
@@ -901,4 +902,4 @@ export {
901
902
  composeState,
902
903
  runPipeline
903
904
  };
904
- //# sourceMappingURL=chunk-SJOOXO34.js.map
905
+ //# sourceMappingURL=chunk-4FETKOY3.js.map
@@ -0,0 +1,76 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ auditDependencies,
4
+ legacyToolResult,
5
+ saveFindings
6
+ } from "./chunk-IDODPGTX.js";
7
+ import {
8
+ Coverage,
9
+ Finding,
10
+ dedupeFindings,
11
+ scanSecrets
12
+ } from "./chunk-Y6SDMZET.js";
13
+ import {
14
+ saveScan
15
+ } from "./chunk-44EGCEB2.js";
16
+ import {
17
+ walkProject
18
+ } from "./chunk-ELKFRTZT.js";
19
+ import {
20
+ loadConfig
21
+ } from "./chunk-2DY4PUR4.js";
22
+
23
+ // src/services/security.ts
24
+ var resultsByScan = /* @__PURE__ */ new WeakMap();
25
+ async function runSecurityScanWithFindings(root, model, opts = {}) {
26
+ const started = Date.now();
27
+ const { config } = await loadConfig(root);
28
+ const walk = await walkProject(root, { config, signal: opts.signal });
29
+ const ctx = { root, config, mode: "all", signal: opts.signal };
30
+ const deps = opts.skipAudit ? null : await auditDependencies(ctx, { model, walk: walk.files, timeoutMs: opts.timeoutMs, onTool: opts.onTool });
31
+ const tools = (deps?.runs ?? []).map(legacyToolResult);
32
+ const counts = { critical: 0, high: 0, moderate: 0, low: 0, unrated: 0 };
33
+ for (const t of tools) for (const f of t.findings) counts[f.severity]++;
34
+ const secrets = await scanSecrets(ctx, { walk: walk.files });
35
+ const scannedAt = (/* @__PURE__ */ new Date()).toISOString();
36
+ const durationMs = Date.now() - started;
37
+ const scan = {
38
+ schemaVersion: 1,
39
+ scannedAt,
40
+ durationMs,
41
+ tools,
42
+ counts,
43
+ secrets: {
44
+ count: secrets.summary.count,
45
+ files: secrets.summary.files.slice(0, 50),
46
+ skippedLongLines: secrets.summary.skippedLongLines,
47
+ ...secrets.summary.truncated ? { truncated: true } : {}
48
+ }
49
+ };
50
+ const outputs = [secrets, ...deps ? [deps] : []];
51
+ const result = {
52
+ schemaVersion: 1,
53
+ scannedAt,
54
+ durationMs,
55
+ scope: { mode: "all" },
56
+ findings: dedupeFindings(outputs.flatMap((o) => o.findings.map((f) => Finding.parse(f)))),
57
+ coverage: [...deps?.coverage ?? [], ...secrets.coverage].map((c) => Coverage.parse(c))
58
+ };
59
+ resultsByScan.set(scan, result);
60
+ return { scan, result };
61
+ }
62
+ async function runSecurityScan(root, model, opts = {}) {
63
+ return (await runSecurityScanWithFindings(root, model, opts)).scan;
64
+ }
65
+ async function saveScan2(root, scan) {
66
+ await saveScan(root, scan);
67
+ const result = resultsByScan.get(scan);
68
+ if (result) await saveFindings(root, result);
69
+ }
70
+
71
+ export {
72
+ runSecurityScanWithFindings,
73
+ runSecurityScan,
74
+ saveScan2 as saveScan
75
+ };
76
+ //# sourceMappingURL=chunk-4IIBVTBS.js.map
@@ -9,10 +9,10 @@ import {
9
9
  } from "./chunk-3IS2X2Z7.js";
10
10
  import {
11
11
  git
12
- } from "./chunk-OLPSEQS5.js";
12
+ } from "./chunk-AKOI4VTD.js";
13
13
  import {
14
14
  scanText
15
- } from "./chunk-JCGDR4UV.js";
15
+ } from "./chunk-WWQ5NKEC.js";
16
16
  import {
17
17
  isBlockModified,
18
18
  parseBlocks
@@ -206,4 +206,4 @@ export {
206
206
  rulesUpdate,
207
207
  rulesRemove
208
208
  };
209
- //# sourceMappingURL=chunk-LEMPCNAY.js.map
209
+ //# sourceMappingURL=chunk-56EXAGTM.js.map
@@ -1,21 +1,21 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  AnalysisScheduler
4
- } from "./chunk-XB66PZ6Z.js";
4
+ } from "./chunk-X7EYOAEX.js";
5
5
  import {
6
6
  applySync,
7
7
  needsIndexRefreshOnly
8
- } from "./chunk-TGJUUB44.js";
8
+ } from "./chunk-PZPMWCXS.js";
9
9
  import {
10
10
  readExclude
11
- } from "./chunk-PANVPNYF.js";
11
+ } from "./chunk-44EGCEB2.js";
12
12
  import {
13
13
  IgnoreMatcher,
14
14
  factsConfigHash
15
15
  } from "./chunk-ELKFRTZT.js";
16
16
  import {
17
17
  git
18
- } from "./chunk-OLPSEQS5.js";
18
+ } from "./chunk-AKOI4VTD.js";
19
19
  import {
20
20
  loadConfig
21
21
  } from "./chunk-2DY4PUR4.js";
@@ -166,4 +166,4 @@ async function watchProject(root, opts) {
166
166
  export {
167
167
  watchProject
168
168
  };
169
- //# sourceMappingURL=chunk-32PRS2MG.js.map
169
+ //# sourceMappingURL=chunk-6OSQMXUP.js.map
@@ -184,6 +184,14 @@ function stripPrefix(files, prefix) {
184
184
  if (!prefix) return files;
185
185
  return files.filter((f) => f.path.startsWith(prefix)).map((f) => ({ ...f, path: f.path.slice(prefix.length), from: f.from?.startsWith(prefix) ? f.from.slice(prefix.length) : f.from }));
186
186
  }
187
+ async function changesSince(cwd, fromRef, opts = {}) {
188
+ if (!isSafeRef(fromRef)) return null;
189
+ const mb = await git(cwd, ["merge-base", fromRef, "HEAD"], { signal: opts.signal });
190
+ if (!mb.ok || !mb.stdout.trim()) return null;
191
+ const r = await git(cwd, ["diff", "--name-status", "-M", "-z", "--relative", "--no-color", mb.stdout.trim(), "HEAD", "--", "."], { signal: opts.signal });
192
+ if (!r.ok) return null;
193
+ return parseNameStatusZ(r.stdout);
194
+ }
187
195
  function parseNameStatusZ(stdout) {
188
196
  const out = [];
189
197
  const parts = stdout.split("\0").filter(Boolean);
@@ -256,9 +264,10 @@ export {
256
264
  isGitRepo,
257
265
  gitInfo,
258
266
  workingChanges,
267
+ changesSince,
259
268
  parseNameStatusZ,
260
269
  isSafeRef,
261
270
  headMovement,
262
271
  statusV2
263
272
  };
264
- //# sourceMappingURL=chunk-OLPSEQS5.js.map
273
+ //# sourceMappingURL=chunk-AKOI4VTD.js.map