project-athena 0.4.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.
- package/CHANGELOG.md +31 -0
- package/README.md +10 -0
- package/dist/{activity-BKW7G4I5.js → activity-XCHKBZTG.js} +4 -4
- package/dist/{agents-DFSNEOP5.js → agents-HUJ4JXIB.js} +4 -4
- package/dist/{ai-ASL4FFQ7.js → ai-LGTLQKL4.js} +3 -3
- package/dist/{analyze-ZY3MXBOI.js → analyze-AP4XJT7D.js} +7 -7
- package/dist/{chunk-ZB7LC6FP.js → chunk-3KFOI2X4.js} +2 -2
- package/dist/{chunk-MPG3IEGB.js → chunk-44EGCEB2.js} +23 -14
- package/dist/{chunk-GGXPG6OE.js → chunk-4FETKOY3.js} +8 -7
- package/dist/chunk-4IIBVTBS.js +76 -0
- package/dist/{chunk-LEMPCNAY.js → chunk-56EXAGTM.js} +3 -3
- package/dist/{chunk-DZDI2HRT.js → chunk-6OSQMXUP.js} +5 -5
- package/dist/{chunk-OLPSEQS5.js → chunk-AKOI4VTD.js} +10 -1
- package/dist/{chunk-FVCDMQUQ.js → chunk-C25FDXOO.js} +133 -23
- package/dist/{chunk-7DZK6WSQ.js → chunk-DH5AGULY.js} +2 -2
- package/dist/{chunk-TDNZ2RYA.js → chunk-F65QINMR.js} +2 -2
- package/dist/{chunk-WVQC2EGO.js → chunk-GU3ZX2J7.js} +2 -2
- package/dist/{chunk-UAZLPNVC.js → chunk-GYQG4Q2N.js} +4 -4
- package/dist/chunk-IDODPGTX.js +595 -0
- package/dist/chunk-KJYSNZXS.js +934 -0
- package/dist/{chunk-3XSDI5WF.js → chunk-L2EHJCH4.js} +5 -5
- package/dist/{chunk-65TSRDQ3.js → chunk-P4TRQMES.js} +2 -2
- package/dist/{chunk-KHMBNT66.js → chunk-PZPMWCXS.js} +5 -5
- package/dist/{chunk-XDCKZ5TV.js → chunk-R5AX7VST.js} +2 -2
- package/dist/{chunk-QLW657NT.js → chunk-RQKGT2EK.js} +2 -2
- package/dist/{chunk-VSYBC3VY.js → chunk-UMWX4UTK.js} +2 -2
- package/dist/{chunk-RXNRMIZP.js → chunk-WUIC65QO.js} +2 -2
- package/dist/{chunk-JCGDR4UV.js → chunk-WWQ5NKEC.js} +3 -1
- package/dist/{chunk-RVTNSNGK.js → chunk-X7EYOAEX.js} +2 -2
- package/dist/chunk-Y6SDMZET.js +278 -0
- package/dist/{clean-MDBYH62P.js → clean-LQOG56AM.js} +2 -2
- package/dist/cli.js +2 -2
- package/dist/{context-PLPCAPCO.js → context-G5YHY3L2.js} +8 -8
- package/dist/{doctor-BX677KRE.js → doctor-L34QJ7WR.js} +8 -8
- package/dist/{event-TNT6CQZR.js → event-6YW6TGFI.js} +3 -3
- package/dist/{git-hook-YZNZGAAP.js → git-hook-Y7Y262F7.js} +2 -2
- package/dist/{init-WQCAOJ2R.js → init-427QR5AS.js} +7 -7
- package/dist/{mcp-U7EPH43L.js → mcp-DWNWRGJW.js} +51 -14
- package/dist/{memory-VSVNLEJC.js → memory-XBZCYQLW.js} +3 -3
- package/dist/{open-UJZRYF4E.js → open-LJMOB6U2.js} +33 -31
- package/dist/{program-CWJNGCTZ.js → program-DCP526LU.js} +46 -32
- package/dist/{review-OOKXSYMP.js → review-VEJBPACX.js} +10 -9
- package/dist/{rules-4FXJUCXB.js → rules-M4DLLXBL.js} +4 -4
- package/dist/scan-JVKCVHPD.js +939 -0
- package/dist/{security-LME3XFL3.js → security-JTJN3E7K.js} +13 -11
- package/dist/{staged-check-X24C3YRD.js → staged-check-PQSLGQBW.js} +11 -11
- package/dist/{status-RR57ZNGI.js → status-PO27BSOZ.js} +4 -4
- package/dist/{sync-KFJANRXF.js → sync-GVO2VHPI.js} +10 -10
- package/dist/{watch-CY7QHIYN.js → watch-TEHFO47V.js} +10 -10
- package/package.json +3 -1
- package/dist/chunk-SJ4DQFIJ.js +0 -379
|
@@ -1,4 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
Coverage,
|
|
4
|
+
Finding,
|
|
5
|
+
SECRETS_ENGINE,
|
|
6
|
+
dedupeFindings,
|
|
7
|
+
fileFingerprint,
|
|
8
|
+
hitsFromMatches,
|
|
9
|
+
secretFindings
|
|
10
|
+
} from "./chunk-Y6SDMZET.js";
|
|
2
11
|
import {
|
|
3
12
|
listRules,
|
|
4
13
|
parseRules
|
|
@@ -6,7 +15,7 @@ import {
|
|
|
6
15
|
import {
|
|
7
16
|
loadScan,
|
|
8
17
|
manifestDependencyNames
|
|
9
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-44EGCEB2.js";
|
|
10
19
|
import {
|
|
11
20
|
API_ROUTE_PATH,
|
|
12
21
|
AUTH_PATH,
|
|
@@ -21,10 +30,10 @@ import {
|
|
|
21
30
|
isSafeRef,
|
|
22
31
|
parseNameStatusZ,
|
|
23
32
|
workingChanges
|
|
24
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-AKOI4VTD.js";
|
|
25
34
|
import {
|
|
26
35
|
scanText
|
|
27
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-WWQ5NKEC.js";
|
|
28
37
|
import {
|
|
29
38
|
athenaDir
|
|
30
39
|
} from "./chunk-2DY4PUR4.js";
|
|
@@ -40,6 +49,82 @@ import {
|
|
|
40
49
|
// src/services/review.ts
|
|
41
50
|
import { promises as fs } from "fs";
|
|
42
51
|
import path from "path";
|
|
52
|
+
|
|
53
|
+
// src/core/scanners/review.ts
|
|
54
|
+
var REVIEW_ENGINE = "athena-review";
|
|
55
|
+
var LEVEL_SEVERITY = { blocker: "high", warning: "medium", info: "info" };
|
|
56
|
+
var CHECK_CONFIDENCE = { tests: "medium", api: "medium", auth: "medium", database: "medium", leftovers: "medium" };
|
|
57
|
+
var CHECK_CWE = { "env-file": ["CWE-540"] };
|
|
58
|
+
var CHECK_TITLE = {
|
|
59
|
+
"env-file": "Environment file in the change",
|
|
60
|
+
dependencies: "New dependencies",
|
|
61
|
+
tests: "Source changed without tests",
|
|
62
|
+
api: "API surface changed",
|
|
63
|
+
database: "Database schema or migrations changed",
|
|
64
|
+
auth: "Authentication/authorization code changed",
|
|
65
|
+
"large-files": "Large file added",
|
|
66
|
+
leftovers: "TODO/FIXME or debug statement added",
|
|
67
|
+
vulnerabilities: "Known vulnerable dependencies",
|
|
68
|
+
knowledge: "Athena knowledge out of date",
|
|
69
|
+
skipped: "Changed file not checked"
|
|
70
|
+
};
|
|
71
|
+
function checkFinding(check, loc, lines) {
|
|
72
|
+
const ruleId = `review/${check.check}`;
|
|
73
|
+
return {
|
|
74
|
+
fingerprint: fileFingerprint({ ruleId, file: loc?.file, key: loc ? void 0 : check.check }),
|
|
75
|
+
ruleId,
|
|
76
|
+
category: "review",
|
|
77
|
+
severity: LEVEL_SEVERITY[check.level],
|
|
78
|
+
confidence: CHECK_CONFIDENCE[check.check] ?? "high",
|
|
79
|
+
label: "DETECTED",
|
|
80
|
+
potential: false,
|
|
81
|
+
title: CHECK_TITLE[check.check] ?? check.message,
|
|
82
|
+
message: loc && lines.length > 1 ? `${check.message} (${lines.length} lines in this file)` : check.message,
|
|
83
|
+
cwe: CHECK_CWE[check.check] ?? [],
|
|
84
|
+
...loc ? { location: { file: loc.file, ...lines[0] ? { startLine: lines[0] } : {} } } : {},
|
|
85
|
+
engine: { id: "athena" },
|
|
86
|
+
...check.hint ? { help: { text: check.hint } } : {}
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function reviewFindings(input) {
|
|
90
|
+
const out = secretFindings(input.secrets);
|
|
91
|
+
for (const { check, locations } of input.checks) {
|
|
92
|
+
if (check.check === "secrets") continue;
|
|
93
|
+
if (!locations.length) {
|
|
94
|
+
out.push(checkFinding(check, null, []));
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const byFile = /* @__PURE__ */ new Map();
|
|
98
|
+
for (const l of locations) {
|
|
99
|
+
const lines = byFile.get(l.file) ?? [];
|
|
100
|
+
if (l.line) lines.push(l.line);
|
|
101
|
+
byFile.set(l.file, lines);
|
|
102
|
+
}
|
|
103
|
+
for (const [file, lines] of byFile) out.push(checkFinding(check, { file }, lines.sort((a, b) => a - b)));
|
|
104
|
+
}
|
|
105
|
+
return out;
|
|
106
|
+
}
|
|
107
|
+
function reviewCoverage(c) {
|
|
108
|
+
const filesSkipped = { tooLarge: c.skipped.tooLarge, unreadable: c.skipped.unreadable, binary: 0, minified: 0, unsupported: 0 };
|
|
109
|
+
const reason = c.incomplete ? `${c.skipped.tooLarge + c.skipped.unreadable} changed file(s) could not be read and were not checked` : void 0;
|
|
110
|
+
return [
|
|
111
|
+
{ engine: REVIEW_ENGINE, category: "review", status: "ok", ...reason ? { reason } : {}, target: "changed files", filesScanned: c.checked, filesSkipped, network: false, durationMs: c.durationMs },
|
|
112
|
+
{ engine: SECRETS_ENGINE, category: "secret", status: "ok", reason: `added lines only${reason ? `; ${reason}` : ""}`, target: "added lines", filesScanned: c.checked, filesSkipped, network: false, durationMs: 0 }
|
|
113
|
+
];
|
|
114
|
+
}
|
|
115
|
+
function reviewScanner(run) {
|
|
116
|
+
return {
|
|
117
|
+
id: REVIEW_ENGINE,
|
|
118
|
+
category: "review",
|
|
119
|
+
title: "Change review checks",
|
|
120
|
+
async run(ctx) {
|
|
121
|
+
if (ctx.mode === "all") return { findings: [], coverage: [{ engine: REVIEW_ENGINE, category: "review", status: "skipped", reason: "review checks need a diff (staged, changed or base scope)", durationMs: 0 }] };
|
|
122
|
+
return run(ctx);
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/services/review.ts
|
|
43
128
|
var ENV_FILE = /(^|\/)\.env(\.(local|production|development|prod|dev|staging))?$/;
|
|
44
129
|
var MANIFEST_FILE = /(^|\/)(package\.json|pyproject\.toml|requirements[^/]*\.txt|go\.mod|Cargo\.toml|composer\.json|Gemfile|pubspec\.yaml|pom\.xml|build\.gradle(\.kts)?)$/;
|
|
45
130
|
var LARGE_ADDED_BYTES = 512 * 1024;
|
|
@@ -113,16 +198,18 @@ function addedLines(patch) {
|
|
|
113
198
|
}
|
|
114
199
|
return out;
|
|
115
200
|
}
|
|
116
|
-
function
|
|
201
|
+
function scanAddedLinesDetailed(lines) {
|
|
117
202
|
const hits = [];
|
|
118
203
|
let block = [];
|
|
119
204
|
const flush = () => {
|
|
120
205
|
if (!block.length) return;
|
|
121
206
|
const b = block;
|
|
122
207
|
block = [];
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
208
|
+
const text = b.map((l) => l.text).join("\n");
|
|
209
|
+
for (const h of hitsFromMatches("", text, scanText(text))) {
|
|
210
|
+
const at = b[h.line - 1] ?? b[0];
|
|
211
|
+
const endAt = h.endLine ? b[h.endLine - 1] : void 0;
|
|
212
|
+
hits.push({ ...h, file: at.file, line: at.line, ...endAt ? { endLine: endAt.line } : {} });
|
|
126
213
|
}
|
|
127
214
|
};
|
|
128
215
|
for (const l of lines) {
|
|
@@ -145,6 +232,7 @@ async function reviewChanges(root, opts = {}) {
|
|
|
145
232
|
}
|
|
146
233
|
}
|
|
147
234
|
async function review(root, opts) {
|
|
235
|
+
const started = Date.now();
|
|
148
236
|
const signal = opts.signal;
|
|
149
237
|
signal?.throwIfAborted();
|
|
150
238
|
const repoCheck = await git(root, ["rev-parse", "--is-inside-work-tree"], { signal });
|
|
@@ -248,14 +336,19 @@ async function review(root, opts) {
|
|
|
248
336
|
};
|
|
249
337
|
const findings = [];
|
|
250
338
|
const paths = changedFiles.map((f) => f.path);
|
|
251
|
-
const
|
|
339
|
+
const locations = /* @__PURE__ */ new Map();
|
|
340
|
+
const add = (f, all) => {
|
|
341
|
+
findings.push(f);
|
|
342
|
+
locations.set(f, (all ?? f.files).map((x) => typeof x === "string" ? { file: x } : x));
|
|
343
|
+
};
|
|
344
|
+
const secretDetail = scanAddedLinesDetailed(added);
|
|
252
345
|
const secretHits = /* @__PURE__ */ new Map();
|
|
253
|
-
for (const hit of
|
|
346
|
+
for (const hit of secretDetail) {
|
|
254
347
|
if (!secretHits.has(hit.type)) secretHits.set(hit.type, /* @__PURE__ */ new Set());
|
|
255
348
|
secretHits.get(hit.type).add(`${hit.file}:${hit.line}`);
|
|
256
349
|
}
|
|
257
|
-
for (const [type,
|
|
258
|
-
add({ level: "blocker", check: "secrets", message: `Possible ${type} added`, files: [...
|
|
350
|
+
for (const [type, locations2] of secretHits) {
|
|
351
|
+
add({ level: "blocker", check: "secrets", message: `Possible ${type} added`, files: [...locations2].slice(0, 10), hint: "Remove the value, use an environment variable, and rotate the credential if it was real." });
|
|
259
352
|
}
|
|
260
353
|
const envFiles = changedFiles.filter((f) => f.status !== "deleted" && ENV_FILE.test(f.path)).map((f) => f.path);
|
|
261
354
|
if (envFiles.length) add({ level: "blocker", check: "env-file", message: "Environment file included in the change", files: envFiles, hint: "Add it to .gitignore and commit a .env.example with names only." });
|
|
@@ -281,14 +374,14 @@ async function review(root, opts) {
|
|
|
281
374
|
const changedSource = paths.filter((p) => SOURCE_FILE.test(p) && !TEST_FILE.test(p));
|
|
282
375
|
const changedTests = paths.filter((p) => TEST_FILE.test(p));
|
|
283
376
|
if (changedSource.length && !changedTests.length) {
|
|
284
|
-
add({ level: "warning", check: "tests", message: `${changedSource.length} source file(s) changed with no test file changes`, files: changedSource.slice(0, 10), hint: "See `.athena/testing.md` for the project test commands and layout." });
|
|
377
|
+
add({ level: "warning", check: "tests", message: `${changedSource.length} source file(s) changed with no test file changes`, files: changedSource.slice(0, 10), hint: "See `.athena/testing.md` for the project test commands and layout." }, changedSource);
|
|
285
378
|
}
|
|
286
379
|
const routeFiles = changedSource.filter((p) => API_ROUTE_PATH.test(p));
|
|
287
|
-
if (routeFiles.length) add({ level: "info", check: "api", message: "API surface changed", files: routeFiles.slice(0, 10), hint: "Check auth/authorization and error handling (`.athena/api.md`, `.athena/auth.md`)." });
|
|
380
|
+
if (routeFiles.length) add({ level: "info", check: "api", message: "API surface changed", files: routeFiles.slice(0, 10), hint: "Check auth/authorization and error handling (`.athena/api.md`, `.athena/auth.md`)." }, routeFiles);
|
|
288
381
|
const schemaFiles = paths.filter((p) => SCHEMA_PATH.test(p));
|
|
289
|
-
if (schemaFiles.length) add({ level: "info", check: "database", message: "Database schema or migrations changed", files: schemaFiles.slice(0, 10), hint: "Check indexes, constraints and backward compatibility (`.athena/database.md`)." });
|
|
382
|
+
if (schemaFiles.length) add({ level: "info", check: "database", message: "Database schema or migrations changed", files: schemaFiles.slice(0, 10), hint: "Check indexes, constraints and backward compatibility (`.athena/database.md`)." }, schemaFiles);
|
|
290
383
|
const authFiles = changedSource.filter((p) => AUTH_PATH.test(p));
|
|
291
|
-
if (authFiles.length) add({ level: "warning", check: "auth", message: "Authentication/authorization code changed", files: authFiles.slice(0, 10), hint: "Review against `.athena/auth.md` and `.athena/security.md`." });
|
|
384
|
+
if (authFiles.length) add({ level: "warning", check: "auth", message: "Authentication/authorization code changed", files: authFiles.slice(0, 10), hint: "Review against `.athena/auth.md` and `.athena/security.md`." }, authFiles);
|
|
292
385
|
for (const f of changedFiles.filter((x) => x.status === "added")) {
|
|
293
386
|
signal?.throwIfAborted();
|
|
294
387
|
let size = null;
|
|
@@ -304,12 +397,12 @@ async function review(root, opts) {
|
|
|
304
397
|
if (large.length) add({ level: "warning", check: "large-files", message: "Large files added", files: large, hint: "Consider whether these belong in Git." });
|
|
305
398
|
const debugHits = added.filter((l) => /\b(TODO|FIXME|XXX|console\.log|debugger|print\(|binding\.pry|dd\()/.test(l.text) && SOURCE_FILE.test(l.file));
|
|
306
399
|
if (debugHits.length) {
|
|
307
|
-
add({ level: "info", check: "leftovers", message: `${debugHits.length} added line(s) contain TODO/FIXME or debug statements`, files: [...new Set(debugHits.map((l) => `${l.file}:${l.line}`))].slice(0, 10) });
|
|
400
|
+
add({ level: "info", check: "leftovers", message: `${debugHits.length} added line(s) contain TODO/FIXME or debug statements`, files: [...new Set(debugHits.map((l) => `${l.file}:${l.line}`))].slice(0, 10) }, debugHits.map((l) => ({ file: l.file, line: l.line })));
|
|
308
401
|
}
|
|
309
|
-
const
|
|
310
|
-
if (
|
|
311
|
-
const vulnerable =
|
|
312
|
-
if (vulnerable.length) add({ level: "warning", check: "vulnerabilities", message: `${vulnerable.length} high/critical dependency advisor${vulnerable.length === 1 ? "y" : "ies"} from the last scan (${
|
|
402
|
+
const lastScan = await loadScan(root);
|
|
403
|
+
if (lastScan) {
|
|
404
|
+
const vulnerable = lastScan.tools.flatMap((t) => t.findings).filter((f) => ["critical", "high"].includes(f.severity));
|
|
405
|
+
if (vulnerable.length) add({ level: "warning", check: "vulnerabilities", message: `${vulnerable.length} high/critical dependency advisor${vulnerable.length === 1 ? "y" : "ies"} from the last scan (${lastScan.scannedAt.slice(0, 10)})`, files: [], hint: "Run `athena security` for details." });
|
|
313
406
|
}
|
|
314
407
|
let knowledgeInSync = null;
|
|
315
408
|
if (opts.checkSync) {
|
|
@@ -321,9 +414,25 @@ async function review(root, opts) {
|
|
|
321
414
|
const reviewDoc = await readTextIfExists(path.join(athenaDir(root), "code-review.md"));
|
|
322
415
|
const checklist = reviewDoc ? [...reviewDoc.matchAll(/^- \[ \] (.+)$/gm)].map((m) => m[1].trim()) : [];
|
|
323
416
|
if (skipped.length) {
|
|
324
|
-
add({ level: "warning", check: "skipped", message: `${skipped.length} changed file${skipped.length === 1 ? " was" : "s were"} not checked`, files: skipped.map((s) => `${s.path} (${SKIP_REASON[s.reason]})`).slice(0, 10), hint: "Athena could not read these files, so their contents were not checked for secrets. Check them yourself." });
|
|
417
|
+
add({ level: "warning", check: "skipped", message: `${skipped.length} changed file${skipped.length === 1 ? " was" : "s were"} not checked`, files: skipped.map((s) => `${s.path} (${SKIP_REASON[s.reason]})`).slice(0, 10), hint: "Athena could not read these files, so their contents were not checked for secrets. Check them yourself." }, skipped.map((s) => s.path));
|
|
325
418
|
}
|
|
326
|
-
|
|
419
|
+
const durationMs = Date.now() - started;
|
|
420
|
+
const tooLarge = skipped.filter((s) => s.reason === "too-large").length;
|
|
421
|
+
const scan = {
|
|
422
|
+
schemaVersion: 1,
|
|
423
|
+
scannedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
424
|
+
durationMs,
|
|
425
|
+
scope: { mode: mode === "working" ? "changed" : mode, ...opts.base !== void 0 ? { base: opts.base } : {}, files: changedFiles.length },
|
|
426
|
+
findings: dedupeFindings(reviewFindings({ checks: findings.map((check) => ({ check, locations: locations.get(check) ?? [] })), secrets: secretDetail }).map((f) => Finding.parse(f))),
|
|
427
|
+
coverage: reviewCoverage({ checked: changedFiles.filter((f) => f.status !== "deleted").length - skipped.length, skipped: { tooLarge, unreadable: skipped.length - tooLarge }, durationMs, incomplete: skipped.length > 0 }).map((c) => Coverage.parse(c))
|
|
428
|
+
};
|
|
429
|
+
return { base, mode, ...mergeBase ? { mergeBase } : {}, changedFiles, findings, rules, checklist, knowledgeInSync, stats: { added: addedCount + untrackedAdded, removed: removedCount, files: changedFiles.length }, incomplete: skipped.length > 0, skipped, scan };
|
|
430
|
+
}
|
|
431
|
+
function createReviewScanner(opts = {}) {
|
|
432
|
+
return reviewScanner(async (ctx) => {
|
|
433
|
+
const r = await reviewChanges(ctx.root, { ...opts, signal: ctx.signal, ...ctx.mode === "staged" ? { staged: true } : {}, ...ctx.mode === "base" ? { base: ctx.base ?? "HEAD" } : {} });
|
|
434
|
+
return { findings: r.scan.findings, coverage: r.scan.coverage };
|
|
435
|
+
});
|
|
327
436
|
}
|
|
328
437
|
var SKIP_REASON = {
|
|
329
438
|
"outside-root": "symlink to a path outside the project",
|
|
@@ -338,6 +447,7 @@ function hasBlockers(result) {
|
|
|
338
447
|
|
|
339
448
|
export {
|
|
340
449
|
reviewChanges,
|
|
450
|
+
createReviewScanner,
|
|
341
451
|
hasBlockers
|
|
342
452
|
};
|
|
343
|
-
//# sourceMappingURL=chunk-
|
|
453
|
+
//# sourceMappingURL=chunk-C25FDXOO.js.map
|
|
@@ -37,7 +37,7 @@ async function confirm(question) {
|
|
|
37
37
|
async function cleanCommand(opts) {
|
|
38
38
|
const root = await requireProjectRoot(opts);
|
|
39
39
|
if (!opts.yes) {
|
|
40
|
-
const memory = (await (await import("./memory-
|
|
40
|
+
const memory = (await (await import("./memory-XBZCYQLW.js")).memorySummary(root))?.total ?? 0;
|
|
41
41
|
const memoryNote = memory ? `${memory} project memory ${memory === 1 ? "entry" : "entries"} in .athena/memory/ (shared with your team)` : "";
|
|
42
42
|
if (!process.stdin.isTTY) throw new AthenaError(`Refusing to delete .athena/${memory ? `, including ${memoryNote},` : ""} without confirmation.`, "Re-run with --yes in non-interactive environments.");
|
|
43
43
|
line(`This removes ${c.bold(".athena/")} (including rules.md and your Developer Notes)${opts.keepAgents ? "" : " and Athena blocks/files in agent configurations"}.`);
|
|
@@ -62,4 +62,4 @@ export {
|
|
|
62
62
|
confirm,
|
|
63
63
|
cleanCommand
|
|
64
64
|
};
|
|
65
|
-
//# sourceMappingURL=chunk-
|
|
65
|
+
//# sourceMappingURL=chunk-DH5AGULY.js.map
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "./chunk-SVTEJYMS.js";
|
|
9
9
|
import {
|
|
10
10
|
scanText
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-WWQ5NKEC.js";
|
|
12
12
|
import {
|
|
13
13
|
parseBlocks
|
|
14
14
|
} from "./chunk-673EPYYH.js";
|
|
@@ -699,4 +699,4 @@ export {
|
|
|
699
699
|
forgetMemory,
|
|
700
700
|
updateMemory
|
|
701
701
|
};
|
|
702
|
-
//# sourceMappingURL=chunk-
|
|
702
|
+
//# sourceMappingURL=chunk-F65QINMR.js.map
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import {
|
|
3
3
|
SCAN_FILE,
|
|
4
4
|
SecurityScan
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-44EGCEB2.js";
|
|
6
6
|
import {
|
|
7
7
|
GRAPH_FILE,
|
|
8
8
|
ProjectGraph
|
|
@@ -163,4 +163,4 @@ export {
|
|
|
163
163
|
projectSession,
|
|
164
164
|
releaseProjectSession
|
|
165
165
|
};
|
|
166
|
-
//# sourceMappingURL=chunk-
|
|
166
|
+
//# sourceMappingURL=chunk-GU3ZX2J7.js.map
|
|
@@ -5,13 +5,13 @@ import {
|
|
|
5
5
|
listMemory,
|
|
6
6
|
recall,
|
|
7
7
|
selectContext
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-F65QINMR.js";
|
|
9
9
|
import {
|
|
10
10
|
projectSession
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-GU3ZX2J7.js";
|
|
12
12
|
import {
|
|
13
13
|
analyzeProject
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-44EGCEB2.js";
|
|
15
15
|
import {
|
|
16
16
|
GRAPH_FILE,
|
|
17
17
|
buildGraph,
|
|
@@ -105,4 +105,4 @@ export {
|
|
|
105
105
|
getRelevantContext,
|
|
106
106
|
graphSummary
|
|
107
107
|
};
|
|
108
|
-
//# sourceMappingURL=chunk-
|
|
108
|
+
//# sourceMappingURL=chunk-GYQG4Q2N.js.map
|