diff --git a/apps/website/content/docs/render/a2ui/catalog.mdx b/apps/website/content/docs/render/a2ui/catalog.mdx index 783d2b53..091ed967 100644 --- a/apps/website/content/docs/render/a2ui/catalog.mdx +++ b/apps/website/content/docs/render/a2ui/catalog.mdx @@ -35,7 +35,7 @@ Renders a span of text. | `text` | `string` | The text content to display | ```json -{"id": "greeting", "component": "Text", "text": "Hello, world!"} +{"id": "greeting", "component": {"Text": {"text": {"literalString": "Hello, world!"}}}} ``` ### Image @@ -103,7 +103,7 @@ Arranges children vertically with a flex column layout. ### Card -Renders children inside a rounded bordered card container with an optional title. +Renders children inside a rounded bordered card container. | A2UI type | Angular component | Selector | |-----------|-------------------|----------| @@ -111,7 +111,6 @@ Renders children inside a rounded bordered card container with an optional title | Prop | Type | Description | |------|------|-------------| -| `title` | `string` | Optional card heading | | `childKeys` | `string[]` | Ordered list of child component IDs | | `spec` | `Spec` | Injected automatically by the render engine | @@ -149,8 +148,8 @@ Renders a button that dispatches an action when clicked. | Prop | Type | Description | |------|------|-------------| -| `label` | `string` | Button label text | -| `variant` | `'primary' \| 'borderless'` | Visual style. Defaults to `'primary'` | +| `childKeys` | `string[]` | Child component IDs whose rendered output is the button's content (e.g., a `Text` label) | +| `primary` | `boolean` | Renders the primary visual style. Defaults to `true` | | `disabled` | `boolean` | Disables the button when `true` | | `action` | `A2uiAction` | Action to execute on click (event or function call) | | `validationResult` | `A2uiValidationResult` | Pre-computed validation result — button is disabled if `valid` is `false` | @@ -183,7 +182,7 @@ A single-line text input with optional label and placeholder. | Prop | Type | Description | |------|------|-------------| | `label` | `string` | Input label | -| `value` | `string` | Current value (resolved from path reference) | +| `text` | `string` | Current value (resolved from path reference). `value` is a read-only computed alias | | `placeholder` | `string` | Placeholder text | | `validationResult` | `A2uiValidationResult` | Validation state — shows errors below input when invalid | | `_bindings` | `Record` | Auto-populated by `surfaceToSpec()` from path references | @@ -192,9 +191,12 @@ A single-line text input with optional label and placeholder. ```json { "id": "name-field", - "component": "TextField", - "label": "Your name", - "value": {"path": "/name"} + "component": { + "TextField": { + "label": {"literalString": "Your name"}, + "text": {"path": "/name"} + } + } } ``` @@ -211,7 +213,8 @@ A labeled checkbox with two-way binding for its checked state. | Prop | Type | Description | |------|------|-------------| | `label` | `string` | Checkbox label | -| `checked` | `boolean` | Current checked state (resolved from path reference) | +| `value` | `boolean` | Current checked state (resolved from path reference) | +| `checked` | `boolean` | Deprecated back-compat alias for `value` | | `validationResult` | `A2uiValidationResult` | Validation state — shows errors below checkbox when invalid | | `_bindings` | `Record` | Auto-populated by `surfaceToSpec()` from path references | | `emit` | injected | Event emitter provided by the render engine | @@ -245,20 +248,27 @@ A date, time, or datetime input with two-way binding. |------|------|-------------| | `label` | `string` | Input label | | `value` | `string` | Current value (resolved from path reference) | -| `inputType` | `'date' \| 'time' \| 'datetime-local'` | HTML input type. Defaults to `'date'` | +| `enableDate` | `boolean` | Include the date portion. Defaults to `true` | +| `enableTime` | `boolean` | Include the time portion. Defaults to `false` | | `min` | `string` | Minimum allowed value | | `max` | `string` | Maximum allowed value | | `validationResult` | `A2uiValidationResult` | Validation state — shows errors below input when invalid | | `_bindings` | `Record` | Auto-populated by `surfaceToSpec()` from path references | | `emit` | injected | Event emitter provided by the render engine | +The HTML input type (`date`, `time`, or `datetime-local`) is derived internally from `enableDate` and `enableTime`. + ```json { "id": "date-field", - "component": "DateTimeInput", - "label": "Appointment date", - "value": {"path": "/appointmentDate"}, - "inputType": "date" + "component": { + "DateTimeInput": { + "label": {"literalString": "Appointment date"}, + "value": {"path": "/appointmentDate"}, + "enableDate": true, + "enableTime": false + } + } } ``` @@ -274,8 +284,8 @@ A range slider input with two-way binding. |------|------|-------------| | `label` | `string` | Slider label | | `value` | `number` | Current value (bind via `_bindings`) | -| `min` | `number` | Minimum value | -| `max` | `number` | Maximum value | +| `minValue` | `number` | Minimum value | +| `maxValue` | `number` | Maximum value | | `step` | `number` | Step increment | | `validationResult` | `A2uiValidationResult` | Validation state — shows errors below slider when invalid | | `_bindings` | `Record` | Auto-populated by `surfaceToSpec()` from path references | @@ -284,12 +294,15 @@ A range slider input with two-way binding. ```json { "id": "volume", - "component": "Slider", - "label": "Volume", - "value": {"path": "/volume"}, - "min": 0, - "max": 100, - "step": 1 + "component": { + "Slider": { + "label": {"literalString": "Volume"}, + "value": {"path": "/volume"}, + "minValue": 0, + "maxValue": 100, + "step": 1 + } + } } ``` diff --git a/apps/website/content/docs/render/a2ui/surface-store.mdx b/apps/website/content/docs/render/a2ui/surface-store.mdx index ed37d20d..75e87125 100644 --- a/apps/website/content/docs/render/a2ui/surface-store.mdx +++ b/apps/website/content/docs/render/a2ui/surface-store.mdx @@ -37,12 +37,12 @@ Processes one `A2uiMessage` and updates the internal surfaces signal. All four m | Message type | Behavior | |--------------|----------| -| `createSurface` | Creates a new `A2uiSurface` entry with an empty component map and data model | -| `updateComponents` | Merges the provided components into the surface's component map by `id` — existing components are replaced, others are kept | -| `updateDataModel` | Applies a JSON Pointer patch to the surface's data model (see below) | +| `surfaceUpdate` | Delivers a surface's components — merges the provided components into the surface's component map by `id` so existing components are replaced and others are kept | +| `dataModelUpdate` | Applies a JSON Pointer patch to the surface's data model (see below) | +| `beginRendering` | Marks the surface root and commits the buffered components and data model into a live surface | | `deleteSurface` | Removes the surface from the map entirely | -Messages for unknown surface IDs are silently ignored (except `createSurface`, which registers the surface). +Messages for unknown surface IDs are silently ignored until a `surfaceUpdate` introduces the surface and a `beginRendering` commits it. ### `surfaces` @@ -50,7 +50,7 @@ A readonly `Signal>` containing all active surfaces. Ea ### `surface(surfaceId)` -Returns a `computed` signal for a single surface. The signal emits `undefined` until a `createSurface` message registers it, and `undefined` again after `deleteSurface` removes it. +Returns a `computed` signal for a single surface. The signal emits `undefined` until a `beginRendering` message commits it, and `undefined` again after `deleteSurface` removes it. ```typescript const dashboard = store.surface('dashboard'); @@ -61,9 +61,9 @@ const dashboard = store.surface('dashboard'); The surface's `dataModel` is synchronized into the render-lib `StateStore` when `surfaceToSpec()` converts the surface to a spec. The conversion sets `state: surface.dataModel` on the produced `Spec`, which initializes the render-lib's internal `StateStore` with the surface data. When components with `_bindings` update values (e.g., a text field changing), those updates flow through the render-lib `StateStore`, and each mutation emits a `RenderStateChangeEvent` through the render-lib event system. This means consumers observing the `events` output on `A2uiSurfaceComponent` see all data model changes as typed `RenderStateChangeEvent` objects with `path`, `value`, and `snapshot` fields. -## updateDataModel Semantics +## dataModelUpdate Semantics -The `updateDataModel` message uses JSON Pointer (RFC 6901) paths to address values in the data model. +The `dataModelUpdate` message uses JSON Pointer (RFC 6901) paths to address values in the data model. | `path` | `value` | Effect | |--------|---------|--------| @@ -73,13 +73,13 @@ The `updateDataModel` message uses JSON Pointer (RFC 6901) paths to address valu ```json // Replace entire model -{"updateDataModel": {"surfaceId": "s1", "value": {"name": "Alice", "score": 42}}} +{"dataModelUpdate": {"surfaceId": "s1", "value": {"name": "Alice", "score": 42}}} // Set a single field -{"updateDataModel": {"surfaceId": "s1", "path": "/score", "value": 99}} +{"dataModelUpdate": {"surfaceId": "s1", "path": "/score", "value": 99}} // Delete a field -{"updateDataModel": {"surfaceId": "s1", "path": "/score"}} +{"dataModelUpdate": {"surfaceId": "s1", "path": "/score"}} ``` ## Usage with createA2uiMessageParser @@ -113,7 +113,7 @@ effect(() => { ``` -The parser expects each line to be wrapped in an envelope object: `{"createSurface": {...}}`, `{"updateComponents": {...}}`, etc. The envelope key determines the message type; its value is the message payload. +The parser expects each line to be wrapped in an envelope object: `{"surfaceUpdate": {...}}`, `{"dataModelUpdate": {...}}`, etc. The envelope key determines the message type; its value is the message payload. ## A2uiSurface Shape diff --git a/apps/website/content/docs/render/api/define-angular-registry.mdx b/apps/website/content/docs/render/api/define-angular-registry.mdx index 4d88be7d..4b6c9057 100644 --- a/apps/website/content/docs/render/api/define-angular-registry.mdx +++ b/apps/website/content/docs/render/api/define-angular-registry.mdx @@ -31,6 +31,7 @@ An `AngularRegistry` object with two methods: ```typescript interface AngularRegistry { get(name: string): AngularComponentRenderer | undefined; + getFallback(name: string): AngularComponentRenderer | undefined; names(): string[]; } ``` @@ -38,6 +39,7 @@ interface AngularRegistry { | Method | Description | |--------|-------------| | `get(name)` | Returns the component class for the given type name, or `undefined` if not registered | +| `getFallback(name)` | Returns the configured fallback renderer for a registered name -- the entry's own `fallback`, the library's default fallback if the entry omits one, or `undefined` if the name isn't registered. | | `names()` | Returns an array of all registered type name strings | ## Usage diff --git a/apps/website/content/docs/render/api/render-spec-component.mdx b/apps/website/content/docs/render/api/render-spec-component.mdx index 11323aef..7af8042c 100644 --- a/apps/website/content/docs/render/api/render-spec-component.mdx +++ b/apps/website/content/docs/render/api/render-spec-component.mdx @@ -83,6 +83,7 @@ interface RenderContext { store: StateStore; functions?: Record; handlers?: Record) => unknown | Promise>; + emitEvent?: (event: RenderEvent) => void; loading?: boolean; } ``` diff --git a/apps/website/content/docs/render/api/signal-state-store.mdx b/apps/website/content/docs/render/api/signal-state-store.mdx index f847fbb7..bb3aa102 100644 --- a/apps/website/content/docs/render/api/signal-state-store.mdx +++ b/apps/website/content/docs/render/api/signal-state-store.mdx @@ -11,7 +11,7 @@ import { signalStateStore } from '@threadplane/render'; ## Signature ```typescript -function signalStateStore(initialState?: StateModel): StateStore; +function signalStateStore(initialState: StateModel = {}): StateStore; ``` ### Parameters diff --git a/apps/website/content/docs/render/concepts/json-render-vs-a2ui.mdx b/apps/website/content/docs/render/concepts/json-render-vs-a2ui.mdx index 074163a6..2d533df7 100644 --- a/apps/website/content/docs/render/concepts/json-render-vs-a2ui.mdx +++ b/apps/website/content/docs/render/concepts/json-render-vs-a2ui.mdx @@ -75,6 +75,8 @@ A surface has an id, catalog id, component map, data model, optional theme, opti interface A2uiSurface { surfaceId: string; catalogId: string; + theme?: A2uiTheme; + sendDataModel?: boolean; components: Map; dataModel: Record; styles?: { font?: string; primaryColor?: string }; @@ -173,6 +175,10 @@ interface A2uiActionMessage { sourceComponentId: string; timestamp: string; context: Record; + label?: string; + }; + metadata?: { + a2uiClientDataModel: A2uiClientDataModel; }; } ``` diff --git a/apps/website/content/docs/render/getting-started/installation.mdx b/apps/website/content/docs/render/getting-started/installation.mdx index 4f6071f8..a456cd72 100644 --- a/apps/website/content/docs/render/getting-started/installation.mdx +++ b/apps/website/content/docs/render/getting-started/installation.mdx @@ -88,6 +88,7 @@ export const appConfig: ApplicationConfig = { ```typescript import { Component, ChangeDetectionStrategy, input } from '@angular/core'; +import type { Spec } from '@json-render/core'; @Component({ selector: 'app-text', @@ -98,7 +99,7 @@ import { Component, ChangeDetectionStrategy, input } from '@angular/core'; export class TextComponent { readonly label = input(''); readonly childKeys = input([]); - readonly spec = input(null); + readonly spec = input.required(); } ``` diff --git a/apps/website/content/docs/render/getting-started/quickstart.mdx b/apps/website/content/docs/render/getting-started/quickstart.mdx index 54e2c2fe..10d3bd1f 100644 --- a/apps/website/content/docs/render/getting-started/quickstart.mdx +++ b/apps/website/content/docs/render/getting-started/quickstart.mdx @@ -14,6 +14,7 @@ Let's start with a simple Angular component for the spec to render. Every render ```typescript // text.component.ts import { Component, ChangeDetectionStrategy, input } from '@angular/core'; +import type { Spec } from '@json-render/core'; @Component({ selector: 'app-text', @@ -24,7 +25,7 @@ import { Component, ChangeDetectionStrategy, input } from '@angular/core'; export class TextComponent { readonly label = input(''); readonly childKeys = input([]); - readonly spec = input(null); + readonly spec = input.required(); } ``` diff --git a/apps/website/content/docs/render/guides/events.mdx b/apps/website/content/docs/render/guides/events.mdx index 0e24915e..276cb51e 100644 --- a/apps/website/content/docs/render/guides/events.mdx +++ b/apps/website/content/docs/render/guides/events.mdx @@ -167,7 +167,7 @@ const handlers = { }; ``` -This works for handlers passed via `[handlers]` on ``, `provideRender()`, or `ChatComponent`. +This works for handlers passed via `[handlers]` on ``, `provideRender()`, or other render-enabled components like `ChatComponent` (from `@threadplane/chat`). ### Resolution Priority diff --git a/apps/website/content/docs/render/guides/registry.mdx b/apps/website/content/docs/render/guides/registry.mdx index e478fb20..c63acc69 100644 --- a/apps/website/content/docs/render/guides/registry.mdx +++ b/apps/website/content/docs/render/guides/registry.mdx @@ -21,17 +21,23 @@ export const uiRegistry = defineAngularRegistry({ }); ``` -The returned `AngularRegistry` object has two methods: +The returned `AngularRegistry` object has three methods: - `get(name: string)` -- returns the component class for the given type name, or `undefined` if not registered +- `getFallback(name: string)` -- returns the configured fallback renderer for a registered name -- the entry's own `fallback`, or the library's default fallback if the entry omits one, or `undefined` if the name isn't registered - `names()` -- returns an array of all registered type names ```typescript -uiRegistry.get('Text'); // TextComponent -uiRegistry.get('Unknown'); // undefined -uiRegistry.names(); // ['Text', 'Card', 'Button', 'Container'] +uiRegistry.get('Text'); // TextComponent +uiRegistry.get('Unknown'); // undefined +uiRegistry.getFallback('Text'); // fallback renderer (or default) +uiRegistry.names(); // ['Text', 'Card', 'Button', 'Container'] ``` +### Fallback Rendering + +When an element's type is not registered, it renders that type's configured fallback if one exists, and otherwise renders nothing. Fallbacks also fill a transient gap during rendering: while an element's state-bound props are still resolving, the library can render a fallback to give visual feedback until the real component is ready. Once the real component mounts, it stays mounted -- later re-renders never revert to the fallback. + ## The Component Input Contract Every component rendered by `@threadplane/render` receives inputs conforming to the `AngularComponentInputs` interface. Your custom props from the spec are spread as additional inputs alongside the standard ones. diff --git a/docs/superpowers/plans/2026-06-06-render-docs-technical-review.md b/docs/superpowers/plans/2026-06-06-render-docs-technical-review.md new file mode 100644 index 00000000..1e1e26fe --- /dev/null +++ b/docs/superpowers/plans/2026-06-06-render-docs-technical-review.md @@ -0,0 +1,298 @@ +# Render Docs Technical Review Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Audit all 18 render documentation pages against library source, produce a severity-ranked findings report, then ship the accuracy fixes — every snippet, API name, signature, import, behavioral claim, and link matching the implementation. + +**Architecture:** Two gated phases. Phase 1 fans out five read-only section-audit subagents (plus a completeness sweep) that cross-reference docs against ground-truth source and emit structured findings; the controller consolidates them into one report. Phase 2 fixes the report's findings grouped by section via subagent-driven development, each group re-verified against the cited source line. The a2ui pages document `@threadplane/chat` APIs, so they are audited against `libs/chat/src/lib/a2ui`, not `libs/render`. + +**Tech Stack:** MDX docs (Next.js App Router), Angular libraries (`libs/render`, `libs/chat`), `docs-config.ts` for link/nav resolution, `git diff` + source citation as the accuracy gate, dev-server/curl for render checks. + +**Reference spec:** `docs/superpowers/specs/2026-06-06-render-docs-technical-review-design.md` + +--- + +## Ground-truth source map (used by every audit task) + +| Docs section | Pages | Ground-truth source | +|---|---|---| +| getting-started | `introduction.mdx`, `quickstart.mdx`, `installation.mdx` | `libs/render/src` | +| guides | `registry.mdx`, `state-store.mdx`, `specs.mdx`, `events.mdx`, `lifecycle.mdx` | `libs/render/src` | +| concepts | `json-render-vs-a2ui.mdx` | `libs/render/src` + `libs/chat/src/lib/a2ui` | +| a2ui | `overview.mdx`, `surface-component.mdx`, `surface-store.mdx`, `catalog.mdx` | `libs/chat/src/lib/a2ui` (+ `libs/chat/src/public-api.ts`) | +| api | `render-spec-component.mdx`, `define-angular-registry.mdx`, `views.mdx`, `signal-state-store.mdx`, `provide-render.mdx` | `libs/render/src/public-api.ts` + named modules + `apps/website/content/docs/render/api/api-docs.json` | + +Confirmed exports: `A2uiSurfaceComponent` = `libs/chat/src/public-api.ts:171`; `createA2uiSurfaceStore` = `libs/chat/src/public-api.ts:163`. The render public API list is `libs/render/src/public-api.ts`. + +## Findings severity taxonomy (used by report + fix gating) + +- **P0 — wrong:** breaks copy-paste (wrong import/package, nonexistent API, wrong signature/type). +- **P1 — misleading:** runs but teaches a wrong model (incorrect behavior claim, wrong option semantics). +- **P2 — gap:** undocumented export, missing option, thin coverage. +- **P3 — polish:** stale wording, inconsistent naming, dead link. + +Finding row schema (every finding MUST use this): +`page:line` · dimension · severity · what's-wrong · source-evidence(`libs/…:line`) · proposed-fix + +Dimensions: `accuracy` | `conceptual` | `links` | `completeness`. + +--- + +# PHASE 1 — AUDIT (read-only, parallel) + +> Phase 1 produces NO docs edits. Audit subagents only read and report. The controller dispatches Tasks 1–5 concurrently (disjoint reads, no conflict), then runs Task 6, then writes the report in Task 7. + +## Tasks 1–5: Section audit subagents + +Each task dispatches ONE read-only audit subagent. The prompt template below is identical except for the **section name**, **page list**, and **ground-truth source** (from the map above). The controller fills those three fields. + +**Shared subagent prompt template:** + +``` +You are a READ-ONLY technical-docs auditor. DO NOT edit, write, or commit any file. You only read and return findings. + +Repo root: /Users/blove/repos/angular-agent-framework. Branch: claude/render-docs-technical-review. + +## Your section:
+## Pages to audit (read each in full): + +## Ground-truth source (read what you need to verify claims): + + +## Method +For every code fence, inline `code`, prose claim, and internal link in your pages, verify it against the ground-truth source. Open the source files and confirm: import paths/packages, exported symbol names, function/class signatures, generic params, option/property keys, types, and documented behavior. For internal links (href="/docs/..."), confirm the target exists in apps/website/src/lib/docs-config.ts (it builds hrefs from product/section/slug — check the entry exists, do not grep literal href strings). + +## The four dimensions to check +1. accuracy — import path/package, API name, signature, generic, option key, type matches source EXACTLY. Wrong package (e.g. @threadplane/render for an API actually exported by @threadplane/chat) or nonexistent symbol = P0. +2. conceptual — prose claims about how the thing behaves match the implementation. Runs-but-wrong-model = P1. +3. links — internal links resolve via docs-config.ts; each example is internally coherent (imports cover every symbol used; required providers present) and would compile/run as written. +4. completeness — note any obviously missing option/behavior a reader would need. (Full export-vs-docs diff is done separately — you just flag gaps you notice.) + +## Severity +P0 wrong (breaks copy-paste) | P1 misleading | P2 gap | P3 polish. + +## Return format — a markdown table, one row per finding, columns EXACTLY: +| page:line | dimension | severity | what's wrong | source evidence | proposed fix | +- page:line = relative path + line number, e.g. render/guides/registry.mdx:42 +- source evidence = libs/…:line you verified against, e.g. libs/render/src/lib/define-angular-registry.ts:88 +- proposed fix = the concrete corrected text/snippet (be specific enough to apply) +If a page is clean, write a row: | | — | clean | no issues found | | none | +Do NOT speculate — every finding must cite a real source line. If you cannot find the source for a documented symbol, that itself is a P0 finding ("documented symbol not found in source"). +End with a short "Systemic notes" paragraph: any pattern repeated across pages (e.g. wrong package used everywhere, a whole page documenting another lib's API). +``` + +- [ ] **Task 1 — getting-started.** Pages: `apps/website/content/docs/render/getting-started/{introduction,quickstart,installation}.mdx`. Source: `libs/render/src`. (Expected hit: `quickstart.mdx` imports `provideAgent` from `@threadplane/langgraph` — render has no agent concept; verify and propose the correct render snippet or removal.) Dispatch the subagent; save its returned table verbatim for Task 7. + +- [ ] **Task 2 — guides.** Pages: `apps/website/content/docs/render/guides/{registry,state-store,specs,events,lifecycle}.mdx`. Source: `libs/render/src` (esp. `define-angular-registry.ts`, `signal-state-store.ts`, `render.types.ts`, `render-element.component.ts`, `render-event.ts`, `lifecycle.ts`, `render-lifecycle.service.ts`, `contexts/repeat-scope.ts`). Dispatch; save table. + +- [ ] **Task 3 — concepts.** Page: `apps/website/content/docs/render/concepts/json-render-vs-a2ui.mdx`. Source: `libs/render/src` + `libs/chat/src/lib/a2ui`. (Verify both sides of the comparison are accurately characterized.) Dispatch; save table. + +- [ ] **Task 4 — a2ui.** Pages: `apps/website/content/docs/render/a2ui/{overview,surface-component,surface-store,catalog}.mdx`. Source: **`libs/chat/src/lib/a2ui`** (`surface.component.ts`, `surface-store.ts`, plus the component catalog/registry there) and `libs/chat/src/public-api.ts`. Explicitly check the import package on every snippet: an a2ui surface API shown as `from '@threadplane/render'` is a P0 (correct is `@threadplane/chat`). Dispatch; save table. + +- [ ] **Task 5 — api.** Pages: `apps/website/content/docs/render/api/{render-spec-component,define-angular-registry,views,signal-state-store,provide-render}.mdx`. Source: `libs/render/src/public-api.ts` + each named module + `apps/website/content/docs/render/api/api-docs.json`. Verify each documented signature/option against both the source AND the generated api-docs.json (flag drift between them). Dispatch; save table. + +## Task 6: Completeness sweep (export-vs-docs diff) + +**Files:** none (analysis). Run inline or as one subagent. + +- [ ] **Step 1: List render public exports** + +```bash +cd /Users/blove/repos/angular-agent-framework +grep -E "^export" libs/render/src/public-api.ts +``` +Expected: the full export list (types, RENDER_CONTEXT, REPEAT_SCOPE, defineAngularRegistry, signalStateStore, provideRender, RENDER_CONFIG, RenderElementComponent, RenderSpecComponent, views/withViews/overrideViews/withoutViews/toRenderRegistry, ViewRegistry, provideViews, VIEW_REGISTRY, RenderEvent family, RENDER_LIFECYCLE, RenderLifecycle, DefaultFallbackComponent, RenderViewEntry). + +- [ ] **Step 2: Cross-check each export against the docs** + +For every exported symbol, grep the render docs for a mention: +```bash +cd /Users/blove/repos/angular-agent-framework +for sym in defineAngularRegistry signalStateStore provideRender RENDER_CONFIG RenderElementComponent RenderSpecComponent views withViews overrideViews withoutViews toRenderRegistry ViewRegistry provideViews VIEW_REGISTRY RENDER_CONTEXT REPEAT_SCOPE RENDER_LIFECYCLE RenderLifecycle DefaultFallbackComponent RenderViewEntry AngularComponentInputs AngularComponentRenderer AngularRegistry RenderConfig RenderEvent RenderHandlerEvent RenderStateChangeEvent RenderLifecycleEvent RepeatScope RenderContext; do + c=$(grep -rl "\b$sym\b" apps/website/content/docs/render 2>/dev/null | wc -l | tr -d ' ') + echo "$c $sym" +done | sort -n +``` +Any symbol with count `0` is a **P2 completeness gap** (exported but undocumented). Record each as a finding. + +- [ ] **Step 3: Reverse check — documented APIs that don't exist** + +From the Task 1–5 tables, collect every API name the docs claim to export from `@threadplane/render`, and confirm each appears in `libs/render/src/public-api.ts`. Any that doesn't (and isn't a known `@threadplane/chat` a2ui API) is a **P0**. Record findings. + +- [ ] **Step 4: a2ui export check** + +```bash +cd /Users/blove/repos/angular-agent-framework +grep -nE "A2ui|a2ui" libs/chat/src/public-api.ts +``` +Confirm the a2ui symbols the docs reference are exactly these exports; record drift as findings. + +## Task 7: Consolidate the findings report + +**Files:** Create `docs/superpowers/specs/2026-06-06-render-docs-review-findings.md` + +- [ ] **Step 1: Assemble the report** + +Structure: +```markdown +# Render Docs Technical Review — Findings + +**Date:** 2026-06-06 +**Pages audited:** 18 **Source verified against:** libs/render, libs/chat/src/lib/a2ui + +## Summary +- P0: P1: P2: P3: +- Systemic issues: + +## Findings by severity +### P0 — wrong + +### P1 — misleading +### P2 — gap +### P3 — polish + +## Structural / won't-fix-here +- a2ui pages document @threadplane/chat APIs while living under render docs (relocation = separate decision). Accuracy fixed in place; placement flagged. +- + +## Fix plan +Group fixes by section (getting-started, guides, concepts, a2ui, api). List which P-levels will be fixed (default: P0+P1+P2; P3 if cheap). Structural + source-bug items are listed, not actioned. +``` +Merge the section tables verbatim into the severity buckets. Keep every source citation. + +- [ ] **Step 2: Commit the report** + +```bash +cd /Users/blove/repos/angular-agent-framework +git add docs/superpowers/specs/2026-06-06-render-docs-review-findings.md +git commit -m "docs(render): technical review findings report" +``` + +- [ ] **Step 3: CHECKPOINT — surface the report to the user** + +Present the summary counts + systemic issues + the proposed fix plan. Confirm the P-level cutoff (default P0+P1+P2, P3 if cheap) and that structural/source items stay flagged-only, before starting Phase 2. + +--- + +# PHASE 2 — FIX (subagent-driven, grouped by section) + +> One implementer task per section that HAS findings to fix (skip clean sections). Each is gated by re-verification against the cited source line. Use the report from Task 7 as the source of truth for what to change. + +**Shared fix-gate (run after each section's edits, before commit):** + +```bash +cd /Users/blove/repos/angular-agent-framework +# $FILES = edited .mdx paths for this section +git --no-pager diff $FILES # eyeball: each change matches a report finding's proposed fix +# Link re-check: every internal href in the edited pages exists in docs-config.ts (manual confirm against the product/section/slug entries) +# Import sanity: no a2ui surface API attributed to @threadplane/render +grep -rn "@threadplane/render" $FILES | grep -iE "A2uiSurface|createA2uiSurfaceStore" && echo "BAD: a2ui API mis-attributed to render" || echo "import attribution OK" +``` + +## Task 8: Fix getting-started findings + +**Files:** the getting-started pages with findings (per report). + +- [ ] **Step 1:** Dispatch an implementer subagent with the report's getting-started findings (full rows). Instruction: apply each proposed fix EXACTLY; for the `provideAgent`/`@threadplane/langgraph` snippet, replace with the correct render usage the audit specified (or remove if the example doesn't belong). Do NOT touch anything not in a finding. Re-read the cited source line before each edit to confirm. +- [ ] **Step 2:** Run the shared fix-gate on the edited files. +- [ ] **Step 3:** Spec/accuracy reviewer subagent: confirm every edit matches its cited source and no finding was missed or over-applied. Loop until clean. +- [ ] **Step 4:** Commit: `git commit -m "docs(render): fix getting-started technical accuracy issues"` + +## Task 9: Fix guides findings + +**Files:** the guides pages with findings (per report). + +- [ ] **Step 1:** Dispatch implementer with the guides findings rows; apply proposed fixes exactly; re-verify each against `libs/render/src` cited lines. +- [ ] **Step 2:** Shared fix-gate. +- [ ] **Step 3:** Reviewer subagent; loop until clean. +- [ ] **Step 4:** Commit: `git commit -m "docs(render): fix guides technical accuracy issues"` + +## Task 10: Fix concepts findings + +**Files:** `apps/website/content/docs/render/concepts/json-render-vs-a2ui.mdx` (if it has findings). + +- [ ] **Step 1:** Dispatch implementer with the concepts findings; verify both render and a2ui claims against `libs/render/src` and `libs/chat/src/lib/a2ui`. +- [ ] **Step 2:** Shared fix-gate. +- [ ] **Step 3:** Reviewer subagent; loop until clean. +- [ ] **Step 4:** Commit: `git commit -m "docs(render): fix concepts technical accuracy issues"` + +## Task 11: Fix a2ui findings + +**Files:** the a2ui pages with findings (per report). + +- [ ] **Step 1:** Dispatch implementer with the a2ui findings; ground every snippet in `libs/chat/src/lib/a2ui` + `libs/chat/src/public-api.ts`. Correct any `@threadplane/render` → `@threadplane/chat` for a2ui surface APIs. Do NOT relocate pages (structural — out of scope). +- [ ] **Step 2:** Shared fix-gate (the import-attribution grep MUST print "import attribution OK"). +- [ ] **Step 3:** Reviewer subagent; loop until clean. +- [ ] **Step 4:** Commit: `git commit -m "docs(render): fix a2ui page technical accuracy (chat-lib APIs)"` + +## Task 12: Fix api findings + +**Files:** the api pages with findings (per report); possibly regenerate `api-docs.json` if drift is the issue. + +- [ ] **Step 1:** Dispatch implementer with the api findings; verify each signature/option against `libs/render/src/public-api.ts` + named modules. If a finding is "doc drifted from generated api-docs.json", fix the doc prose to match source; if the generated JSON itself is stale, note whether `npm run generate-api-docs` is the fix (run it ONLY if the report says the generator output is wrong, and scope the commit to the render api-docs.json). +- [ ] **Step 2:** Shared fix-gate. +- [ ] **Step 3:** Reviewer subagent; loop until clean. +- [ ] **Step 4:** Commit: `git commit -m "docs(render): fix api reference technical accuracy issues"` + +## Task 13: Fill P2 gaps (only those the report chose to fill) + +**Files:** the pages where the report decided to document an exported-but-undocumented API. + +- [ ] **Step 1:** For each gap the checkpoint approved filling, dispatch an implementer to add a concise, source-accurate section/snippet (grounded in `libs/render/src`). Keep it minimal — document the API as it exists; no speculative features. +- [ ] **Step 2:** Shared fix-gate + confirm the new snippet's symbols all exist in `public-api.ts`. +- [ ] **Step 3:** Reviewer subagent; loop until clean. +- [ ] **Step 4:** Commit: `git commit -m "docs(render): document previously-undocumented exports"` + +--- + +## Task 14: Final verification + +**Files:** none (verification) + +- [ ] **Step 1: All 18 render routes return 200** + +```bash +cd /Users/blove/repos/angular-agent-framework +lsof -ti tcp:3000 >/dev/null 2>&1 || (export PATH=/Users/blove/.nvm/versions/node/v22.14.0/bin:$PATH && npx nx serve website --port 3000 > /tmp/render-review.log 2>&1 &) +sleep 25 +for p in \ + getting-started/introduction getting-started/quickstart getting-started/installation \ + guides/registry guides/state-store guides/specs guides/events guides/lifecycle \ + concepts/json-render-vs-a2ui \ + a2ui/overview a2ui/surface-component a2ui/surface-store a2ui/catalog \ + api/render-spec-component api/define-angular-registry api/views api/signal-state-store api/provide-render; do + curl -s -o /dev/null -w "%{http_code} render/$p\n" "http://localhost:3000/docs/render/$p" +done +``` +Expected: all `200`. + +- [ ] **Step 2: No new mis-attribution + no unresolved P0** + +```bash +cd /Users/blove/repos/angular-agent-framework +# No a2ui surface API imported from render anywhere in render docs: +grep -rn "@threadplane/render" apps/website/content/docs/render | grep -iE "A2uiSurface|createA2uiSurfaceStore" && echo "BAD" || echo "OK: no a2ui mis-attribution" +# No stray langgraph provideAgent left in render docs (unless report justified keeping it): +grep -rn "provideAgent" apps/website/content/docs/render || echo "OK: no provideAgent in render docs" +``` + +- [ ] **Step 3: Update the findings report status** + +Mark each fixed finding as ✅ in `2026-06-06-render-docs-review-findings.md`; leave structural/source-bug items as open. Commit: `git commit -m "docs(render): mark resolved review findings"`. + +- [ ] **Step 4: Spawn follow-ups for flagged-but-unfixed items** + +For each real `libs/*` source bug or the a2ui-relocation decision, note it for a separate task (do not fix here). + +--- + +## Manual verification (before merge) +- [ ] Every fix traces to a report finding with a source citation; no edit lacks a finding. +- [ ] All 18 routes render; internal links resolve; no a2ui→render mis-attribution; no stray `provideAgent` in render docs. +- [ ] Findings report committed and updated with resolution status; structural + source items listed, not actioned. + +## Self-Review (completed during planning) + +- **Spec coverage:** 18 pages across 5 sections audited (Tasks 1–5) ✓; four dimensions in every audit prompt ✓; completeness sweep export-vs-docs (Task 6) ✓; severity-ranked report at the spec'd path (Task 7) ✓; two-phase gated methodology with triage checkpoint (Task 7 Step 3) ✓; section-grouped fixes with source re-verification gate (Tasks 8–12) ✓; gap-fill bounded to approved items (Task 13) ✓; a2ui audited against libs/chat, relocation flagged-not-done (Tasks 4, 11; report Structural section) ✓; final render-200 + mis-attribution checks (Task 14) ✓; out-of-scope (relocation, voice, source changes, other libs) honored ✓. +- **Placeholder scan:** No TBD/TODO. Phase 2 fix snippets are intentionally report-driven (the audit produces the exact corrected text) — this is inherent to a review whose fixes aren't known until discovery; the gates (source re-verification, fix-gate grep, reviewer loop) make each edit checkable. Commands have expected output. +- **Consistency:** the ground-truth source map, severity taxonomy, and finding-row schema are defined once and referenced by every task; the a2ui→`libs/chat` mapping is identical in the map, Task 4, Task 11, and the Task 14 grep; the 18-page route list in Task 14 matches the section breakdown in Tasks 1–5; `claude/render-docs-technical-review` branch used throughout. diff --git a/docs/superpowers/specs/2026-06-06-render-docs-review-findings.md b/docs/superpowers/specs/2026-06-06-render-docs-review-findings.md new file mode 100644 index 00000000..0d45be94 --- /dev/null +++ b/docs/superpowers/specs/2026-06-06-render-docs-review-findings.md @@ -0,0 +1,105 @@ +# Render Docs Technical Review — Findings + +**Date:** 2026-06-06 +**Pages audited:** 18 (getting-started ×3, guides ×5, concepts ×1, a2ui ×4, api ×5) +**Source verified against:** `libs/render/src`, `libs/chat/src/lib/a2ui`, `libs/a2ui/src/lib/types.ts`, generated `api-docs.json` +**Method:** 5 parallel read-only section auditors + completeness sweep; every finding cites a source line; borderline findings re-verified by the controller. + +## Resolution status — ✅ ALL 17 FINDINGS FIXED + +Fixed across 5 commits on `claude/render-docs-technical-review`, each gated by a source-cited accuracy review: +- ✅ **a2ui** (#1-7, #11) — `ebe716c3` — envelope names + catalog props corrected. +- ✅ **guides** (#8, #9, #16) — `b04aa7d7` — getFallback + fallback behavior + ChatComponent origin. +- ✅ **api** (#8, #10, #15) — `29592752` — getFallback + emitEvent + signalStateStore signature. +- ✅ **concepts** (#12, #13) — `bc68c2a3` — A2uiSurface/A2uiActionMessage optional fields. +- ✅ **getting-started** (#14) — `36d7b290` — example `spec` inputs typed `input.required()`. +- (#17 thin-coverage required no action.) + +**Verification:** all 18 render routes return HTTP 200; no a2ui→render mis-attribution; no stale envelope names in the corrected pages (the two remaining mentions are an intentional "do not use" warning and a prose reference to the render compat path); no inbound links to the one renamed anchor. + +**Spawned as separate follow-ups (not in this PR):** +- api-docs.json generator signature drift (`generate-api-docs.ts`). +- a2ui-page relocation (information-architecture decision). + +## Summary + +- **P0: 5** · **P1: 2** · **P2: 6** · **P3: 4** +- **Hot spot:** `render/a2ui/catalog.mdx` (6 findings) and `render/a2ui/surface-store.mdx` (1 page-wide P0) — the A2UI pages drifted from the current protocol/catalog. +- **Systemic issues:** + 1. `surface-store.mdx` uses **obsolete A2UI envelope names** (`createSurface`/`updateComponents`/`updateDataModel`) throughout; the real protocol (libs/a2ui) is `surfaceUpdate`/`dataModelUpdate`/`beginRendering`/`deleteSurface`. Same class of staleness previously flagged in the cockpit example. + 2. `catalog.mdx` documents **wrong component prop names** for half the catalog (Button, TextField, Slider, DateTimeInput) and a nonexistent Card `title`. + 3. `getFallback()` — a real `AngularRegistry` method — is undocumented in both the registry guide and its API page. + 4. The generated `api-docs.json` has signature drift (see Structural). +- **Two suspected issues were verified as NON-issues** (see Structural): the `withViews` ordering and a "stray langgraph import." + +--- + +## Findings by severity + +### P0 — wrong (breaks copy-paste) + +| # | page:line | dim | what's wrong | source evidence | fix | +|---|---|---|---|---|---| +| 1 | render/a2ui/surface-store.mdx:38-43, 45, 53, 76-82 | accuracy | Obsolete A2UI envelope names `createSurface` / `updateComponents` / `updateDataModel` used in the message table and all JSON examples | libs/a2ui/src/lib/types.ts:220-223 (`surfaceUpdate` \| `dataModelUpdate` \| `beginRendering` \| `deleteSurface`) | Rename throughout: `createSurface`→`surfaceUpdate`, `updateComponents`→(component changes ride on `surfaceUpdate`), `updateDataModel`→`dataModelUpdate`; describe surface creation as `beginRendering`. Add `deleteSurface`. | +| 2 | render/a2ui/catalog.mdx:152-153 | accuracy | Button props listed as `label`/`variant`; real inputs are `childKeys`/`primary` | libs/chat/src/lib/a2ui/catalog/button.component.ts:52,54 | Replace rows: `childKeys: string[]`, `primary: boolean` (default true); button label comes from child components, not a `label` prop | +| 3 | render/a2ui/catalog.mdx:186 | accuracy | TextField prop listed as `value`; the input is `text` (`value` is a read-only computed alias) | libs/chat/src/lib/a2ui/catalog/text-field.component.ts:80,82 | Change row `value` → `text: string` | +| 4 | render/a2ui/catalog.mdx:240-248 | accuracy | DateTimeInput documents `inputType: 'date'\|'time'\|'datetime-local'`; real inputs are `enableDate`/`enableTime` booleans | libs/chat/src/lib/a2ui/catalog/date-time-input.component.ts:56,58 | Replace `inputType` row with `enableDate: boolean` (default true) and `enableTime: boolean` (default false); note the HTML input type is derived internally | +| 5 | render/a2ui/catalog.mdx:277-278 | accuracy | Slider props listed as `min`/`max`; real inputs are `minValue`/`maxValue` | libs/chat/src/lib/a2ui/catalog/slider.component.ts:49,51 | Change rows `min`→`minValue`, `max`→`maxValue` (keep `value`, `step`) | + +### P1 — misleading (runs/reads but wrong model) + +| # | page:line | dim | what's wrong | source evidence | fix | +|---|---|---|---|---|---| +| 6 | render/a2ui/catalog.mdx:38 | accuracy | Text component JSON uses flat `"component": "Text"` instead of the keyed-union envelope the protocol requires | overview.mdx (same page set) uses `"component": {"Text": {...}}`; matches the a2ui parser | Change to `{"id":"greeting","component":{"Text":{"text":{"literalString":"Hello, world!"}}}}` | +| 7 | render/a2ui/catalog.mdx:214 | accuracy | CheckBox documents `checked` as the prop; canonical input is `value` (`checked` is a deprecated back-compat alias) | libs/chat/src/lib/a2ui/catalog/check-box.component.ts:36,38,47 | List `value: boolean` as primary; note `checked` is a deprecated alias | + +### P2 — gap + +| # | page:line | dim | what's wrong | source evidence | fix | +|---|---|---|---|---|---| +| 8 | render/guides/registry.mdx:24-33 + render/api/define-angular-registry.mdx:29,38-41 | completeness | `AngularRegistry` has 3 methods; docs document only `get`/`names` — `getFallback()` is omitted | libs/render/src/lib/render.types.ts:42 (`getFallback(name): AngularComponentRenderer \| undefined`) | Add `getFallback(name)` to the interface block + methods table on both pages | +| 9 | render/guides/registry.mdx:35-103 | conceptual | No explanation of what renders when a type is unregistered or props are still resolving (fallback behavior) | libs/render/src/lib/render-element.component.ts:220-228 (uses `getFallback()`) | Add a short "Fallback rendering" note: unregistered type → configured fallback (or nothing); resolving props → fallback for visual feedback | +| 10 | render/api/render-spec-component.mdx:82 | completeness | `RenderContext` (RENDER_CONTEXT) section omits `emitEvent?` | libs/render/src/lib/contexts/render-context.ts:12 (`emitEvent?: (event: RenderEvent) => void`) | Add `emitEvent?: (event: RenderEvent) => void` to the documented shape | +| 11 | render/a2ui/catalog.mdx:114-116 | accuracy | Card props table lists a `title` prop that the component does not have | libs/chat/src/lib/a2ui/catalog/card.component.ts (inputs: `childKeys`, `spec` only) | Remove the `title` row | +| 12 | render/concepts/json-render-vs-a2ui.mdx:75-81 | completeness | `A2uiSurface` code fence omits optional `theme?` and `sendDataModel?` fields | libs/a2ui/src/lib/types.ts:227-243 | Add `theme?: A2uiTheme` and `sendDataModel?: boolean` to the fence (or note them in prose) | +| 13 | render/concepts/json-render-vs-a2ui.mdx:168-177 | completeness | `A2uiActionMessage` fence omits optional `label?` (action) and `metadata?` (message) | libs/a2ui/src/lib/types.ts:252-274 | Add `label?: string` to the action and `metadata?` to the message (or note in prose) | + +### P3 — polish + +| # | page:line | dim | what's wrong | source evidence | fix | +|---|---|---|---|---|---| +| 14 | render/getting-started/quickstart.mdx:27,100-101 + installation.mdx:101 | accuracy | Child components type the `spec` input as `input(null)`; the contract type is `Spec` | libs/render/src/lib/render.types.ts:15 (`spec: Spec`) | Optional: `input()` for precision. Low priority — runs fine; illustrative. | +| 15 | render/api/signal-state-store.mdx:14 | accuracy | Signature shows `initialState?` while source uses `initialState: StateModel = {}` (default already shown in the table below) | libs/render/src/lib/signal-state-store.ts:37 | Show `initialState: StateModel = {}` in the signature for consistency | +| 16 | render/guides/events.mdx:170 | conceptual | `ChatComponent` referenced without noting it's from `@threadplane/chat`, not render | render handlers are render-lib; `ChatComponent` is chat-lib | Clarify "…or other render-enabled components like `ChatComponent` (from `@threadplane/chat`)" | +| 17 | (thin coverage) DefaultFallbackComponent, RenderViewEntry, VIEW_REGISTRY | completeness | Each exported symbol is mentioned only once across render docs | libs/render/src/public-api.ts | No action required (all are documented at least once); noted for awareness | + +--- + +## Structural / won't-fix-here + +- **a2ui page placement:** `render/a2ui/*` document `@threadplane/chat` runtime APIs (`A2uiSurfaceComponent`, `createA2uiSurfaceStore`) plus `@threadplane/a2ui` protocol types. The pages **correctly attribute the package** (`@threadplane/chat`) — there is **no** `@threadplane/render` mis-import. Accuracy is fixed in place here; **relocating** these pages out of render docs is a separate structural decision (flagged, not actioned). +- **Generated `api-docs.json` drift (generator bug — separate follow-up, not a prose fix):** + - `withoutViews` signature flattened: rest param `...names: string[]` rendered as `names: string[]` (libs/render/src/lib/views.ts:46-49 is correct; the `.mdx` prose is correct; only the generated JSON is wrong). + - `AngularRegistry.getFallback` and `RenderContext.emitEvent` missing from the generated JSON. + - Root cause is `apps/website/scripts/generate-api-docs.ts` signature extraction — flag for a separate task; do not hand-edit generated JSON in this docs review. + +## Verified NON-issues (no change) + +- **`withViews` ordering:** source is `Object.freeze({ ...additions, ...base })` (libs/render/src/lib/views.ts:24-28) — base keys win on conflict, so the prose "keys that already exist in `base` are preserved" is **correct**. (One auditor mis-flagged this.) +- **"stray langgraph import":** the only `@threadplane/langgraph` reference in render docs is `import { agent }` at `render/a2ui/overview.mdx:258` — a legitimate example of a LangGraph agent as the A2UI streaming source. Not an error. + +--- + +## Fix plan (Phase 2) + +Default cutoff: **fix P0 + P1 + P2; fix P3 where it's a one-line change** (#15, #16; #14 optional). Structural + generator items are listed, not actioned. + +Grouped by section (only sections with actionable findings): + +- **a2ui** (Task 11): #1, #2, #3, #4, #5, #6, #7, #11 — the bulk. Ground every snippet in `libs/chat/src/lib/a2ui` + `libs/a2ui/src/lib/types.ts`. +- **guides** (Task 9): #8 (registry getFallback), #9 (fallback behavior), #16 (events ChatComponent clarity). +- **api** (Task 12): #8 (define-angular-registry getFallback), #10 (render-spec-component emitEvent), #15 (signal-state-store signature). +- **concepts** (Task 10): #12, #13. +- **getting-started** (Task 8): #14 only (optional P3) — may skip. + +Each section group is gated by re-verification against the cited source line + a render-200 check before commit. diff --git a/docs/superpowers/specs/2026-06-06-render-docs-technical-review-design.md b/docs/superpowers/specs/2026-06-06-render-docs-technical-review-design.md new file mode 100644 index 00000000..3d2a7443 --- /dev/null +++ b/docs/superpowers/specs/2026-06-06-render-docs-technical-review-design.md @@ -0,0 +1,144 @@ +# Render Docs Technical Review — Design + +**Date:** 2026-06-06 +**Status:** Draft for review +**Scope:** A full technical-accuracy review of all 18 render documentation pages, cross-referenced against library source, producing a severity-ranked findings report and shipping the fixes as PR(s). + +## Goal + +Make the render docs technically correct: every code snippet, API name, +signature, import path, behavioral claim, and internal link matches the actual +implementation. Catch documented-but-nonexistent APIs and exported-but-undocumented +ones. Discovery is separated from fixing so findings can be triaged before any +edit lands. + +This is a **docs accuracy** review. It does not change `libs/render` source and +does not restructure the docs; it corrects what the docs say so they match what +the code does. + +## Surface under review (18 pages, ~3,670 lines) + +`apps/website/content/docs/render/`: + +- **getting-started** (3): `introduction.mdx`, `quickstart.mdx`, `installation.mdx` +- **guides** (5): `registry.mdx`, `state-store.mdx`, `specs.mdx`, `events.mdx`, `lifecycle.mdx` +- **concepts** (1): `json-render-vs-a2ui.mdx` +- **a2ui** (4): `overview.mdx`, `surface-component.mdx`, `surface-store.mdx`, `catalog.mdx` +- **api** (5): `render-spec-component.mdx`, `define-angular-registry.mdx`, `views.mdx`, `signal-state-store.mdx`, `provide-render.mdx` (+ generated `api/api-docs.json`) + +## Ground-truth sources (per section) + +The audit compares docs against source. The mapping matters because the **a2ui +pages document `@threadplane/chat` APIs, not `@threadplane/render`**: + +| Section | Ground-truth source | +|---|---| +| getting-started | `libs/render/src` (watch quickstart's stray `@threadplane/langgraph` `provideAgent` import) | +| guides | `libs/render/src` — `define-angular-registry.ts`, `signal-state-store.ts`, `render.types.ts`, `render-element.component.ts`, `render-event.ts`, `lifecycle.ts`, `render-lifecycle.service.ts` | +| concepts | `libs/render/src` + `libs/chat/src/lib/a2ui` (it's a comparison page) | +| a2ui | **`libs/chat/src/lib/a2ui`** — `surface.component.ts`, `surface-store.ts`, and the catalog/component registry there; exports confirmed in `libs/chat/src/public-api.ts` | +| api | `libs/render/src/public-api.ts` + each named module + the generated `api-docs.json` | + +Confirmed facts from exploration: +- `A2uiSurfaceComponent` → `libs/chat/src/public-api.ts:171` (from `./lib/a2ui/surface.component`). +- `createA2uiSurfaceStore` → `libs/chat/src/public-api.ts:163` (from `./lib/a2ui/surface-store`). +- Render docs reference `@threadplane/render` ×29, `@threadplane/chat` ×9 (the a2ui pages), `@threadplane/langgraph` ×1 (the quickstart error). +- `libs/render/src/public-api.ts` is the authoritative render export list (registry, state, provider, components, views, events, lifecycle, fallback). + +## Methodology — two gated phases + +### Phase 1 — Audit (read-only, parallel) + +Five section audit subagents run concurrently. Each is read-only (NO edits) and +returns a structured findings list. Each subagent: + +1. Reads every page in its section in full. +2. Reads the mapped ground-truth source. +3. Checks the four dimensions (below) for every snippet, claim, and link. +4. Returns findings as rows: `page:line` · dimension · severity · what's wrong · + source evidence (`libs/…:line`) · proposed fix. + +Then a **completeness sweep** (one subagent or inline): diff `libs/render/src/public-api.ts` +exports against what the api/guides pages document — list exported-but-undocumented +symbols and documented-but-nonexistent ones. For a2ui, do the same against the +a2ui-related exports in `libs/chat/src/public-api.ts`. + +The controller consolidates all findings into one severity-ranked report and +flags systemic/cross-page issues (e.g., a2ui package attribution, repeated wrong +imports). + +### Phase 2 — Fix (subagent-driven-development) + +After the report is reviewed, fix **grouped by section**. Each group: +implementer applies the report's proposed fixes → re-verifies each changed +snippet against the cited source line → re-checks internal links against +`docs-config.ts` → edited pages return HTTP 200. A spec/accuracy reviewer +confirms each fix matches source and introduces no new mis-attribution before the +next group. + +## The four audit dimensions + +1. **Code-snippet accuracy** — every import path/package, API name, signature, + generic parameter, option key, and type matches source exactly. Wrong package + (e.g. `@threadplane/render` for an a2ui API) or nonexistent symbol = P0. +2. **Conceptual correctness** — prose claims about registry resolution, signal + state semantics, specs/elements structure, event/handler flow, and lifecycle + behavior match the implementation. A claim that runs but teaches a wrong model + = P1. +3. **Links + runnability** — every internal link resolves via `docs-config.ts` + (product/section/slug entries exist); each example is internally coherent + (imports cover every symbol used; required providers present) and would + compile/run as written. +4. **Completeness/gaps** — exported-but-undocumented APIs, documented-but-nonexistent + APIs, missing options/behaviors, thin coverage. + +## Findings report format + +One markdown report: `docs/superpowers/specs/2026-06-06-render-docs-review-findings.md`. + +Severity taxonomy: +- **P0 — wrong:** breaks copy-paste. Wrong import/package, nonexistent API, wrong + signature/type. (e.g. the langgraph import; any a2ui page citing + `@threadplane/render` for a chat API.) +- **P1 — misleading:** runs but teaches the wrong mental model (incorrect behavior + claim, wrong option semantics). +- **P2 — gap:** undocumented export, missing option, thin coverage. +- **P3 — polish:** stale wording, inconsistent naming, dead link. + +Each finding row: `file:line` · dimension · severity · what's wrong · source +evidence (`libs/…:line`) · proposed fix. The report ends with a +"Structural / won't-fix-here" section (e.g. a2ui relocation) listed but not +actioned. + +## Testing & verification + +- **Phase 1:** every finding carries a concrete source citation; a reviewer + spot-checks a sample of citations to confirm the audit isn't hallucinating. +- **Phase 2 per group:** each changed snippet re-verified against its cited + source line; internal links re-checked against `docs-config.ts`; edited pages + return HTTP 200; a repo-wide check confirms no a2ui page imports an a2ui surface + API from `@threadplane/render`. +- **Final:** all 18 render routes return 200; the completeness gaps the report + chose to fill are filled; the structural findings remain listed in the report. + +## Out of scope + +- **Relocating** the a2ui pages out of the render docs tree (structural decision; + flagged in the report only). +- Voice/prose-register edits (already shipped) — except where a P0/P1 correction + necessarily rewrites a sentence. +- `libs/render` (or `libs/chat`) **source** changes — real code bugs get flagged + for a separate follow-up, not fixed in this docs review. +- Net-new pages or examples beyond filling documented gaps the report identifies. +- Other libraries' docs (langgraph, chat, ag-ui, a2ui top-level, licensing, + telemetry). + +## Self-review notes + +- **Placeholder scan:** none — every section names concrete files and sources. +- **Internal consistency:** the a2ui→`libs/chat` mapping is used consistently in + the ground-truth table, the dimensions (P0 example), and the verification gate. +- **Scope:** single focused effort (one lib's docs); audit and fix are one + pipeline with a triage gate between, suitable for one plan. +- **Ambiguity:** "fix in PR" = audit findings report committed, then corrections + shipped; a2ui accuracy fixed in place, relocation only flagged.