feat(03-03): Task 2 — driveA31 + orchestrator wiring (A31 password-filter PARTIAL)
- Append driveA31 to tests/uat/lib/harness-page-driver.ts after driveA30:
- Reuses UserEvent type (Plan 03-02 import already present).
- 3-phase pattern: page.evaluate → findLatestZip → JSZip
logs/events.json parse + filter-pipeline grep for sentinel absence
+ control-sentinel presence.
- 3 host-side checks: A31.2 (eventsContainingSentinel.length === 0),
A31.3 (eventsTargetingPassword.length === 0), A31.4
(eventsContainingControl.length >= 1; defense-in-depth proves
the listener is alive so A31.2/A31.3 absences mean the filter
fired rather than a tautological "no events at all" pass).
- Standard guard checks A31.0 (zip present) + A31.0a (events.json
entry exists) + A31.0b (JSON.parse success) gate before A31.2..A31.4
per Plan 02-04 / Plan 03-01 / Plan 03-02 driveA26/A29/A30 precedent.
- Filter-pipeline form preserved (no `continue`) per CLAUDE.md
Control Flow §.
- Wire orchestrator in tests/uat/harness.test.ts:
- Add `driveA31,` to import block after `driveA30,`.
- Add `driveA31Wrapped` const after `driveA30Wrapped`.
- Add `{ name: 'A31', drive: driveA31Wrapped }` entry to drivers
array after the A30 entry with explanatory banner comment
citing the cs-injection-world precedent + the defense-in-depth
A31.4 control check.
- Append `, A31` to the orchestrator banner string.
Acceptance grep gates (post-commit):
- grep -c 'driveA31' tests/uat/lib/harness-page-driver.ts returns 2
- grep -c 'driveA31' tests/uat/harness.test.ts returns 6
- grep -c 'secret-do-not-log-123' tests/uat/lib/harness-page-driver.ts returns 1
- tsc --noEmit exit 0
A29 flake disclosure (per Plan 03-02 SUMMARY "Issues Encountered"):
- During Plan 03-03 empirical verification of A31, the pre-existing
A29 flakiness documented in 03-02-SUMMARY.md surfaced: A29 chains
off incidental zip-mtime ordering against prior assertions' zips,
so when A29's own (empty chrome-extension:// SAVE) zip mtime ties
with a prior real-content zip, findLatestZip non-deterministically
returns the prior zip with rrweb events from iana.org/example.com.
- 3 base runs (HEAD=de398347, no Plan 03-03 changes): 2/3 PASS,
1/3 FAIL — confirms PRE-EXISTING flake, NOT a Plan 03-03 regression.
- Per CLAUDE.md SCOPE BOUNDARY ("Only auto-fix issues DIRECTLY caused
by the current task's changes") + Plan 03-02 SUMMARY's explicit
recommendation ("Plan 03-05's VERIFICATION.md aggregator + a
Phase 4 hardening pass can pick it up"): A29 flake is OUT OF SCOPE
for Plan 03-03. Documented in SUMMARY as deferred item.
This commit is contained in:
@@ -101,6 +101,8 @@ import {
|
||||
driveA29,
|
||||
// Plan 03-02 — event-log verification (SPEC §10 #5 / REQ-user-event-log)
|
||||
driveA30,
|
||||
// Plan 03-03 — password-filter PARTIAL (SPEC §10 #8 PARTIAL per D-P3-02)
|
||||
driveA31,
|
||||
getManifestVersion,
|
||||
} from './lib/harness-page-driver';
|
||||
import {
|
||||
@@ -269,7 +271,7 @@ async function assertA0_GrepGate(): Promise<{
|
||||
*/
|
||||
async function main(): Promise<number> {
|
||||
process.stdout.write('\nMokosh Plan 01-13 + 01-14 + 02-04 — UAT harness orchestrator\n');
|
||||
process.stdout.write('Architecture: A0 pre-flight + extension-internal page driver (A1..A14, A15..A17, A18..A22, A23, A24, A25, A26, A27, A28, A29, A30)\n');
|
||||
process.stdout.write('Architecture: A0 pre-flight + extension-internal page driver (A1..A14, A15..A17, A18..A22, A23, A24, A25, A26, A27, A28, A29, A30, A31)\n');
|
||||
process.stdout.write('='.repeat(72) + '\n');
|
||||
|
||||
// A0 pre-flight (no Chrome launch needed; runs against built dist/).
|
||||
@@ -345,6 +347,12 @@ async function main(): Promise<number> {
|
||||
// of logs/events.json from the just-produced zip.
|
||||
const driveA30Wrapped: (page: import('puppeteer').Page) => Promise<AssertionRecord> =
|
||||
(page) => driveA30(page, handles.downloadsDir);
|
||||
// Plan 03-03 — driveA31 needs downloadsDir for host-side JSZip
|
||||
// negative-assertion against logs/events.json (sentinel absence +
|
||||
// password-selector-target absence) + control-sentinel presence
|
||||
// (defense-in-depth A31.4).
|
||||
const driveA31Wrapped: (page: import('puppeteer').Page) => Promise<AssertionRecord> =
|
||||
(page) => driveA31(page, handles.downloadsDir);
|
||||
|
||||
const drivers: ReadonlyArray<{
|
||||
readonly name: string;
|
||||
@@ -454,6 +462,19 @@ async function main(): Promise<number> {
|
||||
// driveA30 JSZip-parses logs/events.json and asserts presence of
|
||||
// each of the 5 UserEvent.type literal values.
|
||||
{ name: 'A30', drive: driveA30Wrapped },
|
||||
// Plan 03-03 A31: password-filter PARTIAL (SPEC §10 #8 PARTIAL per
|
||||
// D-P3-02). Negative-assertion: opens a fresh https://example.com
|
||||
// probe tab (Plan 03-02 cs-injection-world precedent), injects a
|
||||
// synthetic <input type="password"> + a control <input type="text">
|
||||
// via chrome.scripting.executeScript ISOLATED-world, types the
|
||||
// sentinels, settles, SAVEs while the probe tab is active, finally-
|
||||
// cleanup. Host-side driveA31 inspects logs/events.json and asserts
|
||||
// sentinel value absence + password-selector-target absence (proves
|
||||
// src/content/index.ts:82 filter fired) + control-sentinel presence
|
||||
// (defense-in-depth: proves the listener is alive so A31.2/A31.3
|
||||
// mean the filter actually fired rather than the trivial "no
|
||||
// events at all" tautology).
|
||||
{ name: 'A31', drive: driveA31Wrapped },
|
||||
];
|
||||
|
||||
const buffers = { swConsole: handles.swConsole, offConsole: handles.offConsole };
|
||||
|
||||
Reference in New Issue
Block a user