You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The owner accepted B, a native setup recipe. Implementation 52bc770 activates plugin.views through defineView({ id, execution, requires?, setup }). Setup receives the existing typed dependency/native context/scope API and explicitly registers cleanup. Native rendering, state, RPC and authentication remain native; core/runtime gain no native dependency. Returned handles are not adopted.
The updated decision record includes the accepted sketch, ownership diagrams, failure behavior and rejected alternative. The delivery receipt records shared-recipe execution in both server hosts, Vite development/preview and Chromium/Firefox extension providers, plus dependency teardown, fresh-state republication and a real delayed native-state-response regression. Scoped checks pass; full CI passed, including both production browsers, native persistence, concurrent development transitions and the executed API-evidence gate.
Surface/dock placement retains native host ownership; the server dock API has no unregister method. Complete surface/HMR coverage and the broader management contract remain open. Earlier dated checkpoints below describe their historical commit, not current blockers.
Native JSON service management, 2026-10-01
Implementation ed947feb48ce36c02075cc9ff30d092e5d5adbfd moves the extension example's service Enable/Disable controls into a separate native JSON view. The same options, popup, panel and sidebar document mounts the feature and management views over its existing Port. The management view invokes the existing native RPC methods; the background projects its actual provider catalog into ordinary native view state. No public SDK API, custom action handler registry or dependency patch was added.
native JSON Enable / Disable -> existing RPC -> service installation handle
provider catalog -> native management state -> each mounted extension page
The management view remains available when the service is disabled. Maintained Chromium and Firefox production tests disable through rendered controls, observe status on both clients, reject a dependent action, reenable and resume it. The actual native popup receives the same status and reenables the service. Disconnect removes both mounts; a fresh connection mounts one management view with current state.
A retained detached native button can still invoke its callback. The already-closed native RPC rejects the call before backend dispatch. Native JSON onError/onSuccess callbacks handle that ordinary failure and render status; the tests verify no surviving provider mutation and no stale error after reconnect. This evidence does not claim removal of all native DOM handlers or remote cancellation.
Validation: both production builds, strict scoped lint/TypeScript/formatting, three unit checks, Chromium 153.0.8010.12 production (43 scenarios, zero page errors), Firefox 157.0 production (47 scenarios, no global page-error capture), Chromium JSON actions (13 scenarios, zero page errors), and the maintained concurrent development command (15 Chromium and 11 Firefox scenarios) passed. Production and development screenshots and passing receipts are committed with the example.
During development validation, a new Firefox assertion called getText() on a ShadowRoot lookup Promise without awaiting it. A subsequent lookup rejection during browser teardown obscured that TypeError with a Marionette decoding error. Comparing unchanged main and recording the error before teardown isolated the test defect. Awaiting the element fixes it; no application recovery or retry mechanism was introduced.
Example commands and ownership document the limits. Provider/connection forms, permission controls and diagnostic probes still use host markup. Permission controls retain the direct native user gesture. Portable plugin.views lifecycle/declaration, injected rendering, the complete catalog and host/mode matrix, and arbitrary worker suspension remain open. This is native view composition, not a completed portable view contribution API.
Full repository CI passed for the final pushed head, including workspace checks, native production and concurrent development browser suites, and the combined API evidence gate.
Firefox view disposal and reconnection, 2026-10-01
Implementation 0ec4989 extends the maintained Firefox suite with the previously Chromium-only native server-view lifecycle checks. This changes tests and evidence only; the renderer, transport and public SDK contracts are unchanged.
Retain an actual rendered button, remove its native view, and dispatch a click on the detached node. Republication still reads the unchanged backend counter and creates one working mount.
Disconnect the extension page, verify every server view is removed, and click a retained detached server-view button. The surviving backend remains at counter 4.
Refresh and explicitly reconnect to that backend. Its current view mounts once at 4; one rendered action advances it to 5 while the separate extension counter remains 16.
The live Firefox 157.0 / geckodriver 0.37.1 run passed all 43 scenarios. Executed receipt, maintained checks, and reproduction instructions. Scoped strict lint, TS7 and formatting passed; the conformance browser-evidence gate passed. Full CI for this commit passed, including workspace validation and maintained native browser suites. Firefox retains its explicit lack of global page-error capture.
This closes the detached-button and fresh-connection server-view test gap in the earlier checkpoints. It does not claim the separate detached domain-action button scenario, mixed-backend view HMR, injected surfaces, arbitrary worker suspension, or complete renderer/catalog/host coverage. Those acceptance items keep this issue open.
Native retry-error backport, 2026-10-01
Implementation 8c42168 backports the two runtime lines from Devframe PR 416, reviewed at dc7b205c, through the existing exact-version @devframes/json-render-ui@1.0.0 pnpm patch. The native action bridge clears its retained error before retrying that same action. Other actions leave the error intact, and successful completion does not clear a newer failure received while the retry was pending. SDK routing and renderer contracts are unchanged.
The maintained Chromium regression first failed against the previous dependency patch: the counter advanced after retry, but one native alert remained. After installing the backport and rebuilding, the alert disappears. The Firefox suite now performs the same failed-selection/retry sequence and asserts native alert removal. Current Chromium JSON-action evidence records 13 passing scenarios with no page errors; Firefox production evidence records 40 passing scenarios on Firefox 157.0, retaining its explicit global-error-capture limitation. Chromium is 153.0.8010.12.
Scoped validation passed: extension production builds, three extension tests, six renderer integration tests, lint/type/format checks for the affected examples, and the executable conformance gate against fresh browser receipts. Both recovery scenarios are required by that gate. The lockfile changes only the renderer patch hash and its references; the affected dependency graph installs from the frozen lockfile. Full CI for 8c42168 passed, including workspace validation and the maintained Chromium/Firefox browser suites. The interactive native-permission sequence remains a separate, unverified acceptance item in Permissions and trust.
Patch ownership and removal conditions keep this fix local to the pinned dependency until a compatible released renderer passes the same regressions. No upstream PR was opened or modified in this backport. Remaining native host/mode, injected-surface and renderer-catalog obligations keep this issue open. Earlier statements that no downstream renderer backport exists are superseded by this checkpoint.
Reconciled status, 2026-09-30
Native JSON action routing and the choice of its finite call binding are settled in the implementation record. Reference/custom server renderers, Chromium/Firefox extension surfaces and their recorded module/HTML reload cases are implemented. ef43f0f now discovers each connected server's native JSON view index with separate state and owned mounts. Its maintained Chromium command proves existing/late publication, identical keys across backends, actions, removal/republishing, disconnect and fresh connection without replay. No public SDK API or dependency patch was added. 8f99a3e adds the shared native fixture and passing Firefox publication/state/action/removal/disconnect checks. The full Firefox suite passes on CI's 156.0.1 baseline; the independent 157.0 sidebar-test compatibility gap is tracked in Release and conformance contract.
Devframe PR 416 fixes same-action retry error retention. Its CI run passed all 13 renderer tests in the failed Windows/Node 24 job. Nine Git service/plugin tests timed out, followed by temporary-directory EPERM cleanup errors. The unchanged base run passed Windows/Node 24. This does not establish a pre-existing failure or causality. GitHub denied the failed-job rerun because it requires repository admin rights; owner rerun is pending. The cancelled end-to-end job supplies no acceptance result. No speculative Git test patch or downstream renderer backport has been added.
Chromium-only detached-button/fresh-connection view cases, mixed-backend view HMR, injected surfaces, arbitrary worker suspension and the complete host/API matrix remain open. Earlier claims that JSON routing still needs an owner decision are superseded.
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.
Upstream retry-error fix opened as a draft
Devframe draft PR #416, commit dc7b205c, contains two runtime lines in the native action bridge, one JSDoc update and four regression tests. It clears the stored error before retrying the same action. Unrelated actions preserve the existing error, and failures received during a pending retry remain visible.
The retry test fails on unchanged upstream code. All 13 renderer tests, changed-file ESLint, the package type check and its dependency build pass with the fix. The actual rebuilt renderer also passes the standalone Chromium reproduction: two calls, successful application status, no stale alert and no page errors. The upstream diff contains no downstream implementation details or new APIs.
Full upstream CI is running. Scoped local Knip encountered missing dependencies in unrelated example configurations after the filtered install; the same failure was reproduced on unchanged main. The PR stays draft for owner review. This step does not add a downstream dependency patch.
Confirmed upstream action-error bug, 2026-09-30
Investigation commit 8f425be isolates the stale banner to @devframes/json-render-ui's action bridge. It stores the first rejection but never resets that error on retry or success. The renderer displays this private reference separately from JSON onError/onSuccess state. Calling this preserved native behavior was inaccurate; it is an unfixed error-lifecycle bug.
The real extension reproduced failure → successful retry twice: fulfilled result, counter 1, application error cleared, native banner retained.
A minimal inline view with a plain fail-once callback reproduces without the SDK, extension, router, network RPC or shared-state backend.
The verified unmodified npm 1.0.0 renderer also fails, excluding our existing dependency patch. Upstream main at cac6900ca1fc9e223c728b17e868e9f544bd66c2 still contains the same missing reset.
Clearing the matching action's retained error before retry in a temporary served copy makes both installed and unmodified-package reproductions pass, with zero page errors. No production patch or upstream PR was added.
Validation: Chromium 153.0.8010.12, expected failing original and passing diagnostic candidate; affected example strict Oxlint/TypeScript checks and documentation formatting pass. Production work remains a narrow upstream bridge reset with retry/failure/interleaving regression coverage. The SDK's routing and state contracts need no change. Issue #12 stays open.
Firefox JSON dispatch and full CI confirmed
Follow-up commit 1ef4f90 extends the existing Firefox production fixture to click native JSON controls against the actual extension, Devframe and DevTools providers. It verifies devserver/all-realm recipient selection, an explicit provider filter, two applicable servers, domain applicability that excludes the extension, unknown-domain no-ops and partial failure after server disconnect. Executed Firefox receipt.
The initial implementation CI passed builds, types, lint, formatting, tests and production browser acceptance, then failed in development because native-surface tests still expected one JSON button. The example now declares two. The follow-up checks the exact two labels across panel, popup, DevTools and sidebar HMR/reload, preserving duplicate-mount detection. Both concurrent development suites passed locally. No runtime workaround, skipped check or dependency patch was added.
Full CI passes on this exact commit, including every workspace gate, the dedicated native JSON action matrix, Chromium/Firefox production surfaces, renderer replacement, native Vite timing, optional debugger integration and both concurrent native development suites. Strict local lint/type checks and Firefox production acceptance also pass. Both commits are on linear main, with a clean working tree and no extra worktree.
Provider view discovery/composition, full catalog coverage and mixed-backend JSON HMR remain open. The retained detached domain-button and failed-selection/retry scenarios are Chromium-specific; Firefox covers the cross-provider JSON dispatch behavior. The reference renderer's retained last-error banner is now a confirmed, unfixed upstream bug; see the diagnosis above. There is no owner decision blocking the delivered binding.
Native JSON action routing delivered
Commit a99cb87 connects the unchanged native JSON renderer to the existing portable client. The old background-only probe:increase method is removed. A shared domain-bearing action now executes through Devframe, DevTools and WebExtension implementations. CDB is not involved.
native JSON action ID + input expressions
-> createActionCall: imported action contract + local dispatch policy
-> existing client: outgoing realm/provider selection
-> each selected provider: domain applicability inside its action
-> local counter capability
-> per-provider outcomes displayed by the client
// Implemented API; no new renderer contract or per-button handler.constcall=createActionCall({rpc: nativeRpc,actions: client.actions,bindings: [{action: increaseMatchingCounterAction,selection: [{realm: 'devserver'},{realm: 'webext'}],}],signal: viewLifetime.signal,});// Ordinary native JSON Button event:conston={press: {action: increaseMatchingCounterAction.id,params: {domain: {$state: '/domain'},amount: 1},}};// The shared contribution implementation checks its provider's own domain list:if(!domains.has(input.domain))return{status: 'not-applicable'};constvalue=awaitservices.counter.api.increase({amount: input.amount},{ signal });return{status: 'applied', value };
The binding contains no domain policy, auth, state store, serializer or renderer implementation. Native calls outside the explicit binding map keep their arguments and target. The application preserves shared state and metadata. Native built-ins execute normally. Existing contract/version validation, broadcast partial failures and cancellation remain in their current owners. Duplicate binding IDs and simultaneous selection/routing reject at setup. Direct typed callers retain client.actions.
Slice acceptance evidence
Native rendered JSON controls dispatch shared actions, including two applicable server providers.
Outgoing realm and explicit provider filters determine recipients.
Provider-local domain lists return ordinary fulfilled not-applicable results without side effects.
Unavailable/disconnected providers preserve successful siblings; no replay or fallback after dispatch.
Validation: affected dependency graph build; strict TypeScript 7, type-aware Oxlint and Oxfmt for the four changed packages/examples; 6 Devframe-package tests, 5 contribution tests, 6 server-example tests and 3 extension tests; server native RPC/routing/browser-build checks; real Chromium 153.0.8010.12 and Firefox 156.0.1 production suites. The new matrix records zero Chromium page errors and native counters Devframe=3, DevTools=4, extension=3. CI now runs the dedicated test:json-actions command. Initial implementation CI exposed the obsolete one-button development assertion; the follow-up above fixes it and full CI passes.
Remaining scope is explicit: Firefox cross-provider JSON coverage is supplied by the follow-up above; provider view discovery/composition, complete renderer catalog coverage and mixed-backend JSON HMR are not supplied by this slice. Independent backend stores are not merged. Native renderer last-error banners persist after a successful retry; the example's own status clears through native callbacks. The upstream action bridge has a confirmed missing error reset; it remains unfixed, as detailed above. Issue #12 and the broader map remain open, but the previous routing/renderer choice is no longer pending.
Custom renderer replacement, 2026-09-29
Commit d410852 adds an example-local, framework-free DOM renderer for the existing native JSON counter. The same contribution, view, native state reference and backend RPC action remain unchanged. Local DockRenderersContext.register selects the renderer; its unregister function restores the published reference renderer. No SDK renderer API, alternate schema, new dependency patch or upstream PR was added.
same counter contribution -> same native JSON view + shared state
-> reference renderer served by native host
-> custom DOM renderer registered by this page
both -> native RPC + schema validation -> same counter
// Existing native API used by the example.constunregister=runtime.context.renderers.register('json-render',domRenderer);constmounted=awaitruntime.context.renderers.mount(entry,container);if(mounted.status==='mounted')mounted.dispose();unregister();// Later mounts can use the unchanged host renderer manifest.
The DOM catalog renders this example's Card, Stack, Text and Button usage. Public @json-render/core helpers resolve expressions and action parameters. Devframe owns state, RPC and validation. Each mount owns its DOM/listeners and native state subscription. Switching exposed an actual interoperability bug in the initial implementation: light DOM is hidden after the reference renderer leaves an attached shadow root. The final mount reuses that root. No native patch was needed.
Actual Chromium check, on both Devframe and DevTools
Result
Reference/custom views
Same unchanged JSON view; shared counter starts at zero
Action and state
Custom action updates both rendered pages
Native invalid input
Custom alert displays native rejection, value unchanged, next action clears alert
Validation: six package tests, strict TypeScript 7, type-aware Oxlint, formatting, affected build and real Chromium 153.0.8010.12 acceptance pass locally. The browser artifact check excludes Node/provider implementations and Vue/React. Each backend records seven browser scenario groups and zero page errors. The deliberately rejected action is tested on the custom renderer; this does not change or conceal the reference renderer's previously recorded rejection behavior. Full CI passed for this exact commit, including the new browser command, every workspace gate, maintained Chromium/Firefox suites and native development transitions.
This satisfies the bounded custom-renderer example obligation, not complete renderer conformance. Local built-ins, input bindings, repeated/watched/conditional elements, action lists/confirmation/callbacks, a full catalog, Firefox custom rendering and renderer-module HMR are outside this example. Existing typed native contracts remain the source of truth. The mixed-provider JSON action binding is implemented in the later checkpoint above; its owner choice is no longer pending. Issues 12, 14 and the overall map remain open.
Native browser sidebars delivered, 2026-09-29
#12 commit e29bf39 adds Chromium's global side panel and Firefox's sidebar to the maintained example. Both mount the existing panel.html, native JSON renderer and Port-backed provider. Product changes are browser-specific manifest entries and popup-only minimum sizing; no new SDK API, transport or dependency patch is needed.
flowchart LR
Native[Browser sidebar control] --> Page[Existing panel.html / own document and Port]
Page --> Background[Existing background provider / native state]
Options[Options / independent Port] --> Background
Tabs[Tab switch or navigation] --> Retained[Same sidebar document and caller]
Close[Close and reopen sidebar] --> Fresh[Fresh document and caller]
Fresh --> Background
Loading
// Browser-specific manifest fields, using the same page.constchromium={permissions: ['scripting','sidePanel'],side_panel: {default_path: 'panel.html'},};constfirefox={sidebar_action: {default_panel: 'panel.html',default_title: 'Devkit',open_at_install: false,},};
Native interaction
Verified result
Open actual sidebar and click JSON button with pointer input
Renderer fits the narrow viewport; action updates options state once
Switch tabs or navigate a companion tab
Same sidebar document, caller and subscribed state
Close with work already dispatched
Native document disappears; surviving options completes that action once
Reopen
Fresh caller, retained provider/state, no replay, working JSON action
Chromium open without active user gesture
Native API rejects with its user-gesture error
Chromium repeated open and local form
No duplicate context; form survives tab navigation and resets on reopening
Chromium observes the real SIDE_PANEL context through the public CDP helper already used for DevTools. Firefox uses its native sidebar picker and public extension.getViews({ type: 'sidebar' }); no additional private actor or application test hook is added. The actual Firefox DevTools context omits getViews, so popup sizing checks that optional native method before calling it.
Scoped strict lint, TypeScript 7, formatting, production builds, bundle assertions and both complete production browser suites pass locally. Full CI passed, including every workspace gate and both browsers' production and native development suites.
Firefox 156.0.1's full browser-window screenshot omits an unhovered semi-transparent button while a document screenshot paints the same unchanged state correctly. The sidebar image records its normal hover state after the tested pointer activation. No opacity workaround is shipped; this capture limitation is documented in the example.
This covers the default sidebar in one normal window. Tab-specific configuration, multiple/private windows, worker suspension, injected surfaces, sidebar-specific HMR and the complete conformance matrix remain open. The JSON-routing owner choice remains pending; neither proposed seam is accepted by this checkpoint. Keep #12 open.
Native DevTools panel delivered, 2026-09-29
#12 commit ac8ece6 adds the actual DevTools host in Chromium and Firefox. The application calls chrome.devtools.panels.create('Devkit', '', 'panel.html') from its native devtools_page. The panel reuses the existing packaged page, JSON renderer, admitted Port and background provider. No new SDK abstraction, permission, transport or dependency patch is added.
flowchart LR
Native[Browser DevTools] --> Entry[devtools.html / native panels.create]
Entry --> Panel[Existing panel.html / JSON renderer / own Port]
Panel --> Provider[Existing background provider / native shared state]
Options[Options / independent Port] --> Provider
Hide[Hide then show] --> Same[Same panel document and caller]
Close[Close then reopen DevTools] --> Fresh[New panel document and caller]
Fresh --> Provider
Loading
Actual interaction
Verified result in both browsers
Select native Devkit tab
Existing JSON renderer mounts and shares the options provider
Click JSON action
Counter increases once and options observes it
Hide panel, update from options, show panel
Same document and caller, current subscribed state
Close DevTools with pending action
Native panel disappears; surviving options releases the dispatched action once
Reopen DevTools
New caller, same live provider and state, no replay; JSON action works
Chromium tests observe the real frontend through public CDP target APIs and verify the selected native tab. Firefox's public frame APIs omit the remote XUL browser, so one test helper uses the pinned browser's private Marionette actor. This test maintenance dependency is documented and ships no application hooks. Chromium records zero collected page errors; Firefox makes no global error-capture claim.
Scoped strict lint, TypeScript 7, formatting, both builds, bundle checks and both full production browser suites passed locally. Full CI passed on dc385f6, including every workspace gate, both production browser suites and both native development suites.
52d1eab corrects the Chromium test after Linux CI exposed that Network can be absent from the visible tab strip. The driver uses native next-panel navigation for hiding too and asserts that Devkit itself loses selection. Application code is unchanged. dc385f6 moves screenshot-directory creation into setup for both drivers. Both production suites were rerun successfully with their prior output directory moved aside, proving clean-run behavior.
The JSON action-routing choice still needs owner input. Published native 1.1.0 was checked and does not provide the proposed local-handler API; it also lacks the pending renderer/view exports. No new upstream PR or unapproved native contract was added. Side-panel/injected hosts, inspected-page discovery, debugger authority, DevTools-specific development transitions and custom-renderer coverage remain open. This issue and the parent map remain open.
Native popup and options lifecycle delivered, 2026-09-29
549bbc7 verifies the actual native popup and options hosts in Chromium and Firefox. Both load the same packaged page and native JSON renderer with independent Port connections to the existing background provider. The only application change is shared responsive CSS; there is no new SDK runtime, renderer facade or dependency patch.
flowchart LR
Options[Options page / local form and connection] --> Provider[Background provider / native shared state]
Popup[Native toolbar popup / local form and connection] --> Provider
Popup --> Close[Native close removes document and connection]
Reopen[Reopened popup / new connection] --> Provider
Loading
Real interaction
Verified outcome in both browsers
runtime.openOptionsPage()
Opens the configured page; repeated opening reuses an existing page
action.openPopup()
Native popup registry has one actual view; usable width and no horizontal overflow
JSON-rendered popup action
Shared counter increases exactly once and options observes it
Service disable/enable
Both catalogs update; routed popup action rejects while unavailable
Close with pending action
Popup disappears; options releases the already dispatched action once
Reopen
New caller, cleared local form/result, same provider and retained counter; no replay
The shared browser scenario inspects the actual popup through native extension.getViews. It does not substitute a full tab for the popup or add application test hooks. Firefox invalidates closed-window references, so closure is observed via the native view registry.
Full CI passed, including all workspace gates, both production browser suites and both native development suites.
The JSON action-routing choice remains pending in the detailed sketch. Popup-specific development transitions, DevTools/sidebar/injected hosts, custom renderer coverage and background suspension remain open. This is a partial delivery of this issue's Definition of Done; neither this issue nor the parent map is complete.
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 native JSON view export shares ownership with the existing node entry, verified by duplicate detection, index and replacement tests. The reference renderer uses its existing bundle and cleans up failed mounts. All six server-renderer tests pass. Full multi-provider view composition, popup/DevTools/side-panel lifecycle, custom renderer coverage and extension HMR remain open; this issue is not complete.
It composes createJsonRenderView, toJsonRenderDockEntry, the asset returned by jsonRenderUiRenderer(), and a real createDevframeClientRuntime. The JSON authoring imports no frontend framework. The native renderer sends a params object to one example-owned native RPC method, which uses the shared counter action's schemas and invokes the existing provider. No SDK rendering facade, context cast, copied renderer or new auth/state/serialization system was added.
Five automated tests verify native manifest/dock publication, byte-for-byte serving of the published asset, real-socket authorized/denied/invalid calls, subscribed view updates, projection cleanup, and the browser bundle boundary. Affected builds, TypeScript 7, strict type-aware Oxlint and Oxfmt pass. The existing server example's integration/routing/remote/browser checks and six state tests also pass.
Live in-app tests on both hosts confirmed initial render, native error banners, unmount at 1, peer increment to 2, remount at 2, both views updating to 3, and view removal/disabled mounting after actual host shutdown. A browser-source edit used Vite's native page reload and retained backend state. Temporary tabs and demo servers were closed.
The reference renderer retains the last error banner and emits a console unhandled rejection on deliberately invalid input; subsequent valid actions still work. Those upstream behaviors are recorded without suppression. Native dock/RPC registrations are host-lived; this example claims browser unmount, not backend dock unregister support.
This proves the single-provider native rendering path. Cross-provider UI routing, custom renderer, extension Ports/surfaces, renderer-module replacement and automated real-browser conformance remain open. The installed full browser runtime still has no Port transport type; this working WebSocket example does not disguise that gap.
Reuse @devframes/json-render and /hub model/refs, the published renderer asset, and the native dock mount/dispose contract. Management views should first use the same native JSON catalog. The current DevframeClientContext transport type does not model an extension Port; resolve the smallest supported host typing seam before a surface abstraction. Do not cast a fabricated native context, copy the renderer, or design a second UI protocol.
See the implementation and map review. This narrows implementation mechanisms without dropping the accepted feature or real-host coverage requirements.
Question
How should the shared JSON-render UI mount across server panels and every extension UI surface, expose provider selection and native controls, and preserve the correct state through routing changes and lifecycle events?
Context and current behavior
The authoring API must be framework-neutral; renderer implementations may use any framework. Reusing the existing JSON renderer is preferred. The monorepo supports UI-bearing and UI-free contributions shared across devframe, Vite DevTools, Chromium and Firefox providers.
At inspected devframe commit a3f967755af99a0a0d8dd82b7b5d4f3dd4aec0bc, JSON-render protocol uses serializable inline specs or state-key references. The hub renderer contract mounts into a supplied element, receives a hub browser context, and returns disposal. The reference renderer uses Vue internally, subscribes to shared state and dispatches actions through RPC.
These are inspected branch contracts. Upstream reuse audit establishes released-package availability. The existing renderer does not by itself define popup lifecycle, extension options, side panels, native DevTools placement, provider selection or extension management controls.
Requirements and scope
Define mounting for the devframe/DevTools panel and extension popup, options, DevTools panel, browser side panel/sidebar where supported, and injected page panel. Background and content-script execution contexts must not be conflated with rendered surfaces.
Express feature UI and extension controls through the shared JSON model. Cover contribution management, provider selection, permissions, capability status, connection/reload state and debugger/native-operation controls where supported.
Honor routing defaults and explicit overrides, including broadcast, callback selection, provider ID or realm selection and UI selection according to the resolved routing precedence. Display per-provider outcomes and preserve separate provider state.
Specify renderer registration, catalog extension, styles, mounting errors and disposal. Reuse the existing reference renderer when compatible, while keeping replacement possible.
Define which selection, form and navigation state belongs to a surface versus provider-owned shared state. Restoration must use the state decision and the reload lifecycle rather than copy ad hoc snapshots.
Provide runnable renderer and surface examples. Every public rendering API, hook, component contract and user-visible feature must have real-host success or unsupported behavior, failure and lifecycle coverage.
Options and recommendation
Independent frontend applications for each surface allow custom layouts but duplicate feature logic and make provider behavior diverge. One rigid page cloned into every surface shares code but handles popup size, side-panel lifetime and injected styling poorly.
The recommended direction is one JSON feature contract with a reusable renderer and thin surface hosts supplying mount target, supported controls, selected providers and lifecycle context. Surface layout may differ while feature behavior remains shared. Use the native JSON catalog for management controls unless a concrete unsupported component requires an extension; specify custom-renderer compatibility with that same model before introducing another catalog.
Proposed API or experiment
Begin with the native dock renderer registry in an actual host context; entry is the native JSON dock entry and the owning surface supplies container:
constresult=awaitcontext.renderers.mount(entry,container);if(result.status==='mounted'){// Retain this callback in the surface's actual teardown lifecycle.constdispose=result.dispose;}
Settle what the host passes to the renderer, how routed actions obtain provider identity, how capability changes update controls, and which objects remain local. Show the equivalent mounting in a server dock and injected shadow root without leaking Vue or any other renderer framework into contribution authoring.
Use a shared inspection example with a provider label, editable state, one action and an intentionally unsupported operation. Launch it in each surface against server and extension providers. Add a management view to exercise native controls. A separate runnable custom-renderer example must demonstrate catalog compatibility and disposal. Produce an inventory that maps public rendering methods and hooks to the exact interaction proving them.
Scenarios and acceptance criteria
Opening the same feature in two surfaces shows the appropriate provider state, with surface-local form/navigation behavior matching the resolved state contract.
Switching provider, overriding a default and broadcasting an action follow the same routing rules. Mixed success, unavailable and permission-denied results identify each provider clearly.
Closing and reopening a popup, navigating the inspected page, suspending the worker and rebuilding a renderer have defined disposal and restoration outcomes. No stale subscription can update a replacement view.
A Firefox surface without a Chromium-only native capability displays its specified unavailable outcome. Supported side-panel/sidebar behavior is exercised in the actual browser integration.
A missing renderer, unknown catalog component, rejected action or disconnected provider has an observable recovery path. Injected views retain styles and usable focus within the chosen isolation boundary.
Every exported renderer/surface hook and feature maps to runnable examples and real-host assertions. Browser mocks and compile-only examples are supplemental evidence, never the final proof of surface support.
Dependencies
Blocked by Provider discovery and routing and State scope and recovery through native issue-tracker dependencies. Routing determines selection and outcome semantics; state recovery determines ownership and restoration. Upstream and capability findings are referenced as evidence, not duplicated decisions. Parent-map membership organizes the ticket and does not replace these blocking edges.
Definition of Ready
Demonstrate the native renderer dependency/type gap with public package imports before proposing any new host interface. See the native extension integration checkpoint below.
Both blocking decisions are resolved with explicit selection precedence, per-provider outcomes and state restoration rules.
Supported browser surfaces and native capability differences are available from the browser audit.
A reusable renderer version or inspected source baseline and a concrete shared feature are identified.
Definition of Done
The same native JSON spec works in native and extension surfaces through a supported context seam; a replacement renderer follows that same contract and owned disposal.
A user-reviewed resolution fixes renderer and surface-host interfaces, management controls, catalog extension rules, styles, error handling and disposal.
Each required surface has an explicit support decision and behavioral contract; absence is recorded as an unsupported outcome with proof obligations.
Runnable examples cover renderer replacement, both server hosts, both extension hosts and every supported surface. An exhaustive export/hook/feature matrix specifies actual host interactions, failure cases and lifecycle assertions.
Routing and restoration responsibilities match their authoritative decisions. Remaining uncertainty becomes a named decision ticket.
Close the issue after recording the contract and update the map with its named pointer. This decision does not substitute for implementing and running the eventual verification suite.
The human has confirmed the resolution through discussion; the agent has not supplied the human side of the decision.
Resolution record
Post the chosen mounting and catalog contracts, surface support table, provider-control behavior, restoration rules, compatibility examples, required verification matrix and rejected alternatives in the resolution comment.
Current implementation and owner review, 2026-09-29
The native Port renderer/state exports are backported in the working pinned dependencies from the split upstream drafts RPC/state and JSON view/renderer. The maintained extension example imports installed public exports, runs actual native JSON rendering/state over Ports, and now connects to native Devframe and DevTools backends alongside its worker. Its 24 real Chromium scenarios pass with zero page errors. Full CI is green.
The next concrete gap is JSON-authored cross-provider actions. The JSON counter button currently calls its worker through context.rpc.call. The existing page-owned router provides selection/broadcast/fallback from separate HTML controls. Native per-provider view mounting is already available and does not by itself express a cross-provider command.
The committed owner-review sketch includes current/proposed diagrams, example calls, ownership, failure cases and maintenance costs. Two options are under review:
A, recommended: an optional finite handlers map on the native JSON renderer mount. Listed local actions call the existing router; unlisted actions retain native RPC. Reuse native loading/errors/built-ins/state. The host grants handlers to a specific mount, initially only an application-owned packaged view. This needs a narrow native API addition and a patch until released.
B: adapt the supplied rpc.call for reserved local UI names and forward all other names/arguments to native RPC. No upstream change, but local UI commands share the RPC namespace and the adapter must preserve native call typing.
// Proposal A only; not an implemented API.awaitrenderer({entry: applicationOwnedView,
container,context: nativeContext,handlers: {'example:increase-devservers': ()=>client.actions.broadcast({action: increaseCounterAction,input: {amount: 1},selection: [{realm: 'devserver'}],}),},});
The owner has been asked to choose the seam; neither option is treated as accepted. No new upstream PR has been opened. Any eventual hook should be small, native, independently useful, and reviewed before draft publication. Per-provider results must be projected through ordinary native view state; this does not merge provider stores or add a new state engine.
This checkpoint does not complete full popup/DevTools/side-panel lifecycle, renderer replacement, Firefox, privileged page bridges or extension HMR. Those remain explicit proof obligations.
Portable view setup recipe implemented, 2026-10-02
The owner accepted B, a native setup recipe. Implementation 52bc770 activates
plugin.viewsthroughdefineView({ id, execution, requires?, setup }). Setup receives the existing typed dependency/native context/scope API and explicitly registers cleanup. Native rendering, state, RPC and authentication remain native; core/runtime gain no native dependency. Returned handles are not adopted.The updated decision record includes the accepted sketch, ownership diagrams, failure behavior and rejected alternative. The delivery receipt records shared-recipe execution in both server hosts, Vite development/preview and Chromium/Firefox extension providers, plus dependency teardown, fresh-state republication and a real delayed native-state-response regression. Scoped checks pass; full CI passed, including both production browsers, native persistence, concurrent development transitions and the executed API-evidence gate.
Surface/dock placement retains native host ownership; the server dock API has no unregister method. Complete surface/HMR coverage and the broader management contract remain open. Earlier dated checkpoints below describe their historical commit, not current blockers.
Native JSON service management, 2026-10-01
Implementation ed947feb48ce36c02075cc9ff30d092e5d5adbfd moves the extension example's service Enable/Disable controls into a separate native JSON view. The same options, popup, panel and sidebar document mounts the feature and management views over its existing Port. The management view invokes the existing native RPC methods; the background projects its actual provider catalog into ordinary native view state. No public SDK API, custom action handler registry or dependency patch was added.
The management view remains available when the service is disabled. Maintained Chromium and Firefox production tests disable through rendered controls, observe status on both clients, reject a dependent action, reenable and resume it. The actual native popup receives the same status and reenables the service. Disconnect removes both mounts; a fresh connection mounts one management view with current state.
A retained detached native button can still invoke its callback. The already-closed native RPC rejects the call before backend dispatch. Native JSON onError/onSuccess callbacks handle that ordinary failure and render status; the tests verify no surviving provider mutation and no stale error after reconnect. This evidence does not claim removal of all native DOM handlers or remote cancellation.
Validation: both production builds, strict scoped lint/TypeScript/formatting, three unit checks, Chromium 153.0.8010.12 production (43 scenarios, zero page errors), Firefox 157.0 production (47 scenarios, no global page-error capture), Chromium JSON actions (13 scenarios, zero page errors), and the maintained concurrent development command (15 Chromium and 11 Firefox scenarios) passed. Production and development screenshots and passing receipts are committed with the example.
During development validation, a new Firefox assertion called getText() on a ShadowRoot lookup Promise without awaiting it. A subsequent lookup rejection during browser teardown obscured that TypeError with a Marionette decoding error. Comparing unchanged main and recording the error before teardown isolated the test defect. Awaiting the element fixes it; no application recovery or retry mechanism was introduced.
Example commands and ownership document the limits. Provider/connection forms, permission controls and diagnostic probes still use host markup. Permission controls retain the direct native user gesture. Portable plugin.views lifecycle/declaration, injected rendering, the complete catalog and host/mode matrix, and arbitrary worker suspension remain open. This is native view composition, not a completed portable view contribution API.
Full repository CI passed for the final pushed head, including workspace checks, native production and concurrent development browser suites, and the combined API evidence gate.
Firefox view disposal and reconnection, 2026-10-01
Implementation 0ec4989 extends the maintained Firefox suite with the previously Chromium-only native server-view lifecycle checks. This changes tests and evidence only; the renderer, transport and public SDK contracts are unchanged.
The live Firefox 157.0 / geckodriver 0.37.1 run passed all 43 scenarios. Executed receipt, maintained checks, and reproduction instructions. Scoped strict lint, TS7 and formatting passed; the conformance browser-evidence gate passed. Full CI for this commit passed, including workspace validation and maintained native browser suites. Firefox retains its explicit lack of global page-error capture.
This closes the detached-button and fresh-connection server-view test gap in the earlier checkpoints. It does not claim the separate detached domain-action button scenario, mixed-backend view HMR, injected surfaces, arbitrary worker suspension, or complete renderer/catalog/host coverage. Those acceptance items keep this issue open.
Native retry-error backport, 2026-10-01
Implementation 8c42168 backports the two runtime lines from Devframe PR 416, reviewed at
dc7b205c, through the existing exact-version@devframes/json-render-ui@1.0.0pnpm patch. The native action bridge clears its retained error before retrying that same action. Other actions leave the error intact, and successful completion does not clear a newer failure received while the retry was pending. SDK routing and renderer contracts are unchanged.The maintained Chromium regression first failed against the previous dependency patch: the counter advanced after retry, but one native alert remained. After installing the backport and rebuilding, the alert disappears. The Firefox suite now performs the same failed-selection/retry sequence and asserts native alert removal. Current Chromium JSON-action evidence records 13 passing scenarios with no page errors; Firefox production evidence records 40 passing scenarios on Firefox 157.0, retaining its explicit global-error-capture limitation. Chromium is 153.0.8010.12.
Scoped validation passed: extension production builds, three extension tests, six renderer integration tests, lint/type/format checks for the affected examples, and the executable conformance gate against fresh browser receipts. Both recovery scenarios are required by that gate. The lockfile changes only the renderer patch hash and its references; the affected dependency graph installs from the frozen lockfile. Full CI for 8c42168 passed, including workspace validation and the maintained Chromium/Firefox browser suites. The interactive native-permission sequence remains a separate, unverified acceptance item in Permissions and trust.
Patch ownership and removal conditions keep this fix local to the pinned dependency until a compatible released renderer passes the same regressions. No upstream PR was opened or modified in this backport. Remaining native host/mode, injected-surface and renderer-catalog obligations keep this issue open. Earlier statements that no downstream renderer backport exists are superseded by this checkpoint.
Reconciled status, 2026-09-30
Native JSON action routing and the choice of its finite call binding are settled in the implementation record. Reference/custom server renderers, Chromium/Firefox extension surfaces and their recorded module/HTML reload cases are implemented. ef43f0f now discovers each connected server's native JSON view index with separate state and owned mounts. Its maintained Chromium command proves existing/late publication, identical keys across backends, actions, removal/republishing, disconnect and fresh connection without replay. No public SDK API or dependency patch was added. 8f99a3e adds the shared native fixture and passing Firefox publication/state/action/removal/disconnect checks. The full Firefox suite passes on CI's 156.0.1 baseline; the independent 157.0 sidebar-test compatibility gap is tracked in Release and conformance contract.
Devframe PR 416 fixes same-action retry error retention. Its CI run passed all 13 renderer tests in the failed Windows/Node 24 job. Nine Git service/plugin tests timed out, followed by temporary-directory EPERM cleanup errors. The unchanged base run passed Windows/Node 24. This does not establish a pre-existing failure or causality. GitHub denied the failed-job rerun because it requires repository admin rights; owner rerun is pending. The cancelled end-to-end job supplies no acceptance result. No speculative Git test patch or downstream renderer backport has been added.
Chromium-only detached-button/fresh-connection view cases, mixed-backend view HMR, injected surfaces, arbitrary worker suspension and the complete host/API matrix remain open. Earlier claims that JSON routing still needs an owner decision are superseded.
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.
Upstream retry-error fix opened as a draft
Devframe draft PR #416, commit
dc7b205c, contains two runtime lines in the native action bridge, one JSDoc update and four regression tests. It clears the stored error before retrying the same action. Unrelated actions preserve the existing error, and failures received during a pending retry remain visible.The retry test fails on unchanged upstream code. All 13 renderer tests, changed-file ESLint, the package type check and its dependency build pass with the fix. The actual rebuilt renderer also passes the standalone Chromium reproduction: two calls, successful application status, no stale alert and no page errors. The upstream diff contains no downstream implementation details or new APIs.
Full upstream CI is running. Scoped local Knip encountered missing dependencies in unrelated example configurations after the filtered install; the same failure was reproduced on unchanged main. The PR stays draft for owner review. This step does not add a downstream dependency patch.
Confirmed upstream action-error bug, 2026-09-30
Investigation commit 8f425be isolates the stale banner to
@devframes/json-render-ui's action bridge. It stores the first rejection but never resets that error on retry or success. The renderer displays this private reference separately from JSONonError/onSuccessstate. Calling this preserved native behavior was inaccurate; it is an unfixed error-lifecycle bug.cac6900ca1fc9e223c728b17e868e9f544bd66c2still contains the same missing reset.Full source diagnosis and commands · Minimal executable reproduction
Validation: Chromium 153.0.8010.12, expected failing original and passing diagnostic candidate; affected example strict Oxlint/TypeScript checks and documentation formatting pass. Production work remains a narrow upstream bridge reset with retry/failure/interleaving regression coverage. The SDK's routing and state contracts need no change. Issue #12 stays open.
Firefox JSON dispatch and full CI confirmed
Follow-up commit 1ef4f90 extends the existing Firefox production fixture to click native JSON controls against the actual extension, Devframe and DevTools providers. It verifies devserver/all-realm recipient selection, an explicit provider filter, two applicable servers, domain applicability that excludes the extension, unknown-domain no-ops and partial failure after server disconnect. Executed Firefox receipt.
The initial implementation CI passed builds, types, lint, formatting, tests and production browser acceptance, then failed in development because native-surface tests still expected one JSON button. The example now declares two. The follow-up checks the exact two labels across panel, popup, DevTools and sidebar HMR/reload, preserving duplicate-mount detection. Both concurrent development suites passed locally. No runtime workaround, skipped check or dependency patch was added.
Full CI passes on this exact commit, including every workspace gate, the dedicated native JSON action matrix, Chromium/Firefox production surfaces, renderer replacement, native Vite timing, optional debugger integration and both concurrent native development suites. Strict local lint/type checks and Firefox production acceptance also pass. Both commits are on linear
main, with a clean working tree and no extra worktree.Provider view discovery/composition, full catalog coverage and mixed-backend JSON HMR remain open. The retained detached domain-button and failed-selection/retry scenarios are Chromium-specific; Firefox covers the cross-provider JSON dispatch behavior. The reference renderer's retained last-error banner is now a confirmed, unfixed upstream bug; see the diagnosis above. There is no owner decision blocking the delivered binding.
Native JSON action routing delivered
Commit a99cb87 connects the unchanged native JSON renderer to the existing portable client. The old background-only
probe:increasemethod is removed. A shared domain-bearing action now executes through Devframe, DevTools and WebExtension implementations. CDB is not involved.The binding contains no domain policy, auth, state store, serializer or renderer implementation. Native calls outside the explicit binding map keep their arguments and target. The application preserves shared state and metadata. Native built-ins execute normally. Existing contract/version validation, broadcast partial failures and cancellation remain in their current owners. Duplicate binding IDs and simultaneous selection/routing reject at setup. Direct typed callers retain
client.actions.Slice acceptance evidence
not-applicableresults without side effects.SDK implementation · Shared contribution · Live acceptance · Receipt · Screenshot · API and usage.
Validation: affected dependency graph build; strict TypeScript 7, type-aware Oxlint and Oxfmt for the four changed packages/examples; 6 Devframe-package tests, 5 contribution tests, 6 server-example tests and 3 extension tests; server native RPC/routing/browser-build checks; real Chromium 153.0.8010.12 and Firefox 156.0.1 production suites. The new matrix records zero Chromium page errors and native counters Devframe=3, DevTools=4, extension=3. CI now runs the dedicated
test:json-actionscommand. Initial implementation CI exposed the obsolete one-button development assertion; the follow-up above fixes it and full CI passes.Remaining scope is explicit: Firefox cross-provider JSON coverage is supplied by the follow-up above; provider view discovery/composition, complete renderer catalog coverage and mixed-backend JSON HMR are not supplied by this slice. Independent backend stores are not merged. Native renderer last-error banners persist after a successful retry; the example's own status clears through native callbacks. The upstream action bridge has a confirmed missing error reset; it remains unfixed, as detailed above. Issue #12 and the broader map remain open, but the previous routing/renderer choice is no longer pending.
Custom renderer replacement, 2026-09-29
Commit d410852 adds an example-local, framework-free DOM renderer for the existing native JSON counter. The same contribution, view, native state reference and backend RPC action remain unchanged. Local
DockRenderersContext.registerselects the renderer; its unregister function restores the published reference renderer. No SDK renderer API, alternate schema, new dependency patch or upstream PR was added.The DOM catalog renders this example's Card, Stack, Text and Button usage. Public
@json-render/corehelpers resolve expressions and action parameters. Devframe owns state, RPC and validation. Each mount owns its DOM/listeners and native state subscription. Switching exposed an actual interoperability bug in the initial implementation: light DOM is hidden after the reference renderer leaves an attached shadow root. The final mount reuses that root. No native patch was needed.Native mount · Maintained browser test · Receipt · Run instructions and precise subset.
Validation: six package tests, strict TypeScript 7, type-aware Oxlint, formatting, affected build and real Chromium 153.0.8010.12 acceptance pass locally. The browser artifact check excludes Node/provider implementations and Vue/React. Each backend records seven browser scenario groups and zero page errors. The deliberately rejected action is tested on the custom renderer; this does not change or conceal the reference renderer's previously recorded rejection behavior. Full CI passed for this exact commit, including the new browser command, every workspace gate, maintained Chromium/Firefox suites and native development transitions.
This satisfies the bounded custom-renderer example obligation, not complete renderer conformance. Local built-ins, input bindings, repeated/watched/conditional elements, action lists/confirmation/callbacks, a full catalog, Firefox custom rendering and renderer-module HMR are outside this example. Existing typed native contracts remain the source of truth. The mixed-provider JSON action binding is implemented in the later checkpoint above; its owner choice is no longer pending. Issues 12, 14 and the overall map remain open.
Native browser sidebars delivered, 2026-09-29
#12 commit e29bf39 adds Chromium's global side panel and Firefox's sidebar to the maintained example. Both mount the existing
panel.html, native JSON renderer and Port-backed provider. Product changes are browser-specific manifest entries and popup-only minimum sizing; no new SDK API, transport or dependency patch is needed.Chromium observes the real
SIDE_PANELcontext through the public CDP helper already used for DevTools. Firefox uses its native sidebar picker and publicextension.getViews({ type: 'sidebar' }); no additional private actor or application test hook is added. The actual Firefox DevTools context omitsgetViews, so popup sizing checks that optional native method before calling it.The maintained suites pass 39 Chromium scenarios and 32 Firefox scenario groups. Actual Chromium and Firefox screenshots are committed. Chromium records no collected page errors; Firefox retains its documented global-capture limitation.
Scoped strict lint, TypeScript 7, formatting, production builds, bundle assertions and both complete production browser suites pass locally. Full CI passed, including every workspace gate and both browsers' production and native development suites.
Firefox 156.0.1's full browser-window screenshot omits an unhovered semi-transparent button while a document screenshot paints the same unchanged state correctly. The sidebar image records its normal hover state after the tested pointer activation. No opacity workaround is shipped; this capture limitation is documented in the example.
This covers the default sidebar in one normal window. Tab-specific configuration, multiple/private windows, worker suspension, injected surfaces, sidebar-specific HMR and the complete conformance matrix remain open. The JSON-routing owner choice remains pending; neither proposed seam is accepted by this checkpoint. Keep #12 open.
Native DevTools panel delivered, 2026-09-29
#12 commit ac8ece6 adds the actual DevTools host in Chromium and Firefox. The application calls
chrome.devtools.panels.create('Devkit', '', 'panel.html')from its nativedevtools_page. The panel reuses the existing packaged page, JSON renderer, admitted Port and background provider. No new SDK abstraction, permission, transport or dependency patch is added.The maintained suites now pass 34 Chromium scenarios and 28 Firefox scenario groups. Actual Chromium panel and actual Firefox panel screenshots are committed.
Chromium tests observe the real frontend through public CDP target APIs and verify the selected native tab. Firefox's public frame APIs omit the remote XUL browser, so one test helper uses the pinned browser's private Marionette actor. This test maintenance dependency is documented and ships no application hooks. Chromium records zero collected page errors; Firefox makes no global error-capture claim.
Scoped strict lint, TypeScript 7, formatting, both builds, bundle checks and both full production browser suites passed locally. Full CI passed on dc385f6, including every workspace gate, both production browser suites and both native development suites.
52d1eab corrects the Chromium test after Linux CI exposed that Network can be absent from the visible tab strip. The driver uses native next-panel navigation for hiding too and asserts that Devkit itself loses selection. Application code is unchanged. dc385f6 moves screenshot-directory creation into setup for both drivers. Both production suites were rerun successfully with their prior output directory moved aside, proving clean-run behavior.
The JSON action-routing choice still needs owner input. Published native 1.1.0 was checked and does not provide the proposed local-handler API; it also lacks the pending renderer/view exports. No new upstream PR or unapproved native contract was added. Side-panel/injected hosts, inspected-page discovery, debugger authority, DevTools-specific development transitions and custom-renderer coverage remain open. This issue and the parent map remain open.
Native popup and options lifecycle delivered, 2026-09-29
549bbc7 verifies the actual native popup and options hosts in Chromium and Firefox. Both load the same packaged page and native JSON renderer with independent Port connections to the existing background provider. The only application change is shared responsive CSS; there is no new SDK runtime, renderer facade or dependency patch.
runtime.openOptionsPage()action.openPopup()The shared browser scenario inspects the actual popup through native
extension.getViews. It does not substitute a full tab for the popup or add application test hooks. Firefox invalidates closed-window references, so closure is observed via the native view registry.Live runs pass 30 Chromium scenarios and 24 Firefox scenario groups. Chromium records zero collected page errors; Firefox makes no global error-capture claim. Scoped strict lint, TypeScript 7, both production builds and bundle checks passed. Commands and precise scope.
Full CI passed, including all workspace gates, both production browser suites and both native development suites.
The JSON action-routing choice remains pending in the detailed sketch. Popup-specific development transitions, DevTools/sidebar/injected hosts, custom renderer coverage and background suspension remain open. This is a partial delivery of this issue's Definition of Done; neither this issue nor the parent map is complete.
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.
The native JSON view export shares ownership with the existing node entry, verified by duplicate detection, index and replacement tests. The reference renderer uses its existing bundle and cleans up failed mounts. All six server-renderer tests pass. Full multi-provider view composition, popup/DevTools/side-panel lifecycle, custom renderer coverage and extension HMR remain open; this issue is not complete.
Native JSON renderer delivered, 2026-09-28
Implementation commit adds a maintained native JSON renderer example on both genuine Devframe and DevTools backends.
It composes
createJsonRenderView,toJsonRenderDockEntry, the asset returned byjsonRenderUiRenderer(), and a realcreateDevframeClientRuntime. The JSON authoring imports no frontend framework. The native renderer sends a params object to one example-owned native RPC method, which uses the shared counter action's schemas and invokes the existing provider. No SDK rendering facade, context cast, copied renderer or new auth/state/serialization system was added.Five automated tests verify native manifest/dock publication, byte-for-byte serving of the published asset, real-socket authorized/denied/invalid calls, subscribed view updates, projection cleanup, and the browser bundle boundary. Affected builds, TypeScript 7, strict type-aware Oxlint and Oxfmt pass. The existing server example's integration/routing/remote/browser checks and six state tests also pass.
Live in-app tests on both hosts confirmed initial render, native error banners, unmount at 1, peer increment to 2, remount at 2, both views updating to 3, and view removal/disabled mounting after actual host shutdown. A browser-source edit used Vite's native page reload and retained backend state. Temporary tabs and demo servers were closed.
The reference renderer retains the last error banner and emits a console unhandled rejection on deliberately invalid input; subsequent valid actions still work. Those upstream behaviors are recorded without suppression. Native dock/RPC registrations are host-lived; this example claims browser unmount, not backend dock unregister support.
Run after building its dependency graph:
This proves the single-provider native rendering path. Cross-provider UI routing, custom renderer, extension Ports/surfaces, renderer-module replacement and automated real-browser conformance remain open. The installed full browser runtime still has no Port transport type; this working WebSocket example does not disguise that gap.
Part of Design a portable contribution SDK and WebExtension runtime.
Upstream integration boundary, 2026-09-27
Reuse
@devframes/json-renderand/hubmodel/refs, the published renderer asset, and the native dock mount/dispose contract. Management views should first use the same native JSON catalog. The currentDevframeClientContexttransport type does not model an extension Port; resolve the smallest supported host typing seam before a surface abstraction. Do not cast a fabricated native context, copy the renderer, or design a second UI protocol.See the implementation and map review. This narrows implementation mechanisms without dropping the accepted feature or real-host coverage requirements.
Question
How should the shared JSON-render UI mount across server panels and every extension UI surface, expose provider selection and native controls, and preserve the correct state through routing changes and lifecycle events?
Context and current behavior
The authoring API must be framework-neutral; renderer implementations may use any framework. Reusing the existing JSON renderer is preferred. The monorepo supports UI-bearing and UI-free contributions shared across devframe, Vite DevTools, Chromium and Firefox providers.
At inspected devframe commit
a3f967755af99a0a0d8dd82b7b5d4f3dd4aec0bc, JSON-render protocol uses serializable inline specs or state-key references. The hub renderer contract mounts into a supplied element, receives a hub browser context, and returns disposal. The reference renderer uses Vue internally, subscribes to shared state and dispatches actions through RPC.These are inspected branch contracts. Upstream reuse audit establishes released-package availability. The existing renderer does not by itself define popup lifecycle, extension options, side panels, native DevTools placement, provider selection or extension management controls.
Requirements and scope
Options and recommendation
Independent frontend applications for each surface allow custom layouts but duplicate feature logic and make provider behavior diverge. One rigid page cloned into every surface shares code but handles popup size, side-panel lifetime and injected styling poorly.
The recommended direction is one JSON feature contract with a reusable renderer and thin surface hosts supplying mount target, supported controls, selected providers and lifecycle context. Surface layout may differ while feature behavior remains shared. Use the native JSON catalog for management controls unless a concrete unsupported component requires an extension; specify custom-renderer compatibility with that same model before introducing another catalog.
Proposed API or experiment
Begin with the native dock renderer registry in an actual host context;
entryis the native JSON dock entry and the owning surface suppliescontainer:Settle what the host passes to the renderer, how routed actions obtain provider identity, how capability changes update controls, and which objects remain local. Show the equivalent mounting in a server dock and injected shadow root without leaking Vue or any other renderer framework into contribution authoring.
Use a shared inspection example with a provider label, editable state, one action and an intentionally unsupported operation. Launch it in each surface against server and extension providers. Add a management view to exercise native controls. A separate runnable custom-renderer example must demonstrate catalog compatibility and disposal. Produce an inventory that maps public rendering methods and hooks to the exact interaction proving them.
Scenarios and acceptance criteria
Dependencies
Blocked by Provider discovery and routing and State scope and recovery through native issue-tracker dependencies. Routing determines selection and outcome semantics; state recovery determines ownership and restoration. Upstream and capability findings are referenced as evidence, not duplicated decisions. Parent-map membership organizes the ticket and does not replace these blocking edges.
Definition of Ready
Demonstrate the native renderer dependency/type gap with public package imports before proposing any new host interface. See the native extension integration checkpoint below.
Both blocking decisions are resolved with explicit selection precedence, per-provider outcomes and state restoration rules.
Supported browser surfaces and native capability differences are available from the browser audit.
A reusable renderer version or inspected source baseline and a concrete shared feature are identified.
Definition of Done
The same native JSON spec works in native and extension surfaces through a supported context seam; a replacement renderer follows that same contract and owned disposal.
A user-reviewed resolution fixes renderer and surface-host interfaces, management controls, catalog extension rules, styles, error handling and disposal.
Each required surface has an explicit support decision and behavioral contract; absence is recorded as an unsupported outcome with proof obligations.
Runnable examples cover renderer replacement, both server hosts, both extension hosts and every supported surface. An exhaustive export/hook/feature matrix specifies actual host interactions, failure cases and lifecycle assertions.
Routing and restoration responsibilities match their authoritative decisions. Remaining uncertainty becomes a named decision ticket.
Close the issue after recording the contract and update the map with its named pointer. This decision does not substitute for implementing and running the eventual verification suite.
The human has confirmed the resolution through discussion; the agent has not supplied the human side of the decision.
Resolution record
Post the chosen mounting and catalog contracts, surface support table, provider-control behavior, restoration rules, compatibility examples, required verification matrix and rejected alternatives in the resolution comment.
Current implementation and owner review, 2026-09-29
The native Port renderer/state exports are backported in the working pinned dependencies from the split upstream drafts RPC/state and JSON view/renderer. The maintained extension example imports installed public exports, runs actual native JSON rendering/state over Ports, and now connects to native Devframe and DevTools backends alongside its worker. Its 24 real Chromium scenarios pass with zero page errors. Full CI is green.
The next concrete gap is JSON-authored cross-provider actions. The JSON counter button currently calls its worker through
context.rpc.call. The existing page-owned router provides selection/broadcast/fallback from separate HTML controls. Native per-provider view mounting is already available and does not by itself express a cross-provider command.The committed owner-review sketch includes current/proposed diagrams, example calls, ownership, failure cases and maintenance costs. Two options are under review:
handlersmap on the native JSON renderer mount. Listed local actions call the existing router; unlisted actions retain native RPC. Reuse native loading/errors/built-ins/state. The host grants handlers to a specific mount, initially only an application-owned packaged view. This needs a narrow native API addition and a patch until released.rpc.callfor reserved local UI names and forward all other names/arguments to native RPC. No upstream change, but local UI commands share the RPC namespace and the adapter must preserve native call typing.The owner has been asked to choose the seam; neither option is treated as accepted. No new upstream PR has been opened. Any eventual hook should be small, native, independently useful, and reviewed before draft publication. Per-provider results must be projected through ordinary native view state; this does not merge provider stores or add a new state engine.
This checkpoint does not complete full popup/DevTools/side-panel lifecycle, renderer replacement, Firefox, privileged page bridges or extension HMR. Those remain explicit proof obligations.