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,264 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/core/git/git.ts
4
+ import { spawn } from "child_process";
5
+ var DEFAULT_MAX_BYTES = 32 * 1024 * 1024;
6
+ var MAX_STDERR_BYTES = 64 * 1024;
7
+ function git(cwd, args, opts = {}) {
8
+ const o = typeof opts === "number" ? { timeoutMs: opts } : opts;
9
+ const timeoutMs = o.timeoutMs ?? 15e3;
10
+ const maxBytes = o.maxBytes ?? DEFAULT_MAX_BYTES;
11
+ return new Promise((resolve) => {
12
+ if (o.signal?.aborted) {
13
+ resolve({ ok: false, code: null, stdout: "", stderr: "", aborted: true });
14
+ return;
15
+ }
16
+ const out = [];
17
+ const err = [];
18
+ let outBytes = 0;
19
+ let errBytes = 0;
20
+ let overflow = false;
21
+ let timedOut = false;
22
+ let aborted = false;
23
+ let settled = false;
24
+ const child = spawn("git", args, {
25
+ cwd,
26
+ windowsHide: true,
27
+ stdio: [o.input === void 0 ? "ignore" : "pipe", "pipe", "pipe"],
28
+ env: { ...process.env, GIT_TERMINAL_PROMPT: "0", LC_ALL: "C" }
29
+ });
30
+ const kill = () => {
31
+ if (child.exitCode === null && child.signalCode === null) child.kill("SIGKILL");
32
+ };
33
+ const timer = setTimeout(() => {
34
+ timedOut = true;
35
+ kill();
36
+ }, timeoutMs);
37
+ const onAbort = () => {
38
+ aborted = true;
39
+ kill();
40
+ };
41
+ o.signal?.addEventListener("abort", onAbort, { once: true });
42
+ const finish = (code, spawnError) => {
43
+ if (settled) return;
44
+ settled = true;
45
+ clearTimeout(timer);
46
+ o.signal?.removeEventListener("abort", onAbort);
47
+ let stderr = Buffer.concat(err).toString("utf8");
48
+ if (spawnError) stderr = stderr || spawnError.message;
49
+ if (overflow) stderr = `${stderr}${stderr ? "\n" : ""}output exceeded ${maxBytes} bytes`;
50
+ if (timedOut) stderr = `${stderr}${stderr ? "\n" : ""}timed out after ${timeoutMs} ms`;
51
+ const failed = overflow || timedOut || aborted || Boolean(spawnError);
52
+ resolve({
53
+ ok: !failed && code === 0,
54
+ code: failed ? null : code,
55
+ stdout: Buffer.concat(out).toString("utf8"),
56
+ stderr,
57
+ ...overflow ? { overflow } : {},
58
+ ...aborted ? { aborted } : {},
59
+ ...timedOut ? { timedOut } : {}
60
+ });
61
+ };
62
+ child.stdout.on("data", (chunk) => {
63
+ if (overflow) return;
64
+ outBytes += chunk.length;
65
+ if (outBytes > maxBytes) {
66
+ overflow = true;
67
+ kill();
68
+ return;
69
+ }
70
+ out.push(chunk);
71
+ });
72
+ child.stderr.on("data", (chunk) => {
73
+ if (errBytes >= MAX_STDERR_BYTES) return;
74
+ errBytes += chunk.length;
75
+ err.push(chunk);
76
+ });
77
+ child.on("error", (e) => finish(null, e));
78
+ child.on("close", (code) => finish(code));
79
+ if (o.input !== void 0) {
80
+ child.stdin.on("error", () => {
81
+ });
82
+ child.stdin.end(o.input);
83
+ }
84
+ });
85
+ }
86
+ var GitCommandError = class extends Error {
87
+ constructor(args, result) {
88
+ const detail = result.stderr.trim().split("\n").filter(Boolean).slice(-1)[0]?.slice(0, 300);
89
+ super(`git ${args.find((a) => !a.startsWith("-") && !a.includes("=")) ?? args[0]} failed${detail ? `: ${detail}` : result.code !== null ? ` (exit ${result.code})` : ""}`);
90
+ this.args = args;
91
+ this.result = result;
92
+ this.name = "GitCommandError";
93
+ }
94
+ args;
95
+ result;
96
+ };
97
+ async function gitOrThrow(cwd, args, opts = {}) {
98
+ const r = await git(cwd, args, opts);
99
+ if (r.aborted) throw opts.signal?.reason ?? new Error("Aborted");
100
+ if (!r.ok) throw new GitCommandError(args, r);
101
+ return r.stdout;
102
+ }
103
+ var availability = null;
104
+ function gitAvailable(opts = {}) {
105
+ if (availability) return availability;
106
+ const p = git(process.cwd(), ["--version"], { signal: opts.signal }).then((r) => {
107
+ if (r.aborted && availability === p) availability = null;
108
+ return r.ok;
109
+ });
110
+ availability = p;
111
+ return p;
112
+ }
113
+ async function isGitRepo(cwd, opts = {}) {
114
+ const r = await git(cwd, ["rev-parse", "--is-inside-work-tree"], { signal: opts.signal });
115
+ return r.ok && r.stdout.trim() === "true";
116
+ }
117
+ var HISTORY_DAYS = 180;
118
+ var HISTORY_MAX_COMMITS = 2e3;
119
+ var AUTHOR_MARK = "";
120
+ async function gitInfo(cwd, opts = {}) {
121
+ const { signal } = opts;
122
+ const days = opts.historyDays ?? HISTORY_DAYS;
123
+ const maxCommits = opts.maxCommits ?? HISTORY_MAX_COMMITS;
124
+ const run = (args) => git(cwd, args, { signal });
125
+ const [available, isRepo, branch, head, date, log] = await Promise.all([
126
+ gitAvailable({ signal }),
127
+ isGitRepo(cwd, { signal }),
128
+ run(["rev-parse", "--abbrev-ref", "HEAD"]),
129
+ run(["rev-parse", "HEAD"]),
130
+ run(["log", "-1", "--format=%cI"]),
131
+ run(["log", `--since=${days}.days`, `--max-count=${maxCommits}`, "--no-merges", `--format=${AUTHOR_MARK}%aN`, "--name-only", "--relative", "--", "."])
132
+ ]);
133
+ signal?.throwIfAborted();
134
+ const info = { available, isRepo: false, hotspots: [] };
135
+ if (!info.available) return info;
136
+ info.isRepo = isRepo;
137
+ if (!info.isRepo) return info;
138
+ if (branch.ok) info.branch = branch.stdout.trim();
139
+ if (head.ok) info.head = head.stdout.trim();
140
+ if (date.ok && date.stdout.trim()) info.lastCommitDate = date.stdout.trim();
141
+ if (log.ok) {
142
+ const authors = /* @__PURE__ */ new Set();
143
+ const counts = /* @__PURE__ */ new Map();
144
+ for (const line of log.stdout.split("\n")) {
145
+ if (line.startsWith(AUTHOR_MARK)) {
146
+ authors.add(line.slice(1));
147
+ continue;
148
+ }
149
+ const p = line.trim();
150
+ if (!p || p === ".athena" || p.startsWith(".athena/")) continue;
151
+ const dir = p.includes("/") ? p.split("/").slice(0, 2).join("/") : ".";
152
+ counts.set(dir, (counts.get(dir) ?? 0) + 1);
153
+ }
154
+ info.contributorCount = authors.size;
155
+ info.hotspots = [...counts.entries()].sort((a, b) => b[1] - a[1] || (a[0] < b[0] ? -1 : a[0] > b[0] ? 1 : 0)).slice(0, 10).map(([path, commits]) => ({ path, commits }));
156
+ }
157
+ return info;
158
+ }
159
+ async function workingChanges(cwd, opts = {}) {
160
+ const [r, prefix] = await Promise.all([git(cwd, ["status", "--porcelain=v1", "-z", "--untracked-files=all", "--", "."], { signal: opts.signal }), repoPrefix(cwd, opts)]);
161
+ if (!r.ok) return null;
162
+ const out = [];
163
+ const parts = r.stdout.split("\0");
164
+ for (let i = 0; i < parts.length; i++) {
165
+ const entry = parts[i];
166
+ if (entry.length < 4) continue;
167
+ const code = entry.slice(0, 2);
168
+ const p = entry.slice(3);
169
+ if (code.includes("R")) {
170
+ out.push({ path: p, status: "renamed", from: parts[++i] });
171
+ } else if (code === "??") out.push({ path: p, status: "untracked" });
172
+ else if (code.includes("D")) out.push({ path: p, status: "deleted" });
173
+ else if (code.includes("A")) out.push({ path: p, status: "added" });
174
+ else if (code.includes("M")) out.push({ path: p, status: "modified" });
175
+ else out.push({ path: p, status: "other" });
176
+ }
177
+ return stripPrefix(out, prefix);
178
+ }
179
+ async function repoPrefix(cwd, opts = {}) {
180
+ const r = await git(cwd, ["rev-parse", "--show-prefix"], { signal: opts.signal });
181
+ return r.ok ? r.stdout.trim() : "";
182
+ }
183
+ function stripPrefix(files, prefix) {
184
+ if (!prefix) return files;
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
+ }
187
+ function parseNameStatusZ(stdout) {
188
+ const out = [];
189
+ const parts = stdout.split("\0").filter(Boolean);
190
+ for (let i = 0; i < parts.length; i++) {
191
+ const code = parts[i];
192
+ if (code.startsWith("R") || code.startsWith("C")) {
193
+ const from = parts[++i];
194
+ const to = parts[++i];
195
+ if (to === void 0) break;
196
+ out.push(code.startsWith("R") ? { path: to, status: "renamed", from } : { path: to, status: "added" });
197
+ } else {
198
+ const p = parts[++i];
199
+ if (p === void 0) break;
200
+ out.push({ path: p, status: code === "A" ? "added" : code === "D" ? "deleted" : code === "M" ? "modified" : "other" });
201
+ }
202
+ }
203
+ return out;
204
+ }
205
+ function isSafeRef(ref) {
206
+ return /^[A-Za-z0-9][\w./@^~-]{0,119}$/.test(ref);
207
+ }
208
+ async function headMovement(cwd, from, to, limit = 20, opts = {}) {
209
+ if (!/^[0-9a-f]{7,64}$/i.test(from) || !/^[0-9a-f]{7,64}$/i.test(to)) return null;
210
+ if (from === to) return { commits: [], diverged: false, truncated: false };
211
+ const { signal } = opts;
212
+ const exists = await git(cwd, ["cat-file", "-e", `${from}^{commit}`], { signal });
213
+ if (!exists.ok) return { commits: [], diverged: true, truncated: false };
214
+ const [ancestor, log] = await Promise.all([git(cwd, ["merge-base", "--is-ancestor", from, to], { signal }), git(cwd, ["log", `-n${limit + 1}`, "--format=%H%x1f%s", `${from}..${to}`], { signal })]);
215
+ if (!log.ok) return null;
216
+ const commits = log.stdout.split("\n").filter(Boolean).map((l) => {
217
+ const [sha, subject] = l.split("");
218
+ return { sha, subject: subject ?? "" };
219
+ });
220
+ return { commits: commits.slice(0, limit), diverged: !ancestor.ok, truncated: commits.length > limit };
221
+ }
222
+ function parseStatusV2Z(stdout) {
223
+ const out = [];
224
+ const parts = stdout.split("\0");
225
+ for (let i = 0; i < parts.length; i++) {
226
+ const rec = parts[i];
227
+ if (!rec) continue;
228
+ const kind = rec[0];
229
+ if (kind === "?" || kind === "!") {
230
+ out.push({ kind, path: rec.slice(2), submodule: false });
231
+ continue;
232
+ }
233
+ if (kind === "#") continue;
234
+ if (kind !== "1" && kind !== "2" && kind !== "u") return null;
235
+ const fields = kind === "1" ? 8 : kind === "2" ? 9 : 10;
236
+ let at = 0;
237
+ for (let f = 0; f < fields && at >= 0; f++) at = rec.indexOf(" ", at + 1);
238
+ if (at < 0) return null;
239
+ const sub = rec.split(" ", 3)[2] ?? "N...";
240
+ const entry = { kind, path: rec.slice(at + 1), submodule: sub.startsWith("S") };
241
+ if (kind === "2") entry.from = parts[++i];
242
+ out.push(entry);
243
+ }
244
+ return out;
245
+ }
246
+ async function statusV2(cwd, opts = {}) {
247
+ const r = await git(cwd, ["status", "--porcelain=v2", "-z", "--untracked-files=all", "--ignore-submodules=none", "--", "."], { signal: opts.signal });
248
+ return r.ok ? parseStatusV2Z(r.stdout) : null;
249
+ }
250
+
251
+ export {
252
+ git,
253
+ GitCommandError,
254
+ gitOrThrow,
255
+ gitAvailable,
256
+ isGitRepo,
257
+ gitInfo,
258
+ workingChanges,
259
+ parseNameStatusZ,
260
+ isSafeRef,
261
+ headMovement,
262
+ statusV2
263
+ };
264
+ //# sourceMappingURL=chunk-OLPSEQS5.js.map
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ readTextIfExists,
4
+ writeFileAtomic
5
+ } from "./chunk-IQQBAWSM.js";
6
+ import {
7
+ ATHENA_DIR
8
+ } from "./chunk-EUPETUWA.js";
9
+
10
+ // src/core/local-config.ts
11
+ import crypto from "crypto";
12
+ import path from "path";
13
+ import { z } from "zod";
14
+ var LOCAL_CONFIG_FILE = "local.json";
15
+ var LocalConfig = z.object({
16
+ /** Random per-machine salt for keyed fingerprints of secret findings. Never leaves this machine. */
17
+ salt: z.string().regex(/^[a-f0-9]{64}$/).optional(),
18
+ /** AI settings trusted only from machine-local sources (see src/services/ai.ts). */
19
+ ai: z.object({
20
+ baseUrl: z.string().optional(),
21
+ consent: z.boolean().optional()
22
+ }).optional()
23
+ }).passthrough();
24
+ function localPath(root) {
25
+ return path.join(root, ATHENA_DIR, LOCAL_CONFIG_FILE);
26
+ }
27
+ async function readLocalConfig(root) {
28
+ const text = await readTextIfExists(localPath(root)).catch(() => null);
29
+ if (text === null) return {};
30
+ try {
31
+ const parsed = LocalConfig.safeParse(JSON.parse(text));
32
+ return parsed.success ? parsed.data : {};
33
+ } catch {
34
+ return {};
35
+ }
36
+ }
37
+ async function writeLocalConfig(root, cfg) {
38
+ const ignoreFile = path.join(root, ATHENA_DIR, ".gitignore");
39
+ const ignore = await readTextIfExists(ignoreFile);
40
+ if (!ignore?.split(/\r?\n/).includes(LOCAL_CONFIG_FILE)) {
41
+ await writeFileAtomic(ignoreFile, `${(ignore ?? "").replace(/\s*$/, "")}${ignore ? "\n" : ""}${LOCAL_CONFIG_FILE}
42
+ `);
43
+ }
44
+ await writeFileAtomic(localPath(root), `${JSON.stringify(cfg, null, 2)}
45
+ `);
46
+ }
47
+ async function getOrCreateSalt(root) {
48
+ const cfg = await readLocalConfig(root);
49
+ if (cfg.salt) return cfg.salt;
50
+ const salt = crypto.randomBytes(32).toString("hex");
51
+ await writeLocalConfig(root, { ...cfg, salt });
52
+ return salt;
53
+ }
54
+ function keyedFingerprint(salt, value, length = 16) {
55
+ return crypto.createHmac("sha256", salt).update(value).digest("hex").slice(0, length);
56
+ }
57
+
58
+ export {
59
+ LOCAL_CONFIG_FILE,
60
+ readLocalConfig,
61
+ getOrCreateSalt,
62
+ keyedFingerprint
63
+ };
64
+ //# sourceMappingURL=chunk-PVCIGUIT.js.map
@@ -0,0 +1,217 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/core/model/project-model.ts
4
+ import { z as z2 } from "zod";
5
+
6
+ // src/core/model/fact.ts
7
+ import { z } from "zod";
8
+ var FactStatus = z.enum(["FACT", "DETECTED", "INFERRED", "UNKNOWN"]);
9
+ var Confidence = z.enum(["high", "medium", "low"]);
10
+ var FactSource = z.enum(["code", "config", "filesystem", "git", "developer", "ai"]);
11
+ var Evidence = z.object({
12
+ /** Repo-relative POSIX path. */
13
+ file: z.string(),
14
+ line: z.number().int().positive().optional(),
15
+ detail: z.string().optional()
16
+ });
17
+ var Provenance = z.object({
18
+ status: FactStatus,
19
+ confidence: Confidence,
20
+ source: FactSource,
21
+ evidence: z.array(Evidence)
22
+ });
23
+ function detected(source, evidence, confidence = "high") {
24
+ return { status: "DETECTED", confidence, source, evidence };
25
+ }
26
+ function inferred(source, evidence, confidence = "medium") {
27
+ return { status: "INFERRED", confidence, source, evidence };
28
+ }
29
+ function fact(source, evidence) {
30
+ return { status: "FACT", confidence: "high", source, evidence };
31
+ }
32
+
33
+ // src/core/model/project-model.ts
34
+ var Named = z2.object({ name: z2.string(), provenance: Provenance });
35
+ var Language = z2.object({
36
+ name: z2.string(),
37
+ files: z2.number().int(),
38
+ bytes: z2.number().int()
39
+ });
40
+ var Framework = Named.extend({
41
+ category: z2.enum(["frontend", "backend", "fullstack", "mobile", "desktop", "orm", "testing", "other"]),
42
+ version: z2.string().optional(),
43
+ /** Workspace package root (repo-relative) this belongs to; "." for root. */
44
+ root: z2.string()
45
+ });
46
+ var Manifest = z2.object({
47
+ path: z2.string(),
48
+ ecosystem: z2.string(),
49
+ name: z2.string().optional(),
50
+ version: z2.string().optional(),
51
+ dependencies: z2.array(z2.string()),
52
+ devDependencies: z2.array(z2.string())
53
+ });
54
+ var WorkspacePackage = z2.object({
55
+ name: z2.string(),
56
+ path: z2.string(),
57
+ kind: z2.enum(["app", "package", "root", "unknown"]),
58
+ ecosystem: z2.string(),
59
+ /** Names of other workspace packages this one depends on. */
60
+ internalDependencies: z2.array(z2.string())
61
+ });
62
+ var Command = z2.object({
63
+ name: z2.string(),
64
+ command: z2.string(),
65
+ source: z2.string(),
66
+ purpose: z2.enum(["dev", "build", "test", "lint", "format", "start", "migrate", "deploy", "other"])
67
+ });
68
+ var Route = z2.object({
69
+ method: z2.string(),
70
+ path: z2.string(),
71
+ framework: z2.string(),
72
+ file: z2.string(),
73
+ line: z2.number().int().optional(),
74
+ provenance: Provenance
75
+ });
76
+ var DbEntity = z2.object({
77
+ name: z2.string(),
78
+ kind: z2.enum(["table", "model", "collection"]),
79
+ fields: z2.array(z2.object({ name: z2.string(), type: z2.string().optional(), attributes: z2.array(z2.string()) })),
80
+ indexes: z2.array(z2.string()),
81
+ relations: z2.array(z2.string()),
82
+ file: z2.string(),
83
+ provenance: Provenance
84
+ });
85
+ var Database = Named.extend({ kind: z2.enum(["engine", "orm", "driver", "service"]) });
86
+ var EnvVar = z2.object({
87
+ name: z2.string(),
88
+ /** Where the name was seen. Values are NEVER recorded. */
89
+ references: z2.array(z2.string()),
90
+ secretLike: z2.boolean()
91
+ });
92
+ var SecretFinding = z2.object({
93
+ type: z2.string(),
94
+ file: z2.string(),
95
+ line: z2.number().int(),
96
+ /**
97
+ * Keyed fingerprint (HMAC with the machine-local salt in .athena/local.json, or a
98
+ * per-process key) — allows dedup without storing the secret. Never a plain hash
99
+ * of the value, and never written to committed files.
100
+ */
101
+ fingerprint: z2.string()
102
+ });
103
+ var CiJob = z2.object({ system: z2.string(), file: z2.string(), name: z2.string(), commands: z2.array(z2.string()) });
104
+ var ContainerService = z2.object({
105
+ name: z2.string(),
106
+ image: z2.string().optional(),
107
+ ports: z2.array(z2.string()),
108
+ dependsOn: z2.array(z2.string()),
109
+ file: z2.string()
110
+ });
111
+ var TestInfo = z2.object({
112
+ frameworks: z2.array(Named),
113
+ testFileCount: z2.number().int(),
114
+ testDirs: z2.array(z2.string()),
115
+ coverageConfigs: z2.array(z2.string()),
116
+ /** Workspace packages that contain source files but zero detected test files (structural, not coverage). */
117
+ packagesWithoutTests: z2.array(z2.string())
118
+ });
119
+ var GitInfo = z2.object({
120
+ available: z2.boolean(),
121
+ isRepo: z2.boolean(),
122
+ branch: z2.string().optional(),
123
+ head: z2.string().optional(),
124
+ lastCommitDate: z2.string().optional(),
125
+ contributorCount: z2.number().int().optional(),
126
+ hotspots: z2.array(z2.object({ path: z2.string(), commits: z2.number().int() }))
127
+ });
128
+ var ProjectModel = z2.object({
129
+ schemaVersion: z2.literal(1),
130
+ name: z2.string(),
131
+ description: z2.string().optional(),
132
+ root: z2.string(),
133
+ stats: z2.object({
134
+ filesScanned: z2.number().int(),
135
+ skippedBinary: z2.number().int(),
136
+ skippedLarge: z2.number().int(),
137
+ skippedUnreadable: z2.number().int()
138
+ }),
139
+ topLevelDirs: z2.array(z2.string()),
140
+ languages: z2.array(Language),
141
+ manifests: z2.array(Manifest),
142
+ packageManagers: z2.array(Named),
143
+ buildSystems: z2.array(Named),
144
+ workspace: z2.object({
145
+ isMonorepo: z2.boolean(),
146
+ tool: z2.string().optional(),
147
+ packages: z2.array(WorkspacePackage)
148
+ }),
149
+ frameworks: z2.array(Framework),
150
+ entryPoints: z2.array(z2.object({ path: z2.string(), provenance: Provenance })),
151
+ commands: z2.array(Command),
152
+ databases: z2.array(Database),
153
+ dbEntities: z2.array(DbEntity),
154
+ migrations: z2.array(z2.object({ path: z2.string(), tool: z2.string(), count: z2.number().int() })),
155
+ routes: z2.array(Route),
156
+ apiSpecs: z2.array(z2.object({ path: z2.string(), kind: z2.enum(["openapi", "graphql", "grpc"]) })),
157
+ auth: z2.array(Named.extend({ kind: z2.enum(["library", "provider", "hashing", "middleware", "token"]) })),
158
+ 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) }),
159
+ infrastructure: z2.array(Named.extend({ kind: z2.string(), file: z2.string() })),
160
+ ci: z2.array(CiJob),
161
+ tests: TestInfo,
162
+ env: z2.object({ vars: z2.array(EnvVar), envFilesPresent: z2.array(z2.string()) }),
163
+ security: z2.object({
164
+ secrets: z2.array(SecretFinding),
165
+ tooling: z2.array(Named),
166
+ /** Libraries/middleware relevant to web security controls (helmet, cors, csrf...). */
167
+ controls: z2.array(Named)
168
+ }),
169
+ caching: z2.array(Named),
170
+ queues: z2.array(Named),
171
+ observability: z2.array(Named),
172
+ git: GitInfo,
173
+ warnings: z2.array(z2.string())
174
+ });
175
+ function emptyModel(name, root) {
176
+ return {
177
+ schemaVersion: 1,
178
+ name,
179
+ root,
180
+ stats: { filesScanned: 0, skippedBinary: 0, skippedLarge: 0, skippedUnreadable: 0 },
181
+ topLevelDirs: [],
182
+ languages: [],
183
+ manifests: [],
184
+ packageManagers: [],
185
+ buildSystems: [],
186
+ workspace: { isMonorepo: false, packages: [] },
187
+ frameworks: [],
188
+ entryPoints: [],
189
+ commands: [],
190
+ databases: [],
191
+ dbEntities: [],
192
+ migrations: [],
193
+ routes: [],
194
+ apiSpecs: [],
195
+ auth: [],
196
+ containers: { dockerfiles: [], services: [] },
197
+ infrastructure: [],
198
+ ci: [],
199
+ tests: { frameworks: [], testFileCount: 0, testDirs: [], coverageConfigs: [], packagesWithoutTests: [] },
200
+ env: { vars: [], envFilesPresent: [] },
201
+ security: { secrets: [], tooling: [], controls: [] },
202
+ caching: [],
203
+ queues: [],
204
+ observability: [],
205
+ git: { available: false, isRepo: false, hotspots: [] },
206
+ warnings: []
207
+ };
208
+ }
209
+
210
+ export {
211
+ detected,
212
+ inferred,
213
+ fact,
214
+ ProjectModel,
215
+ emptyModel
216
+ };
217
+ //# sourceMappingURL=chunk-QCC4VJUH.js.map
@@ -0,0 +1,95 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ readRecentEvents,
4
+ summarizeSessions
5
+ } from "./chunk-65TSRDQ3.js";
6
+ import {
7
+ ADAPTERS,
8
+ applyChanges,
9
+ resolveAdapters
10
+ } from "./chunk-YRIS7ZS6.js";
11
+ import {
12
+ athenaDir,
13
+ readState,
14
+ writeState
15
+ } from "./chunk-2DY4PUR4.js";
16
+ import {
17
+ AthenaError
18
+ } from "./chunk-AD4OZCU2.js";
19
+
20
+ // src/services/agents.ts
21
+ function resolve(names) {
22
+ try {
23
+ return names.length === 1 && names[0] === "all" ? ADAPTERS : resolveAdapters(names);
24
+ } catch (err) {
25
+ throw new AthenaError(err.message);
26
+ }
27
+ }
28
+ async function listAgents(root) {
29
+ const st = await readState(athenaDir(root));
30
+ const sessions = summarizeSessions(await readRecentEvents(root, 500));
31
+ const out = [];
32
+ for (const a of ADAPTERS) {
33
+ const presence = await a.detectPresence(root);
34
+ const s = st.kind === "ok" ? st.state.agents[a.id] : void 0;
35
+ const checks = s?.configured ? await a.check(root) : [];
36
+ const hooksInstalled = a.capabilities.hooks && checks.some((c) => c.ok && /hooks installed/i.test(c.message));
37
+ const mine = sessions.filter((x) => x.agent === a.id);
38
+ out.push({
39
+ id: a.id,
40
+ name: a.displayName,
41
+ configured: Boolean(s?.configured),
42
+ configuredAt: s?.configuredAt ?? null,
43
+ files: s?.files ?? [],
44
+ detectedInProject: presence.detectedInProject,
45
+ evidence: presence.evidence,
46
+ note: a.supportNote,
47
+ capabilities: a.capabilities,
48
+ checks,
49
+ activityObservation: !a.capabilities.hooks ? "unsupported" : hooksInstalled ? "hooks" : "not-configured",
50
+ lastActivityAt: mine[0]?.lastEventAt ?? null,
51
+ observedEvents: mine.reduce((n, x) => n + x.events, 0)
52
+ });
53
+ }
54
+ return out;
55
+ }
56
+ async function configureAgents(root, names) {
57
+ const st = await readState(athenaDir(root));
58
+ if (st.kind !== "ok") throw new AthenaError("state.json is missing or corrupted.", "Run `athena analyze` first.");
59
+ const adapters = resolve(names);
60
+ const results = [];
61
+ for (const a of adapters) {
62
+ const planned = await a.plan({ root, projectName: st.state.projectName });
63
+ await applyChanges(root, planned);
64
+ st.state.agents[a.id] = { configured: true, files: planned.map((p) => p.path), configuredAt: (/* @__PURE__ */ new Date()).toISOString() };
65
+ results.push({ id: a.id, files: planned.map((p) => ({ path: p.path, action: p.action })) });
66
+ }
67
+ await writeState(athenaDir(root), st.state);
68
+ return results;
69
+ }
70
+ async function removeAgents(root, names) {
71
+ const st = await readState(athenaDir(root));
72
+ const removed = [];
73
+ const targets = resolve(names);
74
+ for (const a of targets) {
75
+ removed.push(...await a.remove(root));
76
+ if (st.kind === "ok") delete st.state.agents[a.id];
77
+ }
78
+ if (st.kind === "ok") {
79
+ for (const a of ADAPTERS) {
80
+ const s = st.state.agents[a.id];
81
+ if (!s?.configured || targets.includes(a) || !s.files.some((f) => removed.includes(f))) continue;
82
+ const planned = await a.plan({ root, projectName: st.state.projectName });
83
+ await applyChanges(root, planned.filter((p) => removed.includes(p.path)));
84
+ }
85
+ await writeState(athenaDir(root), st.state);
86
+ }
87
+ return removed;
88
+ }
89
+
90
+ export {
91
+ listAgents,
92
+ configureAgents,
93
+ removeAgents
94
+ };
95
+ //# sourceMappingURL=chunk-QLW657NT.js.map