feat(01-13): A14 — post-SAVE state check (badge='', popup='', no new recovery notif)
Plan 01-13 Task 9 closure for operator empirical UAT bug
.planning/debug/01-09-save-stops-recording.md. Adds the harness
assertion that empirically verifies the SAVE-auto-stops-recording fix
(committed at 4f4c3e2) holds end-to-end through a real Chrome instance
+ real MediaRecorder + real chrome.action + real chrome.notifications.
A14 design (read-only post-state check):
1. Snapshot active mokosh-recovery-* notification ids (delta baseline).
2. Settle 500ms for the post-A13 SAVE finally block to land.
3. Read chrome.action.getBadgeText/getPopup + getActiveNotificationIds.
4. Assert badge='', popup='', recoveryDelta=0 — three checks total.
A14 chains off A13's SAVE_ARCHIVE (which under the new fix auto-stops
the recording per SPEC one-shot intent). A14 does NOT dispatch its own
SAVE — A13's SAVE is the event A14 observes the post-state of. This
keeps the harness wall-clock minimal (~500ms added for A14, no
additional 11s segment-settle).
Amendment to A13: now does setupFreshRecording + 11s segment-settle
BEFORE its own SAVE_ARCHIVE dispatch. Under the new fix, A12's
SAVE_ARCHIVE stopped the recording — without this A13 would dispatch
against an empty buffer and fail with EmptyVideoBufferError. The
amendment adds ~11s to harness wall-clock; acceptable given the SPEC
SAVE=stop contract is now load-bearing.
A14 contract notes per orchestrator simpler-design recommendation:
- direct isRecording proxy check skipped (no bridge op exposes it;
transitively verified via badge='' — production state machine
pairs isRecording transitions with badge transitions atomically)
- recovery-notif check is delta-based (A7 left a mokosh-recovery-*
in the active set; we verify A13's SAVE did NOT add another one)
Files modified:
- tests/uat/extension-page-harness.ts: +assertA14 (~110 lines) +
A13 amended with setupFreshRecording + 11s settle + 1 new
SETUP check + window.__mokoshHarness export wire
- tests/uat/lib/harness-page-driver.ts: +driveA14 wrapper
- tests/uat/harness.test.ts: +A14 in drivers array + header doc +
total 14/14 → 15/15 + import line
Verification:
- npm run test:uat: 15/15 GREEN (was 14/14)
- npx tsc --noEmit: exit 0 (no type errors)
- npm run build: exit 0 (production bundle clean)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,23 +1,26 @@
|
||||
// tests/uat/harness.test.ts — Plan 01-13 Wave 3A orchestrator.
|
||||
// tests/uat/harness.test.ts — Plan 01-13 orchestrator (Wave 3A → Task 9).
|
||||
//
|
||||
// Top-level entry for the production UAT harness. Drives all 14
|
||||
// Top-level entry for the production UAT harness. Drives all 15
|
||||
// assertions sequentially against a SINGLE launched Chrome instance with
|
||||
// a SINGLE harness page; bails on the first failure with a structured
|
||||
// diagnostic dump. Exits 0 only when 14/14 GREEN.
|
||||
// diagnostic dump. Exits 0 only when 15/15 GREEN.
|
||||
//
|
||||
// Wave 3A scope — wires A0+A1+A2+A3+A4+A6 (A6 via the proven Wave-2
|
||||
// driver). A5+A7..A13 throw `NOT YET IMPLEMENTED — Wave 3<X> wires this`
|
||||
// driver). A5+A7..A13 threw `NOT YET IMPLEMENTED — Wave 3<X> wires this`
|
||||
// from `tests/uat/lib/harness-page-driver.ts`; the bail-on-first-failure
|
||||
// loop stops at the first such throw.
|
||||
// loop stopped at the first such throw.
|
||||
//
|
||||
// Wave 3B wires A5 (SAVE_ARCHIVE → zip on disk) + A7 (genuine
|
||||
// RECORDING_ERROR → ERR + recovery notification). Wave 3C (this file's
|
||||
// current state) wires A8 (Bug A canonical onStartup-notification
|
||||
// regression rewind) + A9 (icon file sizes meet imageUtil floors) +
|
||||
// A10 (manifest shape contract). Expected diagnostic:
|
||||
// "11/14 GREEN: A0+A1+A2+A3+A4+A5+A6+A7+A8+A9+A10; bail at A11".
|
||||
// RECORDING_ERROR → ERR + recovery notification). Wave 3C wires A8
|
||||
// (Bug A canonical onStartup-notification regression rewind) + A9 (icon
|
||||
// file sizes meet imageUtil floors) + A10 (manifest shape contract).
|
||||
// Wave 3D wires A11+A12+A13 for 14/14 GREEN.
|
||||
//
|
||||
// Plan 01-13 Task 9 closure (debug 01-09-save-stops-recording) adds A14:
|
||||
// post-SAVE auto-stop state check (badge='', popup='', no new
|
||||
// mokosh-recovery-*). Chains off A13's SAVE_ARCHIVE — read-only
|
||||
// observation, no new dispatch. Final target: 15/15 GREEN.
|
||||
//
|
||||
// The orchestrator structure is final from Wave 3A onward; future waves
|
||||
// only fill in the assertion-driver stubs.
|
||||
//
|
||||
@@ -63,6 +66,7 @@ import {
|
||||
driveA11,
|
||||
driveA12,
|
||||
driveA13,
|
||||
driveA14,
|
||||
getManifestVersion,
|
||||
} from './lib/harness-page-driver';
|
||||
import {
|
||||
@@ -219,7 +223,11 @@ async function assertA0_GrepGate(): Promise<{
|
||||
* iterate driver list → bail on first failure → close browser → return
|
||||
* exit code.
|
||||
*
|
||||
* @returns Process exit code: 0 on 14/14 GREEN, 1 on any failure.
|
||||
* Plan 01-13 Task 9 closure (debug 01-09-save-stops-recording) added A14
|
||||
* after A13. The orchestrator now drives 14 page-side assertions
|
||||
* (A1..A14) plus the host-side A0 grep gate = 15 total.
|
||||
*
|
||||
* @returns Process exit code: 0 on 15/15 GREEN, 1 on any failure.
|
||||
*/
|
||||
async function main(): Promise<number> {
|
||||
process.stdout.write('\nMokosh Plan 01-13 — UAT harness orchestrator\n');
|
||||
@@ -295,6 +303,12 @@ async function main(): Promise<number> {
|
||||
{ name: 'A11', drive: driveA11 },
|
||||
{ name: 'A12', drive: driveA12Wrapped },
|
||||
{ name: 'A13', drive: driveA13Wrapped },
|
||||
// Plan 01-13 Task 9 closure (debug 01-09-save-stops-recording): A14
|
||||
// verifies that A13's SAVE_ARCHIVE auto-stopped the recording per
|
||||
// SPEC one-shot intent. Read-only assertion on chrome.action +
|
||||
// notification ids state; no new SAVE dispatch — A13's already
|
||||
// exercised the SAVE path. Recording stays stopped after A14.
|
||||
{ name: 'A14', drive: driveA14 },
|
||||
];
|
||||
|
||||
const buffers = { swConsole: handles.swConsole, offConsole: handles.offConsole };
|
||||
@@ -337,7 +351,7 @@ async function main(): Promise<number> {
|
||||
}
|
||||
|
||||
const passedCount = results.filter((r) => r.passed).length;
|
||||
// Total = 1 (A0) + drivers.length (A1..A13) = 14.
|
||||
// Total = 1 (A0) + drivers.length (A1..A14) = 15.
|
||||
const total = drivers.length + 1;
|
||||
const finalPassed = passedCount + 1; // +1 for A0 (we already passed it to reach here)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user