Skip to content

feat: add internal projection runtime and LLM-authored artifacts - #92

Merged
0xjcf merged 52 commits into
betafrom
fas/accessibility-contract-epic
Jul 11, 2026
Merged

feat: add internal projection runtime and LLM-authored artifacts#92
0xjcf merged 52 commits into
betafrom
fas/accessibility-contract-epic

Conversation

@0xjcf

@0xjcf 0xjcf commented Jul 11, 2026

Copy link
Copy Markdown
Owner

Summary

  • add the private projection binding and committer runtime behind the existing igniteCore surface
  • add validated actor-owned ProjectionDocument state, command-backed actions, and request-driven speech/text targets
  • keep DOM registration source-compatible while adding the opaque disposable non-DOM target overload
  • document the behavior-first accessibility and LLM-authorship boundaries

Verification

  • .fas/scripts/verify.sh --full
  • pnpm --filter ignite-element test -- projection-runtime.test.ts (622 tests)
  • coderabbit review --agent -t committed --base beta -c AGENTS.md
  • fas batch close --dry-run
  • fas batch close

Follow-up boundary

The canonical prompt/speech control-center example and its final docs remain in the existing dependent workbench and documentation tasks; this PR ships the runtime contract those tasks require.

Summary by CodeRabbit

  • New Features
    • Added validated, durable projection documents and speech requests, including incremental patch/upsert handling and command-backed actions.
    • Introduced public helpers for creating document/speech projection targets and a component overload for first-party projection sessions.
    • Expanded runtime/component inspection to support adapter-derived inspection for permissions and schema exposure.
  • Accessibility
    • Refined accessibility-first guidance and tightened rendered DOM verification (keyboard/focus, accessible names, and assertive SAVE_FAILURE live-region behavior).
  • Bug Fixes
    • Hardened headless/runtime behavior against unsafe or executable projection content; improved snapshot/subscription and lifecycle reliability.
  • Documentation
    • Added/updated accessibility-by-default and projection runtime docs and guide content.
  • Tests
    • Expanded projection runtime, security, binding/session lifecycle, and export/typing test coverage.

0xjcf added 30 commits July 9, 2026 17:39
Allow the two first-party target constructors on every adapter entrypoint.

Cover generated target chunks in the DOM polyfill side-effects contract.
Normalize unsafe keys and keep actor-owned inspection coherent.

Remove premature named projection types while preserving target constructors.
Distinguish absent projection channels from explicit empty actor-owned state.
Reject case-insensitive on-plus-letter keys during recursive validation.
Build semantic documents from descriptor-checked data allowlists before commit.
Validate preserved JSON islands and descriptor-copy actor document collections.
@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 15e34dec-bd65-4733-bfd0-3736e27343b4

📥 Commits

Reviewing files that changed from the base of the PR and between 0228e6f and 19e3279.

📒 Files selected for processing (2)
  • packages/ignite-element/src/internal/projectionBinding.ts
  • packages/ignite-element/src/tests/projection-binding.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/ignite-element/src/tests/projection-binding.test.ts
  • packages/ignite-element/src/internal/projectionBinding.ts

Walkthrough

This change replaces registry-oriented projection planning with validated actor-owned projection documents, opaque document and speech targets, private binding and inspection runtime support, stricter adapter contracts, hardened XState lifecycle handling, extensive tests, and updated accessibility/projection documentation.

Changes

Dynamic projection runtime

Layer / File(s) Summary
Architecture and contracts
.fas/*, docs/accessibility-by-default.md, docs/projection-runtime.md, docs/site/src/content/docs/guides/accessibility-first.mdx
Roadmap and documentation now describe validated ProjectionDocument state, private projection machinery, command-backed authoring, and separate headless and DOM verification.
Public API and runtime wiring
packages/ignite-element/src/types/*, packages/ignite-element/src/runtime/*, packages/ignite-element/src/create*Factory.ts, packages/ignite-element/src/IgniteElementFactory.ts
Adds branded projection target constructors, document/speech overloads, inspection resolution, stricter adapter resolver types, schema inspection, and target binding integration.
Validation and commit handling
packages/ignite-element/src/internal/projectionDocument.ts, packages/ignite-element/src/internal/projectionBinding.ts
Adds safe parsing, URI and content filtering, command validation, revisioned patches, document upserts, speech lifecycle handling, and commit result facts.
Adapter lifecycle hardening
packages/ignite-adapters/src/adapters/XStateAdapter.ts, packages/ignite-core/src/utils/failInvariant.ts
Adds descriptor-safe snapshot construction, guarded subscriptions, rollback on setup failures, idempotent teardown, and preservation of non-string invariant failures.
Verification and package surface
packages/ignite-element/src/tests/*, packages/ignite-element/package.json, packages/ignite-element/scripts/verify-exports.mjs
Adds coverage for projection security, targets, binding retries, runtime inspection, adapter lifecycle behavior, type boundaries, renderer isolation, and required exports.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Model
  participant IgniteTools
  participant ActorState
  participant ProjectionRuntime
  participant DOMOrSpeechCommitter
  Model->>IgniteTools: issue upsert or patch command
  IgniteTools->>ActorState: update validated ProjectionDocument
  ActorState->>ProjectionRuntime: publish inspection state
  ProjectionRuntime->>DOMOrSpeechCommitter: commit document or acknowledge speech
  DOMOrSpeechCommitter-->>ProjectionRuntime: return commit result
Loading

Poem

I’m a rabbit with a neat little queue,
Validated projections hop into view.
Documents thump, speech softly sings,
Safe commands guard all the strings.
Tests watch the actors, steady and bright—
Then I nibble a carrot and bid you goodnight.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 6.32% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding an internal projection runtime with LLM-authored artifacts.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fas/accessibility-contract-epic

Comment @coderabbitai help to get the list of available commands.

@codecov

codecov Bot commented Jul 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 88.25112% with 131 lines in your changes missing coverage. Please review.
✅ Project coverage is 89.97%. Comparing base (2f86faa) to head (19e3279).
⚠️ Report is 17 commits behind head on beta.

Files with missing lines Patch % Lines
.../ignite-element/src/internal/projectionDocument.ts 85.47% 91 Missing and 11 partials ⚠️
...ackages/ignite-element/src/IgniteElementFactory.ts 91.37% 17 Missing ⚠️
packages/ignite-element/src/runtime/schema.ts 83.63% 9 Missing ⚠️
...s/ignite-element/src/internal/projectionBinding.ts 97.70% 1 Missing and 1 partial ⚠️
packages/ignite-element/src/runtime/agent.ts 95.45% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##             beta      #92      +/-   ##
==========================================
- Coverage   91.25%   89.97%   -1.29%     
==========================================
  Files          33       38       +5     
  Lines        1830     3052    +1222     
  Branches      498      910     +412     
==========================================
+ Hits         1670     2746    +1076     
- Misses        150      284     +134     
- Partials       10       22      +12     
Flag Coverage Δ
unittests 89.97% <88.25%> (-1.29%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...kages/ignite-element/src/createComponentFactory.ts 91.66% <ø> (ø)
...ages/ignite-element/src/createProjectionFactory.ts 98.59% <100.00%> (+2.43%) ⬆️
...ent/src/igniteCore/createIgniteComponentFactory.ts 100.00% <ø> (ø)
packages/ignite-element/src/igniteCore/redux.ts 91.66% <ø> (ø)
...es/ignite-element/src/runtime/projectionTargets.ts 100.00% <100.00%> (ø)
packages/ignite-element/src/tools/core.ts 94.44% <100.00%> (+0.92%) ⬆️
.../ignite-element/src/types/projectionTargetBrand.ts 100.00% <100.00%> (ø)
packages/ignite-element/src/xstate.ts 100.00% <ø> (ø)
packages/ignite-element/src/runtime/agent.ts 91.03% <95.45%> (-3.91%) ⬇️
...s/ignite-element/src/internal/projectionBinding.ts 97.70% <97.70%> (ø)
... and 3 more

... and 3 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

0xjcf commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

0xjcf commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
packages/ignite-element/src/runtime/projectionTargets.ts (1)

84-183: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract shared brand/freeze helper to remove duplication.

createProjectionDocumentTarget (Lines 84-134) and createProjectionSpeechTarget (Lines 136-183) both build an initial object literal with the brand key, then immediately redefine the same properties via Object.defineProperties before freezing and registering in the WeakMap. The two-step construction is duplicated near-verbatim across both factories.

♻️ Suggested consolidation
+function brandProjectionTarget<T extends Record<string, unknown>>(
+	kind: T["kind"],
+	extra: Omit<T, "kind" | typeof igniteProjectionTargetBrand>,
+): T {
+	const target = {} as T;
+	Object.defineProperties(target, {
+		[igniteProjectionTargetBrand]: {
+			value: true,
+			enumerable: false,
+			writable: false,
+			configurable: false,
+		},
+		kind: { value: kind, enumerable: false, writable: false, configurable: false },
+		...Object.fromEntries(
+			Object.entries(extra).map(([key, value]) => [
+				key,
+				{ value, enumerable: false, writable: false, configurable: false },
+			]),
+		),
+	});
+	return Object.freeze(target);
+}

Both factories can then call this helper instead of repeating the object-literal-then-defineProperties pattern.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ignite-element/src/runtime/projectionTargets.ts` around lines 84 -
183, Extract a shared helper for constructing projection target shells with the
non-enumerable, immutable igniteProjectionTargetBrand and kind properties, then
freeze the result. Update createProjectionDocumentTarget and
createProjectionSpeechTarget to call this helper and remove their duplicated
object-literal/Object.defineProperties setup while preserving documentId
handling and WeakMap registration.
packages/ignite-element/src/IgniteElementFactory.ts (2)

118-208: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Share the command schema helpers
These helpers mirror packages/ignite-element/src/runtime/agent.ts, including the gated: true branch. Move them into a shared internal module, such as runtime/commands.ts, so the registration and inspection schemas stay in sync.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ignite-element/src/IgniteElementFactory.ts` around lines 118 - 208,
Move getCommandMetadata, hasCanExecute, getCommandContract, getAdditionalArg,
createCommandSchemaEntry, and getOwnCommandEntries from IgniteElementFactory.ts
into a shared internal runtime/commands.ts module, then update both registration
and inspection code to import and use them so command schemas, including gated:
true handling, remain synchronized.

906-950: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Cache projection inspection schema generation

resolveProjectionInspection() runs on every active projection commit, but the derived revision isn’t consumed by the binding flow. Consider caching the command/schema serialization here so repeated snapshot updates don’t remap/sort/stringify every command on a hot path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/ignite-element/src/IgniteElementFactory.ts` around lines 906 - 950,
Cache the derived projection inspection schema and revision within
resolveProjectionInspection() so repeated active projection commits reuse
unchanged command mappings, sorting, and serialization. Invalidate or recompute
the cache only when command entries, snapshot, or view data change, while
preserving canExecute, documents, and speech behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.fas/TASKS.md:
- Around line 2179-2189: The task status is inconsistent between TASKS.md and
the live queue. Locate the task block for “Implement internal dynamic projection
pipeline and LLM-authored artifacts” and update its Status to match
task-1783650880370 in .fas/queue/tasks.json, or complete the queue entry with
the required completedAt if the work is actually finished; ensure downstream
gating references the same authoritative state.

In `@packages/ignite-element/src/IgniteElementFactory.ts`:
- Around line 969-1039: Update commitProjectionDocumentTarget in
internal/projectionBinding.ts so documentRevisionById records the current
document revision before validation runs, or otherwise caches revisions that
fail validation. Preserve deduplication for both successful and failed
revisions, preventing repeated validation and error logging on subsequent
snapshot changes until the document revision changes.

In `@packages/ignite-element/src/internal/projectionBinding.ts`:
- Around line 102-117: Address the unused document identity contract between
createProjectionDocument() and commitProjectionDocumentTarget(): either update
commitProjectionDocumentTarget() to invoke projection.identity(document)
consistently with speech projections, or remove the identity() method from the
document projection API and related types/usages.

---

Nitpick comments:
In `@packages/ignite-element/src/IgniteElementFactory.ts`:
- Around line 118-208: Move getCommandMetadata, hasCanExecute,
getCommandContract, getAdditionalArg, createCommandSchemaEntry, and
getOwnCommandEntries from IgniteElementFactory.ts into a shared internal
runtime/commands.ts module, then update both registration and inspection code to
import and use them so command schemas, including gated: true handling, remain
synchronized.
- Around line 906-950: Cache the derived projection inspection schema and
revision within resolveProjectionInspection() so repeated active projection
commits reuse unchanged command mappings, sorting, and serialization. Invalidate
or recompute the cache only when command entries, snapshot, or view data change,
while preserving canExecute, documents, and speech behavior.

In `@packages/ignite-element/src/runtime/projectionTargets.ts`:
- Around line 84-183: Extract a shared helper for constructing projection target
shells with the non-enumerable, immutable igniteProjectionTargetBrand and kind
properties, then freeze the result. Update createProjectionDocumentTarget and
createProjectionSpeechTarget to call this helper and remove their duplicated
object-literal/Object.defineProperties setup while preserving documentId
handling and WeakMap registration.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 95967063-7424-4f96-a70e-06fba3382721

📥 Commits

Reviewing files that changed from the base of the PR and between 8472017 and a28caea.

📒 Files selected for processing (44)
  • .fas/TASKS.md
  • .fas/queue/tasks.json
  • .fas/tasks/add-dom-accessibility-verification-for-ignite-examples.md
  • .fas/tasks/add-headless-accessibility-contract-assertions-to-the-test-d.md
  • .fas/tasks/build-voice-text-agent-control-center-workbench-example-for-.md
  • .fas/tasks/design-the-ignite-element-accessibility-contract-api-and-dx.md
  • .fas/tasks/document-accessibility-first-ignite-implementation-patterns.md
  • .fas/tasks/implement-internal-dynamic-projection-pipeline-and-llm-autho.md
  • .fas/tasks/implement-the-core-accessibility-semantics-projection-surfac.md
  • docs/accessibility-by-default.md
  • docs/projection-runtime.md
  • docs/site/src/content/docs/guides/accessibility-first.mdx
  • packages/ignite-adapters/src/adapters/XStateAdapter.ts
  • packages/ignite-core/src/utils/failInvariant.ts
  • packages/ignite-element/package.json
  • packages/ignite-element/scripts/verify-exports.mjs
  • packages/ignite-element/src/IgniteElementFactory.ts
  • packages/ignite-element/src/actor-web.ts
  • packages/ignite-element/src/createComponentFactory.ts
  • packages/ignite-element/src/createProjectionFactory.ts
  • packages/ignite-element/src/igniteCore/createIgniteComponentFactory.ts
  • packages/ignite-element/src/igniteCore/redux.ts
  • packages/ignite-element/src/igniteCore/types.ts
  • packages/ignite-element/src/index.ts
  • packages/ignite-element/src/internal/projectionBinding.ts
  • packages/ignite-element/src/internal/projectionDocument.ts
  • packages/ignite-element/src/mobx.ts
  • packages/ignite-element/src/redux.ts
  • packages/ignite-element/src/runtime/agent.ts
  • packages/ignite-element/src/runtime/projectionTargets.ts
  • packages/ignite-element/src/runtime/schema.ts
  • packages/ignite-element/src/tests/IgniteElementFactory.test.ts
  • packages/ignite-element/src/tests/adapters/XStateAdapter.test.ts
  • packages/ignite-element/src/tests/createComponentFactory.test.ts
  • packages/ignite-element/src/tests/createProjectionFactory.test.ts
  • packages/ignite-element/src/tests/projection-binding.test.ts
  • packages/ignite-element/src/tests/projection-runtime.test.ts
  • packages/ignite-element/src/tests/projection-target-guard.test.ts
  • packages/ignite-element/src/tests/tools.test.ts
  • packages/ignite-element/src/tests/types/igniteCore.types.test.ts
  • packages/ignite-element/src/tools/core.ts
  • packages/ignite-element/src/types/agent.ts
  • packages/ignite-element/src/types/projectionTargetBrand.ts
  • packages/ignite-element/src/xstate.ts

Comment thread .fas/TASKS.md
Comment thread packages/ignite-element/src/IgniteElementFactory.ts
Comment thread packages/ignite-element/src/internal/projectionBinding.ts

0xjcf commented Jul 11, 2026

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jul 11, 2026

Copy link
Copy Markdown
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@0xjcf
0xjcf merged commit efde929 into beta Jul 11, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant