lavish-axi 0.1.41 → 0.1.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -122,13 +122,13 @@ pnpm link
122
122
  │ Human annotates text │
123
123
  │ or elements, sends │
124
124
  │ chat, or browser audit │
125
- │ reports layout issues │
125
+ │ proves severe failures │
126
126
  └───────┬────────────────┘
127
127
  ▼
128
128
  ┌────────────────────────┐
129
129
  │ lavish-axi poll waits │
130
130
  │ and returns prompts │
131
- │ or layout warnings │
131
+ │ or severe failures │
132
132
  └────────────────────────┘
133
133
  ```
134
134
 
@@ -136,13 +136,13 @@ pnpm link
136
136
  - **Portable artifacts** - The artifact runs in an iframe while Lavish injects a small SDK for annotations, snapshots, feedback controls, and render-time layout checks.
137
137
  Lavish does not inject any design system, so the saved HTML file renders identically whether you open it through `lavish-axi` or directly in a browser.
138
138
  Run `lavish-axi design` for the single source of agent-facing design guidance and optional CDN or Mermaid snippets.
139
- - **Open-time layout gate** - The browser chrome masks each artifact until the real in-iframe layout audit reports no error-severity findings.
140
- Warning-only artifacts reveal normally; error findings notify the agent through the same `layout_warnings` poll path and keep the curtain up until a clean reload.
141
- The user can click **Show anyway**, and a bounded safety timeout reveals with a persistent layout-issues banner so review is never blocked indefinitely.
142
- - **Layout warnings** - After fonts load and layout settles, the injected SDK audits the real browser render for page horizontal overflow, element overflow, clipped or visibly spilling text, and overlapping text.
143
- Intentional horizontal scrollers using `overflow-x: auto` or `scroll` are excluded from horizontal checks, and `overflow-y: auto` or `scroll` is treated as intentional for vertical overflow.
144
- Current findings are returned from `lavish-axi poll` as `layout_warnings` with `selector`, `kind`, `overflowPx`, `viewportWidth`, `severity`, and `persistent`.
145
- Fresh error-severity findings should be fixed and rechecked before asking the human to review; repeated or warning-only findings can be surfaced to the human with a note when the cause is not obvious.
139
+ - **Open-time layout gate** - The browser chrome masks an artifact only while the real in-iframe audit checks for a stable, proven severe layout failure.
140
+ A severe failure notifies the agent through the `layout_warnings` poll path and keeps the curtain up until a clean reload, while cosmetic, intentional, transient, tiny, and uncertain observations stay silent.
141
+ The user can click **Show anyway**, and a bounded safety timeout fails open without an issue banner when no severe failure has been proven.
142
+ - **Layout failures** - After fonts and finite animations settle, the injected SDK confirms severe failures from direct rendered evidence such as materially escaped meaningful content or required controls, clipped text fragments, viewport reachability, or near-total semantic occlusion.
143
+ Explicit ellipsis and line clamp, standard visually hidden accessibility text, intentional scrollers or masks, parent overhang, generic element scroll geometry, decorative overlap, and uncertain motion do not produce findings by themselves.
144
+ Proven failures are returned from `lavish-axi poll` in `layout_warnings` with `selector`, `kind`, `axis`, `overflowPx`, `viewportWidth`, `severity`, and `persistent`.
145
+ Every returned failure should be fixed and rechecked before asking the human to review.
146
146
  - **Local assets** - Copy local images, CSS, fonts, and scripts next to the HTML artifact and reference them with relative paths from that directory; root-prefixed paths such as `/assets/logo.png` will not resolve through Lavish's artifact route.
147
147
  - **Export and sharing** - `lavish-axi export` writes `<name>.export.html` by inlining local assets only, stripping the annotation SDK, and leaving remote CDN/font references as links that still need network access.
148
148
  `lavish-axi share` publishes the same local-inlined HTML to [ht-ml.app](https://ht-ml.app), a third-party hosting service not part of Lavish.
@@ -160,7 +160,9 @@ pnpm link
160
160
  - **Keyboard shortcuts** - In the chrome composer, Enter sends queued prompts and Shift+Enter inserts a newline.
161
161
  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.
162
162
  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.
163
- - **Agent presence** - The browser shows when no agent is listening, keeps queued feedback and fresh layout warnings for the next successful `lavish-axi poll` send even across reloads, and only blocks human sends while the agent is working on delivered feedback. The no-timeout poll writes an immediate stderr banner and periodic stderr heartbeats while stdout stays reserved for the final response; if the poll is interrupted or times out, re-run it because queued feedback is never lost. 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.
163
+ - **Agent presence** - The browser shows when no agent is listening, keeps queued feedback and proven severe layout failures for the next successful `lavish-axi poll` send even across reloads, and only blocks human sends while the agent is working on delivered feedback; the agent's reply (`--agent-reply`) concludes that work and re-enables sends.
164
+ The no-timeout poll writes an immediate stderr banner and periodic stderr heartbeats while stdout stays reserved for the final response; if the poll is interrupted or times out, re-run it because queued feedback is never lost.
165
+ 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.
164
166
  - **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.
165
167
  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.
166
168
  Agent-initiated ends keep reopening normally, same as before.
@@ -179,24 +181,25 @@ pnpm link
179
181
  - **Local-first state** - Session state stays under `~/.lavish-axi/` by default, or `LAVISH_AXI_STATE_DIR` when set.
180
182
  - **Server port** - Set `LAVISH_AXI_PORT` to choose the server port; it defaults to `4387`.
181
183
  - **Network binding** - The server binds to loopback (`127.0.0.1`) by default. Set `LAVISH_AXI_HOST` to bind elsewhere; a wildcard (`0.0.0.0` or `::`) binds every interface. Binding beyond loopback exposes an unauthenticated server that can read and serve arbitrary local files to anything that can reach it, so only do so on a trusted network. Set `LAVISH_AXI_LINK_HOST` to control the hostname written into generated session links (defaults to the bind address, or loopback when bound to a wildcard).
184
+ - **Allowed hosts** - To defend against DNS rebinding, the server rejects (`403`) any request whose `Host` header is missing or not one it answers to: the loopback names (`127.0.0.1`, `::1`, `localhost`) plus the configured bind and link host. If you reach the server under another name - a wildcard bind accessed by LAN IP, a reverse-proxy hostname, or an extra interface - list those names in `LAVISH_AXI_ALLOWED_HOSTS` (whitespace-separated) to allow them. Behind a reverse proxy, the forwarded `X-Forwarded-Host` is validated against the same list, so add your public hostname there and have the proxy send it. Set `LAVISH_AXI_ALLOWED_HOSTS` to `*` to disable the check entirely (only when the server sits behind your own authentication or proxy).
182
185
  - **Browser opening** - Set `LAVISH_AXI_NO_OPEN=1`, equivalent to `--no-open`, to create or resume a session without launching a browser window.
183
186
 
184
187
  ## CLI Reference
185
188
 
186
- | Command | Description |
187
- | ------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
188
- | `lavish-axi` | Show current sessions and usage guidance. |
189
- | `lavish-axi update` | Check for or apply the latest npm release through the AXI SDK self-updater. |
190
- | `lavish-axi <html-file>` | Open or resume a Lavish Editor session, with the open-time layout gate enabled by default. Refuses to reopen a session the user explicitly ended from the browser unless `--reopen` is passed. |
191
- | `lavish-axi poll <html-file>` | Long-poll until the user sends feedback, ends the session, or the browser reports fresh `layout_warnings`; 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. |
192
- | `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. |
193
- | `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. |
194
- | `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, and `--password` makes viewers enter the password before viewing. |
195
- | `lavish-axi stop` | Shut down the background server. |
196
- | `lavish-axi playbook [id]` | List focused artifact guidance or show one playbook; agents must open each matching playbook before writing HTML. |
197
- | `lavish-axi design` | Show agent-facing design guidance, including optional CDN and Mermaid snippets. |
198
- | `lavish-axi setup hooks` | Install or repair optional SessionStart hooks for Claude Code, Codex, OpenCode, and GitHub Copilot CLI; restart the agent session afterward. |
199
- | `lavish-axi server` | Run the local Lavish Editor server. |
189
+ | Command | Description |
190
+ | ------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
191
+ | `lavish-axi` | Show current sessions and usage guidance. |
192
+ | `lavish-axi update` | Check for or apply the latest npm release through the AXI SDK self-updater. |
193
+ | `lavish-axi <html-file>` | Open or resume a Lavish Editor session, with the open-time layout gate enabled by default. Refuses to reopen a session the user explicitly ended from the browser unless `--reopen` is passed. |
194
+ | `lavish-axi poll <html-file>` | Long-poll until the user sends feedback, ends the session, or the browser proves a severe layout failure; 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. |
195
+ | `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. |
196
+ | `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. |
197
+ | `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, and `--password` makes viewers enter the password before viewing. |
198
+ | `lavish-axi stop` | Shut down the background server. |
199
+ | `lavish-axi playbook [id]` | List focused artifact guidance or show one playbook; agents must open each matching playbook before writing HTML. |
200
+ | `lavish-axi design` | Show agent-facing design guidance, including optional CDN and Mermaid snippets. |
201
+ | `lavish-axi setup hooks` | Install or repair optional SessionStart hooks for Claude Code, Codex, OpenCode, and GitHub Copilot CLI; restart the agent session afterward. |
202
+ | `lavish-axi server` | Run the local Lavish Editor server. |
200
203
 
201
204
  Known playbook IDs: `diagram`, `table`, `comparison`, `plan`, `code`, `input`, `slides`.
202
205
  One artifact often combines several playbooks, such as a plan that includes a comparison and a diagram, so agents must match against each `use_when` trigger and open every matching playbook before writing HTML.
@@ -213,7 +216,7 @@ For flows, architecture, state, or sequence diagrams, open the diagram playbook
213
216
  | `lavish-axi export` | `--out <path>` | Write the export to a specific path instead of `<name>.export.html` next to the source. |
214
217
  | `lavish-axi share` | `--password <pw>` | Make the third-party ht-ml.app page private; viewers must supply the password. |
215
218
  | `lavish-axi share` | `--token <t>` | Attach an optional bearer token (`LAVISH_AXI_HTML_APP_TOKEN`); never required to publish. |
216
- | `lavish-axi poll` | `--agent-reply "..."` | Show the agent's reply in the existing browser chat before polling again. |
219
+ | `lavish-axi poll` | `--agent-reply "..."` | Show the agent's reply in the existing browser chat and re-enable human sends before polling again. |
217
220
  | `lavish-axi poll` | `--timeout-ms <ms>` | Test/debug escape hatch only; agents should normally omit it and leave the long poll running. |
218
221
  | `lavish-axi stop` | `--port <port>` | Shut down a server running on a non-default port. |
219
222
  | `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. |
@@ -381,14 +381,19 @@ async function submitQueuedOnce() {
381
381
  }
382
382
 
383
383
  function normalizeLayoutWarningsPayload(value) {
384
- return Array.isArray(value) ? value.filter((item) => item && typeof item === "object") : [];
384
+ return Array.isArray(value)
385
+ ? value.filter((item) => item && typeof item === "object" && String(item.severity || "").toLowerCase() === "error")
386
+ : [];
385
387
  }
386
388
 
387
389
  function isErrorLayoutWarning(warning) {
388
390
  return String(warning?.severity || "").toLowerCase() === "error";
389
391
  }
390
392
 
391
- function setLayoutIssueBanner(visible, text = "This surface may have layout issues. Your agent has been notified.") {
393
+ function setLayoutIssueBanner(
394
+ visible,
395
+ text = "This surface has a severe layout failure. Your agent has been notified.",
396
+ ) {
392
397
  if (!layoutIssueBanner) return;
393
398
  layoutIssueBanner.textContent = text;
394
399
  layoutIssueBanner.hidden = !visible;
@@ -405,7 +410,7 @@ function setLayoutGateCard(state) {
405
410
  if (state === "held") {
406
411
  layoutGateTitle.innerHTML = "Fixing a layout issue...";
407
412
  layoutGateCopy.textContent =
408
- "The real browser found overflow or overlapping content. Your agent has been notified and this will reveal after the next clean reload.";
413
+ "The browser found inaccessible or unusable content. Your agent has been notified and this will reveal after the next clean reload.";
409
414
  return;
410
415
  }
411
416
 
@@ -428,12 +433,16 @@ function revealLayoutGate({ showBanner = false, bannerText = undefined } = {}) {
428
433
 
429
434
  function forceRevealLayoutGate(reason) {
430
435
  if (!layoutGateEnabled || ended) return;
436
+ if (reason === "timeout") {
437
+ // A delayed or unavailable audit is uncertainty, not evidence of a defect.
438
+ revealLayoutGate();
439
+ return;
440
+ }
431
441
  if (reason === "manual") layoutGateManuallyBypassed = true;
432
- const bannerText =
433
- reason === "timeout"
434
- ? "This surface may have layout issues. Lavish revealed it after the safety timeout so review is never blocked."
435
- : "This surface may have layout issues. You chose to show it before the layout check passed.";
436
- revealLayoutGate({ showBanner: true, bannerText });
442
+ revealLayoutGate({
443
+ showBanner: true,
444
+ bannerText: "This surface has a severe layout failure. You chose to show it before the layout check passed.",
445
+ });
437
446
  }
438
447
 
439
448
  function startLayoutGateCycle() {
@@ -472,6 +481,7 @@ function handleLayoutWarningsForGate(layoutWarnings) {
472
481
  return;
473
482
  }
474
483
 
484
+ clearLayoutGateTimer();
475
485
  setLayoutGateCard("held");
476
486
  setLayoutGateActive(true);
477
487
  }