Live picker: derive the command vocabulary from one canonical source

The verbs/labels/icons were copied three ways: live-browser.js (ICONS + ACTIONS),
VISUAL_ACTIONS in live-event-validation.mjs, and the marketing demo. Collapse
them to one source, skill/scripts/live-vocabulary.mjs (LIVE_COMMANDS + derived
VISUAL_ACTIONS).

- live-event-validation.mjs imports VISUAL_ACTIONS from it.
- live-server.mjs serializes LIVE_COMMANDS into window.__IMPECCABLE_VOCAB__ when
  it serves /live.js, next to the token/port. live-browser.js (served raw, can't
  import at runtime) builds its ICONS + ACTIONS from that injected vocab instead
  of an inline copy — byte-identical icons, zero behaviour change.
- site/components/LiveDemoPalette.astro imports the same module at build time, so
  the demo and the real picker can no longer drift.

Adds a /live.js test asserting the injected vocab deep-equals the canonical list.
Harness skill dirs refreshed via build. (Pre-existing, unrelated: `bun run
build:site` fails on an htmlparser2 import in the CLI detector.)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Bakaus
2026-06-05 14:05:41 -07:00
co-authored by Claude Opus 4.8
parent 1f975a69e4
commit 5fb30e03e6
58 changed files with 817 additions and 541 deletions
+4
View File
@@ -24,6 +24,7 @@ import { parseDesignMd } from './design-parser.mjs';
import { resolveContextDir } from './context.mjs';
import { createLiveSessionStore } from './live-session-store.mjs';
import { validateEvent } from './live-event-validation.mjs';
import { LIVE_COMMANDS } from './live-vocabulary.mjs';
import {
getDesignSidecarPath,
getLiveDir,
@@ -1272,6 +1273,9 @@ function createRequestHandler({ detectScript, sessionPath, livePath }) {
const body =
`window.__IMPECCABLE_TOKEN__ = '${state.token}';\n` +
`window.__IMPECCABLE_PORT__ = ${state.port};\n` +
// Canonical command vocabulary (values + labels + icons). live-browser.js
// builds its action picker from this instead of an inline copy.
`window.__IMPECCABLE_VOCAB__ = ${JSON.stringify(LIVE_COMMANDS)};\n` +
sessionScript + '\n' +
liveScript;
res.writeHead(200, {