Skip to content
Open
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
7d42db1
feat: real-time SSE delivery, always-on send, reply threading
Jun 24, 2026
aebd11e
fix(ui): hide reply indicator when no reply target
Jun 24, 2026
fb4abec
fix(store): serialize session-store operations to stop dropped/duplic…
Jun 24, 2026
670c240
fix(server): cap concurrent /api/stream connections
Jun 24, 2026
ab708b1
style(css): fix prettier drift on .reply-indicator[hidden]
Jun 24, 2026
3b51615
fix(cli): only count user-message frames toward stream delivery / --once
Jun 24, 2026
03a7e63
fix(store): make message ids server-owned and validate reply_to targets
Jun 24, 2026
73deffd
docs(security): note unauthenticated endpoints are loopback-only by d…
Jun 24, 2026
94be3a1
fix(stream): deliver-then-ack so a disconnect mid-drain never loses m…
Jun 25, 2026
6850c40
fix(cli): drain all buffered stream frames before honoring --once stop
Jun 25, 2026
8eec657
fix(stream): atomic take + requeue, server-side --once, leak-safe cle…
Jun 25, 2026
d33d059
fix(poll): requeue undelivered feedback on disconnect; keep once dom_…
Jun 25, 2026
3b89755
fix(server): early poll close-tracking, wake on requeue, exactly-once…
Jun 25, 2026
7a427fb
fix(stream): surface a requeue failure instead of silently dropping t…
Jun 25, 2026
76b39a9
fix(poll): requeue on a synchronous write failure in the woken respon…
Jun 25, 2026
02261eb
fix(ui): stop the "Replying to:" indicator overflowing horizontally
Jun 25, 2026
97003a4
feat(ui): inline markdown in agent messages + reply to your own messages
Jun 25, 2026
f1db880
docs: thread panel (Slack-style slide-out) design spec
Jun 25, 2026
ab0d774
docs: thread panel implementation plan
Jun 25, 2026
6ac741b
docs: note Task 4/5 coupling in thread-panel plan
Jun 25, 2026
bca4f98
feat(ui): pure threading helpers (root resolve, grouping, chip, badge…
Jun 25, 2026
f403e1a
chore: prettier-fix pre-existing docs files flagged by format:check
Jun 25, 2026
dd38f8e
feat(ui): thread-pane scaffold in chrome HTML (chat-pane + thread-pane)
Jun 25, 2026
89b1595
feat(ui): thread-panel styles (slide-out pane, chip, Back button + ba…
Jun 25, 2026
e36f04e
feat(ui): render roots + thread chips, slide-out thread view, open/close
Jun 25, 2026
1d2b1be
feat(ui): main composer starts roots; thread composer sends replies w…
Jun 25, 2026
9c19fab
feat(ui): live-route agent replies into the open thread; Back badge f…
Jun 25, 2026
90281b4
chore: prettier-ignore .superpowers SDD scratch dir
Jun 25, 2026
f1522b4
feat(ui): per-message reply targeting in thread view
Jun 25, 2026
73acdd9
fix(threading): reply tri-state, optimistic id, ISO timestamp + seam …
Jun 25, 2026
7841f7f
chore(css): remove dead .reply-quote rule (nothing emits that class)
Jun 25, 2026
3b31cf2
fix(threading): don't thread/target optimistic (local-) messages unti…
Jun 25, 2026
35be448
test(chat): regression guards for the disappearing user-message bug
Jun 25, 2026
9c258e7
docs: annotation actions (Cancel/Queue/Send) design spec
Jun 26, 2026
30fa4b4
docs: unread thread replies design spec
Jun 26, 2026
29c1468
docs: plan for annotation actions + unread thread replies
Jun 26, 2026
c5da794
docs: renumber plan tasks to 1/2/3 for task-brief extraction
Jun 26, 2026
a381240
feat(annotate): explicit Cancel / Queue / Send actions on the annotat…
Jun 26, 2026
ed38e26
feat(ui): session-only unread read-model for threads (baseline, mark-…
Jun 26, 2026
654451e
feat(ui): unread thread chips — solid brass + dot + 'N new'
Jun 26, 2026
7111e9f
fix(ui): baseline/mark-seen before render so chips paint correct read…
Jun 26, 2026
209919b
fix(ui): repaint thread list on open so a read thread's chip clears i…
Jun 26, 2026
c930629
fix(ui): scope layout-gate curtain to the artifact frame so it never …
Jun 27, 2026
3d11d4b
no-mistakes(review): fix pre-await disconnect leaks in /api/stream an…
Jun 27, 2026
d92af95
no-mistakes(document): document SSE stream command, message threading…
Jun 27, 2026
ecd8147
no-mistakes(document): surface stream command in home, skill, and top…
Jun 27, 2026
6c0f10a
docs(agents): item 10 — sends are always-on, blocked only when the se…
Jun 28, 2026
341623f
chore: untrack .superpowers scratch dir; drop its .prettierignore patch
Jun 28, 2026
330a03d
no-mistakes(review): fix sendChatSync write-after-end, render id-less…
Jun 28, 2026
712b882
no-mistakes(document): note streams defer idle shutdown in server com…
Jun 28, 2026
ff4fa9e
Merge branch 'main' into feat/realtime-sse-threading
Jul 12, 2026
2d70c1b
Merge branch 'main' into feat/realtime-sse-threading
Jul 14, 2026
29b8c38
Merge branch 'main' into feat/realtime-sse-threading
Jul 21, 2026
62e5116
Merge branch 'main' into feat/realtime-sse-threading
Aug 25, 2026
5d58255
Merge remote-tracking branch 'origin/main' into merge/main-into-sse
Aug 25, 2026
1074dc6
no-mistakes(review): fix stream artifact-failure delivery and phone t…
Aug 25, 2026
bde6965
no-mistakes(review): signal unthreaded replies, lock ended thread, ha…
Aug 25, 2026
c048ecf
no-mistakes(review): replace CSS z-index grep with browser occlusion …
Aug 25, 2026
10b4fb7
no-mistakes(review): guard SSE listeners, touch reply, phone gate, fl…
Aug 25, 2026
f6f77cb
no-mistakes(review): correct stream durability claims, terminate ende…
Aug 25, 2026
b4f94a8
no-mistakes(document): correct stream delivery docs; prettier a test …
Aug 26, 2026
adb2625
no-mistakes(document): correct stale layout-gate rationale; document …
Aug 26, 2026
a8a3372
no-mistakes: apply CI fixes
Aug 26, 2026
8bec2be
no-mistakes: apply CI fixes
Aug 26, 2026
f1ab0d2
no-mistakes(document): align presence docs with stream delivery; note…
Aug 26, 2026
c1c7a94
Merge branch 'main' into feat/realtime-sse-threading
Aug 29, 2026
efcebfc
no-mistakes(review): clamp thread seen counts when optimistic replies…
Aug 29, 2026
fe1606a
no-mistakes(review): refund thread seen credit per retracted optimist…
Aug 29, 2026
fab819d
no-mistakes(review): settle thread seen credit on stand-in retraction
Aug 29, 2026
b5409e8
no-mistakes(review): record image-only messages; hold retraction for …
Aug 29, 2026
13d0504
no-mistakes(review): share transcript-message predicate across stream…
Aug 30, 2026
a54cb96
no-mistakes(review): flush stream stdout before signal exit, bounded …
Aug 30, 2026
4ba05f1
no-mistakes(review): settle thread seen credit only for retracted roots
Aug 30, 2026
d6162f9
no-mistakes(review): credit refunded thread seen count when a retry d…
Aug 30, 2026
3beafc4
no-mistakes(review): correct credit guard comment; record declined se…
Aug 30, 2026
aa1a9f7
no-mistakes(document): document thread reply composer Enter shortcut …
Aug 30, 2026
a3beba3
no-mistakes: apply CI fixes
Aug 30, 2026
620afd8
no-mistakes(document): note SSE stream alongside long poll in AGENTS.md
Aug 30, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ coverage/
!/.omc/skills/
.DS_Store
*.log
.superpowers/
package-lock.json
.no-mistakes/evidence/
/.planning/
24 changes: 18 additions & 6 deletions AGENTS.md

Large diffs are not rendered by default.

17 changes: 12 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,13 +199,16 @@ pnpm link
Mark only custom (non-native) clickable elements with `data-lavish-action` so Lavish does not annotate them, and use `data-lavish-question` or `queueKey` when pre-send updates for the same question should replace each other.
On wider screens, queued annotation preview pills and chat history share a scrollable Conversation panel above a sticky composer, so long feedback queues do not push the text box or send controls off screen.
The browser chrome keeps editing actions in the overflow menu (copy path, reload artifact, copy DOM snapshot, export standalone HTML, publish link, end session), while the composer exposes **Send & End** beside **Send to Agent** to submit queued prompts and user-ended attribution together.
- **Reviewing on a phone** - Below 860px wide, the artifact takes the whole screen above a **Conversation** dock, and the conversation opens as a bottom sheet over it: tap the dock, swipe it up, or press the chevron to raise it; tap the dimmed artifact, swipe the sheet down, press the chevron, or press Escape to lower it. The dock reports what matters while the sheet is down - how many prompts are queued, a reply that arrived while you were reading, or whether the agent is listening - and the sheet stays open across a reload of the review page. The sheet sizes itself to the visible viewport and respects safe-area insets; if the keyboard or attachments leave little room, conversation content yields or scrolls while the send actions remain pinned above the bottom edge. In landscape the sheet covers the top bar as well. Wider screens keep the side-by-side layout.
The annotation card ends in **Cancel**, then **Queue** and **Send**: Queue adds the annotation to the queue so you can keep reviewing, and Send queues it and delivers the whole queue to the agent immediately - the pointer equivalent of Ctrl+Enter (Cmd+Enter on macOS). Send on an empty card just closes it, same as Cancel.
- **Reviewing on a phone** - Below 860px wide, the artifact takes the whole screen above a **Conversation** dock, and the conversation opens as a bottom sheet over it: tap the dock, swipe it up, or press the chevron to raise it; tap the dimmed artifact, swipe the sheet down, press the chevron, or press Escape to lower it. The dock reports what matters while the sheet is down - how many prompts are queued, a reply that arrived while you were reading, or whether the agent is listening - and the sheet stays open across a reload of the review page. Opening a thread slides it in over the conversation while the dock stays put, so you can still lower the sheet with a thread open. The sheet sizes itself to the visible viewport and respects safe-area insets; if the keyboard or attachments leave little room, conversation content yields or scrolls while the send actions remain pinned above the bottom edge. In landscape the sheet covers the top bar as well. Wider screens keep the side-by-side layout.
- **Keyboard shortcuts** - In the chrome composer, Enter sends queued prompts and Shift+Enter inserts a newline.
In the annotation card, Enter queues the annotation, Shift+Enter inserts a newline, and Ctrl+Enter (Cmd+Enter on macOS) queues it and sends all queued prompts immediately. Escape closes the card, same as Cancel, but only while it is empty (no text, no attachment); with unsent text or an attachment present, Escape does nothing rather than risk discarding it.
In the annotation card, Enter queues the annotation (same as **Queue**), Shift+Enter inserts a newline, and Ctrl+Enter (Cmd+Enter on macOS) queues it and sends all queued prompts immediately (same as **Send**). Escape closes the card, same as Cancel, but only while it is empty (no text, no attachment); with unsent text or an attachment present, Escape does nothing rather than risk discarding it.
Cmd+I or Ctrl+I toggles between annotate and explore mode from either the browser chrome or the artifact iframe, including while focus is in a textarea or control.
- **Agent presence** - The browser shows when no agent is listening, keeps queued feedback for the next successful `lavish-axi poll` send even across reloads, and keeps human feedback actions available while the agent is working because the server queues them for the next poll. The agent's reply (`--agent-reply`) concludes delivered work and returns presence to waiting.
- **Agent presence** - The browser shows when no agent is listening, keeps queued feedback for the next successful `lavish-axi poll` or `lavish-axi stream` delivery even across reloads, and keeps human feedback actions available while the agent is working because the server holds them for that next delivery. The agent's reply (`--agent-reply`) concludes delivered work and returns presence to waiting.
The no-timeout poll always writes an immediate stderr banner so it is visibly not hung; it adds the periodic stderr wait ticks only in an interactive terminal, so when stderr is piped (as under agent harnesses) the captured output carries no tick noise. Stdout always stays reserved for the final response; if the poll is interrupted or times out before feedback arrives, re-run it because feedback remains queued until delivery. Poll delivery consumes the response, so read the complete response before truncating or filtering it.
Codex-specific guidance keeps that poll attached to the active turn instead of hiding it in a background task, because completed background tasks may not resume the agent.
- **Real-time streaming** - `lavish-axi stream <html-file>` is a push alternative to `poll`: it holds a live connection open and prints one NDJSON line per user message as it arrives, so the agent can handle each message individually (for example, fan out a subagent per message) instead of draining one batch and exiting. Each line carries a `type`: `message` for a user message, `feedback` for a batch that carries only annotations or layout-issue prompts, and a final `ended` when the session ends. Re-run it if the connection drops - anything not yet delivered stays queued until delivery, though delivery consumes it, so messages the dropped stream already printed do not arrive again - or pass `--once` to stop after the first message.
- **Threaded replies** - Each message carries a server-assigned id, so the conversation panel groups replies into Slack-style threads with unread chips. Reply to a whole thread or to a specific message in it, and agents can thread their own replies with `lavish-axi stream <html-file> --agent-reply "..." --reply-to <id>`. Agent messages render a small inline-markdown subset - `**bold**`, `*italic*` (or `_italic_`), and `` `code` `` - so a reply can emphasize a file name or a value; your own messages render as written.
- **Session end etiquette** - Lavish tracks who ended a session: a human clicking **End session** (or **Send & end session**) in the browser is a user-initiated end, while `lavish-axi end <html-file>` is agent-initiated.
When either side ends the session, every open review tab becomes visibly read-only and disables its feedback controls; feedback submitted after the end is refused instead of being accepted without an agent to receive it.
A plain `lavish-axi <html-file>` after a user-initiated end refuses to reopen the browser and returns guidance instead; pass `--reopen` only when the user asks for further review or something important needs their visual attention.
Expand All @@ -231,11 +234,11 @@ pnpm link
The agent updates the artifact's Mermaid source, which remains authoritative.
Flowchart, sequence, class, ER, and state diagrams convert to editable shapes; other diagram types are images that reviewers can draw and annotate.
Lavish changes only the browser view, so saved, standalone, and exported artifacts still render plain Mermaid.
- **Server cleanup** - The detached server stops after the last session ends when nothing is connected, or after `LAVISH_AXI_IDLE_TIMEOUT_MS` (default 30 minutes) with no browser or poll connections.
- **Server cleanup** - The detached server stops after the last session ends when nothing is connected, or after `LAVISH_AXI_IDLE_TIMEOUT_MS` (default 30 minutes) with no browser, poll, or stream connections.
Set `LAVISH_AXI_IDLE_TIMEOUT_MS=0` or `off` to disable idle self-shutdown.
- **Server upgrades** - One background server serves every session, so upgrading `lavish-axi` while reviews are open makes the next `lavish-axi <html-file>` replace that server. Only the review page for the artifact being opened reloads itself once the replacement answers - and not even that one while you have unsent annotation text open, which gets the same banner instead so the reload is yours to make. Every other open review page keeps working and shows a banner reading "Lavish was updated. This page is running the previous version.", with a Check and reload button and a Dismiss button, so no page you are reading reloads on its own. After `lavish-axi stop` those pages say Lavish was stopped and to reload after you start it again, and a restart that only picks up a local build says that rather than claiming an update.
Every **Check and reload** control asks the server whether it is running before it navigates; while nothing answers, the page stays where it is and says so, and a check that gets no answer at all says that instead of guessing.
In-flight `lavish-axi poll` commands end with an interrupted-poll error and are safe to re-run; queued feedback is never lost, and annotation text you have typed but not queued yet survives the reload as described under **Live reload**.
In-flight `lavish-axi poll` commands end with an interrupted-poll error and are safe to re-run, as are `lavish-axi stream` connections the replacement drops; feedback that was not delivered stays queued, and annotation text you have typed but not queued yet survives the reload as described under **Live reload**.
A page waits for the replacement rather than reloading into a port nothing is listening on, and tells the user to restart Lavish if it never returns.
- **Local-first state** - Session state stays under `~/.lavish-axi/` by default, or `LAVISH_AXI_STATE_DIR` when set.
- **Diagnostic viewports** - `LAVISH_AXI_DIAGNOSTIC_VIEWPORTS` sets which viewport classes the layout-issue inbox tracks (`mobile`, `compact`, `desktop`; comma-separated, default all). Warnings whose class leaves the set are marked obsolete with an explicit reason instead of silently reading as fixed.
Expand All @@ -252,6 +255,7 @@ pnpm link
| `lavish-axi update` | Check for or apply the latest npm release through the AXI SDK self-updater. |
| `lavish-axi <html-file>` | Open or resume a Lavish Editor session, with the open-time layout gate enabled by default. Unresolved layout issues from earlier in the session are preserved. Refuses to reopen a session the user explicitly ended from the browser unless `--reopen` is passed. |
| `lavish-axi poll <html-file>` | Long-poll until the user sends feedback or ends the session; detected layout issues wait in the user's Layout issues inbox and arrive only when queued. Leave no-timeout polls running, or re-run them if interrupted. Codex guidance keeps polls attached to the active turn. On `status: ended`, stop polling and do not reopen uninvited. |
| `lavish-axi stream <html-file>` | Real-time push alternative to `poll`: hold a live connection open and print one NDJSON line per user message as it arrives; re-run it if it drops, or pass `--once` to stop after the first message. |
| `lavish-axi end <html-file>` | End a session as the agent; unlike a user-initiated end from the browser, this still allows a plain reopen later. |
| `lavish-axi export <html-file>` | Write a portable copy of the artifact: one HTML file with its local assets inlined, so it opens with no server and no sibling files. Remote CDN/font references are left as links. |
| `lavish-axi share <html-file>` | Publish the artifact (local assets inlined) to [ht-ml.app](https://ht-ml.app), a third-party host not part of Lavish, and print a visitable URL plus a secret update key; shares are public by default, `--private` locks one behind a generated password, and the same command republishes or unpublishes an existing page with `--site`/`--update-key`. |
Expand Down Expand Up @@ -283,6 +287,9 @@ For flows, architecture, state, or sequence diagrams, open the diagram playbook
| `lavish-axi share` | `--token <t>` | Attach an optional bearer token (`LAVISH_AXI_HTML_APP_TOKEN`) when creating a page; never required, and rejected on a republish or `--unpublish`, where the `update_key` is the credential. |
| `lavish-axi poll` | `--agent-reply "..."` | Show the agent's reply in the existing browser chat, conclude delivered work, and return presence to waiting before polling again. |
| `lavish-axi poll` | `--timeout-ms <ms>` | Test/debug escape hatch only; agents should normally omit it and leave the long poll running. |
| `lavish-axi stream` | `--once` | Stop after the first user message; the server requeues the rest of the batch for the next consumer. |
| `lavish-axi stream` | `--agent-reply "..."` | Show the agent's reply in the existing browser chat before streaming. |
| `lavish-axi stream` | `--reply-to <id>` | Thread the `--agent-reply` message under a specific message id. An id this session does not hold posts the reply as a new top-level message and says so on stderr. |
| `lavish-axi stop` | `--port <port>` | Shut down a server running on a non-default port. |
| `lavish-axi server` | `--verbose` | Log session and watcher events to stderr; can also be enabled with `LAVISH_AXI_DEBUG=1`. Detached server output is appended to `~/.lavish-axi/server.log` (or `LAVISH_AXI_STATE_DIR/server.log`) for startup and crash diagnostics. |

Expand Down
Loading
Loading