Skip to content

000233 proof discharged; register the lspServers userConfig-defaults defect (000241) - #169

Merged
manderse21 merged 1 commit into
mainfrom
dispatch/000241-lspservers-userconfig-defaults
Aug 15, 2026
Merged

000233 proof discharged; register the lspServers userConfig-defaults defect (000241)#169
manderse21 merged 1 commit into
mainfrom
dispatch/000241-lspservers-userconfig-defaults

Conversation

@manderse21

Copy link
Copy Markdown
Owner

Canonicalizes dispatch 000233's installed-plugin integration proof -- which its own outbox recorded as BLOCKED -- and registers the separate defect that obtaining the proof surfaced. 000233 is not reopened: it stays verified and its ruling stands. No runtime change; plugin.json is untouched.

The proof

A marketplace install registered the LSP server, answered documentSymbol / hover / goToDefinition against demo.ps1, produced the expected PSUseApprovedVerbs diagnostic, and logged all three knobs with provenance: env and configured=shim effective=shim.

Legs 1 and 4 (settings block, shim log) were re-observed from disk while writing the ledger entry. Legs 2 and 3 are recorded from Mike's session and corroborated by demo.ps1 being exactly the two-line fixture that produces that symbol, that unapproved-verb diagnostic and that hover target.

Two corrections land in the ledger rather than by editing a verified outbox:

  • The outbox's closing instruction names pluginConfig['powershell-lsp']. The real path is pluginConfigs (plural), keyed by the qualified name powershell-lsp@claude-powershell-lsp, values under a nested options object. Followed verbatim, the outbox's instruction writes a key Claude Code never reads.
  • The proving artifact is main@939048e, not the v1.31.1 release. The manifest self-reports 1.31.1, but git tag --contains d563b84 is empty and tagged v1.31.1 carries only PSES_BUNDLE_PATH in that env block.

The new defect (dispatch 000241, minted)

On Claude Code 2.1.233, ${user_config.*} inside lspServers resolves against explicitly-set options only, ignoring declared userConfig defaults, and one unset key discards every LSP server the plugin declares:

Failed to load LSP servers for plugin powershell-lsp: Error: Plugin option "profile" isn't set.

Root cause is an asymmetry inside Claude Code: the MCP path merges schema defaults before interpolating; the lspServers path passes stored options straight through. Full write-up, decompiled call sites, the 13-plugin control, the reproducer and the proposed one-line upstream fix: docs/upstream/claude-code-lspservers-userconfig-defaults.md.

The fix belongs both upstream and here. Upstream is primary. A plugin-side mitigation is required now -- the mappings are live in the distribution channel (marketplace.json sources at ./, so installs track the default branch) while absent from every tag. That mitigation is a real trade against 000233's ruling and is left for adjudication in dispatch 000241, not chosen here.

Regression coverage

tests/PowerShellLsp.LspServerLoadability.Tests.ps1 -- 19 tests, green on pwsh 7.6.3 and Windows PowerShell 5.1.

Deliberately does not pin today's answer:

  • models the upstream interpolator ordinally (the lookup is a JS property read, and PowerShell's @{} is case-insensitive -- which would have hidden exactly the mismatch the block exists to catch);
  • counts the mandatory-configuration cost of every ${user_config.*} mapping, so a fourth cannot be added unnoticed;
  • ties that count to the troubleshooting entry;
  • its zero-configuration prediction flips with its own premise, so it stays honest under either mitigation.

Writing it refuted a plausible guess: dropping a referenced key's declared default does not keep the block failing -- the merge assigns default ?? "", so the knob silently resolves to empty. Only required-without-a-default stays fatal. Both are pinned as separate tests.

Also

Corrects a stale id: the action-pinning gate was annotated "dispatch 000241", an id that did not exist when it shipped (the hub counter stood at 000240, and 000240's outbox lists that exact file and commit 3aeb415). 000241 has since been minted for this defect, so the annotation now names 000240.

Verification

block result
new loadability block (pwsh 7.6.3) 19/19
new loadability block (WPS 5.1) 19/19
000233 serve-userConfig block 32/32
action-pinning gate 26/26
CHANGELOG extraction 7/7

A local full-suite run was started but had not reported at hand-off; the four-leg CI on this PR is the gate.

https://claude.ai/code/session_01T8DmRQcMFZZuA4MbJeruCR

…defect

Canonicalizes dispatch 000233's installed-plugin integration proof, which its
own outbox recorded as BLOCKED, and registers the separate defect that obtaining
the proof surfaced. 000233 is NOT reopened -- it stays verified and its ruling
stands.

The proof. A marketplace install registered the LSP server, answered
documentSymbol / hover / goToDefinition against demo.ps1, produced the expected
PSUseApprovedVerbs diagnostic, and logged all three knobs with provenance: env
and configured=shim effective=shim. Legs 1 and 4 were re-observed from disk
while writing the ledger entry; legs 2 and 3 are recorded from Mike's session
and corroborated by demo.ps1 being exactly the fixture that produces them.

Two corrections to the record, made in the ledger rather than by editing a
verified outbox:

  - The outbox's closing instruction names pluginConfig['powershell-lsp'].
    The real path is pluginConfigs (plural), keyed by the QUALIFIED name
    powershell-lsp@claude-powershell-lsp, values under a nested options object.
  - The proving artifact is main@939048e, not the v1.31.1 release. The manifest
    self-reports 1.31.1, but `git tag --contains d563b84` is empty and tagged
    v1.31.1 carries only PSES_BUNDLE_PATH in that env block.

The new defect. On Claude Code 2.1.233, ${user_config.*} inside lspServers is
resolved against explicitly-set options only, ignoring declared userConfig
defaults, and one unset key discards every LSP server the plugin declares:

    Failed to load LSP servers for plugin powershell-lsp:
    Error: Plugin option "profile" isn't set.

Root cause is an asymmetry inside Claude Code: the MCP path merges schema
defaults before interpolating, the lspServers path passes stored options
straight through. Fix belongs BOTH upstream (primary, one call) and here (a
mitigation is required now -- the mappings are live in the distribution channel
via marketplace source "./" while absent from every tag). The plugin-side
mitigation is a real trade against 000233's ruling and is left for adjudication
in dispatch 000241, not chosen here.

Regression coverage, 19 tests, green on pwsh 7.6.3 and Windows PowerShell 5.1.
Deliberately does not pin today's answer: it models the upstream interpolator
ordinally (the lookup is a JS property read), counts the mandatory-configuration
cost of every ${user_config.*} mapping, ties that count to the troubleshooting
entry, and its zero-configuration prediction flips with its own premise so it
stays honest under either mitigation. Writing it refuted a plausible guess --
dropping a referenced key's declared default does not keep the block failing,
the merge assigns `default ?? ""` so the knob silently resolves to empty; only
required-without-a-default stays fatal. Both are pinned as separate tests.

Also corrects a stale id: the action-pinning gate was annotated "dispatch
000241", an id that did not exist when it shipped (the hub counter stood at
000240, and 000240's outbox lists that exact file and commit 3aeb415). 000241
has since been minted for this defect, so the annotation now names 000240.

No runtime change. plugin.json is untouched.

Claude-Session: https://claude.ai/code/session_01T8DmRQcMFZZuA4MbJeruCR
@manderse21
manderse21 merged commit a0e0572 into main Aug 15, 2026
6 checks passed
@manderse21
manderse21 deleted the dispatch/000241-lspservers-userconfig-defaults branch August 15, 2026 14:20
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