Almost none of this branch's Live work was actually Codex-specific. The publisher,
the fences, the source locks and the browser's partial-arrival UI are plain node
and DOM with zero provider references, and the progressive E2E already passes on
five frameworks driven by a non-Codex agent. The Codex-only part was policy prose
and one frontmatter line, so Claude Code shipped the progressive browser UI it
could never trigger.
Progressive delivery, Codex and Claude Code:
- Add a `live-progressive` capability tag and opt codex, agents, and claude-code
in. A provider block takes one tag, so naming harnesses would have meant
duplicating the recipe per tag; a capability reads better than a provider list
anyway. Cursor and everyone else keep the atomic path until their poll loop is
known not to stall on the extra publish calls.
- Claude Code publishes variant 1 as soon as it validates rather than waiting to
write the whole trio in one edit. Nothing about the arrival path needed
changing: the publisher writes, framework HMR pushes, and the browser's
MutationObserver counts variants. The parent conversation was never in that
path, which is why Claude Code's lack of subagent progress streaming does not
matter here.
Generator subagent:
- Drop `providers: codex` from impeccable-live-generator. The build already maps
its frontmatter correctly for Claude Code, and impeccable-manual-edit-applier
has shipped to .claude/agents/ this way all along.
- The reason differs per harness, so the reference says so: Codex delegates to
unblock a foreground poll, Claude Code delegates to keep a long session's
screenshots and variant CSS out of the main context. Follows the existing
manual-edit-applier convention: both agent names, and an inline fallback when
native subagents are unavailable.
Fixes found on the way:
- The two publish commands hardcoded `.agents/skills/impeccable/scripts/` while
the other thirteen commands in live.md use {{scripts_path}}. Correct only for
the Codex repo-skills bundle; it would have pointed Claude Code at a directory
its install never creates. The shipped .codex variant was already internally
inconsistent. Now covered by a test.
- `--agent=codex` resolved to the canned fake agent, because the flag parsed as
`x === 'llm' ? 'llm' : 'fake'`. The private evals Live runner passes exactly
that, so a real-harness run would have scored deterministic stub variants and
reported them as Codex output. Unknown values for --agent, --scenario and
--delivery now fail loudly.
- live-reference tests now compile with each provider's real providerTags instead
of hand-written lists, so a providers.js misconfiguration fails in tests rather
than shipping.
Verified: progressive E2E green on vite8-react-plain against a real Vite server
and Chromium; every provider variant's publish and poll paths now agree; Cursor
and Gemini still compile to atomic only.
Prepared with AI assistance under maintainer direction.
Co-Authored-By: Claude <noreply@anthropic.com>
Addresses the review findings on #371, plus several the bots did not catch.
All fixes have regression coverage that fails on the prior code.
Source corruption:
- Vue accept dropped valueless root attrs (disabled, v-cloak) and, worse,
rewrote @click="x" as a literal click="x" DOM attribute, because the attr
parser was name-anchored and skipped the sigil. Tokenize the whole Vue attr
grammar and normalize shorthands so accept round-trips directives.
- --variant was interpolated unescaped into a RegExp, so --variant '.*' matched
the original block first and reported a successful accept while silently
restoring the original. Validate against the digits pattern the browser and
the /events schema already enforce.
- --id reached path.join unvalidated, so --id ../../../../etc/evil wrote and
read receipts outside the project. Hoist the existing safeSessionId check
into impeccable-paths and apply it at every id-to-path sink.
Accept/lock correctness:
- Plain HTML/JSX accept and discard did not catch SOURCE_LOCKED, so contention
exited non-zero with empty stdout and the agent got no JSON to retry on.
- Lock staleness was mtime-only and never read the pid it records: a holder
whose critical section outran 60s had its live lock swept, admitting a second
writer to the same file, while a crashed holder blocked accepts for a full
60s. Decide staleness by owner liveness, and release only our own lock.
Detector:
- isNeutralColor only parses computed color forms, so routing authored CSS
through it reported inset 4px 0 0 #000 / black / #e5e7eb as chromatic
side-tab stripes. Add an authored-color neutrality test covering hex and
named neutrals; the fixture had no literal-color cases at all.
- Rule line numbers were off by one for every rule after the first, and
commented-out CSS was scanned as live rules.
Server:
- An error reply carries no sourceEventType, and inferSourceEventType returned
undefined, which acknowledgePendingEvent treats as a wildcard: a stale
generate worker's failure consumed the user's queued Accept, which then
reached no agent and left the browser in SAVING forever.
- The generate preflight spawned live-wrap.mjs synchronously inside the request
handler, freezing the single-threaded server for the whole scaffold (~7.6s
measured on this repo, 15s ceiling) and stalling Accept/Discard/SSE. Make it
async, claiming the lease before the first await so no event double-delivers.
- Every browser checkpoint was echoed back as variant_progress, so a Tune
slider drag remounted the preview under the user's cursor and latched the
*_reviewable phases from the wrong trigger. Gate on the reason.
Cleanup:
- Collapse four divergent benchmark argv parsers into scripts/lib/cli-args.mjs.
Three silently misread flags: --iterations 20 benchmarked 5, --agent llm ran
the fake agent, --median-target=0.4 used the default threshold.
- Drop a snapshot cache this branch made write-only (it grew per session for
the server's lifetime and was never read), a dead exported reconcile helper,
and the unused deferReply branch.
Prepared with AI assistance under maintainer direction.
Co-Authored-By: Claude <noreply@anthropic.com>
Restore foreground/background polling as the primary harness architecture, add progressive publication and framework-safe previews, and harden quality and regression coverage. The experimental app-server runtime is intentionally excluded.\n\nPrepared with AI assistance under maintainer direction.