feat(o4b): @positron/lit — the Lit DOM renderer (Renderer<S, TemplateResult> + LitHost)#10
Merged
Merged
Conversation
…Result> + LitHost) O4b-2 — the DOM/TS outlier of the positron Renderer/Host contract, the sibling of the wgpu backend on the web surface. Completes O4b (the contract's TypeScript crossing, foundation landed in O4b-1 / PR #9). New package `@positron/lit`: - `renderer.ts` — `LitRenderer<S> = Renderer<S, TemplateResult>`. Not a fresh interface: the render contract lives once in @positron/core; this only pins the DOM output type (compression rule). - `host.ts` — `LitHost` implements core's `Host`: state flows down (render → injected commit sink), events flow up (injected event→command mapper). DOM-free by construction — imports only the `TemplateResult` type, never a DOM value — so it's headlessly testable. - `dom.ts` — `domCommit(container)`, the ONE DOM-touching seam (Lit's `render` into a container). The analogue of the wgpu outlier's `gpu.rs`: quarantined from the pure projection, off the headless test path. Same pure/impure split as both Rust outliers. - `lit.test.ts` — Counter + CounterLitRenderer fixture (mirrors core's contract.test.ts). Asserts the projection headlessly on the TemplateResult's `strings`/`values` — the DOM analogue of wgpu's quad assertions — plus LitHost state-down/event-up. 4/4 pass, no jsdom. Toolchain: adds `npm/lit/` to the workspaces; deps `lit ^3.2.0` + `@positron/core` (type-only — lit imports only interfaces from core, all erased, so no runtime coupling). The existing `web` CI job gates it. Docs: ARCHITECTURE.md marks O4b landed and records the deferred subsume-vs-complement decision — positron's portable contract (ViewState/Renderer/Host/Observer + session frames) and continuum's `sdk/typescript` (its Commands/Events/domain types) COMPLEMENT; they meet at ContinuumHost (O5), neither subsumes the other. README Status + diagram updated. Task #117 (positron O1..O6 build-out). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
Review non-blocking nit: in Lit 4, `TemplateResult` becomes possibly- compiled and drops `.strings`, so the static-structure assertion is the exact line that will need an `UncompiledTemplateResult` narrowing on that bump. Note it in place so future-you doesn't have to re-derive it. Comment only — no behavior change (8/8 still green, typecheck clean). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LoTjvf5j3Ez13g6k8mRkFo
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
O4b-2 —
@positron/lit, the DOM/TS outlierSecond and final slice of O4b. O4b-1 (#9) crossed the contract into TypeScript (the four Rust traits as hand-authored TS interfaces + the
webCI gate). This lands the actual DOM renderer on that foundation — the sibling ofpositron-wgpuon the web surface.The package
renderer.ts—LitRenderer<S> = Renderer<S, TemplateResult>. A type alias, not a new interface: the render contract lives once in@positron/core; this file only pinsOutput = TemplateResult(compression rule — no second source of truth).host.ts—LitHostimplements core'sHost: state flows down (onState→ render → injected commit sink), events flow up (onEvent→ injected event→command mapper). It imports only theTemplateResulttype, never a DOM value — DOM-free by construction, so it's headlessly testable.dom.ts—domCommit(container), the one DOM-touching call (Lit'srenderinto a container). The analogue of the wgpu outlier'sgpu.rs: quarantined from the pure projection, kept off the headless test path. Same pure/impure split as both Rust outliers.Proof (headless, no jsdom)
lit.test.tsreuses core'sCounterfixture and asserts the projection on theTemplateResult'sstrings/values— the DOM analogue of wgpu's quad assertions — plusLitHoststate-down/event-up (including theundefined/Noneno-command path). 4/4 pass, typecheck clean across both packages.Toolchain / drift
Adds
npm/lit/to the workspaces; depslit ^3.2.0+@positron/core. The core dep is type-only — lit imports only interfaces from core, all erased underverbatimModuleSyntax, so there's no runtime coupling to core's TS. The existingwebCI job (npm install→tsc --noEmit→node --test) gates it; no new CI needed.Decision recorded
The roadmap deferred "does the positron DOM stack subsume or complement continuum's
sdk/typescript?" to O4b. Answer: complement. positron owns the portable contract (ViewState/Renderer/Host/Observer+ transport-neutral session frames); continuum's SDK owns itsCommands/Events/domain types. They meet atContinuumHost(O5); neither subsumes the other, so there's no merge and no duplicated truth. Written into ARCHITECTURE.md (§ decisions + roadmap, O4b marked landed) and README.Task #117 (positron O1..O6 build-out). Next: O5
ContinuumHost(in continuum).🤖 Generated with Claude Code