Files
lda-wf/web
T

lda.chat Workflow Console

A local React console for inspecting workflow JSON-RPC servers. Connects to a loopback wf-rpc-server through a Hono proxy, displays capability and draft workspace reads, and keeps raw protocol evidence inspectable.

Quick Start

# Terminal 1: workflow JSON-RPC server
uv run wf-rpc-server --config wf.config.json --host 127.0.0.1 --port 8765

# Terminal 2: development (Vite + Hono)
pnpm --dir web install
pnpm --dir web dev

Open http://127.0.0.1:5173/console/discover in the browser. Paste the target URL:

http://127.0.0.1:8765/rpc

Click Connect. The console will:

  1. Validate the target is a loopback address
  2. Call workflow.health on the upstream server
  3. Display the read-only capability catalog and preserve the connection while navigating the console routes
  4. Show raw protocol evidence for each connection and workspace read

Workflow Console Routes

The root route and /console redirect to /console/discover. The routed workspace currently exposes:

  • /console/discover for searchable, source-filtered capability discovery and input/output contract inspection
  • /console/drafts for the persisted draft workspace index
  • /console/drafts/:workspaceId for the draft authoring workbench: a desktop capability palette, graph canvas, and context inspector with real draft mutations, revision/status diagnostics, and bounded raw-draft evidence
  • /console/artifacts and /console/artifacts/:artifactId/:version for the existing read-only artifact explorer
  • /console/deployments and /console/deployments/:deploymentId for deployment inspection
  • /console/runs and /console/runs/:runId for run, interrupt, and trace inspection

Enter a loopback RPC URL in Workflow JSON-RPC URL and click Connect. The health exchange establishes the target for the routed shell; subsequent read-only route calls go through the Hono /api/rpc boundary. The target and the operation-evidence ledger persist across console route navigation. The draft workbench keeps the graph as the primary touch surface on mobile and opens the capability palette and context inspector as independently scrolling, accessible full-height sheets. Forms remain mounted while sheets are closed so dirty values and selection survive palette/inspector close and reopen cycles.

Capability Playground

The Discover route includes a generated Try capability form for direct capability smoke tests. Run the local services with loopback defaults:

# Terminal 1: workflow JSON-RPC server
uv run wf-rpc-server --config wf.config.json --host 127.0.0.1 --port 8765

# Terminal 2: web console
pnpm --dir web dev

Connect to http://127.0.0.1:8765/rpc, select wf.std.concat, acknowledge the side-effect warning, and submit items: ["hello", "world"] with separator: " ". A direct capability call executes immediately against the target. It is not a workflow run and creates no graph, state, route, run, or trace records. The acknowledgement is an accidental-action guard, not authentication or authorization; capabilities may still have side effects.

wf.source.read_resource is a useful form-generation check. Its local JSON Schema $ref resolves into logical_source, uri, and the defaulted kind field instead of an unresolved reference blob. A node-spec direct call can still finish with a runtime_error when it requires workflow platform context. That completed receipt is truthful runtime behavior, not a failed form implementation; use a workflow deployment with the required platform context for the successful path.

The evidence ledger retains the target, equivalent CLI, and bounded request and response values. It keeps at most 100 records, traverses to depth 8, retains at most 100 collection entries, limits strings to 4096 characters, and limits each retained request or response to 32 KiB serialized. Sensitive keys such as authorization, cookie, token, secret, password, and api_key are redacted before evidence enters the console state.

Production Build

pnpm --dir web build
pnpm --dir web start

A single Hono process serves the built React application and API routes from http://127.0.0.1:8787.

LAN Presentation Rehearsal

Build once, then bind the production Hono server to the laptop's LAN interfaces:

pnpm --dir web build
$env:WEB_HOST = "0.0.0.0"
pnpm --dir web start

Open http://<laptop-lan-ip>:8787/presenter on the phone and http://<laptop-lan-ip>:8787/present on the audience display. Either route can Start session or Join session. Starting shows a six-character code, QR target, and opposite-route join link; the other device can scan the QR, open the link, or enter the code. Navigation is bidirectional, and the presenter route can end the session for every paired device.

Rooms are short-lived and in memory. After a temporary disconnect or reload, the client reconnects and applies the latest server snapshot; that snapshot wins over navigation performed locally while offline. A server restart or room expiry requires a new session.

This mode is for a trusted LAN only. The join code is not authentication, the built server does not provide TLS, and this runbook makes no public-internet security claim. Keep wf-rpc-server on loopback at port 8765: browser workflow operations continue through the Hono boundary on port 8787, so the workflow RPC server does not need a LAN binding.

Commands

Command Description
pnpm --dir web install Install all workspace dependencies
pnpm --dir web dev Start Vite + Hono development servers
pnpm --dir web test Run all test suites
pnpm --dir web typecheck Run TypeScript type checking
pnpm --dir web build Build the React console for production
pnpm --dir web start Start the production Hono server
pnpm --dir web test:workflow-console:e2e Build and run real-server desktop/mobile console acceptance tests
pnpm --dir web --filter @lda/workflow-rpc contract:write Regenerate TypeScript wire names and raw types from the checked workflow manifest
pnpm --dir web --filter @lda/workflow-rpc contract:check Fail when the generated TypeScript contract has drifted
pnpm --dir web --filter @lda/console test:presentation-sync:e2e:install Install the Chromium binary required by the browser smoke test
pnpm --dir web --filter @lda/console test:presentation-sync:e2e Run isolated two-context presentation synchronization smoke tests against a built server

Run the E2E install command once after pnpm install on each clean development or CI machine. Playwright keeps the matching Chromium binary in its browser cache for subsequent smoke runs.

Architecture

web/
  apps/
    console/    React + Vite frontend
    server/     Hono local server (API + static serving)
  packages/
    rpc/        Effect-based JSON-RPC client, schemas, and errors
    presentation-sync/  Bounded presentation room wire contract

The browser communicates with Hono at /api/connect and /api/rpc. Hono validates targets against loopback policy, executes typed JSON-RPC calls through Effect, and returns plain JSON DTOs to the browser.

Product And Design Context

The console app carries two design-context files:

  • apps/console/PRODUCT.md captures the strategic product contract: users, purpose, personality, anti-references, and design principles.
  • apps/console/DESIGN.md captures the current visual system: tokens, typography, components, elevation, and do/don't rules.

This structure comes from the local Impeccable design workflow. PRODUCT.md uses its product-register format, and DESIGN.md follows the DESIGN.md convention: YAML frontmatter for machine-readable tokens, followed by six fixed sections (Overview, Colors, Typography, Elevation, Components, and Do's and Don'ts). Future UI work should read these files before changing visual direction.

Workflow Console

After connecting, the console opens a route-based workspace rather than one combined explorer screen.

  • Discover searches the capability catalog and inspects typed capability contracts.
  • Drafts lists persisted draft workspaces and opens the authoring workbench for capability insertion, step edits, route edits, validation, diagnostics, revision, and raw protocol evidence.
  • Selected-step editing exposes Setup, Inputs, and Outputs tabs for a selected capability step. Inputs replace the ordered capability input bindings, while Outputs replace output-to-state bindings; the controller sends the complete canonical row list for each save. Persisted malformed rows remain visible as repair rows and block save or clear until repaired.
  • Artifacts, Deployments, and Runs provide focused lifecycle lists and detail routes, including artifact graphs, deployment validation, run interrupts, and trace evidence.
  • Evidence records JSON-RPC request and response receipts with equivalent CLI text across the workspace.
  • Pagination is available for cursor-backed artifact and run collections.

Security

  • Only loopback targets are accepted (127.0.0.1, localhost, [::1])
  • Upstream redirects are rejected
  • Request bodies are limited to 256 KiB
  • Response bodies are limited to 4 MiB
  • The server binds to 127.0.0.1 by default
  • Browser capability calls are enabled automatically only when WEB_HOST is loopback
  • A non-loopback bind requires the explicit override WEB_ENABLE_CAPABILITY_CALLS=1 before the Try capability surface can call upstream capabilities
  • TLS-terminating proxies can allow exact browser origins with the comma-separated WEB_TRUSTED_ORIGINS setting. Forwarded headers are not trusted implicitly.

The non-loopback override is an explicit risk acceptance for a trusted environment, not authentication, TLS, tenant isolation, or a public-internet security boundary. It can let LAN clients execute side-effecting capabilities against the configured workflow target:

pnpm --dir web build
$env:WEB_HOST = "0.0.0.0"
$env:WEB_ENABLE_CAPABILITY_CALLS = "1"
$env:WEB_TRUSTED_ORIGINS = "https://workflow-console.example"
pnpm --dir web start

Smoke Test

With the Python server running, verify in the browser:

  1. The initial page makes no upstream request
  2. Connect succeeds against http://127.0.0.1:8765/rpc
  3. Capability discovery returns catalog entries and supports qualified-name inspection
  4. Raw health and capability exchanges are selectable in the evidence inspector
  5. Equivalent CLI text is visible
  6. Select Try capability, acknowledge the immediate-call warning, and submit wf.std.concat with items: ["hello", "world"] and separator: " "; verify hello world, the target-bearing evidence receipt, and no workflow run or trace record
  7. Select wf.source.read_resource; verify logical_source, uri, and the defaulted kind field render, then verify a completed runtime_error receipt when it is called without platform context
  8. Create a draft, add and edit a capability step, set a route, validate, and reload its direct draft URL while checking graph and evidence state
  9. http://example.com:8765/rpc is rejected without upstream fetch
  10. Stopping the Python server produces the unreachable state while preserving the entered URL
  11. Persisted draft workspaces populate and a selected draft shows its graph, diagnostics, and revision
  12. Artifact, deployment, and run routes populate independently
  13. Selecting an artifact shows its plan graph and detail panel
  14. Selecting a run shows trace frames and interrupt details
  15. Clicking a trace frame shows resolved input and output

LDA Report Workflow Smoke

# Terminal 1: start the workflow server with the report example
uv run wf-rpc-server --config examples/lda_report_workflow/wf.config.json --host 127.0.0.1 --port 8765

# Terminal 2: start the console dev server
pnpm --dir web dev

Connect to http://127.0.0.1:8765/rpc. The smoke passes when capability discovery, draft inspection, lifecycle routes, graph visualization, trace frames, and raw evidence are visible.

lda Report Workflow Demo

Start the prepared workflow RPC server from the repository root:

uv run wf-rpc-server --config examples/lda_report_workflow/wf.config.json --host 127.0.0.1 --port 8765

Start the web console:

pnpm --dir web dev

Open http://127.0.0.1:5173/, connect to http://127.0.0.1:8765/rpc, then use the lda report workflow demo panel. The panel expects lda_report_case_study.default to already exist in the connected store. If it is missing, the panel displays the exact product CLI setup commands.

Demo Timeline Modes

  • Live executes the prepared deployment through public JSON-RPC calls.
  • Replay uses the committed lda-report-success-v1 recording and does not contact the workflow server during playback.

Start presentation begins autoplay. Pause stops before the next operation, and Next applies exactly one operation or recorded event. Playback always stops at issue_review; approval remains a human action in both modes. Replay is visibly labeled and does not create real issues.

Presentation Mode

The console exposes /present, a 720p no-scroll defense compositor for the prepared lda_report_workflow story. It renders a 13-scene, multi-beat storyboard with an adaptive aspect-ratio canvas, stable stage regions, discussion branches, one editorial canvas, persistent scene-aware assistant surfaces, and keyboard navigation.

The companion /presenter route is a speech and Q&A reader. It uses the same #scene/<scene>/<beat> and #discuss/<branch> hashes, shows target and cumulative timing, keeps optional detail/evidence/Q&A collapsed, and links to the corresponding audience slide in a new tab. It performs no workflow RPC, replay, or live-target operations. Its shared pairing controller synchronizes canonical navigation hashes with /present through Hono without duplicating storyboard semantics. Use ArrowLeft and ArrowRight to move between notes; covered checkboxes remain local to the page. Must-say notes support authored inline Markdown emphasis for rapid scanning, and the stable Previous/Next bar remains available at narrow viewport widths.

The final presentation beats frame the evaluation as bounded evidence, make claim boundaries and future work explicit, and end on the canonical defense discussion index rather than a benchmark or generic conclusion.

Scenes 7 and 8 use the canonical prepared-authoring recording as their only execution evidence. Scene 7 is a single full-screen chat-entry beat: its prefilled request is submitted locally, then reveals the first deterministic user, assistant, and Discover tool group. It is deterministic replay, not a live LLM chat, and does not start a workflow run. Scene 8 breaks the prepared authoring into six beats with a persistent prepared-agent assistant pane on the left and a dominant phase canvas on the right. The adaptive split starts near 26/74 and keeps the matching prepared tool group synchronized with each factual source, graph, repair, artifact, or deployment view. Neither scene calls workflow authoring RPC operations — they consume deterministic prepared data. Scenes 9 through 11 use the canonical replay by default when no live target is available. When the resolved target is healthy, the same prepared run flow can execute through the public JSON-RPC operations and record live evidence using the same DemoRunFacts projection. Raw protocol payloads are available through the evidence receipt and inspector.

Scenes 711 share one compact footer demo rail. Scene 7 remains a local scripted conversation, with its chat composer as the main surface, while the rail owns Run prepared workflow, replay fallback, retry, running, paused, resuming, and completed labels. With a healthy target, the rail starts the live chain through the existing /api/rpc proxy; when health fails, it keeps Play replay walkthrough as an explicit fallback. The presentation does not silently replace a live failure with recorded evidence.

For local live rehearsal, run both services:

pnpm --dir web dev
uv run wf-rpc-server --config examples/lda_report_workflow/wf.config.json --host 127.0.0.1 --port 8765

The browser runs on 5173, the console server proxy runs on 8787, and the workflow RPC server listens on 8765/rpc.

The presentation chat surface is source-owned and follows the AI Elements conversation/message/tool/prompt-action model. It currently renders the prepared timeline agent and approval flow; a future AI SDK driver should target AgentMessagePart / TimelineAgent-compatible events instead of replacing the presentation timeline.

The key deep-link-addressable defense states include:

  • /present#scene/agent-handoff/request — Scene 7, prepared authoring request
  • /present#scene/prepared-lifecycle/discover — Scene 8, discover phase
  • /present#scene/prepared-lifecycle/draft — Scene 8, draft phase
  • /present#scene/prepared-lifecycle/deployment — Scene 8, deployment phase
  • /present#scene/run-from-deployment/operation — Scene 9, run operation
  • /present#scene/run-from-deployment/graph — Scene 9, workflow graph
  • /present#scene/typed-human-boundary/approval — Scene 10, typed approval
  • /present#scene/resume-output-evidence/resume — Scene 11, resume proof

Legacy aliases from the earlier 12-scene plan (such as workflow-demo and interrupt-evidence) are replaced by the IDs above and no longer resolve.

Scene 11 is factual by design. It projects the reviewed/live run into visible workflow input, interrupt payload, resume decision, output, and trace facts. Empty trace frame objects are shown as captured empty objects; absent fields are called out as not captured rather than replaced by generic placeholders.

pnpm --dir web dev
# open http://127.0.0.1:5173/present

Navigation

  • ArrowRight / Space: advance to the next beat within a scene, then to the next scene
  • ArrowLeft: rewind to the previous beat or scene
  • Escape: close overlays in priority order (node spotlight, evidence, discussion)
  • P: toggle presenter controls

Hash Format

  • Main scenes: #scene/<scene-id>/<beat-id>
  • Discussion branches: #discuss/<branch-id>

Invalid hashes fall back to the first scene and beat.

Chat Modes

Chat is composed per-beat with four modes: hidden, full, rail, and dock. When dock is active, a floating button in the lower-left corner expands the chat to rail.

Presentation Canvas

The presentation uses one warm Editorial Canvas across all scenes. Dark surfaces are local to product evidence such as chat, graphs, traces, and terminal-style operation blocks; they are not whole-stage themes.

Discussion Branches

Five discussion branches exist under the positioning scene. Opening a branch from the main scene saves the originating beat as the return location. Direct hash links to #discuss/<branch-id> return to the parent scene's first beat.

Replay-First Startup

Replay is the default mode. The demo timeline auto-starts in replay using the committed lda-report-success-v1 recording. No RPC server is required.

Editorial Canvas

The presentation renders on an adaptive editorial canvas that derives its aspect ratio from the browser viewport. The canvas fills the available viewport while clamping its aspect ratio between 4:3 and 16:9. It intentionally avoids transform: scale(...): React Flow figures, popovers, and floating UI measure DOM geometry, so the stage must expose real element positions instead of scaled coordinates. No URL query parameters or local-storage settings control the ratio.

Scene 6 uses a recursive Interactive Figure with expand/collapse and breadcrumb navigation.

Key Scene 6 deep links:

  • /present#scene/architecture/client — root architecture overview
  • /present#scene/architecture/runtime/focus/runtime-providers — one level deep
  • /present#scene/architecture/runtime/focus/runtime-providers/configured-providers — two levels deep

Figure Controls

  • Enter / click: expand a child figure
  • Escape: pop one focus level
  • Tab / arrows: move focus between figure nodes without advancing the presentation
  • Breadcrumbs: jump to any ancestor focus level

Evidence Presentation

Evidence availability never resizes the primary presentation region. Each beat may request an evidence presentation state (hidden, receipt, or inspector), and a global override can be set through the presentation tool. The state is cleared on scene navigation (next, previous, jump) but preserved through discussion transitions.

  • Receipt: a compact bottom-row button showing the count and label of available evidence records. Clicking opens the inspector.
  • Inspector: a centered modal dialog with Interpreted and Raw tabs, a record selector, and focus trapping. Escape closes the inspector.

Constraints

This plan deliberately defers:

  • AI Elements / Vercel AI chat primitives
  • Live LLM driver integration
  • Public-internet presentation hosting, TLS, and authentication
  • Final visual polish and motion choreography

Constrained Demo Agent

/present includes a prepared agent recipe for the thesis readiness report. The recipe is deterministic: it emits standard chat message parts, workflow tool calls, and presentation tool actions without requiring a model provider key.

The current prepared recipe can:

  • identify the lda_report_case_study.default workflow deployment;
  • show tool calls for run start, resume, and trace read;
  • focus the review_issues interrupt node through a presentation tool action;
  • open evidence linked to the run trace.

This is intentionally not a general autonomous planner. A future server-side Vercel AI SDK driver can feed the same message-part interface.

Authoring Story (Scenes 7 and 8)

Scenes 7 and 8 are the prepared authoring story. They use deterministic data from the committed projectPreparedAuthoring() recording and never call workflow authoring RPC operations.

  • Scene 7 (Agent Request): a single full-screen deterministic chat entry that pre-fills the report-authoring request. Send is local presentation state and reveals the first prepared Discover tool group. This is not a live LLM chat or workflow run.

  • Scene 8 (Prepared Workflow Lifecycle): a six-beat lifecycle (discover, draft, diagnose, repair, artifact, deployment) with a compact phase rail and one dominant factual product projection per beat. A persistent prepared assistant pane stays visible on the left while the phase canvas remains dominant on the right; the starting split is approximately 26/74 and adapts to the available width. Its active tool group follows the current beat. There is no lower chat dock, detached trace modal, or second transcript.

    One staged message box remains visible in every phase. Discover starts empty with useful placeholders; Draft and Artifact use the exact next authoring prompts. Sending an edited Draft advances through Diagnose and Repair and preserves that text as the projected user turn; sending an edited Artifact does the same for Deployment. Deployment Send records only Run request prepared for the next execution slice. and makes no run or RPC request.

The authoring scenes consume deterministic prepared data and never call workflow authoring RPCs. Scene 8 ends at the truthful run-request handoff; Scenes 911 own run activation, typed approval, resume, output, and trace evidence. No Scene 8 message submission starts a workflow run.

Demo Climax (Scenes 711)

Scenes 7 through 11 are the demo climax. They keep a continuity rail visible while the prepared replay moves from persisted workflow run, to typed human interrupt, to resume/output/evidence. The rail and outcome panel are presentation-only projections over the committed replay; they do not add live backend dependencies.