diff --git a/src/resources/extensions/gsd/auto-start.ts b/src/resources/extensions/gsd/auto-start.ts index f8013394a..f0b45a04e 100644 --- a/src/resources/extensions/gsd/auto-start.ts +++ b/src/resources/extensions/gsd/auto-start.ts @@ -67,6 +67,7 @@ import { getDebugLogPath, } from "./debug-logger.js"; import { parseUnitId } from "./unit-id.js"; +import { setLogBasePath } from "./workflow-logger.js"; import type { AutoSession } from "./auto/session.js"; import { existsSync, @@ -461,6 +462,7 @@ export async function bootstrapAutoSession( s.verbose = verboseMode; s.cmdCtx = ctx; s.basePath = base; + setLogBasePath(base); s.unitDispatchCount.clear(); s.unitRecoveryCount.clear(); s.lastBudgetAlertLevel = 0; diff --git a/src/resources/extensions/gsd/auto.ts b/src/resources/extensions/gsd/auto.ts index 73ce6fd16..1a9eff6d7 100644 --- a/src/resources/extensions/gsd/auto.ts +++ b/src/resources/extensions/gsd/auto.ts @@ -114,6 +114,7 @@ import { formatCost, formatTokenCount, } from "./metrics.js"; +import { setLogBasePath } from "./workflow-logger.js"; import { join } from "node:path"; import { readFileSync, existsSync, mkdirSync, writeFileSync, unlinkSync } from "node:fs"; import { atomicWriteSync } from "./atomic-write.js"; @@ -1102,6 +1103,7 @@ export async function startAuto( s.stepMode = requestedStepMode; s.cmdCtx = ctx; s.basePath = base; + setLogBasePath(base); s.unitDispatchCount.clear(); s.unitLifetimeDispatches.clear(); if (!getLedger()) initMetrics(base); diff --git a/src/resources/extensions/gsd/tests/workflow-logger.test.ts b/src/resources/extensions/gsd/tests/workflow-logger.test.ts index db7fbb5b8..911c0d770 100644 --- a/src/resources/extensions/gsd/tests/workflow-logger.test.ts +++ b/src/resources/extensions/gsd/tests/workflow-logger.test.ts @@ -1,8 +1,11 @@ // GSD Extension — Workflow Logger Tests // Tests for the centralized warning/error accumulator. -import { describe, test, beforeEach } from "node:test"; +import { describe, test, beforeEach, afterEach } from "node:test"; import assert from "node:assert/strict"; +import { existsSync, readFileSync } from "node:fs"; +import { join } from "node:path"; +import { makeTempDir, cleanup } from "./test-utils.ts"; import { logWarning, logError, @@ -14,6 +17,7 @@ import { hasAnyIssues, summarizeLogs, formatForNotification, + setLogBasePath, _resetLogs, } from "../workflow-logger.ts"; @@ -222,6 +226,44 @@ describe("workflow-logger", () => { }); }); + describe("audit log persistence", () => { + let dir: string; + + beforeEach(() => { + dir = makeTempDir("wl-audit-"); + }); + + afterEach(() => { + setLogBasePath(""); + cleanup(dir); + }); + + test("writes entry to .gsd/audit-log.jsonl after setLogBasePath", () => { + setLogBasePath(dir); + logWarning("engine", "audit test entry"); + + const auditPath = join(dir, ".gsd", "audit-log.jsonl"); + assert.ok(existsSync(auditPath), "audit-log.jsonl should exist"); + const content = readFileSync(auditPath, "utf-8"); + const entry = JSON.parse(content.trim()); + assert.equal(entry.severity, "warn"); + assert.equal(entry.component, "engine"); + assert.equal(entry.message, "audit test entry"); + }); + + test("_resetLogs does not clear the audit base path", () => { + setLogBasePath(dir); + _resetLogs(); + logWarning("engine", "post-reset entry"); + + const auditPath = join(dir, ".gsd", "audit-log.jsonl"); + assert.ok(existsSync(auditPath), "audit-log.jsonl should exist after _resetLogs"); + const content = readFileSync(auditPath, "utf-8"); + const entry = JSON.parse(content.trim()); + assert.equal(entry.message, "post-reset entry"); + }); + }); + describe("buffer limit", () => { test("caps at MAX_BUFFER entries, dropping oldest", () => { const OVER = 110; diff --git a/src/resources/extensions/gsd/workflow-logger.ts b/src/resources/extensions/gsd/workflow-logger.ts index 35e79bde5..0770408d0 100644 --- a/src/resources/extensions/gsd/workflow-logger.ts +++ b/src/resources/extensions/gsd/workflow-logger.ts @@ -199,7 +199,6 @@ export function readAuditLog(basePath?: string): LogEntry[] { */ export function _resetLogs(): void { _buffer = []; - _auditBasePath = null; } // ─── Internal ───────────────────────────────────────────────────────────