@mcptoolshop/venvkit 0.2.1 → 0.2.5

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 (57) hide show
  1. package/README.es.md +263 -0
  2. package/README.fr.md +263 -0
  3. package/README.hi.md +267 -0
  4. package/README.it.md +263 -0
  5. package/README.ja.md +263 -0
  6. package/README.md +16 -2
  7. package/README.pt-BR.md +263 -0
  8. package/README.zh.md +263 -0
  9. package/package.json +6 -5
  10. package/dist/doctorLite.d.ts +0 -75
  11. package/dist/doctorLite.d.ts.map +0 -1
  12. package/dist/doctorLite.js +0 -705
  13. package/dist/doctorLite.js.map +0 -1
  14. package/dist/doctorLite.test.d.ts +0 -2
  15. package/dist/doctorLite.test.d.ts.map +0 -1
  16. package/dist/doctorLite.test.js +0 -268
  17. package/dist/doctorLite.test.js.map +0 -1
  18. package/dist/index.d.ts +0 -6
  19. package/dist/index.d.ts.map +0 -1
  20. package/dist/index.js +0 -6
  21. package/dist/index.js.map +0 -1
  22. package/dist/mapRender.d.ts +0 -105
  23. package/dist/mapRender.d.ts.map +0 -1
  24. package/dist/mapRender.js +0 -718
  25. package/dist/mapRender.js.map +0 -1
  26. package/dist/mapRender.test.d.ts +0 -2
  27. package/dist/mapRender.test.d.ts.map +0 -1
  28. package/dist/mapRender.test.js +0 -470
  29. package/dist/mapRender.test.js.map +0 -1
  30. package/dist/map_cli.d.ts +0 -3
  31. package/dist/map_cli.d.ts.map +0 -1
  32. package/dist/map_cli.js +0 -278
  33. package/dist/map_cli.js.map +0 -1
  34. package/dist/runLog.d.ts +0 -71
  35. package/dist/runLog.d.ts.map +0 -1
  36. package/dist/runLog.js +0 -98
  37. package/dist/runLog.js.map +0 -1
  38. package/dist/runLog.test.d.ts +0 -2
  39. package/dist/runLog.test.d.ts.map +0 -1
  40. package/dist/runLog.test.js +0 -160
  41. package/dist/runLog.test.js.map +0 -1
  42. package/dist/scanEnvPaths.d.ts +0 -18
  43. package/dist/scanEnvPaths.d.ts.map +0 -1
  44. package/dist/scanEnvPaths.js +0 -174
  45. package/dist/scanEnvPaths.js.map +0 -1
  46. package/dist/taskCluster.d.ts +0 -62
  47. package/dist/taskCluster.d.ts.map +0 -1
  48. package/dist/taskCluster.js +0 -180
  49. package/dist/taskCluster.js.map +0 -1
  50. package/dist/taskCluster.test.d.ts +0 -2
  51. package/dist/taskCluster.test.d.ts.map +0 -1
  52. package/dist/taskCluster.test.js +0 -291
  53. package/dist/taskCluster.test.js.map +0 -1
  54. package/dist/vitest.config.d.ts +0 -3
  55. package/dist/vitest.config.d.ts.map +0 -1
  56. package/dist/vitest.config.js +0 -8
  57. package/dist/vitest.config.js.map +0 -1
package/dist/map_cli.js DELETED
@@ -1,278 +0,0 @@
1
- #!/usr/bin/env node
2
- // map_cli.ts
3
- //
4
- // CLI that scans envs, runs doctorLite, renders Mermaid + JSON graph.
5
- // Writes outputs to disk and prints Mermaid to stdout.
6
- //
7
- // Usage examples:
8
- // node dist/map_cli.js --root C:\repo --out .venvkit
9
- // node dist/map_cli.js --root . --maxDepth 6 --strict --httpsProbe
10
- //
11
- // Outputs:
12
- // <out>/venv-map.json
13
- // <out>/venv-map.mmd
14
- // <out>/venv-map.html (optional viewer)
15
- // <out>/reports.json (raw doctorLite reports)
16
- import * as fs from "node:fs/promises";
17
- import * as path from "node:path";
18
- import * as os from "node:os";
19
- import { fileURLToPath } from "node:url";
20
- import { scanEnvPaths } from "./scanEnvPaths.js";
21
- import { doctorLite } from "./doctorLite.js";
22
- import { mapRender } from "./mapRender.js";
23
- import { readRunLog } from "./runLog.js";
24
- function parseArgs(argv) {
25
- const roots = [];
26
- let outDir = path.join(process.cwd(), ".venvkit");
27
- let maxDepth = 5;
28
- let strict = false;
29
- let httpsProbe = false;
30
- let minScore;
31
- let concurrency = Math.max(2, Math.min(8, os.cpus().length));
32
- let runLogPath;
33
- let includeTasks = true;
34
- for (let i = 0; i < argv.length; i++) {
35
- const a = argv[i];
36
- if (a === "--root" || a === "-r")
37
- roots.push(argv[++i] ?? "");
38
- else if (a === "--out")
39
- outDir = argv[++i] ?? outDir;
40
- else if (a === "--maxDepth")
41
- maxDepth = Number(argv[++i]);
42
- else if (a === "--strict")
43
- strict = true;
44
- else if (a === "--httpsProbe")
45
- httpsProbe = true;
46
- else if (a === "--minScore")
47
- minScore = Number(argv[++i]);
48
- else if (a === "--concurrency")
49
- concurrency = Number(argv[++i]);
50
- else if (a === "--runlog")
51
- runLogPath = argv[++i];
52
- else if (a === "--no-tasks")
53
- includeTasks = false;
54
- }
55
- if (roots.length === 0)
56
- roots.push(process.cwd());
57
- return { roots, outDir, maxDepth, strict, httpsProbe, minScore, concurrency, runLogPath, includeTasks };
58
- }
59
- async function ensureDir(p) {
60
- await fs.mkdir(p, { recursive: true });
61
- }
62
- async function writeText(p, s) {
63
- await ensureDir(path.dirname(p));
64
- await fs.writeFile(p, s, "utf8");
65
- }
66
- async function writeJson(p, obj) {
67
- await ensureDir(path.dirname(p));
68
- await fs.writeFile(p, JSON.stringify(obj, null, 2), "utf8");
69
- }
70
- // Simple concurrency pool
71
- async function mapLimit(items, limit, fn) {
72
- const out = [];
73
- let idx = 0;
74
- const workers = new Array(Math.min(limit, items.length)).fill(0).map(async () => {
75
- while (idx < items.length) {
76
- const my = idx++;
77
- const item = items[my];
78
- if (item !== undefined) {
79
- out[my] = await fn(item);
80
- }
81
- }
82
- });
83
- await Promise.all(workers);
84
- return out;
85
- }
86
- function htmlViewerTemplate() {
87
- // Single-file viewer: loads venv-map.json from same directory and renders:
88
- // - summary
89
- // - insights
90
- // - mermaid diagram via mermaid CDN
91
- return `<!doctype html>
92
- <html>
93
- <head>
94
- <meta charset="utf-8"/>
95
- <meta name="viewport" content="width=device-width, initial-scale=1"/>
96
- <title>venvkit map</title>
97
- <style>
98
- body { font-family: system-ui, -apple-system, Segoe UI, Roboto, sans-serif; margin: 20px; }
99
- .row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
100
- .card { border: 1px solid #e5e7eb; border-radius: 12px; padding: 14px; }
101
- .muted { color: #6b7280; }
102
- pre { background: #0b1020; color: #e5e7eb; padding: 12px; border-radius: 12px; overflow: auto; }
103
- .pill { display:inline-block; padding: 3px 8px; border-radius: 999px; border: 1px solid #e5e7eb; margin-right: 6px; }
104
- .good { background:#eaffea; }
105
- .warn { background:#fff4d6; }
106
- .bad { background:#ffe3e3; }
107
- </style>
108
- </head>
109
- <body>
110
- <h1>venvkit map</h1>
111
- <div id="meta" class="muted"></div>
112
-
113
- <div class="row" style="margin-top:12px;">
114
- <div class="card">
115
- <h3>Summary</h3>
116
- <div id="summary"></div>
117
- <div style="margin-top:10px;">
118
- <h4>Top issues</h4>
119
- <div id="topIssues"></div>
120
- </div>
121
- </div>
122
- <div class="card">
123
- <h3>Insights</h3>
124
- <div id="insights"></div>
125
- </div>
126
- </div>
127
-
128
- <div class="card" style="margin-top:16px;">
129
- <h3>Mermaid</h3>
130
- <div class="muted">Rendered from <code>venv-map.mmd</code></div>
131
- <div class="mermaid" id="mermaid"></div>
132
- </div>
133
-
134
- <div class="card" style="margin-top:16px;">
135
- <h3>Graph JSON</h3>
136
- <div class="muted">From <code>venv-map.json</code></div>
137
- <pre id="json"></pre>
138
- </div>
139
-
140
- <script type="module">
141
- import mermaid from "https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs";
142
- mermaid.initialize({ startOnLoad: false });
143
-
144
- async function loadText(name) {
145
- const r = await fetch(name, { cache: "no-store" });
146
- return await r.text();
147
- }
148
- async function loadJson(name) {
149
- const r = await fetch(name, { cache: "no-store" });
150
- return await r.json();
151
- }
152
-
153
- function pill(text, cls) {
154
- const span = document.createElement("span");
155
- span.className = "pill " + (cls || "");
156
- span.textContent = text;
157
- return span;
158
- }
159
-
160
- const graph = await loadJson("./venv-map.json");
161
- const mmd = await loadText("./venv-map.mmd");
162
-
163
- document.getElementById("meta").textContent =
164
- "Generated: " + graph.generatedAt + " • Host: " + graph.host.hostname + " • " + graph.host.os + " • " + graph.host.arch;
165
-
166
- const s = graph.summary;
167
- const sum = document.getElementById("summary");
168
- sum.appendChild(pill("envs: " + s.envCount));
169
- sum.appendChild(pill("bases: " + s.baseCount));
170
- sum.appendChild(pill("good: " + s.healthy, "good"));
171
- sum.appendChild(pill("warn: " + s.warning, "warn"));
172
- sum.appendChild(pill("bad: " + s.broken, "bad"));
173
-
174
- const top = document.getElementById("topIssues");
175
- (s.topIssues || []).forEach(x => {
176
- const div = document.createElement("div");
177
- div.style.marginBottom = "6px";
178
- div.innerHTML = "<b>" + x.code + "</b> (" + x.count + ")<div class='muted'>" + x.hint + "</div>";
179
- top.appendChild(div);
180
- });
181
-
182
- // Insights live in results.json normally; but we can display from a sibling file if present
183
- // If not present, show fallback.
184
- let insights = [];
185
- try { insights = await loadJson("./insights.json"); } catch {}
186
- const ins = document.getElementById("insights");
187
- if (!insights.length) {
188
- ins.innerHTML = "<div class='muted'>No insights file found.</div>";
189
- } else {
190
- insights.forEach(x => {
191
- const div = document.createElement("div");
192
- div.style.marginBottom = "10px";
193
- div.innerHTML = "<b>" + x.severity.toUpperCase() + "</b><div>" + x.text + "</div>";
194
- ins.appendChild(div);
195
- });
196
- }
197
-
198
- document.getElementById("mermaid").textContent = mmd;
199
- await mermaid.run({ nodes: [document.getElementById("mermaid")] });
200
-
201
- document.getElementById("json").textContent = JSON.stringify(graph, null, 2);
202
- </script>
203
- </body>
204
- </html>`;
205
- }
206
- export async function main(argv = process.argv.slice(2)) {
207
- const args = parseArgs(argv);
208
- await ensureDir(args.outDir);
209
- process.stderr.write(`Scanning for Python environments in: ${args.roots.join(", ")}\n`);
210
- const scan = await scanEnvPaths({
211
- roots: args.roots,
212
- maxDepth: args.maxDepth,
213
- includeHidden: false,
214
- includeUserHomeCache: true,
215
- });
216
- process.stderr.write(`Found ${scan.pythonPaths.length} Python executables (${scan.meta.foundVenvs} venvs, ${scan.meta.foundBases} bases)\n`);
217
- if (scan.pythonPaths.length === 0) {
218
- process.stderr.write("No Python environments found. Nothing to do.\n");
219
- return;
220
- }
221
- process.stderr.write(`Running doctorLite on ${scan.pythonPaths.length} environments (concurrency: ${args.concurrency})...\n`);
222
- // Run doctorLite in parallel
223
- const reports = await mapLimit(scan.pythonPaths, args.concurrency, async (pythonPath) => {
224
- return doctorLite({
225
- pythonPath,
226
- requiredModules: [], // router/task can supply later
227
- requireX64: true,
228
- strict: args.strict,
229
- httpsProbe: args.httpsProbe,
230
- }, undefined);
231
- });
232
- // Load run logs if available
233
- const runLogPath = args.runLogPath ?? path.join(args.outDir, "runs.jsonl");
234
- const runs = args.includeTasks ? await readRunLog(runLogPath, { maxLines: 5000 }) : [];
235
- if (runs.length > 0) {
236
- process.stderr.write(`Loaded ${runs.length} task runs from ${runLogPath}\n`);
237
- }
238
- const { graph, mermaid, insights } = mapRender(reports, runs, {
239
- format: "both",
240
- filter: { minScore: args.minScore },
241
- includeBaseSubgraphs: true,
242
- includeHotEdgeLabels: true,
243
- maxTopIssues: 10,
244
- });
245
- // Write outputs
246
- const outJson = path.join(args.outDir, "venv-map.json");
247
- const outMmd = path.join(args.outDir, "venv-map.mmd");
248
- const outHtml = path.join(args.outDir, "venv-map.html");
249
- const outReports = path.join(args.outDir, "reports.json");
250
- const outInsights = path.join(args.outDir, "insights.json");
251
- await writeJson(outJson, graph);
252
- await writeText(outMmd, mermaid ?? "");
253
- await writeJson(outReports, reports);
254
- await writeJson(outInsights, insights);
255
- await writeText(outHtml, htmlViewerTemplate());
256
- // Print Mermaid to stdout so it shows up in logs immediately
257
- process.stdout.write((mermaid ?? "") + "\n");
258
- process.stderr.write(`\nWrote:\n ${outJson}\n ${outMmd}\n ${outHtml}\n ${outReports}\n ${outInsights}\n\n`);
259
- // Summary
260
- const { summary } = graph;
261
- process.stderr.write(`Summary: ${summary.envCount} envs, ${summary.baseCount} bases, ${summary.taskCount} tasks\n`);
262
- process.stderr.write(` good: ${summary.healthy}, warn: ${summary.warning}, bad: ${summary.broken}\n`);
263
- if (summary.taskCount > 0) {
264
- process.stderr.write(` runs: ${summary.runsPassed} passed, ${summary.runsFailed} failed\n`);
265
- }
266
- if (summary.topIssues.length > 0) {
267
- process.stderr.write(` Top issue: ${summary.topIssues[0]?.code} (${summary.topIssues[0]?.count})\n`);
268
- }
269
- }
270
- // ESM entry point detection
271
- const __filename = fileURLToPath(import.meta.url);
272
- if (process.argv[1] === __filename) {
273
- main().catch((e) => {
274
- console.error(e);
275
- process.exit(1);
276
- });
277
- }
278
- //# sourceMappingURL=map_cli.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"map_cli.js","sourceRoot":"","sources":["../map_cli.ts"],"names":[],"mappings":"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"}
package/dist/runLog.d.ts DELETED
@@ -1,71 +0,0 @@
1
- export type RunLogEventV1 = {
2
- version: "1.0";
3
- runId: string;
4
- at: string;
5
- cwd?: string;
6
- task: {
7
- name: string;
8
- command: string;
9
- args?: string[];
10
- requirements?: {
11
- python?: string;
12
- packages?: string[];
13
- features?: string[];
14
- tags?: string[];
15
- requireX64?: boolean;
16
- };
17
- };
18
- selected: {
19
- pythonPath: string;
20
- envId?: string;
21
- score?: number;
22
- status?: "good" | "warn" | "bad" | "unknown";
23
- };
24
- outcome: {
25
- ok: boolean;
26
- exitCode?: number | null;
27
- durationMs?: number;
28
- errorClass?: string;
29
- stderrSnippet?: string;
30
- };
31
- doctor?: {
32
- dominantIssue?: string;
33
- findings?: string[];
34
- };
35
- };
36
- export type RunLogReadOptions = {
37
- maxLines?: number;
38
- };
39
- /**
40
- * Generate a run ID.
41
- * @param input Optional deterministic seed (task signature). If omitted, returns UUID.
42
- */
43
- export declare function newRunId(input?: string): string;
44
- /**
45
- * Append a run event to the JSONL log file.
46
- * Creates parent directories if needed.
47
- */
48
- export declare function appendRunLog(logPath: string, evt: RunLogEventV1): Promise<void>;
49
- /**
50
- * Read run events from a JSONL log file.
51
- * Returns the last `maxLines` events (default 5000).
52
- * Skips malformed lines gracefully.
53
- */
54
- export declare function readRunLog(logPath: string, opts?: RunLogReadOptions): Promise<RunLogEventV1[]>;
55
- /**
56
- * Count runs by outcome status.
57
- */
58
- export declare function summarizeRuns(runs: RunLogEventV1[]): {
59
- total: number;
60
- passed: number;
61
- failed: number;
62
- byTask: Map<string, {
63
- passed: number;
64
- failed: number;
65
- }>;
66
- byEnv: Map<string, {
67
- passed: number;
68
- failed: number;
69
- }>;
70
- };
71
- //# sourceMappingURL=runLog.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runLog.d.ts","sourceRoot":"","sources":["../runLog.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,KAAK,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IAEb,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;QAChB,YAAY,CAAC,EAAE;YACb,MAAM,CAAC,EAAE,MAAM,CAAC;YAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;YACpB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;YAChB,UAAU,CAAC,EAAE,OAAO,CAAC;SACtB,CAAC;KACH,CAAC;IAEF,QAAQ,EAAE;QACR,UAAU,EAAE,MAAM,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;KAC9C,CAAC;IAEF,OAAO,EAAE;QACP,EAAE,EAAE,OAAO,CAAC;QACZ,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;IAEF,MAAM,CAAC,EAAE;QACP,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;KACrB,CAAC;CACH,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,CAK/C;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAIrF;AAED;;;;GAIG;AACH,wBAAsB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAwBxG;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG;IACpD,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxD,CA8BA"}
package/dist/runLog.js DELETED
@@ -1,98 +0,0 @@
1
- // runLog.ts
2
- //
3
- // Append-only JSONL run log for tracking task executions against Python envs.
4
- // Each line is one RunLogEventV1 — durable, streaming-friendly, keeps forever.
5
- //
6
- // Used by mapRender to create:
7
- // - task nodes (one per run)
8
- // - ROUTES_TASK_TO edges (task → env)
9
- // - FAILED_RUN edges (task → env with dominant issue label)
10
- import * as fs from "node:fs/promises";
11
- import * as path from "node:path";
12
- import { createHash, randomUUID } from "node:crypto";
13
- /**
14
- * Generate a run ID.
15
- * @param input Optional deterministic seed (task signature). If omitted, returns UUID.
16
- */
17
- export function newRunId(input) {
18
- if (!input)
19
- return randomUUID();
20
- // deterministic id from task signature if desired
21
- const h = createHash("sha256").update(input).digest("hex").slice(0, 16);
22
- return `run_${h}`;
23
- }
24
- /**
25
- * Append a run event to the JSONL log file.
26
- * Creates parent directories if needed.
27
- */
28
- export async function appendRunLog(logPath, evt) {
29
- await fs.mkdir(path.dirname(logPath), { recursive: true });
30
- const line = JSON.stringify(evt) + "\n";
31
- await fs.appendFile(logPath, line, "utf8");
32
- }
33
- /**
34
- * Read run events from a JSONL log file.
35
- * Returns the last `maxLines` events (default 5000).
36
- * Skips malformed lines gracefully.
37
- */
38
- export async function readRunLog(logPath, opts = {}) {
39
- const maxLines = opts.maxLines ?? 5000;
40
- let raw = "";
41
- try {
42
- raw = await fs.readFile(logPath, "utf8");
43
- }
44
- catch {
45
- return [];
46
- }
47
- const lines = raw.trimEnd().split("\n");
48
- const tail = lines.slice(Math.max(0, lines.length - maxLines));
49
- const out = [];
50
- for (const l of tail) {
51
- if (!l.trim())
52
- continue;
53
- try {
54
- const obj = JSON.parse(l);
55
- if (obj?.version === "1.0")
56
- out.push(obj);
57
- }
58
- catch {
59
- // ignore malformed lines
60
- }
61
- }
62
- return out;
63
- }
64
- /**
65
- * Count runs by outcome status.
66
- */
67
- export function summarizeRuns(runs) {
68
- const byTask = new Map();
69
- const byEnv = new Map();
70
- let passed = 0;
71
- let failed = 0;
72
- for (const run of runs) {
73
- if (run.outcome.ok) {
74
- passed++;
75
- }
76
- else {
77
- failed++;
78
- }
79
- // By task name
80
- const taskName = run.task.name;
81
- const taskStats = byTask.get(taskName) ?? { passed: 0, failed: 0 };
82
- if (run.outcome.ok)
83
- taskStats.passed++;
84
- else
85
- taskStats.failed++;
86
- byTask.set(taskName, taskStats);
87
- // By env path
88
- const envPath = run.selected.pythonPath;
89
- const envStats = byEnv.get(envPath) ?? { passed: 0, failed: 0 };
90
- if (run.outcome.ok)
91
- envStats.passed++;
92
- else
93
- envStats.failed++;
94
- byEnv.set(envPath, envStats);
95
- }
96
- return { total: runs.length, passed, failed, byTask, byEnv };
97
- }
98
- //# sourceMappingURL=runLog.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runLog.js","sourceRoot":"","sources":["../runLog.ts"],"names":[],"mappings":"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"}
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=runLog.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runLog.test.d.ts","sourceRoot":"","sources":["../runLog.test.ts"],"names":[],"mappings":""}
@@ -1,160 +0,0 @@
1
- // runLog.test.ts
2
- // Unit tests for run log append + read
3
- import { describe, it, expect, beforeEach, afterEach } from "vitest";
4
- import * as fs from "node:fs/promises";
5
- import * as path from "node:path";
6
- import * as os from "node:os";
7
- import { newRunId, appendRunLog, readRunLog, summarizeRuns, } from "./runLog.js";
8
- function makeRunEvent(overrides = {}) {
9
- return {
10
- version: "1.0",
11
- runId: overrides.runId ?? newRunId(),
12
- at: overrides.at ?? new Date().toISOString(),
13
- cwd: overrides.cwd ?? "/repo",
14
- task: overrides.task ?? {
15
- name: overrides.taskName ?? "pytest",
16
- command: "pytest tests/",
17
- args: ["tests/"],
18
- requirements: {
19
- packages: ["pytest"],
20
- tags: ["test"],
21
- },
22
- },
23
- selected: overrides.selected ?? {
24
- pythonPath: overrides.pythonPath ?? "C:\\repo\\.venv\\Scripts\\python.exe",
25
- score: 95,
26
- status: "good",
27
- },
28
- outcome: overrides.outcome ?? {
29
- ok: overrides.ok ?? true,
30
- exitCode: overrides.ok === false ? 1 : 0,
31
- durationMs: 1500,
32
- errorClass: overrides.ok === false ? (overrides.errorClass ?? "RUNTIME_ERROR") : undefined,
33
- stderrSnippet: overrides.ok === false ? "AssertionError: expected true" : undefined,
34
- },
35
- doctor: overrides.doctor,
36
- };
37
- }
38
- describe("runLog", () => {
39
- describe("newRunId", () => {
40
- it("generates UUID when no input provided", () => {
41
- const id1 = newRunId();
42
- const id2 = newRunId();
43
- expect(id1).not.toBe(id2);
44
- // UUID format
45
- expect(id1).toMatch(/^[\da-f-]{36}$/i);
46
- });
47
- it("generates deterministic ID from input", () => {
48
- const id1 = newRunId("pytest|pytest tests/|2024-01-01");
49
- const id2 = newRunId("pytest|pytest tests/|2024-01-01");
50
- expect(id1).toBe(id2);
51
- expect(id1).toMatch(/^run_[\da-f]{16}$/);
52
- });
53
- it("different inputs produce different IDs", () => {
54
- const id1 = newRunId("task1");
55
- const id2 = newRunId("task2");
56
- expect(id1).not.toBe(id2);
57
- });
58
- });
59
- describe("appendRunLog + readRunLog", () => {
60
- let tempDir;
61
- let logPath;
62
- beforeEach(async () => {
63
- tempDir = await fs.mkdtemp(path.join(os.tmpdir(), "venvkit-test-"));
64
- logPath = path.join(tempDir, "runs.jsonl");
65
- });
66
- afterEach(async () => {
67
- await fs.rm(tempDir, { recursive: true, force: true });
68
- });
69
- it("appends and reads a single event", async () => {
70
- const evt = makeRunEvent({ taskName: "lint" });
71
- await appendRunLog(logPath, evt);
72
- const runs = await readRunLog(logPath);
73
- expect(runs).toHaveLength(1);
74
- expect(runs[0]?.task.name).toBe("lint");
75
- expect(runs[0]?.version).toBe("1.0");
76
- });
77
- it("appends multiple events", async () => {
78
- await appendRunLog(logPath, makeRunEvent({ taskName: "test1" }));
79
- await appendRunLog(logPath, makeRunEvent({ taskName: "test2" }));
80
- await appendRunLog(logPath, makeRunEvent({ taskName: "test3" }));
81
- const runs = await readRunLog(logPath);
82
- expect(runs).toHaveLength(3);
83
- expect(runs.map((r) => r.task.name)).toEqual(["test1", "test2", "test3"]);
84
- });
85
- it("returns empty array for missing file", async () => {
86
- const runs = await readRunLog(path.join(tempDir, "nonexistent.jsonl"));
87
- expect(runs).toEqual([]);
88
- });
89
- it("skips malformed lines gracefully", async () => {
90
- // Write valid + invalid lines
91
- await fs.writeFile(logPath, [
92
- JSON.stringify(makeRunEvent({ taskName: "valid1" })),
93
- "{ broken json",
94
- "",
95
- JSON.stringify(makeRunEvent({ taskName: "valid2" })),
96
- '{"version": "0.9", "old": true}', // wrong version
97
- ].join("\n"), "utf8");
98
- const runs = await readRunLog(logPath);
99
- expect(runs).toHaveLength(2);
100
- expect(runs.map((r) => r.task.name)).toEqual(["valid1", "valid2"]);
101
- });
102
- it("respects maxLines option", async () => {
103
- for (let i = 0; i < 10; i++) {
104
- await appendRunLog(logPath, makeRunEvent({ taskName: `task${i}` }));
105
- }
106
- const runs = await readRunLog(logPath, { maxLines: 3 });
107
- expect(runs).toHaveLength(3);
108
- // Should be last 3 lines
109
- expect(runs.map((r) => r.task.name)).toEqual(["task7", "task8", "task9"]);
110
- });
111
- it("creates parent directories if needed", async () => {
112
- const nestedPath = path.join(tempDir, "deep", "nested", "dir", "runs.jsonl");
113
- await appendRunLog(nestedPath, makeRunEvent({ taskName: "nested" }));
114
- const runs = await readRunLog(nestedPath);
115
- expect(runs).toHaveLength(1);
116
- });
117
- });
118
- describe("summarizeRuns", () => {
119
- it("counts passed and failed runs", () => {
120
- const runs = [
121
- makeRunEvent({ ok: true }),
122
- makeRunEvent({ ok: true }),
123
- makeRunEvent({ ok: false }),
124
- ];
125
- const summary = summarizeRuns(runs);
126
- expect(summary.total).toBe(3);
127
- expect(summary.passed).toBe(2);
128
- expect(summary.failed).toBe(1);
129
- });
130
- it("groups by task name", () => {
131
- const runs = [
132
- makeRunEvent({ taskName: "pytest", ok: true }),
133
- makeRunEvent({ taskName: "pytest", ok: false }),
134
- makeRunEvent({ taskName: "lint", ok: true }),
135
- ];
136
- const summary = summarizeRuns(runs);
137
- expect(summary.byTask.get("pytest")).toEqual({ passed: 1, failed: 1 });
138
- expect(summary.byTask.get("lint")).toEqual({ passed: 1, failed: 0 });
139
- });
140
- it("groups by env path", () => {
141
- const runs = [
142
- makeRunEvent({ pythonPath: "C:\\env1\\python.exe", ok: true }),
143
- makeRunEvent({ pythonPath: "C:\\env1\\python.exe", ok: false }),
144
- makeRunEvent({ pythonPath: "C:\\env2\\python.exe", ok: true }),
145
- ];
146
- const summary = summarizeRuns(runs);
147
- expect(summary.byEnv.get("C:\\env1\\python.exe")).toEqual({ passed: 1, failed: 1 });
148
- expect(summary.byEnv.get("C:\\env2\\python.exe")).toEqual({ passed: 1, failed: 0 });
149
- });
150
- it("handles empty array", () => {
151
- const summary = summarizeRuns([]);
152
- expect(summary.total).toBe(0);
153
- expect(summary.passed).toBe(0);
154
- expect(summary.failed).toBe(0);
155
- expect(summary.byTask.size).toBe(0);
156
- expect(summary.byEnv.size).toBe(0);
157
- });
158
- });
159
- });
160
- //# sourceMappingURL=runLog.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"runLog.test.js","sourceRoot":"","sources":["../runLog.test.ts"],"names":[],"mappings":"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"}