-
Notifications
You must be signed in to change notification settings - Fork 0
Architecture
How the command and the local review server work when you run them.
The extension has two parts:
-
A markdown command.
commands/speckit.axi.review.mdis a prompt the Spec Kit assistant reads. It has no runtime of its own; the assistant follows it. -
A local review tool.
.specify/extensions/axi/templates/web-review/axi-server.mjsis a small Node program that uses only the Node standard library (zero dependencies). The assistant launches it withnode. Unlike a pure-text extension, this part does have a runtime: a short-lived HTTP server bound to127.0.0.1.
The browser talks to the server; the agent talks to the server through its subcommands. The server bridges the two.
The pieces are deliberately small and dependency-light.
-
Review server (
.specify/extensions/axi/templates/web-review/axi-server.mjs): the Node standard library only.node:httpruns the loopback server,node:fsreads the markdown and watches for edits,node:cryptoderives the per-feature state directory. No third-party packages and no install step; the agent runs it withnode. - Browser surface: a single static page (HTML, CSS, and a small amount of JavaScript) that the server serves from loopback. It holds the annotation and chat interactions and the live status of the session.
-
Markdown rendering: done in the browser by
marked,DOMPurify, andmermaid, loaded from a pinned CDN. See Rendering. -
Transport: HTTP over loopback throughout, with no WebSocket. The
browser fetches content with plain requests and gets live updates over a
server-sent events (SSE) stream. The agent runs the CLI subcommands
(
start,poll,reply,end,stop), which reach the server over HTTP, and receives the queued notes by long-polling. - Queue format: the agent receives the reviewer's notes as TOON, a compact tabular encoding that costs fewer tokens than JSON. See Annotation Format.
At runtime nothing leaves your machine except the renderer's CDN fetch. The markdown and your notes are served only over loopback.
The agent-facing command line follows the AXI conventions for tools that agents drive over a shell, which is where the TOON output and the content-first command responses come from. The review surface itself was inspired by lavish-axi.
You run /speckit.axi.review [feature-dir]
↓
The slash command resolves to commands/speckit.axi.review.md
↓
The agent resolves the feature directory (argument, branch, or most recent specs/*)
↓
The agent runs: node .specify/extensions/axi/templates/web-review/axi-server.mjs start <feature-dir>
↓
The server binds to 127.0.0.1 on an open port and opens your browser
↓
The browser fetches the rendered markdown; you annotate and click Send
↓
The agent's `poll` returns the queue; the agent edits the .md files
↓
fs.watch detects the edit and pushes a live reload to the browser
↓
The agent runs `reply` with a summary; repeat until you end the session
↓
The agent runs `stop`; the server exits
The server holds the session in memory and bridges the two sides over HTTP on loopback. Neither side talks to the other directly; both talk to the server.
The browser uses plain requests for content and one long-lived stream for updates:
-
GET /api/manifestlists the feature's markdown files;GET /md/<file>returns one raw file. -
PUT /api/queuesaves the working queue to disk so it survives a page reload;POST /api/sendhands the queue to the agent when you click Send. -
GET /api/eventsis a server-sent events stream. The server pushesstatus(is the agent listening),reload(a file changed),reply(an agent message), andendedover it.
The agent drives the session through its CLI, which calls the matching endpoints:
-
pollis a long-poll onGET /api/poll. It blocks until you click Send, then returns your notes as TOON and prints them. While it waits, the server marks the agent as connected and pushes astatusevent, so the browser shows "agent ready". -
replyposts to/api/reply; the server relays it to the browser as areplyevent.endandstopclose the session and the server.
So one round trip is: you click Send, the browser posts the queue to
/api/send, the blocked poll returns it as TOON, the agent edits the .md
files, a recursive fs.watch on the feature directory (debounced) fires, the
server broadcasts reload, the browser re-fetches the current document, and
reply posts a one-line summary to the chat. Each queued note carries its
kind (anno or chat), the file, the nearest heading, the quoted text, and
your comment; see Annotation Format.
The queue and the server handshake are persisted under
.speckit-axi/<feature>-<hash>/ in your project (queue.json and
server.json). They never leave your machine.
The browser renders each document with marked for markdown, DOMPurify to
sanitize the result, and mermaid for fenced mermaid diagrams. These
libraries load from a pinned CDN, so they never reach the Node server and the
server stays dependency-free. Because the renderer is fetched from a CDN, the
pages need an internet connection; offline, the surface shows a notice. The
markdown itself and your notes are served only from loopback.
The feature's .md files are canonical. The agent edits them in place, only as
your queued notes direct, and never writes a derived copy. Everything the
server keeps (sessions, the queue) is local working state under .speckit-axi/
and is discarded when you stop the server. The review surface changes how you
review the markdown, not what is authoritative: the files on disk remain the
single source of truth.