mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-21 10:36:27 +03:00
Keep the generate lane's boot extras behind flags
The speed pass had every `impeccable live` boot probe for the dev server and print three new keys (devUrl, contextMissing, contextNote), which moved an oracle golden and cost a plain live session a probe it never asked for. The lane's extras are opt-in now: `--dev-url` runs the probe and reports devUrl; `--allow-missing-context` reports the context keys. Without either flag the boot's work and payload are byte-identical to before, which the restored golden and a new boot test pin. generate.md passes both flags; the contract doc says so. Written with AI assistance (Claude). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
committed by
Abdul Wahab
co-authored by
Claude Fable 5
parent
1220f26d08
commit
f29636a3d5
@@ -1727,13 +1727,13 @@ Conventions: every script's "run directly" guard is `process.argv[1]` ending wit
|
||||
- Flow & outputs (all pretty-printed JSON, 2 spaces, exit 0 unless noted):
|
||||
1. Workspace monorepo selection (`resolveTargetSelection`, only when no target, cwd is a workspace/monorepo root with discoverable children): `{ok:false, error:'target_selection_required', targetPath:null, projectRoot, repoRoot, targetCandidates:[{name, path, targetExample, …context summary}], hint:'Ask the user which app Impeccable should use, then rerun live from that child app cwd. Use --target <path> only as a fallback or explicit path diagnostic.'}`.
|
||||
2. `resolveRoots` selection → `{ok:false, error:'target_selection_required', targetCandidates:[{name,path}], hint:'Several apps with a dev-server config exist. Ask the user which one to use, then rerun with --target <path into that app>.'}`.
|
||||
3. Missing/unreadable/empty PRODUCT.md or DESIGN.md → `{ok:false, error:'context_missing', missing:['PRODUCT.md'?,'DESIGN.md'?], nextCommand:'init'|'document', targetPath, projectRoot, repoRoot, productPath:rel|null, designPath:rel|null}`. With `--allow-missing-context` the boot continues instead: the success payload carries `contextMissing:[...]` (the same names; `[]` when nothing is missing) and `contextNote` (a sentence telling the agent to extract the identity from the page and never run init or document mid-session; `null` when nothing is missing), with `hasProduct`/`hasDesign` false and `product`/`design` null for the missing ones.
|
||||
3. Missing/unreadable/empty PRODUCT.md or DESIGN.md → `{ok:false, error:'context_missing', missing:['PRODUCT.md'?,'DESIGN.md'?], nextCommand:'init'|'document', targetPath, projectRoot, repoRoot, productPath:rel|null, designPath:rel|null}`. With `--allow-missing-context` the boot continues instead, and only then the success payload gains `contextMissing:[...]` (the same names; `[]` when nothing is missing) and `contextNote` (a sentence telling the agent to extract the identity from the page and never run init or document mid-session; `null` when nothing is missing), with `hasProduct`/`hasDesign` false and `product`/`design` null for the missing ones.
|
||||
4. `writeRootsManifest(roots)`.
|
||||
5. `node live-inject.mjs --check` (cwd appRoot, 15 s): not ok → print that JSON (`{ok:false,error:'config_missing'|'config_invalid',path,message?}` or `{ok:false,error:'check_failed',raw}`) + `targetPath, projectRoot, repoRoot`, exit 0.
|
||||
6. Reuse server if `server.json` pid alive, else `node live-server.mjs --background`; failure → `{ok:false,error:'server_start_failed'}` exit 1.
|
||||
7. `node live-inject.mjs --port P --token T`; not ok → `{ok:false,error:'inject_failed',detail:<json|raw>,serverPort}` exit 1.
|
||||
8. Drift scan: `.html` files under `public, src, app, pages` (skipping ignored dirs/dot-dirs) not in resolved files and not user-excluded → `configDrift = {orphans:[≤20], orphanCount, hint:'N HTML file(s) exist but aren\'t in config.files. Consider adding them, or use a glob pattern like "public/**/*.html".'}` else `null`.
|
||||
9. Success: `{ok:true, serverPort, serverToken, devUrl, contextMissing, contextNote, pageFiles:[…resolved], liveConfigPath, configDrift, targetPath, projectRoot:appRoot, repoRoot, roots:{manifest}, hasProduct:true, product:<text>, productPath:rel, hasDesign:true, design:<text>, designPath:rel, hasSurfaceBrief, surfaceBrief:<text|null>, surfaceBriefPath:rel|null, _instructions:'Open the app URL that serves a pageFiles entry (never serverPort; that is the helper). Then start the poll loop per your harness policy in live.md and re-run node <scripts>/live-poll.mjs immediately after every event or reply. Every event carries _instructions: follow them; they are the authoritative next step with real ids and paths filled in. A poll that is running is a poll you are SERVICING: never announce you are waiting and idle your turn; stay on the exec session until it returns an event, and never end a turn while a poll is outstanding.'}`. Surface brief resolved from `.impeccable/surfaces` under appRoot, contextRoot, repoRoot (first hit). `devUrl` is the origin of the dev server serving this app right now, found by fetching `/` on the candidate origins (`http://127.0.0.1:<p>/` and `http://localhost:<p>/` for p in 5173, 3000, 4321, 8080, 4173, 3001, 5174, 8000, 4200, 5000, 1234, probed in parallel with sub-second timeouts; `IMPECCABLE_DEV_URL_CANDIDATES` replaces the list with a comma-separated one) and keeping the first whose document contains the injected `live.js?token=<serverToken>` tag; `null` when none does.
|
||||
9. Success: `{ok:true, serverPort, serverToken, pageFiles:[…resolved], liveConfigPath, configDrift, targetPath, projectRoot:appRoot, repoRoot, roots:{manifest}, hasProduct:true, product:<text>, productPath:rel, hasDesign:true, design:<text>, designPath:rel, hasSurfaceBrief, surfaceBrief:<text|null>, surfaceBriefPath:rel|null, _instructions:'Open the app URL that serves a pageFiles entry (never serverPort; that is the helper). Then start the poll loop per your harness policy in live.md and re-run node <scripts>/live-poll.mjs immediately after every event or reply. Every event carries _instructions: follow them; they are the authoritative next step with real ids and paths filled in. A poll that is running is a poll you are SERVICING: never announce you are waiting and idle your turn; stay on the exec session until it returns an event, and never end a turn while a poll is outstanding.'}`. Surface brief resolved from `.impeccable/surfaces` under appRoot, contextRoot, repoRoot (first hit). With `--dev-url` (and only then) the payload also carries `devUrl`, the origin of the dev server serving this app right now, found by fetching `/` on the candidate origins (`http://127.0.0.1:<p>/` and `http://localhost:<p>/` for p in 5173, 3000, 4321, 8080, 4173, 3001, 5174, 8000, 4200, 5000, 1234, probed in parallel with sub-second timeouts; `IMPECCABLE_DEV_URL_CANDIDATES` replaces the list with a comma-separated one) and keeping the first whose document contains the injected `live.js?token=<serverToken>` tag; `null` when none does. Without either flag the payload and the boot's work are exactly as before: no probe runs and neither key appears.
|
||||
- Tests: `tests/live-target-context.test.mjs`, `tests/live-roots.test.mjs`, `tests/live-e2e.test.mjs` (`session.liveBoot` for `appDir` fixtures), `tests/live-recovery-commands.test.mjs`.
|
||||
|
||||
#### `live-server.mjs` -> `impeccable live-server`
|
||||
|
||||
Reference in New Issue
Block a user