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>