feat: Lumens (Live Interactivity) 1.1 — canvas-core + Tier-2 producer (server)#315
Merged
Conversation
…, LX interpreter, capability policy omadia-canvas-protocol/1.1, additive over 1.0 (PR byte5ai/omadia-ui#31, issue #34). - L0: lx-ast/scene/ports-wires/capability-manifest/lumen JSON schemas (+ var read node, get projection node) with accept/reject conformance fixtures. - L1: deterministic, gas+depth+value-size-bounded, no-eval LX interpreter with seeded random/now and a static semantic validator. Prototype-pollution hardened; all 10 findings from an adversarial (Forge/GPT-5.4) review fixed. - L5/L7/L8 Tier-2 policy (pure, consumed by the orchestrator when built): effect classification, broker egress bounds (rate/quota/in-flight/idempotency/ backpressure), content-addressed never-stale asset cache, import consent, content-addressed presets + resolve-then-generate + fork lineage, share token re-mint (assets travel by id, never the author token). - validateLumenFull combined gate. 172 tests, tsc clean. Land this before the omadia-ui UI PR (UI syncs these schemas).
…r-2) Makes Lumens reachable end-to-end over a live server (the producer half of #34): - canvas_publish_lumen — a canvas-output producer that instantiates a vetted reference Lumen (variant: arcade game · interactive map · defrag animation) as a surface_snapshot. Authorised in the canvas-output allow-set AND the deterministic-action allow-set, so a canvas action of that type dispatches LLM-free (a click renders the Lumen with no model turn). - referenceLumens.ts — the three vetted reference Lumens (declarative LX data), each exercising a different slice: tick simulation + events, interactive selection/zoom via get/if, and a map(range) tick animation. - treeValidator: extended additively to omadia-canvas-protocol/1.1 — the 1.0 canvas-tree with scene + lumen added to the primitive oneOf, so a snapshot carrying a Lumen validates server-side. Depends on the canvas-core 1.1 schemas in this PR.
canvas_publish_lumen now PREFERS an agent-authored `lumen` (the real thesis: the LLM generates declarative LX data; the host validates it). The tool validates the authored Lumen structurally (validateLumenNode against the 1.1 lumen schema) and, on failure, returns a path-pointed error so the agent self-corrects — this is what makes LLM-generated interactivity safe (the model proposes data, the host proves it bounded/total/deterministic before it runs). The tool description carries the compact LX grammar + a worked example. The `variant` reference presets remain as a canned-demo fallback (resolve-then- generate). Semantic bounds beyond the schema are enforced Tier-1 by the interpreter (halts a bad Lumen with surface_error, never the canvas).
…atasets (L5 loadData) canvas_publish_lumen now also takes a privacy-shield `datasetId` (+ optional labelField/valueField). The real rows are resolved SERVER-SIDE via the same privacy provider canvas_publish_rows uses — the unmasked data never reaches the LLM — and an interactive, tappable data Lumen is built deterministically in datasetLumen.ts (one selectable row per record; tap highlights via a state-driven conditional). This is the privacy-safe answer to 'visualise the user's real data as a live artifact': the model only passes the dataset handle, the host resolves + constructs. Locally verified (validateLumen ok; view + tap transition evaluate correctly).
Adds a `data` param to canvas_publish_lumen: when the agent already HOLDS the rows (an unshielded fetch — e.g. dynamics tools in bypass mode emit real rows directly, no datasetId interned), it passes them as `data` and the server builds the interactive data Lumen via buildDatasetLumen — no LX authoring needed. Complements `datasetId` (masked/shielded path, resolved server-side). Tool description now steers: visible rows → `data`, masked → `datasetId`.
…registration assertions The producer now registers three canvas-output tools (rows + choice + lumen); update the registration/dispose assertions accordingly (3 registered, 3 disposed).
5 tasks
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.
What
The server side of Live Interactivity (Lumens),
omadia-canvas-protocol/1.1— additive over 1.0. Companion to the spec in byte5ai/omadia-ui#31; implements byte5ai/omadia-ui#34. Pairs with the host-app PR byte5ai/omadia-ui#36.Verified live end-to-end against a local omadia stack: a real-data prompt → agent fetches Dynamics course rows →
canvas_publish_lumen→ an interactive, tappable Lumen renders at Tier-1 (60fps, no per-frame round-trip).Contents
Protocol + interpreter (
canvas-core)schema/):lx-ast,scene,ports-wires,capability-manifest,lumen(JSON Schema 2020-12, strict whitelist). Added two LX nodes the spec needed:var(read a lexical/iteration binding) andget(project a record field / list element). Accept/reject conformance fixtures.src/lx/): pure, total, deterministic evaluator — seededrandom/now, gas + AST-depth + produced-value-size budgets, boundedmap/filter/fold/range, functionalset, full §2.3 std-lib + a static semantic validator.src/capabilities/, pure): effect classification, broker egress bounds, content-addressed asset cache, import consent, content-addressed presets + resolve-then-generate, share token re-mint.Tier-2 producer (
omadia-ui-orchestrator)canvas_publish_lumen— a canvas-output + deterministic-action producer with three paths: (1) authored — the agent writes a fulllumen; hard-validated (validateLumenNode), invalid → actionable error so it self-corrects (this is what makes LLM-generated interactivity safe); (2) data-bound — an inlinedatarows array OR a privacy-shielddatasetIdresolved server-side (real values never reach the LLM) → an interactive data Lumen built deterministically (datasetLumen.ts); (3) preset — a vetted reference (referenceLumens.ts: arcade · map · defrag).treeValidatorextended additively to 1.1 (scene + lumen in the primitive oneOf) so a Lumen-bearing snapshot validates server-side.Security
A full adversarial review (Forge / GPT-5.4) found 10 issues in the interpreter — all fixed and covered by tests (value-size DoS, deep-AST stack overflow, non-finite/determinism, prototype pollution, arity, sandbox-closedness, validator/interpreter scope).
Tests
canvas-core172 passing;tscclean across packages.Merge order
Land this before byte5ai/omadia-ui#36 (the host app syncs these schemas at build time).