From 990cf15ff33d0e3684f826fa57b1bc3ad35b3436 Mon Sep 17 00:00:00 2001 From: opencode Date: Thu, 13 Aug 2026 07:23:39 -0700 Subject: [PATCH] fix(test): make httpapi-exercise 500s carry their cause (TKT-372, fb 183) An effect-mode failure reported {"name":"UnknownError","ref":"err_xxxxxxxx"} and nothing else. On TKT-323 that turned a one-glance answer -- Unbound layer node: @opencode/InstanceBootstrap -- into a dedicated diagnosis assignment. The cause was never lost. The error middleware already logs it via Effect.logError, and feedback 183 attributed the loss to backend.ts's disableLogger:true. That attribution is wrong: disableLogger only skips adding HttpMiddleware.logger, the per-request access log. Built both ways against the same dying route, the Cause prints either way. The actual suppressor is core's observability layer, which builds with Logger.layer(..., { mergeWithExisting: false }) over Logging.loggers() -- and loggers() returns the file logger alone unless OPENCODE_PRINT_LOGS is set. So the Cause went to opencode.log while the harness printed an opaque ref. The exerciser now defaults OPENCODE_PRINT_LOGS=1 and OPENCODE_LOG_LEVEL=ERROR where it already isolates OPENCODE_DB and the XDG roots, before the app modules load. Errors only: a green run adds four lines, from the integration scenarios that deliberately assert 500, and the logged ref matches the ref in the response body so a failure correlates to its cause. Verified against a deliberately broken route: with the default the failure prints the full Cause with file and line; with OPENCODE_PRINT_LOGS=0 the same failure reproduces the reported symptom exactly. All three modes stay green, 237/237. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01KbNYZHcnxRCknFmhhPHe7L --- .../server/httpapi-exercise/environment.ts | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/packages/opencode/test/server/httpapi-exercise/environment.ts b/packages/opencode/test/server/httpapi-exercise/environment.ts index 9d3eaa0e5329..17fd967fb65a 100644 --- a/packages/opencode/test/server/httpapi-exercise/environment.ts +++ b/packages/opencode/test/server/httpapi-exercise/environment.ts @@ -11,6 +11,29 @@ process.env.XDG_CONFIG_HOME = path.join(exerciseGlobalRoot, "config") process.env.XDG_STATE_HOME = path.join(exerciseGlobalRoot, "state") process.env.XDG_CACHE_HOME = path.join(exerciseGlobalRoot, "cache") process.env.OPENCODE_DISABLE_SHARE = "true" + +/** + * Make this harness's own 500s readable. + * + * The httpapi error middleware already logs the real Cause of every defect-500 + * (`Effect.logError("failed", { ref, error, cause })`), but core's observability layer + * installs ONLY a file logger unless OPENCODE_PRINT_LOGS is set -- it builds with + * `Logger.layer(..., { mergeWithExisting: false })`, which replaces the console logger + * rather than adding to it. So the cause was never lost, only written somewhere nobody + * reading exercise output would look, and a failing scenario showed + * `{"name":"UnknownError","ref":"err_xxxxxxxx"}` and nothing else. That cost a full + * diagnosis assignment on TKT-323, where the answer was one line + * (`Unbound layer node: @opencode/InstanceBootstrap`). + * + * Error level only, so the added output is one line per defect and nothing else. A green + * effect-mode run currently prints exactly four, from the integration scenarios that + * deliberately assert 500 (`Key method not found`, `OAuth method not found`, and two + * `OAuth attempt not found`) -- those routes raise plain Errors rather than returning a + * typed 404, which this makes visible rather than causes. Both variables are overridable + * for a noisier local run. + */ +process.env.OPENCODE_PRINT_LOGS ??= "1" +process.env.OPENCODE_LOG_LEVEL ??= "ERROR" export const exerciseConfigDirectory = path.join(exerciseGlobalRoot, "config", "opencode") export const exerciseDataDirectory = path.join(exerciseGlobalRoot, "data", "opencode")