Uh oh!
There was an error while loading. Please reload this page.
fix(cloud-connection): derive features.installLocal from what is mounted, keep the option as a ceiling (#8388) - #8466
Conversation
…ted, keep the option as a ceiling (#8388) `GET /api/v1/runtime/config` reported `installLocal` straight from the constructor option, beside a `marketplace` key #8356 had just made an observation — two flags in one object answered by different rules. The declared one is the key #8343 measured wrong on a real self-hosted deployment: `installLocal: true` with both verbs of `/api/v1/marketplace/install-local` returning 404. The flag is now observed per request off the serving app's route ledger, by a sibling predicate rather than a shared one: the browse predicate subtracts exactly the paths this one requires. The two share the prefix constant, so "what counts as install-local" has a single definition. The constructor option is kept (hosts pass it today) as a ceiling: omitted or `true` defers to the observation, `false` lowers it. It cannot raise the answer — the CLI's own frozen RUNTIME_CONFIG_OPTIONS passes `installLocal: true` unconditionally, so honouring `true` upward would have left the derivation inert on exactly the path #8343 reported. Repairs one pin in packages/cli that this change correctly invalidates: the "two offline guards are INDEPENDENT" case handed the resolver an install-local identity without mounting a route, which was faithful while the flag was declarative. It now mounts the real plugin; its assertions are unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P7vaLs7bhBPi9m3JyzkhDj
The latest updates on your projects. Learn more about Vercel for GitHub. 1 Skipped Deployment
|
📓 Docs Drift CheckThis PR changes 1 package(s): 1 hand-written doc(s) reference the affected code and may need an implementation-accuracy re-verification:
⛔ 1 release-owned page(s) also reference the affected code. These are read-only:
|
Uh oh!
There was an error while loading. Please reload this page.
Fixes#8388
GET /api/v1/runtime/configbuilt its response with two capability flags in oneobject, answered by different rules:
Nothing checked that
MarketplaceInstallLocalPluginwas mounted on the kernelserving the response, so
new RuntimeConfigPlugin({ installLocal: true })on aruntime that never mounted it announced a capability whose route 404s. That is
the second symptom measured on a real self-hosted deployment in #8343:
installLocal: truein the payload, with both verbs of/api/v1/marketplace/install-localreturning404 {"error":"Not found"}.What changed
features.installLocalis now observed per request off the serving app's routeledger, the same seam #8356 built.
A sibling predicate, not a reuse. The browse predicate deliberately
subtracts the install-local paths, so no single predicate can answer both
questions. What genuinely had to be shared is smaller and more precise:
MARKETPLACE_INSTALL_LOCAL_PREFIX— the one definition of "what install-localis", now read in opposite directions by the two predicates (negatively by
browse, positively by install-local). Neither flag can claim, or disown, a
route the other one does if the prefix ever moves.
someRoutePatternhelper.The predicates stay separate because they answer different questions about the
same ledger. The install-local one uses a segment boundary rather than a bare
startsWith, so.../install-local/:manifestIdcounts and.../install-localitydoes not.The constructor option is kept, as a ceiling
Per the triage ruling, the published option is not removed — hosts pass it today.
It is now a bound on the derived answer rather than its source:
truefalsefalse, even where the plugin IS mounted (operator opt-out)Why a ceiling and not a plain override — this is the one judgement call in
the card, and it is load-bearing. A plain override honours
trueupward, and theCLI's own frozen
RUNTIME_CONFIG_OPTIONSpassesinstallLocal: trueunconditionally. So an override would keep "declared
true, route 404s"reachable on exactly the product path #8343 reported, leaving the derivation
inert precisely where it is needed. The card itself lists the ceiling as one of
the three triage-time options, and it is the only one that satisfies the stated
acceptance ("nothing mounted ⇒
false") on the real CLI path.Nothing is lost:
resolveFeaturesstill merges over the derived base and overthe ceiling, so a host whose adapter exposes no route ledger declares the
capability it knows it serves, exactly as for
marketplace.Also note the constructor now reads
config.installLocal !== falserather than!!config.installLocal: once the flag is derived, an omitted option must notread as an opt-out.
The cross-package repair
This change correctly invalidates one pin that landed in #8389 twenty minutes
before this card was dispatched —
packages/cli/test/serve-marketplace-offline-runtime-config.test.ts,the case "the two offline guards are INDEPENDENT". That fixture handed the
resolver an install-local identity without mounting a route; because
offlineInstallLocalresolvesfalse,bootOfflineArmnever started the realplugin, so the app had no install-local route at all. It passed only because the
flag was the constructor value.
Neither side was wrong: the derived answer is correct for that app, and the
fixture was faithful while the flag was declarative. The fixture now mounts the
real plugin via the same
preMountedseam the positive control already uses, so"the host wires its own" means the host really mounts one. The assertions are
unchanged — one was added (the route really is on the ledger), none weakened.
Measured rather than assumed: before the repair, exactly one case in that
file went red (
:322), and the other 10 stayed green — including the acceptancecase and the positive control, which both mount the real plugin. That confirms
the dispatch note's prediction about the rest of the file.
Verification
packages/cloud-connection— 19 files, 138 tests, all pass.packages/cli— 117 files, 1276 tests, all pass. Run in full, because thisis the shape where PR CI runs the affected subset and two individually-green
changes first meet in the merge queue.
expression: 12 of the 15 new cases go red. The three that stay green are
exactly the ones that should — "no mount at all" (the old flag also said
false), the ceiling-falsecase (it pins the option, not the derivation),and the
resolveFeaturesescape hatch. Both pre-existing runtime-config suitesstayed green under the ablation too, so neither ever depended on the derivation.
check:type-check-debt(green after building the closure it demands —it reports "surplus: none", so the new test file moved nothing),
check:type-check-coverage,check:query-options-erasure,check:startup-registry-verdict,check:changeset-gate-self-tests,check:objectui-changeset,check:nul-bytes,check-changeset-no-major,check-empty-changeset.Gate families were re-derived from the actual changed paths with
scripts/pm/dispatch-gates.mjs; beyond the namedcheck:type-check-debtitsurfaced
check:type-check-coverageandcheck:query-options-erasure(bothconvention-triggered by adding a test file) plus the changeset family. All run
and green.
Scope note
One file outside the declared surface:
packages/cloud-connection/README.md.Its wiring example carries a comment stating that
marketplaceis derived "sothere is nothing here to keep in sync" while still presenting
installLocal: trueas a declaration — and that README is one of the two placesthe card names as having failed to keep a hand-maintained flag in step with its
own mounting. The edit is comment-only, in this card's own package, zero
behaviour. Flagged here rather than done silently.
Generated by Claude Code