Skip to content

test: a live service starts on the caller's config dir and serves the saved one after startup - #470

Merged
Blind-Striker merged 1 commit into
masterfrom
test/env-precedence-proof
Oct 17, 2026
Merged

Blind-Striker merged 1 commit into
masterfrom
test/env-precedence-proof

Conversation

@Blind-Striker

@Blind-Striker Blind-Striker commented Oct 17, 2026 •

Copy link
Copy Markdown
Collaborator

What

This PR adds one live characterization test for the env precedence that the 2.0.32 refresh (#465) documented. When the caller and a background service's saved service config both set a key, the caller's value wins for anything the service reads at startup, and the saved value wins for anything it reads after startup.

Why the behaviour is what it is (upstream at the pin, 843a6c5)

packages/cli/src/server-process.ts, in service mode:

  • Bootstrap reads env first: OPENCODE_CONFIG_DIR at :38, then process.chdir(global.home), ServiceConfig.options() / read(), and the incumbent probe (:61-73).
  • :75 then runs Object.assign(process.env, config.env) on every service-mode start.
  • After that point, the application's config directory is read again (:118, through routes.ts:124 and config/discovery.ts:68-71).

The test

OpenCodeServerEnsureLiveTests.EnsureAsync_Should_Start_On_The_Callers_Config_Dir_And_Serve_The_Saved_One_After_Startup uses a single key, OPENCODE_CONFIG_DIR.

  • The caller's value, A, is the context's isolated config directory, passed through OpenCodeServerEnsureOptions.Environment. A's channel config holds port = context.Port and env = { OPENCODE_CONFIG_DIR: B }.
  • The saved value, B, is a directory inside the run root. B's channel config holds a different reserved port, Q, which the real-daemon port guard checks.
  • At startup, the service listens on context.Port: it read A's config before applying the saved env.
  • After startup, GET /api/config returns ConfigDirectory entries that contain B and not A. Paths are normalized with GetFullPath, and membership is checked by element.

Everything stays inside the context's run root, and the machine's real service is never touched. Cleanup is the existing per-test context teardown.

What this does not cover: the harness runs the ensure in direct-registration mode, where ConfigFile is null, so ServiceElection.OverlayAsync reads no service config there. The SDK's own map merge stays covered by ServiceEnsurerTests (lines 437-456). This test pins the upstream server behaviour that the merge feeds.

Proof

There is no product mutant, because the behaviour belongs to upstream. Instead, two fixture controls each made a temporary edit to the new test's arrange, were run, and were restored:

Control Red at net10.0 net472
Omit A's saved env Contains(GetFullPath(B)): "the item was not found in the collection" red red
Swap the two config ports server.Endpoint.Port == context.Port: "Expected to be 62388 but found 62389" red red

Checks:

  • OpenCodeServerEnsureLiveTests: 8 of 8 on net10.0 and on net472, 7 existing tests plus the new one.
  • The whole OpenCode.Sdk.Tools.Tests project: 2072 of 2072.
  • verify-clones: 0 new. Slopwatch: 0.
  • These local results ran on Bun 1.4.3 with OPENCODE_SDK_TESTS_BUN_MISMATCH=allow, so they are local evidence only. CI runs the exact pin, and its election pass covers Linux and macOS.
  • Local check: GATE PASS on 88194dae (master df25ea59): all 8 steps, with 10,790 tests and 27 election tests, 0 failed. The first run failed the election step because the gate worktree's submodule was still checked out at v2.0.29 although its gitlink named v2.0.32. On that 2.0.29 server the new test is red, so it tells the two versions apart. After a submodule sync it passed. The prerequisite hole that let a stale submodule run is Pinned-server prerequisites accept a submodule checkout that differs from the recorded gitlink #469.

Provenance

Sol Fast did a read-only research pass and then drafted the test from the coordinator's spec. The coordinator verified the evidence, read the change and ran the local check.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.

… saved one after startup

At the 2.0.32 pin the service re-applies its saved service-config env once it
has started: the port comes from the caller's config directory, read at
startup, while config discovery after startup uses the saved directory.
@Blind-Striker
Blind-Striker added this pull request to the merge queue Oct 17, 2026
Merged via the queue into master with commit ac0bb55 Oct 17, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant