216 lines
11 KiB
Markdown
216 lines
11 KiB
Markdown
---
|
|
created: 2026-09-05
|
|
status: complete
|
|
requirements:
|
|
- REQ-UI-NATIVE-HTML-PREVIEW-001
|
|
system_design:
|
|
- ../../specs/ui/system-design/native-html-preview.md
|
|
legacy_specs: []
|
|
---
|
|
|
|
# Implementation Plan: Trusted Browser HTML File Preview
|
|
|
|
## Overview
|
|
|
|
Replace the QuickJS and virtual-DOM implementation with a one-click static
|
|
preview server in agentctl. Publish the current editor buffer as an in-memory
|
|
entry document. Serve relative workspace assets from disk. Desktop and mobile
|
|
replace the active file editor body with the focused iframe. The Browser panel
|
|
remains an explicit secondary desktop action.
|
|
|
|
The product owner selected the trusted native-browser model. Implementation and
|
|
documentation must state that previewing executes trusted workspace code and
|
|
must not claim hostile-content isolation.
|
|
|
|
## Scope
|
|
|
|
### In scope
|
|
|
|
- An ephemeral loopback static server owned by each agentctl instance.
|
|
- Bounded in-memory overlays for current, unsaved HTML buffers.
|
|
- Workspace-rooted relative asset serving with traversal and symlink-escape
|
|
protection.
|
|
- A session-authorized backend publish endpoint and agentctl client contract.
|
|
- Existing session port-proxy routing for every supported executor.
|
|
- Desktop in-editor iframe, `Show code`, refresh, and optional Browser-panel
|
|
behavior.
|
|
- A full-height mobile iframe with the same recovery and preserved editor state.
|
|
- Localized trusted-code, progress, error, and retry copy in all locales.
|
|
- Removal of the preview-specific QuickJS and direct parse5 dependencies, the
|
|
virtual DOM, worker code, and obsolete tests.
|
|
- Public documentation and focused backend, frontend, E2E, and desktop checks.
|
|
|
|
### Out of scope
|
|
|
|
- An untrusted-content security boundary or dedicated preview origin.
|
|
- Framework builds, HMR, server-side routes, or package installation.
|
|
- Review-diff previews, source mapping, and new Browser-panel inspector features.
|
|
- Replacing explicit development-server commands for non-static applications.
|
|
|
|
## Technical approach
|
|
|
|
### Workspace preview server
|
|
|
|
Add a concurrency-safe manager to agentctl. It binds one loopback ephemeral port
|
|
per selected workspace or repository root. The manager publishes up to 32
|
|
current-buffer overlays of at most 5 MiB each. It stops all servers with the
|
|
agentctl instance. Exact overlay paths win over disk content. All responses use
|
|
`Cache-Control: no-store`.
|
|
|
|
The server resolves request paths with the existing repository path helpers and
|
|
rejects traversal, encoded traversal, and symlink targets outside the selected
|
|
root. It does not rewrite document content or emulate browser behavior.
|
|
|
|
### Session publish contract
|
|
|
|
Add a task-session endpoint that authenticates the session, ensures agentctl is
|
|
ready, bounds the request, and forwards `{repo, path, content}`. Agentctl repeats
|
|
validation and returns `{port, path, version}`. The frontend builds the existing
|
|
session port-proxy URL and appends the version as a cache buster.
|
|
|
|
### Responsive UI
|
|
|
|
Desktop and mobile keep the file tab identity and replace the source body with
|
|
`HtmlPreviewContent` after publication. Kandev-owned chrome provides `Show
|
|
code`, refresh, errors, retry, and an optional desktop Browser-panel action.
|
|
Preview state is scoped to the active session and file identity and is not
|
|
restored across reloads.
|
|
|
|
Before execution, user-facing copy identifies the action as trusted workspace
|
|
code. The iframe uses the existing Browser-panel sandbox policy. The feature
|
|
does not add an isolation claim or browser capability filter.
|
|
|
|
### Migration and documentation
|
|
|
|
Delete the worker runtime, virtual DOM, Shadow DOM renderer, navigation
|
|
normalizer, and preview-only QuickJS/direct parse5 dependencies. Keep Markdown
|
|
behavior and explicit development-server controls unchanged. Update public
|
|
guidance to distinguish the zero-configuration static preview from application
|
|
development servers and to state the trust consequence.
|
|
|
|
## Acceptance evidence
|
|
|
|
| Acceptance criteria | Evidence |
|
|
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| `.1`, `.2`, `.3`, `.7`, `.8`, `.9`, `.10` | Frontend API/component tests plus desktop and mobile E2E for current buffers, in-editor toggling, explicit Browser-panel opening, trust copy, source preservation, and recovery |
|
|
| `.4`, `.5`, `.11` | Agentctl server tests and browser E2E for native scripts, browser APIs, relative assets, bounds, path containment, eviction, and shutdown |
|
|
| `.6` | Backend handler/client tests plus existing session port-proxy regression coverage |
|
|
|
|
## Work orders
|
|
|
|
### Trusted Browser delivery
|
|
|
|
- [done] [Task 10: Build the agentctl workspace preview server](task-10-agentctl-workspace-preview-server.md)
|
|
- [done] [Task 11: Add the session publish contract](task-11-session-preview-publish-contract.md)
|
|
- [done] [Task 12: Replace the virtual runtime with Browser-panel UI](task-12-browser-panel-preview-ui.md)
|
|
- [done] [Task 13: Document and prove browser-fidelity preview](task-13-browser-fidelity-docs-and-e2e.md)
|
|
|
|
### In-editor preview revision
|
|
|
|
- [done] [Task 14: Move desktop HTML preview into the file editor](task-14-in-editor-html-preview.md)
|
|
- [done] [Task 15: Revise preview guidance and browser E2E](task-15-in-editor-preview-docs-e2e.md)
|
|
|
|
### Superseded implementation work
|
|
|
|
Tasks 01 through 04 describe the original scriptless prototype. Tasks 05
|
|
through 09 describe the QuickJS and virtual-DOM implementation. They are
|
|
retained for traceability but cancelled because the selected product contract
|
|
is native browser fidelity:
|
|
|
|
- [cancelled] [Task 01: Establish preview state and sandbox contract](task-01-preview-state-and-sandbox.md)
|
|
- [cancelled] [Task 02: Add responsive HTML preview surfaces](task-02-responsive-html-preview.md)
|
|
- [cancelled] [Task 03: Publish HTML preview guidance](task-03-public-html-preview-guidance.md)
|
|
- [cancelled] [Task 04: Prove responsive HTML preview flows](task-04-responsive-html-preview-e2e.md)
|
|
- [cancelled] [Task 05: Build the capability-free preview runtime](task-05-script-capable-preview-runtime.md)
|
|
- [cancelled] [Task 06: Integrate the runtime with preview state and renderer](task-06-preview-state-and-renderer.md)
|
|
- [cancelled] [Task 07: Wire responsive preview surfaces](task-07-responsive-preview-surfaces.md)
|
|
- [cancelled] [Task 08: Publish script-capable preview guidance](task-08-script-capable-preview-guidance.md)
|
|
- [cancelled] [Task 09: Prove script execution and isolation](task-09-script-capable-preview-e2e.md)
|
|
|
|
## Dependency order
|
|
|
|
```text
|
|
Task 10 agentctl server
|
|
|
|
|
v
|
|
Task 11 session contract
|
|
|
|
|
v
|
|
Task 12 responsive UI and runtime removal
|
|
|
|
|
v
|
|
Task 13 docs, E2E, and final verification
|
|
|
|
|
v
|
|
Task 14 in-editor desktop preview
|
|
|
|
|
v
|
|
Task 15 revised docs and E2E
|
|
```
|
|
|
|
Tasks 10 and 11 establish the serving and authorization boundary before any UI
|
|
depends on it. Task 12 removes the old runtime only after the end-to-end URL can
|
|
be produced. Task 13 verified the first shipped flow. Tasks 14 and 15 revise the
|
|
desktop presentation without changing the serving boundary, then update its
|
|
documentation and browser evidence.
|
|
|
|
## Risks
|
|
|
|
- Same-origin Browser-panel content can exercise Kandev/browser authority. This
|
|
is an accepted product tradeoff and must remain visible to users.
|
|
- Agentctl server teardown and overlay locking must cover stop, restart, and
|
|
executor failure paths without leaking listeners or data.
|
|
- Proxy rewriting and capability cookies must preserve relative, root-relative,
|
|
redirect, module, and fetch requests.
|
|
- Multi-repository roots and symlinks can accidentally widen filesystem access
|
|
unless existing canonical path helpers are used consistently.
|
|
- In-editor preview state must not outlive its session or file identity, and
|
|
stale publish completions must not replace another file's source body.
|
|
- Removing runtime packages changes the shared lockfile and generated license
|
|
catalog. The Markdown renderer still owns transitive parse5 licenses, so the
|
|
verification must distinguish those from the removed preview dependency.
|
|
|
|
## Completion gate
|
|
|
|
The package is ready to merge after all required checks pass. These checks cover
|
|
the backend, frontend, documentation, localization, E2E, desktop, dependencies,
|
|
licenses, and PR CI. Every review thread must have a disposition before merge.
|
|
|
|
## Verification results
|
|
|
|
- Agentctl API tests and race tests passed, including deterministic concurrent
|
|
publish/read, per-root ports, and HEAD/405 method coverage.
|
|
- Full backend tests passed with the task-host internal config overrides cleared.
|
|
- Focused frontend tests passed: 13 files and 69 tests, including stale
|
|
session completion guards.
|
|
- Agentctl client and task-handler tests passed for typed 400/413/503
|
|
propagation, malformed responses, oversized requests, and unavailable
|
|
sessions. The unused lifecycle forwarding layer was removed.
|
|
- Web typecheck, lint, i18n checks, i18n ratchet, license generation, and Vite
|
|
E2E build passed.
|
|
- Public-doc validation passed: 61 tests and 43 published pages.
|
|
- Raw desktop Chromium and mobile Chrome preview suites passed: 2 tests each.
|
|
- Desktop shell E2E passed.
|
|
- Fresh desktop and mobile screenshots were captured, inspected, and compressed
|
|
for the pull request.
|
|
- Reproduced and fixed the CI-only frontend failure in the saved-repository
|
|
picker by synchronizing the Radix menu dismissal and asynchronous discovery
|
|
assertions.
|
|
- Disabled Happy DOM main-frame and child-frame fixture navigation, and isolated
|
|
Vitest-importable E2E utilities from Playwright runtime imports to remove the
|
|
unhandled loopback `ECONNREFUSED` failures.
|
|
- The full frontend suite passed after the fix: 1,871 test files, 15,869
|
|
passed, and 4 skipped, with no unhandled network errors.
|
|
- Re-ran desktop and mobile native preview E2E locally: 2 tests passed in each
|
|
project. Web lint, direct web typecheck, i18n checks, and formatting checks
|
|
also passed.
|
|
- Revised the desktop presentation so `Preview HTML` replaces the active editor
|
|
body instead of automatically opening a Browser panel. Focused frontend
|
|
coverage passed 6 files and 22 tests, including source recovery, latest-buffer
|
|
refresh, explicit Browser-panel opening, and file/session identity resets.
|
|
- Revised desktop and mobile preview E2E passed 2 tests in each project on the
|
|
first attempt. Specification validation passed all 30 tests, public-doc
|
|
validation passed 61 tests across 46 pages, and desktop shell E2E passed.
|
|
- The final full frontend suite passed 1,872 test files and 15,902 tests, with
|
|
four intentional skips and no failures.
|