[PR #6587] [CLOSED] fix(setup): write the native OpenCode table inherited from any layer #7380

Closed
opened 2026-11-01 21:47:27 +00:00 by bsakaguchi · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/morluto/rea/pull/6587
Author: @kittimzhe
Created: 10/23/2026
Status: ❌ Closed

Base: main ← Head: fix/opencode-inherited-native-table


📝 Commits (1)

  • 5491d3a fix(setup): write the native OpenCode table inherited from any layer

📊 Changes

3 files changed (+166 additions, -65 deletions)

View changed files

📝 src/application/ClientConfigurationDocument.ts (+29 -0)
📝 src/application/SetupClientConfiguration.ts (+15 -2)
📝 tests/acceptance/setup/opencodeV2ClientSetup.test.ts (+122 -63)

📄 Description

Fixes #6573

Summary

Setup decided which OpenCode table to write from the target file's own content, so an upper opencode.json without an mcp table (or a missing upper file) made approved setup write a legacy V1 mcp.rea member while the client loads the native mcp.servers table inherited from a lower layer: configuration reported configured and later already_current, but the effective registration inspection stayed disabled/stale. The write view now promotes a V1 target document to its native V2 view when any applicable layer has the native table.

Problem and expected behavior

  • Smallest trigger (from the issue, reproduced locally before the fix): lower config.json holds a disabled native V2 registration; upper opencode.json holds only {"theme":"system"} or is absent. configureClientConfiguration writes a V1 mcp.rea entry with enabled: true into the upper file, returns configured, and the following inspection reports already_current — while readClientRegistrationInspections reports activation: "disabled", state: "stale". The passing control (upper file with an explicit mcp.servers table) is the shape #3469/#3318 already covered.
  • Violated invariant: setup must produce an enabled effective registration and agree with the registration reader about whether another update is required. Per the documented OpenCode configuration contract, setup uses native V2 tables where present and doctor checks the merged user registration.
  • Root cause: parseClientConfiguration correctly derives each file's dialect from its own content, but the write path used the target file's dialect to choose the table shape, ignoring the effective layered view's precedence (native table from any layer wins over legacy members, per effectiveClientServer).

Change and scope

  • src/application/ClientConfigurationDocument.ts exports opencodeNativeClientConfiguration, the native V2 view of a V1 document (native mcp.servers table, V1 members kept as legacy so withClientServers removes REA's legacy entry beside the native table). It lives beside the dialect derivation it mirrors.
  • src/application/SetupClientConfiguration.ts (configureClientDocument): when any source in files.value has dialect opencode_v2, the write view promotes the parsed target document (and the pre-parse existing view used for policy evaluation). The promoted dialect makes the desired entry take the existing opencode_v2 generation path, so the written entry carries disabled: false (the #3318 inherited-flag override).
  • Reading semantics (effectiveClientConfiguration, inspection) are unchanged; fresh setups where no layer has a native table keep writing the V1 member exactly as before; only the inherited-native-table scenario changes shape. The JSONC writer path and backup behavior are untouched.
  • Intentionally not included: changing the default table shape for brand-new OpenCode setups (no layers with native tables) — that is a behavior decision beyond this report's scope; the issue's workaround-equivalent cases are the inherited-table ones fixed here.
  • Contribution scope: ordinary fix within existing boundaries — no maintainer scope decision required ("not applicable").

Contract and boundary impact

  • Semantic owner and earliest changed stage: the setup write plan (src/application/SetupClientConfiguration.ts) consuming the dialect owner's new V2 view (src/application/ClientConfigurationDocument.ts).
  • CLI and MCP/tool-catalog contract: rea setup --client opencode now writes mcp.servers.rea with disabled: false when any applicable layer has a native table; doctor reports aligned/enabled after setup instead of stale/disabled. No schema or tool changes.
  • Provider, bridge, target-format, or platform compatibility: OpenCode only; other clients untouched.
  • Evidence, artifact, provenance contract: none.
  • Generated metadata: none.

Expected effects:

  • Read existing files or captured data. (the probe reads and writes synthetic user configurations only)
  • Launch or attach to a process.
  • Inject instrumentation or run scripts/code.
  • Change process memory, registers, files, or configuration. (synthetic isolated HOME fixtures only; no real client configuration is modified)
  • Contact network services.
  • Recover protected code or work around protections.
  • Documentation or usability only; no target interaction.
  • Not sure yet; investigation or maintainer guidance needed.

Evidence and regression coverage

  • RED (executed on this machine, current main 45a411e8f before the fix): the issue's production-function probe ran in three isolated HOMEs with locked dependencies and Node 24.22.1. plain and missing modes reproduced the report exactly — setup wrote V1 mcp.rea with enabled: true, returned configured, inspection already_current, while effective registration reported stale/disabled; v2-control passed.
  • GREEN (executed after the fix): all three modes report aligned/enabled; the upper file receives the native mcp.servers.rea with disabled: false; theme and the lower file remain byte-identical.
  • Tests added (tests/acceptance/setup/opencodeV2ClientSetup.test.ts): the layered matrix extends to an upper file without a native table (plain) across the existing disabled×JSONC combinations, plus a missing upper-file case asserting the native write, idempotent re-run, and doctor aligned. All run through the real CLI (rea setup --client opencode --skill=false --yes --json).
  • Base reproduction: the issue's probe and source analysis were rechecked against current main before fixing; the parse-side dialect derivation and the #3318 disabled override are unchanged.
  • Remaining proof gaps: Linux and Windows hosts were not executed here (the fixtures are platform-neutral JSON handling); a real OpenCode session loading the written configuration was not run.

For evidence-bearing changes:

  • Observed, derived, and inferred claims remain distinguishable. (executed probe vs source-derived reasoning is labeled)
  • Artifact identity, source provenance, and failed attempts remain preserved.
  • Unsupported, incomplete, unavailable, or uncertain outcomes remain visible.

Validation performed

  • npm ci — locked dependencies, Node 24.22.1 (.nvmrc), macOS 14 arm64.
  • Issue's probe (three isolated HOME trials), before and after the fix — RED/GREEN output quoted above.
  • npm run test:focused -- tests/acceptance/setup/opencodeV2ClientSetup.test.ts — 10 passed (8 matrix + missing + the pre-existing malformed-lower case).
  • npm run test:focused -- tests/acceptance/setup/duplicateJsonMemberSetup.test.ts tests/acceptance/setup/clientConfigurationDiagnosticsCli.test.ts tests/boundary/filesystem/clientConfigurationEnvironment.test.ts tests/boundary/filesystem/clientLifecycle.test.ts — 121 passed, 10 skipped.
  • npm run check:fast — typecheck + lint pass (uncached).

Compatibility, safety, and release

  • Breaking changes or migration steps: none. The write-shape change only fires when an inherited native table exists; existing native-table setups were already written natively.
  • Real Hopper/Ghidra, browser, or OS coverage: not applicable — no provider is launched; HOPPER_LAUNCHER_PATH points at an absent path in the fixtures.
  • Package or release metadata impact: none.
  • Security, privacy, process, or containment review: none.

Author readiness

Human owner: @kittimzhe

  • I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work.
  • I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps.
  • I declare this PR ready for initial maintainer review.

Before merge

  • This PR addresses a concrete problem or an agreed enhancement.
  • Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff.
  • The PR has one focused outcome and the title follows type(scope): outcome.
  • Related issue is linked: Fixes #6573.
  • Tests cover changed observable behavior and meaningful failure paths. (plain/missing matrix through the real CLI, idempotence, doctor alignment, plus the pre-existing malformed-lower guard)
  • Owning docs, contracts, and generated metadata are updated where needed. (the documented native-table contract is what this restores; no doc enumerates the write-shape decision)
  • User-visible CLI/MCP changes include representative output. (RED/GREEN probe output quoted in Evidence)
  • I checked the final diff for secrets, unrelated cleanup, and unsupported claims.

🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/morluto/rea/pull/6587 **Author:** [@kittimzhe](https://github.com/kittimzhe) **Created:** 10/23/2026 **Status:** ❌ Closed **Base:** `main` ← **Head:** `fix/opencode-inherited-native-table` --- ### 📝 Commits (1) - [`5491d3a`](https://github.com/morluto/rea/commit/5491d3ac969447d6585c3c169e591b30568863a4) fix(setup): write the native OpenCode table inherited from any layer ### 📊 Changes **3 files changed** (+166 additions, -65 deletions) <details> <summary>View changed files</summary> 📝 `src/application/ClientConfigurationDocument.ts` (+29 -0) 📝 `src/application/SetupClientConfiguration.ts` (+15 -2) 📝 `tests/acceptance/setup/opencodeV2ClientSetup.test.ts` (+122 -63) </details> ### 📄 Description Fixes #6573 ## Summary Setup decided which OpenCode table to write from the target file's own content, so an upper `opencode.json` without an `mcp` table (or a missing upper file) made approved setup write a legacy V1 `mcp.rea` member while the client loads the native `mcp.servers` table inherited from a lower layer: configuration reported `configured` and later `already_current`, but the effective registration inspection stayed `disabled`/`stale`. The write view now promotes a V1 target document to its native V2 view when any applicable layer has the native table. ## Problem and expected behavior - Smallest trigger (from the issue, reproduced locally before the fix): lower `config.json` holds a disabled native V2 registration; upper `opencode.json` holds only `{"theme":"system"}` or is absent. `configureClientConfiguration` writes a V1 `mcp.rea` entry with `enabled: true` into the upper file, returns `configured`, and the following inspection reports `already_current` — while `readClientRegistrationInspections` reports `activation: "disabled"`, `state: "stale"`. The passing control (upper file with an explicit `mcp.servers` table) is the shape #3469/#3318 already covered. - Violated invariant: setup must produce an enabled effective registration and agree with the registration reader about whether another update is required. Per the documented OpenCode configuration contract, setup uses native V2 tables where present and doctor checks the merged user registration. - Root cause: `parseClientConfiguration` correctly derives each file's dialect from its own content, but the write path used the target file's dialect to choose the table shape, ignoring the effective layered view's precedence (native table from any layer wins over legacy members, per `effectiveClientServer`). ## Change and scope - `src/application/ClientConfigurationDocument.ts` exports `opencodeNativeClientConfiguration`, the native V2 view of a V1 document (native `mcp.servers` table, V1 members kept as legacy so `withClientServers` removes REA's legacy entry beside the native table). It lives beside the dialect derivation it mirrors. - `src/application/SetupClientConfiguration.ts` (`configureClientDocument`): when any source in `files.value` has dialect `opencode_v2`, the write view promotes the parsed target document (and the pre-parse `existing` view used for policy evaluation). The promoted dialect makes the desired entry take the existing `opencode_v2` generation path, so the written entry carries `disabled: false` (the #3318 inherited-flag override). - Reading semantics (`effectiveClientConfiguration`, inspection) are unchanged; fresh setups where no layer has a native table keep writing the V1 member exactly as before; only the inherited-native-table scenario changes shape. The JSONC writer path and backup behavior are untouched. - Intentionally not included: changing the default table shape for brand-new OpenCode setups (no layers with native tables) — that is a behavior decision beyond this report's scope; the issue's workaround-equivalent cases are the inherited-table ones fixed here. - Contribution scope: ordinary fix within existing boundaries — no maintainer scope decision required ("not applicable"). ## Contract and boundary impact - Semantic owner and earliest changed stage: the setup write plan (`src/application/SetupClientConfiguration.ts`) consuming the dialect owner's new V2 view (`src/application/ClientConfigurationDocument.ts`). - CLI and MCP/tool-catalog contract: `rea setup --client opencode` now writes `mcp.servers.rea` with `disabled: false` when any applicable layer has a native table; `doctor` reports `aligned`/enabled after setup instead of `stale`/disabled. No schema or tool changes. - Provider, bridge, target-format, or platform compatibility: OpenCode only; other clients untouched. - Evidence, artifact, provenance contract: none. - Generated metadata: none. Expected effects: - [x] Read existing files or captured data. *(the probe reads and writes synthetic user configurations only)* - [ ] Launch or attach to a process. - [ ] Inject instrumentation or run scripts/code. - [ ] Change process memory, registers, files, or configuration. *(synthetic isolated HOME fixtures only; no real client configuration is modified)* - [ ] Contact network services. - [ ] Recover protected code or work around protections. - [ ] Documentation or usability only; no target interaction. - [ ] Not sure yet; investigation or maintainer guidance needed. ## Evidence and regression coverage - RED (executed on this machine, current main `45a411e8f` before the fix): the issue's production-function probe ran in three isolated HOMEs with locked dependencies and Node 24.22.1. `plain` and `missing` modes reproduced the report exactly — setup wrote V1 `mcp.rea` with `enabled: true`, returned `configured`, inspection `already_current`, while effective registration reported `stale`/`disabled`; `v2-control` passed. - GREEN (executed after the fix): all three modes report `aligned`/`enabled`; the upper file receives the native `mcp.servers.rea` with `disabled: false`; `theme` and the lower file remain byte-identical. - Tests added (`tests/acceptance/setup/opencodeV2ClientSetup.test.ts`): the layered matrix extends to an upper file without a native table (`plain`) across the existing disabled×JSONC combinations, plus a `missing` upper-file case asserting the native write, idempotent re-run, and doctor `aligned`. All run through the real CLI (`rea setup --client opencode --skill=false --yes --json`). - Base reproduction: the issue's probe and source analysis were rechecked against current main before fixing; the parse-side dialect derivation and the #3318 disabled override are unchanged. - Remaining proof gaps: Linux and Windows hosts were not executed here (the fixtures are platform-neutral JSON handling); a real OpenCode session loading the written configuration was not run. For evidence-bearing changes: - [x] Observed, derived, and inferred claims remain distinguishable. *(executed probe vs source-derived reasoning is labeled)* - [x] Artifact identity, source provenance, and failed attempts remain preserved. - [x] Unsupported, incomplete, unavailable, or uncertain outcomes remain visible. ## Validation performed - `npm ci` — locked dependencies, Node 24.22.1 (`.nvmrc`), macOS 14 arm64. - Issue's probe (three isolated HOME trials), before and after the fix — RED/GREEN output quoted above. - `npm run test:focused -- tests/acceptance/setup/opencodeV2ClientSetup.test.ts` — 10 passed (8 matrix + missing + the pre-existing malformed-lower case). - `npm run test:focused -- tests/acceptance/setup/duplicateJsonMemberSetup.test.ts tests/acceptance/setup/clientConfigurationDiagnosticsCli.test.ts tests/boundary/filesystem/clientConfigurationEnvironment.test.ts tests/boundary/filesystem/clientLifecycle.test.ts` — 121 passed, 10 skipped. - `npm run check:fast` — typecheck + lint pass (uncached). ## Compatibility, safety, and release - Breaking changes or migration steps: none. The write-shape change only fires when an inherited native table exists; existing native-table setups were already written natively. - Real Hopper/Ghidra, browser, or OS coverage: not applicable — no provider is launched; `HOPPER_LAUNCHER_PATH` points at an absent path in the fixtures. - Package or release metadata impact: none. - Security, privacy, process, or containment review: none. ## Author readiness Human owner: @kittimzhe - [ ] I reviewed the final diff and relevant existing code, understand the change and its edge cases, and take responsibility for the complete PR, including AI-assisted work. - [ ] I checked the evidence above, confirmed it supports the current change, and recorded meaningful validation gaps. - [ ] I declare this PR ready for initial maintainer review. ## Before merge - [ ] This PR addresses a concrete problem or an agreed enhancement. - [ ] Material scope and authority questions are resolved, and any required maintainer scope decision covers the final diff. - [x] The PR has one focused outcome and the title follows `type(scope): outcome`. - [x] Related issue is linked: Fixes #6573. - [x] Tests cover changed observable behavior and meaningful failure paths. *(plain/missing matrix through the real CLI, idempotence, doctor alignment, plus the pre-existing malformed-lower guard)* - [x] Owning docs, contracts, and generated metadata are updated where needed. *(the documented native-table contract is what this restores; no doc enumerates the write-shape decision)* - [x] User-visible CLI/MCP changes include representative output. *(RED/GREEN probe output quoted in Evidence)* - [x] I checked the final diff for secrets, unrelated cleanup, and unsupported claims. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
bsakaguchi 2026-11-01 21:47:27 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
morluto/rea#7380
No description provided.