From 13ea79f6fd453203e9c20e442083aa332fc0ec55 Mon Sep 17 00:00:00 2001 From: Dai Ha Date: Thu, 13 Aug 2026 21:03:46 +0200 Subject: [PATCH] CB-523 (opencode): generated worker config pins compaction.auto MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A worker that exhausts its context dies mid-turn and its bridge_reply — the whole point of the turn — dies with it. Auto-compaction is a condition of the turn contract for a spawned peer, not an operator preference. OPENCODE_CONFIG is merged over ~/.config/opencode/config.json rather than replacing it, so workers already inherited auto:true from the home file. That inheritance is exactly what this removes as a dependency: the home file is outside this repo, differs per machine, and is not ours to rely on. The trade is recorded in the code: an OPENCODE_CONFIG value overrides the home value, so an operator cannot disable compaction for bridged workers from home. Deliberate for peers we spawn and whose turns we must land; per-profile control would be a profile knob, not the removal of this line. Origin: fleet-wide auto-compaction audit by peer lead gpt-sol-5.6, which found autoCompactEnabled:false alongside a 300k window across the Claude instance configs. Handed over uncommitted; taken deliberately, with rationale added. --- .../dev/ltms/bridged/worker/OpenCodeLauncher.java | 15 +++++++++++++++ .../ltms/bridged/worker/OpenCodeLauncherTest.java | 2 ++ 2 files changed, 17 insertions(+) diff --git a/bridged/src/main/java/dev/ltms/bridged/worker/OpenCodeLauncher.java b/bridged/src/main/java/dev/ltms/bridged/worker/OpenCodeLauncher.java index a93d5b1..b2757e4 100644 --- a/bridged/src/main/java/dev/ltms/bridged/worker/OpenCodeLauncher.java +++ b/bridged/src/main/java/dev/ltms/bridged/worker/OpenCodeLauncher.java @@ -247,6 +247,21 @@ public final class OpenCodeLauncher extends HerdrPeerLauncher { ObjectNode root = JSON.createObjectNode(); root.put("$schema", "https://opencode.ai/config.json"); + // CB-523, opencode side: a worker that runs out of context dies mid-turn, and its reply + // — the entire point of the turn — is lost with it. Auto-compaction is therefore not an + // operator preference for a bridged worker, it is a condition of the turn contract. + // + // Stated deliberately even though it is redundant today: OPENCODE_CONFIG is MERGED over + // ~/.config/opencode/config.json rather than replacing it, so a worker already inherits + // an `auto: true` set at home. We do not want that inheritance to be what the guarantee + // rests on — the home file is outside this repo, differs per machine, and is not ours. + // + // Know the cost before removing it: this key WINS over the home config (verified — an + // OPENCODE_CONFIG value overrides the home value, it does not defer to it), so an + // operator who sets `compaction.auto: false` at home cannot turn it off for bridged + // workers. That is the intended trade for peers we spawn and whose turns we must land; + // if per-profile control is ever wanted, add a profile knob rather than dropping this. + root.putObject("compaction").put("auto", true); if (cfg.hasMcp()) { Path charter = dir.resolve("reply-charter.md"); diff --git a/bridged/src/test/java/dev/ltms/bridged/worker/OpenCodeLauncherTest.java b/bridged/src/test/java/dev/ltms/bridged/worker/OpenCodeLauncherTest.java index 3d93939..bf42fd1 100644 --- a/bridged/src/test/java/dev/ltms/bridged/worker/OpenCodeLauncherTest.java +++ b/bridged/src/test/java/dev/ltms/bridged/worker/OpenCodeLauncherTest.java @@ -74,6 +74,8 @@ class OpenCodeLauncherTest { // Assert on parsed structure, not substrings: the generated config is real JSON and its // whitespace is the formatter's business, not the contract's. JsonNode json = new ObjectMapper().readTree(Path.of(cfgPath).toFile()); + assertTrue(json.path("compaction").path("auto").asBoolean(), + "spawned opencode peers explicitly enable automatic compaction"); JsonNode bridge = json.path("mcp").path("bridge"); assertEquals("remote", bridge.path("type").asText(), "bridge is mounted as a remote MCP server"); assertEquals("http://127.0.0.1:8765/mcp", bridge.path("url").asText(),