mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-22 02:56:52 +03:00
feat(live): make live sessions recoverable (#125)
* feat(live): make live sessions recoverable tired of live mode losing the plot when the browser moved faster than the agent. now the state is boring: journal it, resume it, finish it. --- - add durable live-session journal, checkpoint events, and status/resume/complete commands - split browser session storage into a testable helper and harden accept/discard completion - fix Astro live CSS preview mode and add recovery/live E2E coverage - declare Bun as the package manager and add a Bun-native audit script * fix(live): acknowledge fallback recovery states * fix(live): flush recoverable handoffs promptly * fix(live): keep recovery handoffs accurate * fix(live): preserve poll reply metadata * fix(live): treat event HTTP failures as failed sends * fix(live): acknowledge manual completion through helper * Add .impeccable project state paths * Fix live disconnect recovery phase * Refine live CSS authoring contract * Test live CSS authoring guidance * Harden live LLM E2E recovery * Fix live recovery review issues --------- Co-authored-by: Paul Bakaus <paulbakaus@pauls-mbp-3.lan>
This commit is contained in:
co-authored by
Paul Bakaus
parent
88b82ae5f5
commit
d874af046a
@@ -0,0 +1,24 @@
|
||||
import { describe, it } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
|
||||
const SOURCE = readFileSync(join(process.cwd(), 'source/skills/impeccable/scripts/live-browser.js'), 'utf-8');
|
||||
|
||||
describe('live-browser source contracts', () => {
|
||||
it('keeps sendEvent fire-and-forget by default while accept/discard opt into rejection', () => {
|
||||
assert.match(
|
||||
SOURCE,
|
||||
/function sendEvent\(msg, opts\)[\s\S]*if \(opts && opts\.throwOnError\) throw err;[\s\S]*return null;/,
|
||||
'event=live_browser.send_event_contract actor=browser operation=send_event_failure risk=fire_and_forget_callers_get_unhandled_rejections expected=default swallow with opt-in throw actual=missing',
|
||||
);
|
||||
assert.match(SOURCE, /if \(res\.ok\) return res;[\s\S]*handleFailure\(new Error\('HTTP ' \+ res\.status \+ ' ' \+ res\.statusText\)\)/);
|
||||
assert.match(
|
||||
SOURCE,
|
||||
/\.then\(res => \{[\s\S]*if \(res\.ok\) return res;[\s\S]*\}\)\.catch\(handleFailure\)/,
|
||||
'event=live_browser.http_error_contract actor=browser operation=accept_discard_ack risk=http_500_clears_local_state_without_durable_receipt expected=non-ok response handled before then-success actual=missing',
|
||||
);
|
||||
assert.match(SOURCE, /sendEvent\(acceptPayload, \{ throwOnError: true \}\)/);
|
||||
assert.match(SOURCE, /sendEvent\(\{ type: 'discard', id: currentSessionId \}, \{ throwOnError: true \}\)/);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user