From ae3ef627e649d3a017ebfcbdddb31a7a3636a159 Mon Sep 17 00:00:00 2001 From: Aung Myo Kyaw Date: Fri, 2 Jan 2026 19:14:21 +0700 Subject: [PATCH 1/2] fix: prevent log file deletion when using --log-level DEBUG The init() function was calling cleanup() before creating new log file, which caused cleanup logic to delete existing log files including one from a previous run. Move cleanup() call to after new log file is created and truncated to ensure current log is never deleted during initialization. Fixes #6583 --- packages/opencode/src/util/log.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/opencode/src/util/log.ts b/packages/opencode/src/util/log.ts index 6941310bbbd..483d9a337dc 100644 --- a/packages/opencode/src/util/log.ts +++ b/packages/opencode/src/util/log.ts @@ -57,7 +57,6 @@ export namespace Log { export async function init(options: Options) { if (options.level) level = options.level - cleanup(Global.Path.log) if (options.print) return logpath = path.join( Global.Path.log, @@ -71,6 +70,7 @@ export namespace Log { writer.flush() return num } + cleanup(Global.Path.log) } async function cleanup(dir: string) { From 0d5bf1efb27b0969baa51dcfd582cbff2ab5abe7 Mon Sep 17 00:00:00 2001 From: Aung Myo Kyaw Date: Fri, 2 Jan 2026 19:14:21 +0700 Subject: [PATCH 2/2] fix: prevent log file deletion when using --log-level DEBUG The init() function was calling cleanup() before creating new log file, which caused cleanup logic to delete existing log files including one from a previous run. Move cleanup() call to after new log file is created and truncated to ensure current log is never deleted during initialization. Added test case to verify log preservation across reinitializations. Fixes #6583 --- packages/opencode/test/util/log.test.ts | 68 +++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 packages/opencode/test/util/log.test.ts diff --git a/packages/opencode/test/util/log.test.ts b/packages/opencode/test/util/log.test.ts new file mode 100644 index 00000000000..6878ec674c5 --- /dev/null +++ b/packages/opencode/test/util/log.test.ts @@ -0,0 +1,68 @@ +import { test, expect } from "bun:test" +import { Log } from "@/util/log" +import fs from "fs/promises" +import path from "path" +import * as Global from "@/global" + +describe("Log", () => { + const testLogDir = path.join(process.cwd(), ".test-log") + const logDir = path.join(testLogDir, "share", "opencode", "log") + + test("should not delete existing log file when reinitializing with DEBUG", async () => { + await fs.mkdir(testLogDir, { recursive: true }) + await fs.mkdir(logDir, { recursive: true }) + + await Log.init({ print: true }) + const initialLogPath = Log.file() + expect(initialLogPath).toBeTruthy() + expect(initialLogPath).toContain(logDir) + + const initialContent = "Initial log content\n" + await fs.appendFile(initialLogPath, initialContent) + + await Log.init({ print: true, level: "DEBUG" }) + const debugLogPath = Log.file() + + const initialExists = await fs + .access(initialLogPath) + .then(() => true) + .catch(() => false) + expect(initialExists).toBe(true) + + const initialFileContent = await fs.readFile(initialLogPath, "utf-8") + expect(initialFileContent).toContain(initialContent) + + expect(debugLogPath).toBeTruthy() + expect(debugLogPath).not.toBe(initialLogPath) + + await fs.rm(testLogDir, { recursive: true, force: true }) + }) + + test("should maintain log rotation when reinitializing with DEBUG", async () => { + await fs.mkdir(testLogDir, { recursive: true }) + await fs.mkdir(logDir, { recursive: true }) + + const oldFiles: string[] = [] + for (let i = 0; i < 15; i++) { + const timestamp = new Date(Date.now() - i * 1000 * 60 * 60 * 24) + const filename = timestamp.toISOString().split(".")[0].replace(/:/g, "") + ".log" + const filepath = path.join(logDir, filename) + await fs.writeFile(filepath, `Old log ${i}\n`) + oldFiles.push(filepath) + } + + await Log.init({ print: true, level: "DEBUG" }) + + const allFiles = (await fs.readdir(logDir)).sort() + expect(allFiles.length).toBeLessThanOrEqual(10) + + const currentLogPath = Log.file() + const currentExists = await fs + .access(currentLogPath) + .then(() => true) + .catch(() => false) + expect(currentExists).toBe(true) + + await fs.rm(testLogDir, { recursive: true, force: true }) + }) +})