import { spawnSync } from "node:child_process"; import { mkdirSync, mkdtempSync, rmSync, writeFileSync } from "node:fs"; import { tmpdir } from "node:os"; import path from "node:path"; import { afterEach, describe, expect, it } from "vitest"; const e2ePath = path.resolve(import.meta.dirname, "../__e2e__/json.ts"); function record(event: string, details: Record = {}) { return JSON.stringify({ timestamp: "2026-01-01T00:00:00.000Z", extension: "nushell", pid: 1234, event, ...details, }); } describe("Nushell JSON trace oracle", () => { let root: string | undefined; afterEach(() => { if (root) rmSync(root, { recursive: true, force: true }); root = undefined; }); it("pairs generated spans and counts a malformed final line", () => { const evidenceRoot = path.join(tmpdir(), "pi-ext-nushell-json"); mkdirSync(evidenceRoot, { recursive: true, mode: 0o700 }); root = mkdtempSync(path.join(evidenceRoot, "oracle-")); const traceDirectory = path.join(root, "trace"); const workspace = path.join(traceDirectory, "workspace"); const debugDirectory = path.join( traceDirectory, "state/pi-ext/debug/nushell", ); mkdirSync(workspace, { recursive: true }); mkdirSync(debugDirectory, { recursive: true }); writeFileSync( path.join(debugDirectory, "trace.jsonl"), [ record("fresh.start", { spanId: "1234-1" }), record("fresh.start", { spanId: "1234-2" }), record("fresh.finish", { spanId: "1234-2", durationMs: 30, status: "nonzero", }), record("fresh.finish", { spanId: "1234-1", durationMs: 10, status: "success", }), record("session.request.start", { spanId: "1234-3" }), record("session.request.finish", { spanId: "1234-3", durationMs: 40, }), record("session.request.start", { spanId: "1234-4" }), record("session.request.error", { spanId: "1234-4", durationMs: 60, kind: "nu", }), record("fresh.start", { spanId: "1234-5" }), record("fresh.error", { spanId: "1234-orphan", durationMs: 99, status: "failed", }), '{"event":"fresh.finish"', ].join("\n"), ); writeFileSync( path.join(workspace, "trace.nu"), 'export def summarize [input: string] { { fresh: { count: 2, p50: 10, p95: 30, statusCounts: { nonzero: 1, success: 1 } }, session: { count: 2, p50: 40, p95: 60, errorKindCounts: { nu: 1 } }, unmatchedStartSpanIds: ["1234-5"], malformedFinalLineCount: 1 } }\n', ); writeFileSync( path.join(root, "results.json"), `${JSON.stringify([ { name: "trace", directory: traceDirectory, exitCode: 0, timedOut: false, stopReason: "stop", settled: true, debugEnabled: true, toolCalls: { nu: 1 }, }, ])}\n`, ); const check = spawnSync( process.execPath, [ "--no-warnings", "--experimental-strip-types", e2ePath, "--verify", root, ], { encoding: "utf8" }, ); expect(check.status, check.stderr).toBe(0); expect(check.stdout).toContain('"traceValidation":true'); }); });