Native capability broadcast, 2026-10-01
Implementation 45fffe3ff13f230c98fda8dc6f5c8378c4f7139e adds a working capability-broadcast diagnostic to the extension example. It calls the existing client API against the extension, Devframe and DevTools providers already attached to the page. It shares the existing recipient selector and result display; no SDK API, action wrapper, backend RPC method, serializer or transport changed.
client.capabilities.broadcast({
capability: counterCapability,
operation: 'read',
input: {},
selection: [{ realm: 'devserver' }, { realm: 'webext' }],
});
extension page -> existing client selection -> native Port -> extension service
-> native RPC -> Devframe service
-> native RPC -> DevTools service
<- one outcome per provider, retaining provider identity
Both maintained browser suites read distinct backend values, assert complete provider identities and attachment order, select each realm or an explicit server, disable/reenable the extension service through its JSON controls, and close a server. Known unavailable recipients return rejected outcomes while the selected surviving providers still fulfill. Read calls preserve the existing mutation counts; recovery reads the original values.
Scoped strict lint, TypeScript, formatting, both extension production builds and three example tests pass. Fresh Chromium 153.0.8010.12 passed 47 scenarios with zero page errors; Firefox 157.0 passed 51 scenarios and retains its explicit lack of global page-error capture. The committed receipts and screenshots come from those successful terminal runs. The client unit suite also passed all 31 tests. Unchanged development scenarios were not rerun locally; full CI owns that broader check.
The new control is a host diagnostic. This does not introduce a second JSON action API or complete the broader JSON management interface. Automatic discovery, unmatched-selector browser details, cancellation/lifecycle races and full host/mode conformance remain open. Full CI passed for the final pushed head, including workspace validation, native Chromium/Firefox production tests, concurrent development transitions and the combined API evidence gate.
Reconciled status, 2026-09-30
Portable catalog/router composition over real extension Ports is delivered in d4d2115, mixed native backends in fe349b3, selected-page handoff in d58a0d4, and native JSON action routing in a99cb87. 1ef4f90 records Firefox and HMR regression evidence.
The handler/RPC seam is settled and implemented. Reconnecting to a surviving backend preserves its incarnation; replacing that backend changes it. Selectors are strings, with realm required and provider optional. CDB discovery is optional integration work, not a prerequisite for generic routing.
Native server view-index composition now has Chromium and Firefox acceptance in ef43f0f. Automatic discovery, untrusted-page authority, the remaining view/browser matrix and full capability/host conformance remain open.
Earlier checkpoints below are dated evidence. Their then-pending items are superseded by this status and later accepted resolutions; they do not reopen settled architecture choices.
Latest implementation checkpoint, 2026-09-29
The native integration is now installed in the workspace, with no upstream checkout required. Port binding 3fb91fd, RPC/state backport 5ebcb5a, renderer/view backport 631db2b, and maintained example 86b24b3 are separate ticket commits on main.
examples/webext consumes built public exports from the pinned, patched 1.0 dependency graph. Its real Chromium test passes 12 scenarios with zero page errors. The same test now runs in full SDK CI, which passes. The old temporary prototype is replaced by this maintained example.
The upstream review is split into draft RPC/state #410, JSON view/renderer #411, and independent baseline snapshot repair #412. The renderer declaration shim and implementation file moves are removed.
createPortChannel({ port, onDisconnect }) reuses native framing, serializer and close behavior. Native state tests prove per-peer subscriptions, writes and disconnect isolation. All 48 existing server tests pass. Portable WebExtension provider/catalog/router composition remains the next step. Full surfaces, content/page authority, debugger, worker suspension, Firefox browser conformance and HMR remain open; this issue is not complete.
Accepted two-layer selection amendment, 2026-09-27
The owner chose typed command/results with native state observation, and implementation-owned applicability. Contract migration and authenticated native proof are on main. The architecture diagram and API examples supersede the earlier universal target contract and A1/A2/B mapping questions.
Client selectors choose realm/provider recipients. Selected action/service implementations inspect schema-defined domain/resource input and return their own declared result, such as applied or not-applicable. There is no SDK target envelope, target resolver, accepts hook or new topic/event bus. A not-applicable result is fulfilled; it neither makes the provider unavailable nor triggers fallback/replay. If multiple selected implementations match, all may act.
Provider incarnation, contribution activation generation, exact versions, native authorization/serialization and dispatch ownership remain unchanged. Browser/debugger capabilities still validate actual resources and permissions.
Part of Design a portable contribution SDK and WebExtension runtime.
Current status, 2026-09-27
@devkit/client now executes local multi-provider routing. The accepted missing-recipient rule is implemented: if any broadcast selector has no known provider, reject the entire broadcast before dispatch, with code unmatched-selection, all unmatched .selectors, and a message explaining how to correct the request. Known unavailable providers instead receive individual rejected outcomes.
Commit: 2c6ef9b. This builds on the local catalog, declarative route defaults, provider identity validation and scoped invocation requests.
Implemented and tested:
- Client-owned connection registry with exact
(realm, provider ID) identity, duplicate rejection, immutable snapshots and owned subscription/cancellation cleanup. Detaching a connection does not dispose its host.
- Per-call policy replaces action default, then client default. Ordered fallback selects before dispatch, ambiguity requires a discriminant, unknown catalogs never imply confirmed absence, and execution failures never cause replay.
- Local callbacks observe original candidate owners and recheck readiness for those same attachments. Replaced/detached selected owners reject as stale; fresh invocations may select successors. Cancellation prevents a late callback from dispatching.
- Capability bindings remain pinned to their attachment/incarnation. Resource identity and applicability belong to schema-defined input and the selected implementation.
- Separate typed capability/action broadcast methods, required non-empty
selection, no inherited ordinary routing defaults, complete unmatched-selector preflight, deduplication and individual outcomes.
- Working simultaneous Devframe hub and DevTools kit example using both real local server handles. The missing-recipient increment leaves native counters
[3, 6]; overlapping selectors increment each once to [4, 7]. Client disposal leaves native commands/state alive.
const client = createClient({
connections: [devframeProvider, devtoolsProvider],
routing: [
{ realm: 'devserver', provider: 'frontend' },
{ realm: 'devserver', provider: 'tools' },
],
});
await client.actions.invoke({ action, input });
await client.actions.broadcast({
action,
input,
selection: [{ realm: 'devserver', provider: 'frontend' }, { realm: 'webext' }],
});
Local validation passes: 75 core tests, 32 client tests, 78 runtime tests, 20 native server tests, both individual server examples and their new simultaneous routing check. Strict TypeScript 7, type-aware Oxlint, scoped formatting/builds and tooling checks pass. The packed consumer installs core/runtime/client tarballs, checks Bundler and NodeNext declarations, executes callback/broadcast behavior and builds a portable browser bundle without host/framework modules. Full repository CI passes on this commit.
The owner has accepted the local routing semantics, including rejecting all dispatch when any requested recipient is missing. The maintained routing record, client API, glossary, architecture and API/example/test matrix record the implementation and its limits.
Authorized remote catalog synchronization and native remote routing are now implemented. Still open: verified endpoint discovery, extension actors and capability resource checks, renderer/extension examples, and the optional CDB path. The workspace has the connection.isolated backport from Devframe draft 401; that solves native SDK-owned connection isolation, not these missing adapter contracts. The local client adds no daemon, transport engine or global state store.
Upstream integration boundary, 2026-09-27
Keep the implemented client focused on selection and ownership. Server connections use devframe/client; extension Port integration first uses the channel seam in devframe/rpc/client. Each native connection owns auth, serialization and request correlation. The contribution catalog supplies exact contract/version/lifecycle metadata that native discovery does not supply; do not duplicate the entire native service registry or add a daemon.
See the implementation and map review. This narrows implementation mechanisms without dropping the accepted feature or real-host coverage requirements.
Question
How does a contribution discover compatible providers and route each operation when extension, Devframe, Devtools, and optional CDB providers are available together?
Resolve provider identity, discovery, selection precedence, callback selection, broadcast outcomes, and the meaning of unavailable providers. The answer must let one JSON-authored UI operate against several backends without choosing a backend through renderer-specific code.
Context and current behavior
The agreed destination is a generic framework in the devkit-extension pnpm/Turbo monorepo. Build-time npm contributions may provide UI, actions, transforms, realm implementations, or any composition. Devframe and Devtools hosts coexist with Chromium and Firefox extension hosts. Raw APIs remain local, with separately typed realm, execution context, and UI surface.
The local ownership and selection rules above are implemented. Remote endpoint discovery remains outstanding; authenticated native catalog/invocation adapters are implemented. Devtools and extension providers may reach the same page, while another tab exposes a different target, potentially through the same provider installation. Choosing the first connection could direct a mutation to the wrong target.
The accepted routing modes are broadcast, a caller callback, provider-ID or realm precedence, and a UI choice supplied as callback input. Contributions declare defaults; individual operations may override them. Provider state remains separate, and synchronization is optional.
Requirements and scope
- Identify the provider instance and backend incarnation. A reconnect must distinguish a returning logical provider from a replacement backend. Capability implementations separately identify resource lifetimes when needed.
- Advertise operations and their availability, including supported, permission-required, temporarily unavailable, disconnected, and unsupported cases. Unknown discovery information must remain distinguishable from confirmed absence.
- Keep contribution defaults separate from the selected route for an individual invocation. Record the route that actually ran.
- Return a provider-specific outcome for every broadcast target. One rejection must preserve successful sibling outcomes.
- Support local extension discovery and the registered remote adapters. An optional CDB integration must use its real discovery and transport behavior when installed.
- Keep provider selection and state synchronization separate. Selecting two providers does not merge their state or make repeated mutations safe.
Options and recommendation
One global preferred backend is easy to explain but cannot express operations that need different capabilities. Hidden fallback chains make availability convenient while obscuring which provider performed an action. A central router with explicit selectors gives callers enough control without duplicating transport handling.
Recommend the central router. An operation override replaces the contribution default for that invocation. A selector requires a realm and may pin a provider within that realm; both constraints must match. Provider-only selectors and symbol/number coercion are excluded. A missing explicitly selected provider returns an unavailable result unless the caller declared a fallback. Ordered realm preferences choose the first eligible realm, with an explicit ambiguity result when several equally eligible instances remain.
Callbacks receive immutable candidate descriptions and caller input, including any UI selection. They return provider identities, not raw transports. Revalidate the chosen incarnation before dispatch. Do not silently reroute an interrupted mutation. Broadcast takes a candidate snapshot, dispatches once to each selected instance, and returns all settled outcomes.
Ordinary invocations already use dispatch-time readiness without implicit waiting, and fallback is limited to explicit ordered alternatives. The settled core prohibits rerouting or automatic replay after dispatch for every operation, including reads; a separately requested call makes a new selection. Callback staleness now rejects, and broadcast requires a separate selection list. An unmatched broadcast selector rejects the entire broadcast before dispatch; cancellation of a running handler does not imply that its side effects did not happen.
Proposed API or experiment
The implemented compact local calls and core client contracts are:
await provider.invoke({ action: increaseCounterAction, input: { amount: 2 } });
const resolution = await provider.resolve({ capability: counterCapability });
// Implemented by @devkit/client over attached provider connections.
await capabilities.invoke({
capability: counterCapability,
operation: 'increase',
input: { amount: 2 },
});
CapabilityInvocationRequest preserves each operation name and its schema-defined input as a correlated union. ActionInvocationRequest infers input and output from the action descriptor. Bound capability methods retain input, options; a local provider handle has no routing override.
The accepted callback contract rejects a selection whose provider incarnation changed while the picker waited. Broadcast uses broadcast({ action, input, selection: [...] }), where selection is a union of recipients. These are implemented by the local client. Missing recipients reject the whole request before dispatch and are listed in the error.
Build a runnable routing example with two real providers and a selector UI rendered from the shared JSON authoring format. Print each provider identity, availability, dispatch decision, and result. Add a CLI or test consumer for the same route callback so the selection logic is demonstrably independent of a renderer. Connect the real optional CDB adapter in its separately enabled example profile.
Scenarios and acceptance criteria
- The same operation runs through a contribution default, an exact-ID override, a realm preference, a callback, and broadcast.
- A chosen provider disconnects after selection. The caller receives an outcome naming that provider; another provider does not unexpectedly perform the mutation.
- Broadcast produces one success, one permission-required outcome, and one transport failure without discarding any result.
- Two matching providers remain ambiguous until the callback or explicit preference selects one. UI selection reaches that callback as ordinary input.
- A reconnect updates the provider incarnation and capability information without duplicating discovery entries or listeners.
- Chrome and Firefox examples exercise real extension discovery. Capability failures remain visible even when a different browser supports the operation.
Record every selected public API and hook in the versioned API-to-example-to-test-to-host matrix owned by Examples and API coverage contract.
Dependencies
Contribution and realm contract blocks this decision because it defines contribution identity, host registration, typed local contexts, and capability ownership. Routing must consume those definitions rather than invent a competing realm hierarchy. State scope and recovery consumes the selected provider identities but owns synchronization and persistence semantics.
Definition of Ready
Definition of Done
Local slice delivered:
Complete issue gate:
Resolution record
Local routing, authenticated remote catalogs, mixed server/extension routing and a selected-page native handoff are implemented. Automatic monitoring and complete supported-host conformance remain open. Close this decision with a resolution comment recording the selected contract, rejected alternatives, example/test obligations, and any newly exposed decisions. A written proposal does not establish that the router or adapters already work.
Current implementation checkpoint, 2026-09-29
Delivered on linear main in separate commits:
| Commit |
Change |
| d4d2115 |
Extract existing native provider/catalog integration into browser-safe @devkit/devframe; compose the same contracts over server RPC and actual extension Ports. |
| f217321 |
Preserve server-owned public declaration names for consumers. |
| fe349b3 |
One extension page connects to real Devframe and DevTools backends plus its worker; verify native origin/auth denial, realm broadcast, explicit preference and pre-dispatch fallback. |
| d58a0d4 |
Adopt a selected page's natively published connection with an isolated native client; verify absence, malformed envelope, closed source, scripting denial and independent connection lifetime. |
The existing server factories delegate to the shared adapter and retain their API. A Port supplies real native call/collector/events members; no full server context is fabricated. Native RPC/auth/codec/state remain upstream-owned. The registry still owns only portable provider metadata, exact contract availability and selection. No credential store, retry, operation replay, new auth callback or discovery daemon was added.
// Shared provider composition; existing server factories supply their real native context.
const provider = await createRpcProvider({
context: { rpc, realm, execution, native },
providerId,
services,
plugins,
expose: { actions, capabilities },
});
const connection = await createRpcProviderConnection({ rpc: nativeClient, realm, providerId });
client.providers.attach({ connection });
The application still owns endpoint/domain selection. Explicit configuration and one-shot selected-document handoff are demonstrated. The latter reads the public native descriptor in the selected top-level MAIN world and grants the source page no extension RPC authority. It checks the native envelope only, not a duplicate full metadata schema or endpoint identity. Native server allowedOrigins and native RPC authentication remain separate. Standard initHub supplies no viewer-origin token by default; its explicit native allowlist is used.
Validation: 49 server tests, eight channel/provider tests and two shared-adapter tests passed for the extraction. Affected strict TypeScript 7, type-aware Oxlint, Oxfmt and builds pass. The maintained example now passes 24 actual Chromium scenarios with zero page errors, using installed workspace packages and native backend hosts. Commands, API ownership, screenshot and receipt. Full CI at d58a0d4 is green, including the real browser test.
Existing exact-version pnpm patches carry reviewed native isolation/RPC/state/renderer exports while upstream drafts remain open. These slices needed no new upstream patch. The feature drafts remain RPC/state and JSON view/renderer; snapshot repair is independent.
Remaining gates are real Firefox conformance, complete extension surfaces, automatic discovery if an embedding application needs it, privileged page request authority, and JSON-authored cross-provider controls. The last item belongs to Renderer and surface contract: current JSON actions call their owning native backend, while the proven routing controls use HTML. A native handler-hook versus RPC-call-adapter proposal is under owner review. Do not close this issue as full supported-host conformance.
Native capability broadcast, 2026-10-01
Implementation 45fffe3ff13f230c98fda8dc6f5c8378c4f7139e adds a working capability-broadcast diagnostic to the extension example. It calls the existing client API against the extension, Devframe and DevTools providers already attached to the page. It shares the existing recipient selector and result display; no SDK API, action wrapper, backend RPC method, serializer or transport changed.
Both maintained browser suites read distinct backend values, assert complete provider identities and attachment order, select each realm or an explicit server, disable/reenable the extension service through its JSON controls, and close a server. Known unavailable recipients return rejected outcomes while the selected surviving providers still fulfill. Read calls preserve the existing mutation counts; recovery reads the original values.
Scoped strict lint, TypeScript, formatting, both extension production builds and three example tests pass. Fresh Chromium 153.0.8010.12 passed 47 scenarios with zero page errors; Firefox 157.0 passed 51 scenarios and retains its explicit lack of global page-error capture. The committed receipts and screenshots come from those successful terminal runs. The client unit suite also passed all 31 tests. Unchanged development scenarios were not rerun locally; full CI owns that broader check.
The new control is a host diagnostic. This does not introduce a second JSON action API or complete the broader JSON management interface. Automatic discovery, unmatched-selector browser details, cancellation/lifecycle races and full host/mode conformance remain open. Full CI passed for the final pushed head, including workspace validation, native Chromium/Firefox production tests, concurrent development transitions and the combined API evidence gate.
Reconciled status, 2026-09-30
Portable catalog/router composition over real extension Ports is delivered in d4d2115, mixed native backends in fe349b3, selected-page handoff in d58a0d4, and native JSON action routing in a99cb87. 1ef4f90 records Firefox and HMR regression evidence.
The handler/RPC seam is settled and implemented. Reconnecting to a surviving backend preserves its incarnation; replacing that backend changes it. Selectors are strings, with realm required and provider optional. CDB discovery is optional integration work, not a prerequisite for generic routing.
Native server view-index composition now has Chromium and Firefox acceptance in ef43f0f. Automatic discovery, untrusted-page authority, the remaining view/browser matrix and full capability/host conformance remain open.
Earlier checkpoints below are dated evidence. Their then-pending items are superseded by this status and later accepted resolutions; they do not reopen settled architecture choices.
Latest implementation checkpoint, 2026-09-29
The native integration is now installed in the workspace, with no upstream checkout required. Port binding
3fb91fd, RPC/state backport5ebcb5a, renderer/view backport631db2b, and maintained example86b24b3are separate ticket commits on main.examples/webext consumes built public exports from the pinned, patched 1.0 dependency graph. Its real Chromium test passes 12 scenarios with zero page errors. The same test now runs in full SDK CI, which passes. The old temporary prototype is replaced by this maintained example.
The upstream review is split into draft RPC/state #410, JSON view/renderer #411, and independent baseline snapshot repair #412. The renderer declaration shim and implementation file moves are removed.
createPortChannel({ port, onDisconnect })reuses native framing, serializer and close behavior. Native state tests prove per-peer subscriptions, writes and disconnect isolation. All 48 existing server tests pass. Portable WebExtension provider/catalog/router composition remains the next step. Full surfaces, content/page authority, debugger, worker suspension, Firefox browser conformance and HMR remain open; this issue is not complete.Accepted two-layer selection amendment, 2026-09-27
The owner chose typed command/results with native state observation, and implementation-owned applicability. Contract migration and authenticated native proof are on main. The architecture diagram and API examples supersede the earlier universal target contract and A1/A2/B mapping questions.
Client selectors choose realm/provider recipients. Selected action/service implementations inspect schema-defined domain/resource input and return their own declared result, such as
appliedornot-applicable. There is no SDK target envelope, target resolver,acceptshook or new topic/event bus. Anot-applicableresult is fulfilled; it neither makes the provider unavailable nor triggers fallback/replay. If multiple selected implementations match, all may act.Provider incarnation, contribution activation generation, exact versions, native authorization/serialization and dispatch ownership remain unchanged. Browser/debugger capabilities still validate actual resources and permissions.
Part of Design a portable contribution SDK and WebExtension runtime.
Current status, 2026-09-27
@devkit/clientnow executes local multi-provider routing. The accepted missing-recipient rule is implemented: if any broadcast selector has no known provider, reject the entire broadcast before dispatch, with codeunmatched-selection, all unmatched.selectors, and a message explaining how to correct the request. Known unavailable providers instead receive individual rejected outcomes.Commit: 2c6ef9b. This builds on the local catalog, declarative route defaults, provider identity validation and scoped invocation requests.
Implemented and tested:
(realm, provider ID)identity, duplicate rejection, immutable snapshots and owned subscription/cancellation cleanup. Detaching a connection does not dispose its host.selection, no inherited ordinary routing defaults, complete unmatched-selector preflight, deduplication and individual outcomes.[3, 6]; overlapping selectors increment each once to[4, 7]. Client disposal leaves native commands/state alive.Local validation passes: 75 core tests, 32 client tests, 78 runtime tests, 20 native server tests, both individual server examples and their new simultaneous routing check. Strict TypeScript 7, type-aware Oxlint, scoped formatting/builds and tooling checks pass. The packed consumer installs core/runtime/client tarballs, checks Bundler and NodeNext declarations, executes callback/broadcast behavior and builds a portable browser bundle without host/framework modules. Full repository CI passes on this commit.
The owner has accepted the local routing semantics, including rejecting all dispatch when any requested recipient is missing. The maintained routing record, client API, glossary, architecture and API/example/test matrix record the implementation and its limits.
Authorized remote catalog synchronization and native remote routing are now implemented. Still open: verified endpoint discovery, extension actors and capability resource checks, renderer/extension examples, and the optional CDB path. The workspace has the
connection.isolatedbackport from Devframe draft 401; that solves native SDK-owned connection isolation, not these missing adapter contracts. The local client adds no daemon, transport engine or global state store.Upstream integration boundary, 2026-09-27
Keep the implemented client focused on selection and ownership. Server connections use
devframe/client; extension Port integration first uses the channel seam indevframe/rpc/client. Each native connection owns auth, serialization and request correlation. The contribution catalog supplies exact contract/version/lifecycle metadata that native discovery does not supply; do not duplicate the entire native service registry or add a daemon.See the implementation and map review. This narrows implementation mechanisms without dropping the accepted feature or real-host coverage requirements.
Question
How does a contribution discover compatible providers and route each operation when extension, Devframe, Devtools, and optional CDB providers are available together?
Resolve provider identity, discovery, selection precedence, callback selection, broadcast outcomes, and the meaning of unavailable providers. The answer must let one JSON-authored UI operate against several backends without choosing a backend through renderer-specific code.
Context and current behavior
The agreed destination is a generic framework in the devkit-extension pnpm/Turbo monorepo. Build-time npm contributions may provide UI, actions, transforms, realm implementations, or any composition. Devframe and Devtools hosts coexist with Chromium and Firefox extension hosts. Raw APIs remain local, with separately typed realm, execution context, and UI surface.
The local ownership and selection rules above are implemented. Remote endpoint discovery remains outstanding; authenticated native catalog/invocation adapters are implemented. Devtools and extension providers may reach the same page, while another tab exposes a different target, potentially through the same provider installation. Choosing the first connection could direct a mutation to the wrong target.
The accepted routing modes are broadcast, a caller callback, provider-ID or realm precedence, and a UI choice supplied as callback input. Contributions declare defaults; individual operations may override them. Provider state remains separate, and synchronization is optional.
Requirements and scope
Options and recommendation
One global preferred backend is easy to explain but cannot express operations that need different capabilities. Hidden fallback chains make availability convenient while obscuring which provider performed an action. A central router with explicit selectors gives callers enough control without duplicating transport handling.
Recommend the central router. An operation override replaces the contribution default for that invocation. A selector requires a realm and may pin a provider within that realm; both constraints must match. Provider-only selectors and symbol/number coercion are excluded. A missing explicitly selected provider returns an unavailable result unless the caller declared a fallback. Ordered realm preferences choose the first eligible realm, with an explicit ambiguity result when several equally eligible instances remain.
Callbacks receive immutable candidate descriptions and caller input, including any UI selection. They return provider identities, not raw transports. Revalidate the chosen incarnation before dispatch. Do not silently reroute an interrupted mutation. Broadcast takes a candidate snapshot, dispatches once to each selected instance, and returns all settled outcomes.
Ordinary invocations already use dispatch-time readiness without implicit waiting, and fallback is limited to explicit ordered alternatives. The settled core prohibits rerouting or automatic replay after dispatch for every operation, including reads; a separately requested call makes a new selection. Callback staleness now rejects, and broadcast requires a separate selection list. An unmatched broadcast selector rejects the entire broadcast before dispatch; cancellation of a running handler does not imply that its side effects did not happen.
Proposed API or experiment
The implemented compact local calls and core client contracts are:
CapabilityInvocationRequestpreserves each operation name and its schema-defined input as a correlated union.ActionInvocationRequestinfers input and output from the action descriptor. Bound capability methods retaininput, options; a local provider handle has no routing override.The accepted callback contract rejects a selection whose provider incarnation changed while the picker waited. Broadcast uses
broadcast({ action, input, selection: [...] }), where selection is a union of recipients. These are implemented by the local client. Missing recipients reject the whole request before dispatch and are listed in the error.Build a runnable routing example with two real providers and a selector UI rendered from the shared JSON authoring format. Print each provider identity, availability, dispatch decision, and result. Add a CLI or test consumer for the same route callback so the selection logic is demonstrably independent of a renderer. Connect the real optional CDB adapter in its separately enabled example profile.
Scenarios and acceptance criteria
Record every selected public API and hook in the versioned API-to-example-to-test-to-host matrix owned by Examples and API coverage contract.
Dependencies
Contribution and realm contract blocks this decision because it defines contribution identity, host registration, typed local contexts, and capability ownership. Routing must consume those definitions rather than invent a competing realm hierarchy. State scope and recovery consumes the selected provider identities but owns synchronization and persistence semantics.
Definition of Ready
Identify the actual native connection, close and channel APIs; distinguish native close rejection from the remaining cooperative server cancellation guarantee.
Contribution and realm contract supplies the provider registration boundary and availability vocabulary.
Simultaneous native Devframe/DevTools/extension provider examples are maintained.
Record the optional CDB discovery path within that integration, without gating generic routing.
The human compared and accepted precedence, fallback, callback lifetime and missing-recipient behavior through concrete mutation scenarios.
Definition of Done
Local slice delivered:
Complete issue gate:
The resolution specifies identity, discovery ownership, precedence, ambiguity, cancellation, broadcast, and reconnect behavior.
Runnable routing examples and named tests are required for every selected routing API and supported host.
Unsupported and permission-related paths have explicit expected outcomes.
Remaining implementation work is handed off with no unresolved routing policy.
The human has confirmed the resolution through discussion; the agent has not supplied the human side of the decision.
Resolution record
Local routing, authenticated remote catalogs, mixed server/extension routing and a selected-page native handoff are implemented. Automatic monitoring and complete supported-host conformance remain open. Close this decision with a resolution comment recording the selected contract, rejected alternatives, example/test obligations, and any newly exposed decisions. A written proposal does not establish that the router or adapters already work.
Current implementation checkpoint, 2026-09-29
Delivered on linear main in separate commits:
@devkit/devframe; compose the same contracts over server RPC and actual extension Ports.The existing server factories delegate to the shared adapter and retain their API. A Port supplies real native call/collector/events members; no full server context is fabricated. Native RPC/auth/codec/state remain upstream-owned. The registry still owns only portable provider metadata, exact contract availability and selection. No credential store, retry, operation replay, new auth callback or discovery daemon was added.
The application still owns endpoint/domain selection. Explicit configuration and one-shot selected-document handoff are demonstrated. The latter reads the public native descriptor in the selected top-level MAIN world and grants the source page no extension RPC authority. It checks the native envelope only, not a duplicate full metadata schema or endpoint identity. Native server
allowedOriginsand native RPC authentication remain separate. StandardinitHubsupplies no viewer-origin token by default; its explicit native allowlist is used.Validation: 49 server tests, eight channel/provider tests and two shared-adapter tests passed for the extraction. Affected strict TypeScript 7, type-aware Oxlint, Oxfmt and builds pass. The maintained example now passes 24 actual Chromium scenarios with zero page errors, using installed workspace packages and native backend hosts. Commands, API ownership, screenshot and receipt. Full CI at d58a0d4 is green, including the real browser test.
Existing exact-version pnpm patches carry reviewed native isolation/RPC/state/renderer exports while upstream drafts remain open. These slices needed no new upstream patch. The feature drafts remain RPC/state and JSON view/renderer; snapshot repair is independent.
Remaining gates are real Firefox conformance, complete extension surfaces, automatic discovery if an embedding application needs it, privileged page request authority, and JSON-authored cross-provider controls. The last item belongs to Renderer and surface contract: current JSON actions call their owning native backend, while the proven routing controls use HTML. A native handler-hook versus RPC-call-adapter proposal is under owner review. Do not close this issue as full supported-host conformance.