mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-18 09:06:53 +03:00
Prewarm Codex Live with safe fallback
Return after a durable starting record, overlap app-server initialization with page startup, dynamically reclaim generation after worker failure, and cap hard-crash leases at 15 seconds.\n\nAI-assisted: OpenAI Codex.
This commit is contained in:
@@ -26,7 +26,7 @@ The global bar **Impeccable mark** dims and shows a pulsing amber dot when no ag
|
||||
Harness policy:
|
||||
- **Claude Code**: run the poll as a **background task** (no short timeout). The harness notifies you when it completes, so the main conversation stays free. Do not block the shell.
|
||||
- **Cursor**: run **one-shot** poll in a **background terminal** with notify on `"type":"(steer|generate|accept|discard|exit)"`. After each event the poll exits; handle it, `--reply`, then start `live-poll.mjs` again. Do **not** use `--stream` on Cursor: incremental stdout notify is slower in practice than exit-based notify (~5s vs sub-second in testing).
|
||||
- **Codex**: the main thread is the **foreground poll supervisor**. Keep the poll command itself in a yielded foreground exec session and retain its session id; do not suffix it with `&`. A yielded foreground process continues while other tool calls run, whereas a traditional shell-backgrounded child may be reaped when its shell exits. On `generate`, delegate to the low-effort `impeccable_live_generator` agent when available. Give it a compact handoff: project/scripts paths, the complete event plus scaffold, the identity lock, relevant source/component excerpt, available tokens, and current design/product constraints. Do not paste this full reference into the handoff. The worker publishes variants and posts the generation reply; poll again immediately in the main thread so the supervisor remains available for early Accept/Discard and the next Go. If the named agent is unavailable, use one generic generation worker with the same compact contract. Do not put the poll itself in a subagent or a fire-and-forget background shell: browser control events must return to the main thread immediately. The explicit experimental dedicated-worker switch documented under Recovery partitions the queue: keep only its filtered foreground control poll, never an overlapping unfiltered poll.
|
||||
- **Codex**: `live.mjs` starts a dedicated app-server generation lane by default and returns its exact foreground control command. Run that command in a yielded foreground exec session; do not suffix it with `&`. It dynamically adds generation events only if the dedicated worker fails or exits. When the worker is explicitly disabled or unavailable, keep the default poll in the main thread and delegate to the low-effort `impeccable_live_generator` agent with a compact handoff. Do not paste this full reference into the handoff. Never run an overlapping unfiltered poll while the dedicated worker owns generation.
|
||||
- **Other harnesses**: one-shot foreground unless you know stdout reliably returns to this session when a shell exits.
|
||||
|
||||
Generation delivery policy:
|
||||
@@ -46,7 +46,7 @@ node {{scripts_path}}/live.mjs
|
||||
|
||||
Output JSON: `{ ok, serverPort, serverToken, pageFiles, hasProduct, product, productPath, hasDesign, design, designPath }`. `pageFiles` is the list of HTML entries the live script was injected into. Keep PRODUCT.md and DESIGN.md in mind for variant generation; **DESIGN.md wins on visual decisions; PRODUCT.md wins on strategic/voice decisions.** When DESIGN.md is missing, identity is **not** absent; extract it from CSS variables, computed styles, and sibling components on the page (see Step 4 Phase A). Identity preservation is the default; departure from existing identity requires an explicit trigger from PRODUCT.md anti-references or the user's freeform prompt.
|
||||
|
||||
If output includes `codexWorker.enabled: true`, the dedicated lane owns only `generate,accept,discard,prefetch`. Keep the main task on the non-overlapping control lane with `node {{scripts_path}}/live-poll.mjs --types=steer,manual_edit_apply,carbonize_cleanup,exit`; after each event, immediately restart that filtered command. Do not also run the default unfiltered poll while the worker is enabled.
|
||||
If output includes `codexWorker.enabled: true`, run the returned `codexWorker.foregroundPoll` command. The dedicated lane owns `generate,accept,discard,prefetch`; the foreground owns `steer,manual_edit_apply,carbonize_cleanup,exit`. The fallback flag restores generation to the foreground only when the worker's owned process record is failed or unreachable. After each event, restart that same command. Do not also run the default unfiltered poll.
|
||||
|
||||
`serverPort` and `serverToken` belong to the small **Impeccable live helper** HTTP server (serves `/live.js`, SSE, and `/poll`). That port is **not** your dev server and is usually not the URL you open to view the app. The browser page is whatever origin serves one of the `pageFiles` entries (Vite / Next / Bun / tunnel / LAN hostname).
|
||||
|
||||
@@ -118,7 +118,11 @@ Activation is process-local: the worker is enabled by default only when the proc
|
||||
}
|
||||
```
|
||||
|
||||
The app-server worker is **default-on in Codex and Codex-only**. Claude, Gemini, Cursor, and every other harness keep the portable foreground/atomic behavior. When enabled, `live.mjs` returns `codexWorker.enabled: true`; run only the filtered foreground control poll shown under Start. If app-server startup, authentication, or model selection fails and the child terminates cleanly, `live.mjs` returns `codexWorker.fallback: true` and leaves the portable foreground poll path untouched.
|
||||
The app-server worker is **default-on in Codex and Codex-only**. Claude, Gemini, Cursor, and every other harness keep the portable foreground/atomic behavior. Live records the worker as `starting` and returns immediately, so app-server initialization overlaps page/dev-server startup. Run only the returned foreground control poll. It checks the owned worker process every two seconds and safely restores generation/accept/discard leasing if startup, authentication, model selection, or the worker process fails. Dedicated-worker leases expire after 15 seconds, so a hard process loss cannot strand browser work behind the portable ten-minute lease.
|
||||
|
||||
```bash
|
||||
node {{scripts_path}}/live-poll.mjs --types=steer,manual_edit_apply,carbonize_cleanup,exit --codex-worker-fallback
|
||||
```
|
||||
|
||||
The supervisor launches its own `codex app-server --stdio` process, dynamically prefers the strongest visible general model (currently GPT-5.6 Sol), and uses medium reasoning. The optional `fast` profile retains Spark/mini selection and low reasoning for controlled comparisons. It creates a dedicated Impeccable-owned thread and persists only that id in `.impeccable/live/codex-worker.json`; it never lists, resumes, steers, or writes to the desktop task. A crash reconnect may resume that id only when the ownership marker and project cwd both match. Clean Live exit interrupts the active turn, archives the dedicated thread, and stops app-server.
|
||||
|
||||
@@ -563,7 +567,7 @@ When `_acceptResult.carbonize === true`, the accepted variant was stitched into
|
||||
|
||||
After the file is clean, the cleanup owner runs `live-complete.mjs --id SESSION_ID` and verifies `phase: "completed"`. The Codex supervisor keeps polling throughout; synchronous harnesses poll again only after that verification.
|
||||
|
||||
With the experimental dedicated worker, Accept emits a foreground `carbonize_cleanup` control event: `{id, sessionId, file, variantId, acceptResult}`. Perform the same five steps above for `sessionId`, run `live-complete.mjs --id SESSION_ID`, then acknowledge the control event with `live-poll.mjs --reply EVENT_ID complete --file FILE`. Restart the filtered control poll immediately. The dedicated generation lane may prepare the next request concurrently, but its publisher must re-prepare after any stale source fence.
|
||||
With the dedicated worker, Accept emits a foreground `carbonize_cleanup` control event: `{id, sessionId, file, variantId, acceptResult}`. Perform the same five steps above for `sessionId`, run `live-complete.mjs --id SESSION_ID`, then acknowledge the control event with `live-poll.mjs --reply EVENT_ID complete --file FILE`. Restart the returned control poll immediately. The dedicated generation lane may prepare the next request concurrently, but its publisher must re-prepare after any stale source fence.
|
||||
|
||||
## Handle `discard`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user