mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-15 07:36:50 +03:00
Bring Live progressive delivery and the generator subagent to Claude Code
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>
This commit is contained in:
@@ -3,6 +3,7 @@ import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { compileProviderBlocks } from '../scripts/lib/utils.js';
|
||||
import { PROVIDERS } from '../scripts/lib/transformers/providers.js';
|
||||
|
||||
const ROOT = process.cwd();
|
||||
|
||||
@@ -68,7 +69,14 @@ describe('live reference authoring contract', () => {
|
||||
assert.match(liveMd, /Do not paste this full reference into the handoff/);
|
||||
assert.match(generationAgentMd, /codex-name: impeccable_live_generator/);
|
||||
assert.match(generationAgentMd, /effort: low/);
|
||||
assert.match(generationAgentMd, /providers: codex/);
|
||||
// The generator ships to every harness with an agent format, not just Codex:
|
||||
// Codex delegates to unblock its foreground poll, Claude Code delegates to
|
||||
// keep a long session's screenshots and variant CSS out of the main context.
|
||||
assert.doesNotMatch(
|
||||
generationAgentMd,
|
||||
/^providers:/m,
|
||||
'the live generator must not be gated to one harness',
|
||||
);
|
||||
assert.match(generationAgentMd, /Never poll, Accept, Discard/);
|
||||
assert.match(generationAgentMd, /Publish the first reviewable result/);
|
||||
assert.match(generationAgentMd, /preserve every already-published variant byte-for-byte/i);
|
||||
@@ -118,8 +126,11 @@ describe('live reference authoring contract', () => {
|
||||
|
||||
it('keeps Codex sandbox guidance Codex-only', () => {
|
||||
const liveMd = readFileSync(join(ROOT, 'skill/reference/live.md'), 'utf-8');
|
||||
const codexLiveMd = compileProviderBlocks(liveMd, ['codex']);
|
||||
const claudeLiveMd = compileProviderBlocks(liveMd, ['claude-code', 'claude']);
|
||||
// Compile with each provider's real tags rather than hand-written ones, so a
|
||||
// providers.js misconfiguration fails here instead of shipping.
|
||||
const compileFor = (provider) => compileProviderBlocks(liveMd, PROVIDERS[provider].providerTags);
|
||||
const codexLiveMd = compileFor('codex');
|
||||
const claudeLiveMd = compileFor('claude-code');
|
||||
|
||||
assert.match(
|
||||
codexLiveMd,
|
||||
@@ -133,7 +144,7 @@ describe('live reference authoring contract', () => {
|
||||
);
|
||||
assert.doesNotMatch(
|
||||
codexLiveMd,
|
||||
/<\/?codex>/,
|
||||
/<\/?(codex|live-progressive)>/,
|
||||
'provider block tags should not leak into compiled Codex live reference',
|
||||
);
|
||||
assert.doesNotMatch(
|
||||
@@ -141,16 +152,57 @@ describe('live reference authoring contract', () => {
|
||||
/sandbox_permissions: "require_escalated"/,
|
||||
'Codex-only sandbox guidance should not appear in Claude live reference',
|
||||
);
|
||||
assert.match(
|
||||
codexLiveMd,
|
||||
/Codex progressive override/,
|
||||
'Codex live reference should progressively deliver the first reviewable variant',
|
||||
);
|
||||
});
|
||||
|
||||
it('gives progressive delivery to the harnesses that opt in, and only those', () => {
|
||||
const liveMd = readFileSync(join(ROOT, 'skill/reference/live.md'), 'utf-8');
|
||||
const compileFor = (provider) => compileProviderBlocks(liveMd, PROVIDERS[provider].providerTags);
|
||||
|
||||
// Codex delegates to unblock a foreground poll; Claude Code polls in a
|
||||
// background task. Both can publish variant 1 before the trio is finished.
|
||||
for (const provider of ['codex', 'agents', 'claude-code']) {
|
||||
const compiled = compileFor(provider);
|
||||
assert.match(
|
||||
compiled,
|
||||
/Transactional progressive delivery/,
|
||||
`${provider} should get the progressive publish recipe`,
|
||||
);
|
||||
assert.match(
|
||||
compiled,
|
||||
/Progressive delivery \(Codex, Claude Code\)/,
|
||||
`${provider} should get the progressive delivery policy`,
|
||||
);
|
||||
}
|
||||
|
||||
// Everyone else keeps the atomic single-edit path until their poll loop is
|
||||
// known not to stall on the extra publish calls.
|
||||
for (const provider of ['cursor', 'gemini']) {
|
||||
const compiled = compileFor(provider);
|
||||
assert.doesNotMatch(
|
||||
compiled,
|
||||
/Transactional progressive delivery|Progressive delivery \(Codex, Claude Code\)/,
|
||||
`${provider} has not opted into progressive delivery`,
|
||||
);
|
||||
assert.match(compiled, /\*\*Atomic default:\*\*/, `${provider} should keep the atomic path`);
|
||||
assert.doesNotMatch(
|
||||
compiled,
|
||||
/<\/?live-progressive>/,
|
||||
`capability block tags should not leak into the compiled ${provider} reference`,
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
it('routes every live-publish command through the per-provider scripts path', () => {
|
||||
const liveMd = readFileSync(join(ROOT, 'skill/reference/live.md'), 'utf-8');
|
||||
// The progressive recipe used to hardcode `.agents/skills/...`, which is only
|
||||
// correct for the Codex repo-skills bundle. Every other harness would have
|
||||
// been told to run the publisher from a directory its install never creates.
|
||||
assert.doesNotMatch(
|
||||
claudeLiveMd,
|
||||
/Codex progressive override|first-reviewable milestone/,
|
||||
'Claude live reference should retain the atomic path without Codex-specific delivery instructions',
|
||||
liveMd,
|
||||
/node\s+\.[a-z-]+\/skills\/impeccable\/scripts\//,
|
||||
'live.md must not hardcode a harness config dir; use {{scripts_path}}',
|
||||
);
|
||||
assert.match(liveMd, /node \{\{scripts_path\}\}\/live-publish\.mjs --prepare/);
|
||||
});
|
||||
|
||||
it('keeps live preview CSS guidance capability-mode driven', () => {
|
||||
|
||||
Reference in New Issue
Block a user