From 7a60938057a322e3088fcbd3ab5e70149f2f9173 Mon Sep 17 00:00:00 2001 From: Anton Pepperok Date: Sat, 31 Oct 2026 13:14:35 +0200 Subject: [PATCH 1/2] Start manual window observations without host timer pauses --- CHANGELOG.md | 7 ++++++ README.md | 6 ++--- benchmarks/native-reference.ts | 7 +++--- docs/ci-concurrency.md | 31 ++++++++++++++++++++++++++ docs/performance.md | 2 ++ docs/release-checklist.md | 2 ++ docs/release-handoff.md | 2 ++ docs/releases/0.1.0-alpha.6.md | 2 ++ docs/reliability.md | 2 ++ docs/roadmap.md | 2 ++ docs/tabs.md | 9 ++++---- docs/verification.md | 2 ++ src/engine/observation-window.ts | 4 ---- src/scenarios/tabs.ts | 8 +++---- tests/integration/tabs.spec.ts | 24 ++++++++++++++++++++ tests/unit/observation-window.test.mjs | 22 ++++++++---------- 16 files changed, 100 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c1253d..b9c622a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,13 @@ ## 0.1.0-alpha.6 — source candidate +- Start the next manual-window browser read immediately after validating the previous + snapshot, removing a host pause that contributed to the ARM 109.8 ms gap. + Retain the 100 ms limit, actual timestamps, fresh locators and zero retries. + Add a timer-order regression and match the native benchmark scheduler; + prior measurements remain historical until refreshed. + + - Add a read-only release-evidence check that lists all pending records without running tests or changing artifacts. Share its validation with the final package gate and reject contradictory CI-guard exit codes, missing hashes and empty cases. diff --git a/README.md b/README.md index d6fbc95..44cc534 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Development verification:** The default repeatability check runs four full rounds and a separate four-worker comparison. Final 100-round acceptance remains deferred until the candidate is frozen; [protocol and retained results](docs/reliability.md). Ordinary CI checks the real package and clean consumers without claiming final acceptance. -**Release preparation:** the [review snapshot and exact tested archive](docs/release-handoff.md) are recorded for merged `da7e663`. Main CI passed Linux 169/169 and macOS ARM 507/507. Publication and final acceptance remain pending. +**Release preparation:** main `02ee0953` passed Linux but failed macOS ARM on a 109.8 ms observation gap. The candidate removes the host timer between manual-window reads; short CI validation is pending. Earlier archives, repeatability proofs and benchmarks retain their original source identity. [Diagnosis and validation](docs/ci-concurrency.md#consecutive-window-reads). Publication and final acceptance remain pending. Inspect the remaining saved evidence with `node scripts/check-release-readiness.mjs` from the repository root. This read-only command does not start tests or publish a package. @@ -209,9 +209,9 @@ and [CI evidence](docs/evidence/ci-atomic-observations.json) bind the results to this source revision. This short development sample is not a guarantee against future runner stalls. [The investigation](docs/ci-concurrency.md) retains earlier failures and measured limits. Final 100-round acceptance remains deferred; the -[current-source benchmark](docs/performance.md) has now passed all 108 tests. Real-world adoption has not been established. +[historical benchmark](docs/performance.md) has now passed all 108 tests. Real-world adoption has not been established. -### Measured overhead (`da7e663`, 31 October 2026) +### Historical measured overhead (`da7e663`, 31 October 2026) ![KeyTrail overhead against equivalent native Playwright checks](docs/assets/performance.svg) diff --git a/benchmarks/native-reference.ts b/benchmarks/native-reference.ts index d33dca5..ec2e0cf 100644 --- a/benchmarks/native-reference.ts +++ b/benchmarks/native-reference.ts @@ -270,7 +270,6 @@ export async function nativeJourney(page: Page, info: TestInfo, manifest: Manife let firstObserved: number | undefined, lastObserved: number | undefined, maxGap = 0; const intervals: number[] = []; while (true) { - const readStarted = performance.now(); const state = await capture(!negative); const readings = await Promise.all(group.map(c => read(c, state))); guard(); if (negative) { @@ -291,9 +290,9 @@ export async function nativeJourney(page: Page, info: TestInfo, manifest: Manife for (let n = 0; n < group.length; n++) mark(group[n]!, readings[n]!); break; } - // Match the same 25 ms target and 10 ms maximum pause as the journey. - const pause = negative ? Math.max(1, Math.min(10, 25 - (performance.now() - readStarted))) : 20; - await delay(Math.max(1, Math.min(pause, negative ? config.observationWindowMs - (state.observedAt - firstObserved!) : deadline - performance.now(), remaining()))); + // Match the journey's consecutive asynchronous reads in negative windows. + // Positive waits retain their bounded pause. + if (!negative) await delay(Math.max(1, Math.min(20, deadline - performance.now(), remaining()))); } index += group.length - 1; } diff --git a/docs/ci-concurrency.md b/docs/ci-concurrency.md index efcd5db..8e00729 100644 --- a/docs/ci-concurrency.md +++ b/docs/ci-concurrency.md @@ -8,6 +8,37 @@ The four-worker isolation comparison remains part of the local four-round verifier. A real gap above 100 ms still blocks a negative observation; retries remain disabled. Results below identify their source revision and runner. +## Consecutive window reads + +The [post-merge main run](https://github.com/PerchAnton/keytrail/actions/runs/41194618651) +at `02ee0953` passed Linux 169/169 and its package consumers. ARM passed 168/169 +in the first of three planned rounds. `tabs pass manual Home End` stopped at +`T05.backward.003.unchanged` with a **109.8 ms** gap; its snapshot took **98.514 ms**. +The remaining ARM rounds and package checks did not run. The full raw failure and +snapshot profile are retained; no retry replaces this result. + +The previous reader took 12.342 ms, so the old scheduler then slept up to 10 ms. +A short previous read cannot predict the latency of the next one. The follow-up +removes that deliberate pause within negative windows. After checking one complete +snapshot, the driver immediately starts the next asynchronous browser read. There +is no overlapping snapshot or background action chain. Fresh locator resolution, +atomic state reads, cleanup and scenario budgets are unchanged. Positive waits +keep their bounded pauses. + +This trades additional observations during each bounded window for more timing +headroom. It cannot make an arbitrary browser or shared host meet a hard deadline: +every actual gap above **100 ms** still blocks, and retries remain zero. The native +benchmark reference uses the same consecutive-read policy; its old numbers are +historical until remeasured. Timing records identify the slow read, not the exact +cause of a runner delay. + +A new regression queues a host timer after the first real window snapshot and +requires the next read to start before it runs. Restoring the old pause must fail +that regression. Existing before/after transport-delay tests, short-window coverage, +scenario deadlines, transient component failures and handle cleanup remain required. +Validation is limited to three ARM rounds and one Linux round in ordinary CI; +final 100-round acceptance is not requested. + ## Private observation store Each driver owns one private browser `Map`, accessed through a public Playwright diff --git a/docs/performance.md b/docs/performance.md index 34eb601..33a2223 100644 --- a/docs/performance.md +++ b/docs/performance.md @@ -1,5 +1,7 @@ # Equivalent-work benchmark +**Historical measurements:** the table and graph below apply to `da7e663`. The consecutive-read candidate changes both the journey scheduler and the native reference. These timings are preserved unchanged and are not performance evidence for that candidate. A fresh equivalent-work benchmark is pending; it is separate from the requested short CI validation. + **Development verification:** The default repeatability check runs four full rounds and a separate four-worker comparison. Final 100-round acceptance remains deferred until the candidate is frozen; [protocol and retained results](reliability.md). Ordinary CI checks the real package and clean consumers without claiming final acceptance. These measurements describe current main `da7e663`, recorded on 31 October 2026. diff --git a/docs/release-checklist.md b/docs/release-checklist.md index ad8dc1a..6d0e3bf 100644 --- a/docs/release-checklist.md +++ b/docs/release-checklist.md @@ -1,5 +1,7 @@ # First alpha release checklist +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). + **Development verification:** The default repeatability check runs four full rounds and a separate four-worker comparison. Final 100-round acceptance remains deferred until the candidate is frozen; [protocol and retained results](reliability.md). Ordinary CI checks the real package and clean consumers without claiming final acceptance. Candidate: **0.1.0-alpha.6**, ruleset **0.4.0**, schema **1**. The earlier alpha diff --git a/docs/release-handoff.md b/docs/release-handoff.md index 286300a..630e9e4 100644 --- a/docs/release-handoff.md +++ b/docs/release-handoff.md @@ -1,5 +1,7 @@ # Review the first release candidate +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). + The reviewed development snapshot is `da7e66378619816cd9c7e065df95f0e2a6e67661` for **KeyTrail 0.1.0-alpha.6**. It is not a published release or final acceptance. The [readiness record](evidence/release-readiness.json) identifies completed checks, diff --git a/docs/releases/0.1.0-alpha.6.md b/docs/releases/0.1.0-alpha.6.md index eb47c38..6d206e7 100644 --- a/docs/releases/0.1.0-alpha.6.md +++ b/docs/releases/0.1.0-alpha.6.md @@ -1,5 +1,7 @@ # KeyTrail 0.1.0-alpha.6 — draft first-release notes +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](../ci-concurrency.md#consecutive-window-reads). + **Draft: final acceptance deferred.** Development uses four rounds and independent package-consumer checks. The historical 100-round counts refer to `0300552` and cannot certify the changed release candidate. Fresh benchmark evidence is recorded separately. **Prepared, not published.** KeyTrail checks declared keyboard journeys in diff --git a/docs/reliability.md b/docs/reliability.md index 3c616cb..3e0e531 100644 --- a/docs/reliability.md +++ b/docs/reliability.md @@ -1,5 +1,7 @@ # Full-suite repeatability protocol +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). + **Development verification:** The default repeatability check runs four full rounds and a separate four-worker comparison. Final 100-round acceptance remains deferred until the candidate is frozen; [protocol and retained results](reliability.md). Ordinary CI checks the real package and clean consumers without claiming final acceptance. ## Current development policy diff --git a/docs/roadmap.md b/docs/roadmap.md index 14549fc..266941e 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,5 +1,7 @@ # Milestones +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). + The supplied development specification v1.0 (28 October 2026) defines a full 0.1.0 target. This repository starts with its DEV01–DEV05 dialog checkpoint, designated `0.1.0-alpha.1`. The current `0.1.0-alpha.6` source candidate includes DEV09 verification diff --git a/docs/tabs.md b/docs/tabs.md index 228a3ec..b553f7a 100644 --- a/docs/tabs.md +++ b/docs/tabs.md @@ -91,10 +91,11 @@ sequenceDiagram The negative window begins with a real snapshot after focus and roving checks, and requires a final snapshot at least `observationWindowMs` later. Browser-side monotonic timestamps measure the intervals between snapshots, including browser -round-trip and scheduling delays. Polling sleeps at most 20 ms between reads and -shortens that pause to account for the time spent reading the browser; the target -sampling interval is at most 50 ms. Any measured gap **greater than -100 ms** produces `blocked / OBSERVATION_GAP`, stops before activation, and leaves +round-trip and scheduling delays. Each next read starts immediately after the +previous snapshot is checked, without an added host timer. Awaiting the browser +read yields to asynchronous I/O; snapshots remain sequential. This uses more +observations during the bounded window and cannot guarantee scheduling latency +on a stalled host. Any measured gap **greater than 100 ms** produces `blocked / OBSERVATION_GAP`, stops before activation, and leaves dependent checks `not_run`. A component mismatch observed in the same snapshot retains its specific failure instead of being hidden by the timing problem. diff --git a/docs/verification.md b/docs/verification.md index e065fca..7ffc1ef 100644 --- a/docs/verification.md +++ b/docs/verification.md @@ -1,5 +1,7 @@ # Verification +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). + **Development verification:** The default repeatability check runs four full rounds and a separate four-worker comparison. Final 100-round acceptance remains deferred until the candidate is frozen; [protocol and retained results](reliability.md). Ordinary CI checks the real package and clean consumers without claiming final acceptance. The current source candidate is `0.1.0-alpha.6`, ruleset 0.4.0, schema 1. diff --git a/src/engine/observation-window.ts b/src/engine/observation-window.ts index ac1c8d1..065f6e4 100644 --- a/src/engine/observation-window.ts +++ b/src/engine/observation-window.ts @@ -1,10 +1,6 @@ import type { SafeObservation } from '../contracts/types.js'; export const MAX_OBSERVATION_GAP_MS = 100; -/** Target a quarter of the gap budget; leave room for variable browser transport. */ -export function observationPauseMs(readDurationMs: number): number { - return Math.max(1, Math.min(10, MAX_OBSERVATION_GAP_MS / 4 - readDurationMs)); -} /** Timestamps come from the same browser clock at the start of each DOM snapshot. */ export class ObservationWindow { private first: number | undefined; diff --git a/src/scenarios/tabs.ts b/src/scenarios/tabs.ts index 177e5b0..8d4e7bf 100644 --- a/src/scenarios/tabs.ts +++ b/src/scenarios/tabs.ts @@ -6,7 +6,7 @@ import { DEFAULTS } from '../contracts/common.js'; import { validateTabs } from '../contracts/tabs.js'; import type { CheckResult, JourneyResult, MessageCode, SafeObservation, TabsContract } from '../contracts/types.js'; import { planTabs } from '../engine/tabs-plan.js'; -import { ObservationWindow, observationPauseMs } from '../engine/observation-window.js'; +import { ObservationWindow } from '../engine/observation-window.js'; import { Blocked, BoundaryExit, Driver, type Snapshot } from '../browser/driver.js'; import { coverage, outcome, JourneyAssertionError } from '../reporting/result.js'; import { serializeJourneyResult } from '../reporting/serialize.js'; @@ -154,7 +154,6 @@ export async function assertTabsJourney(page: Page, info: TestInfo, input: TabsC const step = d.steps.at(-1)!; try { while (true) { - const readStarted = performance.now(); state = await d.snapshot('interaction'); window.add(state.observedAt); current.observed = { ...selection(state, selected).observed, focus: state.focus, @@ -163,8 +162,9 @@ export async function assertTabsJourney(page: Page, info: TestInfo, input: TabsC ready(state); d.guard(); if (window.gap) throw new Blocked('OBSERVATION_GAP'); if (window.complete(config.observationWindowMs)) break; - await delay(Math.max(1, Math.min(observationPauseMs(performance.now() - readStarted), - config.observationWindowMs - window.elapsed, d.remaining()))); + // Each awaited snapshot yields to browser I/O. Start the next read + // immediately: a fast previous read cannot predict the next one's + // latency, so a host timer would spend part of its 100 ms budget. } finish(unchanged, { ok: true, observed: current.observed }, 'PREMATURE_ACTIVATION'); } finally { diff --git a/tests/integration/tabs.spec.ts b/tests/integration/tabs.spec.ts index 72157db..aa62330 100644 --- a/tests/integration/tabs.spec.ts +++ b/tests/integration/tabs.spec.ts @@ -4,6 +4,7 @@ import { readFileSync } from 'node:fs'; import { mock } from 'node:test'; import { assertTabsJourney, JourneyAssertionError, type JourneyResult, type TabsContract } from '../../src/index.js'; import { ObservationWindow } from '../../src/engine/observation-window.js'; +import { Driver } from '../../src/browser/driver.js'; import { tabsHtml, tabsContract, type TabsOptions } from '../fixtures/tabs.js'; import { recordSnapshotTimings } from '../support/snapshot-timings.js'; @@ -202,3 +203,26 @@ test('manual tabs record initial and final observations even for a short window' expect(observed.maxObservationGapMs).toBeLessThanOrEqual(100); } }); + +test('manual windows start the next browser read without a host timer pause', async ({ page }, info) => { + await page.setContent(tabsHtml({ activation: 'manual' })); + const snapshot = Driver.prototype.snapshot; + let reads = 0, timerRan = false, nextReadWasImmediate = false; + let timer: ReturnType | undefined; + Driver.prototype.snapshot = async function (...args) { + if (this.page !== page || args[0] !== 'interaction') return snapshot.apply(this, args); + if (++reads === 2) { + nextReadWasImmediate = !timerRan; + clearTimeout(timer); + } + const state = await snapshot.apply(this, args); + if (reads === 1) timer = setTimeout(() => { timerRan = true; }, 0); + return state; + }; + try { + const result = await assertTabsJourney(page, info, tabsContract(page, { activation: 'manual' })); + verify(result, info); + expect(reads).toBeGreaterThan(2); + expect(nextReadWasImmediate).toBe(true); + } finally { clearTimeout(timer); Driver.prototype.snapshot = snapshot; } +}); diff --git a/tests/unit/observation-window.test.mjs b/tests/unit/observation-window.test.mjs index 77fc142..9b223a1 100644 --- a/tests/unit/observation-window.test.mjs +++ b/tests/unit/observation-window.test.mjs @@ -1,6 +1,6 @@ import { test } from 'node:test'; import assert from 'node:assert/strict'; -import { ObservationWindow, observationPauseMs } from '../../artifacts/unit/observationWindow.js'; +import { ObservationWindow } from '../../artifacts/unit/observationWindow.js'; test('negative observations require two readings spanning the window', () => { const window = new ObservationWindow(); window.add(800); @@ -17,16 +17,12 @@ test('100 ms gaps are allowed but larger gaps remain blocked after later samples assert.equal(window.complete(200), false); assert.deepEqual(window.observed().observationIntervalsMs, [100, 100.125, 0.875]); }); -test('slow browser reads do not receive an avoidable extra 20 ms gap', () => { - const fixed = new ObservationWindow(); fixed.add(0); fixed.add(85 + 20); - assert.equal(fixed.gap, true); - const adaptive = new ObservationWindow(); adaptive.add(0); - adaptive.add(85 + observationPauseMs(85)); - assert.equal(adaptive.gap, false); - assert.equal(40 + observationPauseMs(40), 41); - assert.equal(observationPauseMs(10), 10); - assert.equal(20 + observationPauseMs(20), 25); - assert.equal(observationPauseMs(150), 1); - adaptive.add(300); - assert.equal(adaptive.gap, true, 'Scheduling cannot excuse a real observation gap'); +test('alternating fast and slow readings retain every actual interval', () => { + const window = new ObservationWindow(); + for (const at of [0, 12, 110.5, 120, 219.5]) window.add(at); + assert.equal(window.complete(200), true); + assert.deepEqual(window.observed().observationIntervalsMs, [12, 98.5, 9.5, 99.5]); + window.add(320); + assert.equal(window.gap, true, 'An actual slow reading still blocks'); + assert.equal(window.complete(200), false); }); From 9a73f2f2aed2e15efaf978420de002cc82273e94 Mon Sep 17 00:00:00 2001 From: Anton Pepperok Date: Sat, 31 Oct 2026 13:30:41 +0200 Subject: [PATCH 2/2] Record three passing ARM rounds and retain failed main evidence [skip ci] --- CHANGELOG.md | 1 - README.md | 4 +- docs/ci-concurrency.md | 19 + .../evidence/ci-consecutive-observations.json | 554 ++++++++++++++++++ docs/evidence/ci-guard.json | 6 +- docs/performance.md | 2 +- docs/release-checklist.md | 8 +- docs/release-handoff.md | 10 +- docs/releases/0.1.0-alpha.6.md | 4 +- docs/reliability.md | 2 +- docs/roadmap.md | 4 +- docs/verification.md | 18 +- 12 files changed, 602 insertions(+), 30 deletions(-) create mode 100644 docs/evidence/ci-consecutive-observations.json diff --git a/CHANGELOG.md b/CHANGELOG.md index b9c622a..d41dd1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,6 @@ Add a timer-order regression and match the native benchmark scheduler; prior measurements remain historical until refreshed. - - Add a read-only release-evidence check that lists all pending records without running tests or changing artifacts. Share its validation with the final package gate and reject contradictory CI-guard exit codes, missing hashes and empty cases. diff --git a/README.md b/README.md index 44cc534..a7721e4 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ **Development verification:** The default repeatability check runs four full rounds and a separate four-worker comparison. Final 100-round acceptance remains deferred until the candidate is frozen; [protocol and retained results](docs/reliability.md). Ordinary CI checks the real package and clean consumers without claiming final acceptance. -**Release preparation:** main `02ee0953` passed Linux but failed macOS ARM on a 109.8 ms observation gap. The candidate removes the host timer between manual-window reads; short CI validation is pending. Earlier archives, repeatability proofs and benchmarks retain their original source identity. [Diagnosis and validation](docs/ci-concurrency.md#consecutive-window-reads). Publication and final acceptance remain pending. +**Release preparation:** main `02ee0953` passed Linux but failed macOS ARM on a 109.8 ms observation gap. The candidate removes the host timer between manual-window reads; CI at `7a60938` passed **510/510 on ARM** and **170/170 on Linux**, plus package consumers, with zero retries. Maximum ARM gaps were **35.8 / 45.2 / 31.0 ms** against the unchanged **100 ms** limit. Earlier archives, repeatability proofs and benchmarks retain their original source identity. [Diagnosis and validation](docs/ci-concurrency.md#consecutive-window-reads). Publication and final acceptance remain pending. Inspect the remaining saved evidence with `node scripts/check-release-readiness.mjs` from the repository root. This read-only command does not start tests or publish a package. @@ -209,7 +209,7 @@ and [CI evidence](docs/evidence/ci-atomic-observations.json) bind the results to this source revision. This short development sample is not a guarantee against future runner stalls. [The investigation](docs/ci-concurrency.md) retains earlier failures and measured limits. Final 100-round acceptance remains deferred; the -[historical benchmark](docs/performance.md) has now passed all 108 tests. Real-world adoption has not been established. +[historical benchmark](docs/performance.md) passed all 108 tests at `da7e663`. Real-world adoption has not been established. ### Historical measured overhead (`da7e663`, 31 October 2026) diff --git a/docs/ci-concurrency.md b/docs/ci-concurrency.md index 8e00729..cba2df1 100644 --- a/docs/ci-concurrency.md +++ b/docs/ci-concurrency.md @@ -39,6 +39,25 @@ scenario deadlines, transient component failures and handle cleanup remain requi Validation is limited to three ARM rounds and one Linux round in ordinary CI; final 100-round acceptance is not requested. +The [CI run at `7a60938`](https://github.com/PerchAnton/keytrail/actions/runs/41196060997) +passed all stages on both platforms. Independent validation checked four raw +reports, **680 executions**, **644 distinct journey IDs**, semantic signatures, +source hashes, guard exits and actual archive checksums. Both vanilla and React +consumers passed on each platform. [Complete record](evidence/ci-consecutive-observations.json). + +| Platform / round | Passed | Maximum passing-window gap | +| --- | ---: | ---: | +| Linux / 1 | 170/170 | 32.2 ms | +| macOS ARM / 1 | 170/170 | 35.8 ms | +| macOS ARM / 2 | 170/170 | 45.2 ms | +| macOS ARM / 3 | 170/170 | 31.0 ms | + +All rounds use one worker and zero retries or skips. Deliberate 150 ms gaps still +block. These short results support the change in the recorded environments; they +do not guarantee future shared-host latency. No final 100-round series or new local +four-worker comparison was run. A six-case native-reference pilot passed semantic +equivalence and negative controls, but supplies no performance claim. + ## Private observation store Each driver owns one private browser `Map`, accessed through a public Playwright diff --git a/docs/evidence/ci-consecutive-observations.json b/docs/evidence/ci-consecutive-observations.json new file mode 100644 index 0000000..0980551 --- /dev/null +++ b/docs/evidence/ci-consecutive-observations.json @@ -0,0 +1,554 @@ +{ + "recordedAt": "2026-10-31T11:27:31.088Z", + "sourceCommit": "7a60938057a322e3088fcbd3ab5e70149f2f9173", + "runId": "41196060997", + "runUrl": "https://github.com/PerchAnton/keytrail/actions/runs/41196060997", + "scope": "Independently checked complete CI run: three consecutive ARM rounds, one Linux round and both actual tarball consumers. No retries or final acceptance; this is not a host-latency guarantee.", + "finalAcceptance": false, + "sourceHashes": { + "package.json": "f621dc5a5a045b7adc78248e5c008f7ee404556d47eb194b78d2fe5fcce1c86a", + "playwright.config.ts": "b37dd21c3b202d61916f34d3391678470f85346e2ace5e825d8d116df1acd343", + "pnpm-lock.yaml": "576e299340865b49bafd46859e458ab14a2937a6a5f07fe90b3057b8bf84f183", + "schema/journey-result.v1.json": "4deafd92cdccf4e923da6c19f350f1e9b3641f86007863e2ebb680cea7c48ce6", + "scripts/build.mjs": "de9d5b90f5f2439850417349259e843502d456fbb6c1b8ed5c341333067fe830", + "scripts/verify-reliability.mjs": "dd2d64fd7c3b73e532f843d85d29ff480c83ad5a614cd574b4cf90f84c656f1e", + "src/browser/driver.ts": "f7fd30689fecd1b0d43fadccd3fe30804928b4c5a8297cdb67654481472b9530", + "src/browser/observation-store.ts": "0ef8c192bebb8bba446739bbcaa7725f832034f9abb1f93ac857f9345faa7995", + "src/ci-guard.ts": "7aa34fda24c8b77e6fbd87c7318db5ded891b7ec483588dd773ab64e6502c7cf", + "src/contracts/common.ts": "cf4082518e4210aa054db7fb98cc7edef8dbb2fdb222c95ed8ff3811d7772890", + "src/contracts/dialog.ts": "99384b67e23425a7a89f34518c710ca1903e3ce424d49a711ddb227f507cd210", + "src/contracts/form-errors.ts": "44cc1838967ecf319e55c7e6aff5211a0742ff2075e42058df741ca628c64d9b", + "src/contracts/tabs.ts": "73d387a8040df26e07d7f1f9138e18bb522578b5806b1a4cdf818d3b43ac11e9", + "src/contracts/types.ts": "78cef4b95bed88ac622170a8a8e92b43f8ecaf5ea91571384d602f126c060432", + "src/engine/form-errors-plan.ts": "c094e2acf0e5665b4b3400d8fb980ed8dbbb46ef4839692810caeddc6219c44a", + "src/engine/observation-window.ts": "5f165904842f33e170f6f8f38fd53789c3124b39a1149335430e1ecbd1bd46b9", + "src/engine/plan.ts": "cab99a7e19fea3fb1f5b80ba2136ae24bf867ba2920162e4d439ff7ec85b8f53", + "src/engine/tabs-plan.ts": "1add41b1bc5500a28fd65d196e84ac58ae60b898db47825db0990226e44e5f34", + "src/index.ts": "db30784e5f37a98070cd0c5b7ba1f172274031a253abfc850a11874de7029a4d", + "src/reporting/result.ts": "06bbe42cba6f4ff464d68c0a00ce181830b9c8724dfa72c934edf5907cb6a7f2", + "src/reporting/serialize.ts": "766736300eec0ab76e58fb935c4bdd95692d49e6fcb3c1bb1f363255e800e45d", + "src/reporting/validate.ts": "70e38e30858af50c29b785619c9f42ea6515251ddc9c4fe8d30f3134417e2dc6", + "src/scenarios/dialog.ts": "ef7c163b05542c44b119639602d910e86b2581d9fd256ba8857c7f143b057b00", + "src/scenarios/form-errors.ts": "78cb7de2c9130105b9259060a6ae8d57f9a3473dd9b8a90fff6fe7e5c9546c7b", + "src/scenarios/tabs.ts": "b8bdedb38e3c0642da9ad242dca79c1bbd9458013cccda3fd9ec32904853fd76", + "src/version.ts": "1d8ad83fca6e82ceb3adfddd60d35f681a650646b7e5af0428e94267d819b894", + "tests/fixtures/dialog.ts": "bff39b874a4041757b3a32116e2313cc4e18be43bad78ce82bd05c4d15835604", + "tests/fixtures/form-errors.ts": "d91f33c21ff4e9d5bb6ad3b4e5d55ae7ee5e43ce4df30328778b9b22c18ac6ac", + "tests/fixtures/tabs.ts": "13bc81a70dacc4828a9a1c881509bf52098691595be28b1dcb39e89a1eb0092c", + "tests/guard/fault-reporter.mjs": "1d71672317608ea4356c94eb52a6c0c87942cd1b4f104efe87f90a278fc67391", + "tests/guard/fixture.spec.mjs": "d5cb1caf78222537f88196d69146827cff7e325f1f9b0fb841a98ca67314297b", + "tests/guard/playwright.config.mjs": "fc9771a33ee076bf3e0c1096a83bf1ccf2ed02730ade36705041704e27e92427", + "tests/guard/report.mjs": "d37e6c570e20f382cc08d97134acb71f33335b287c6d0b3e6fd80bb21e6483c3", + "tests/guard/setup.spec.mjs": "5125ccc3199877c152e07729f2c70e260f395f9260f89761c81c5923e10ad0c5", + "tests/integration/canary.spec.ts": "281f69a4ae8e65bbc0fbb7c2db9b72437cec84f48fffc5785007b3942bedb32e", + "tests/integration/dialog.spec.ts": "01901b749874696f1b01066b27a770c10d04125baa5552521ab7800af889ee3b", + "tests/integration/form-errors.spec.ts": "1cd15ccb3415ab4b1b2ac74486397fc4b0d47cd130db536f8d6f9922ee7d5206", + "tests/integration/observations.spec.ts": "6dbc89aae8b27295caf3a127364d27ed89319bac1ccd8b31b4c2ca60eab92321", + "tests/integration/tabs.spec.ts": "e07df3d59efb49ac38607cdc29780a14184e7b52bc8d51400aec435e0ede8263", + "tests/support/snapshot-timings.ts": "c35da8727cca4bb6e54f4f897bed42c479dbe8cf46603f8c9c8c2e426417903f", + "tests/unit/contracts.test.mjs": "0f64c49ba8567247ea63dedcd75d642a8dd37f62cd1ea17193bdbb3ec9dd5d12", + "tests/unit/deadline.test.mjs": "dad56ec32093098d3a8a1a90a9ccce2abd120ced8fb9901c8733aa9d758fa3f9", + "tests/unit/form-errors.test.mjs": "e2ff649e4650ebd1f2f7a0fc6b53d8802bf4e83c227a9143a6425854d74bc2bd", + "tests/unit/observation-window.test.mjs": "2bc6d547e234f4cf545c30c2ea4fa0258c1a325606d35cb3430cc3180bf909ff", + "tests/unit/reliability.test.mjs": "a7a097f5388dbabdd08f98264bdf0926bfe6b51cad8d4934675771cd9fb9aac8", + "tests/unit/reporting.test.mjs": "df8032dc07392a5eb6b64551b56f7bd712342fbdf99c3d4a5683b1ac746fd40a", + "tests/unit/tabs.test.mjs": "4c50cb57f642192d25a05aa314e0e789e589a4d3cfc5e747b7247c4745ef94b2", + "tests/unit/verification-modes.test.mjs": "ff8211b23a9df0897a0c8731985bcab754b07a89c3e64e4c23c6e81372477173", + "verification/inputs.mjs": "078bc601ef51e9b01827b079355fa04cfc1388956cb596d22dae79c70d87b6e6", + "verification/modes.mjs": "433218ce8b54643eda0011977a3908c6ec773956c4913b9c64c600f0248e296a", + "verification/signatures.mjs": "528fd54649777629c05db13d942187d17904382039f8cd904c0d752cb027ae7c" + }, + "platforms": [ + { + "platform": "linux", + "environment": { + "platform": "linux", + "arch": "x64", + "release": "7.0.0-1017-azure", + "node": "24.22.1", + "cpu": "Intel(R) Xeon(R) Platinum 8370C CPU @ 2.80GHz", + "logicalCpus": 4, + "memoryBytes": 16759304192 + }, + "workers": 1, + "retries": 0, + "checkedManualWindows": 57, + "maximumPassingWindowGapMs": 32.19999999999709, + "guardCases": 52, + "guardRecordSha256": "96c05ea8ce3ab32dcf3f033dcca3e9482f26862055ef2003c221b5a097ad14aa", + "packageRecord": { + "package": "keytrail", + "version": "0.1.0-alpha.6", + "checkedAt": "2026-10-31T11:21:05.553Z", + "verificationLevel": "development", + "finalAcceptance": false, + "node": "v24.22.1", + "platform": "linux", + "playwright": "1.64.1", + "archive": { + "file": "keytrail-0.1.0-alpha.6.tgz", + "bytes": 357344, + "sha256": "e00b35a94df4bc2d29d96f0fef82396d388be783ce8b053e619209e998be8652", + "files": 102 + }, + "checks": { + "evidenceSourceHashes": false, + "offlineConsumer": true, + "esm": true, + "cjs": true, + "typesEsm": true, + "typesCjs": true, + "browserExamples": 6, + "guardedBrowserExamples": 3, + "guardEsm": true, + "guardCjs": true + }, + "consumers": { + "vanilla": { + "registryMetadataPreparation": true, + "offlineInstall": true, + "frozenDependencyGraph": true, + "types": true, + "browserTests": 6, + "guardedJourneys": 3 + }, + "reactPortal": { + "registryMetadataPreparation": true, + "offlineInstall": true, + "frozenDependencyGraph": true, + "react": "19.3.1", + "reactDom": "19.3.1", + "types": true, + "strictMode": true, + "browserTests": 3, + "guardedJourneys": 1, + "negativeExitCode": 1, + "html": true, + "junit": true, + "failedAttachment": true, + "dependencyReferences": true + } + }, + "published": false + }, + "packageRecordSha256": "d2c5d17ec5b6f806d72d47589b33bfab2df35233a4611f7f5246f41c1ae9afe0", + "rounds": [ + { + "filename": "browser-results.json", + "sha256": "1e09dcd7c2f0ebea57d225f4d2ee43c377d51687262b90494c34f855fc37d13c", + "workers": 1, + "tests": 170, + "stats": { + "startTime": "2026-10-31T11:16:47.397Z", + "duration": 214019.74300000002, + "expected": 170, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "checkedManualWindows": 57, + "healthyFixtureAggregate": { + "snapshot": { + "count": 596, + "medianMs": 13.628291, + "p95Ms": 16.748701, + "maxMs": 24.040109 + }, + "evaluate": { + "count": 596, + "medianMs": 0, + "p95Ms": 0, + "maxMs": 0 + }, + "resolution": { + "count": 5960, + "medianMs": 10.39003, + "p95Ms": 13.385339, + "maxMs": 20.126359 + }, + "interval": { + "count": 558, + "medianMs": 13.699999999982538, + "p95Ms": 16.60000000000582, + "maxMs": 26.79999999998836 + }, + "gapsAbove100ms": 0 + }, + "maximumPassingWindowGapMs": 32.19999999999709, + "slowestPassingWindow": { + "fixture": "canary isolation tabs successful input", + "checkId": "T05.forward.003.unchanged", + "maxObservationGapMs": 32.19999999999709 + } + } + ], + "totalExecutions": 170, + "testsPerRound": 170, + "journeysPerRound": 161, + "lastRoundStats": { + "startTime": "2026-10-31T11:16:47.397Z", + "duration": 214019.74300000002, + "expected": 170, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "lastRoundRawReportSha256": "1e09dcd7c2f0ebea57d225f4d2ee43c377d51687262b90494c34f855fc37d13c", + "lastRoundHealthyFixtureAggregate": { + "snapshot": { + "count": 596, + "medianMs": 13.628291, + "p95Ms": 16.748701, + "maxMs": 24.040109 + }, + "evaluate": { + "count": 596, + "medianMs": 0, + "p95Ms": 0, + "maxMs": 0 + }, + "resolution": { + "count": 5960, + "medianMs": 10.39003, + "p95Ms": 13.385339, + "maxMs": 20.126359 + }, + "interval": { + "count": 558, + "medianMs": 13.699999999982538, + "p95Ms": 16.60000000000582, + "maxMs": 26.79999999998836 + }, + "gapsAbove100ms": 0 + } + }, + { + "platform": "macos-latest", + "environment": { + "platform": "darwin", + "arch": "arm64", + "release": "25.6.0", + "node": "24.22.1", + "cpu": "Apple M1 (Virtual)", + "logicalCpus": 3, + "memoryBytes": 7516192768, + "imageOS": "macos26", + "imageVersion": "20261021.0445.8" + }, + "workers": 1, + "retries": 0, + "checkedManualWindows": 171, + "maximumPassingWindowGapMs": 45.20000000006985, + "guardCases": 52, + "guardRecordSha256": "88b5dbf703e46f7cadf39fbfcfd7c2f0d00a44944373a3682a589274d583e571", + "packageRecord": { + "package": "keytrail", + "version": "0.1.0-alpha.6", + "checkedAt": "2026-10-31T11:26:21.685Z", + "verificationLevel": "development", + "finalAcceptance": false, + "node": "v24.22.1", + "platform": "darwin", + "playwright": "1.64.1", + "archive": { + "file": "keytrail-0.1.0-alpha.6.tgz", + "bytes": 357344, + "sha256": "609bae2b134f6ba8c995c38f50cbc73f614d7bd27effac856fc1cbabe66ab206", + "files": 102 + }, + "checks": { + "evidenceSourceHashes": false, + "offlineConsumer": true, + "esm": true, + "cjs": true, + "typesEsm": true, + "typesCjs": true, + "browserExamples": 6, + "guardedBrowserExamples": 3, + "guardEsm": true, + "guardCjs": true + }, + "consumers": { + "vanilla": { + "registryMetadataPreparation": true, + "offlineInstall": true, + "frozenDependencyGraph": true, + "types": true, + "browserTests": 6, + "guardedJourneys": 3 + }, + "reactPortal": { + "registryMetadataPreparation": true, + "offlineInstall": true, + "frozenDependencyGraph": true, + "react": "19.3.1", + "reactDom": "19.3.1", + "types": true, + "strictMode": true, + "browserTests": 3, + "guardedJourneys": 1, + "negativeExitCode": 1, + "html": true, + "junit": true, + "failedAttachment": true, + "dependencyReferences": true + } + }, + "published": false + }, + "packageRecordSha256": "a464fecea6b9e3489f9f717b5c5f98237da7097a2fdb62ba19dd9631281d9945", + "rounds": [ + { + "filename": "browser-round-1.json", + "sha256": "d529e98f7e5c419f6e72e68dd1f67093f556497675ad3eb7426e9cb83cc4da9e", + "workers": 1, + "tests": 170, + "stats": { + "startTime": "2026-10-31T11:16:23.709Z", + "duration": 195811.93, + "expected": 170, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "checkedManualWindows": 57, + "healthyFixtureAggregate": { + "snapshot": { + "count": 1120, + "medianMs": 6.4811875, + "p95Ms": 10.68725, + "maxMs": 39.343958 + }, + "evaluate": { + "count": 1120, + "medianMs": 0, + "p95Ms": 0, + "maxMs": 0 + }, + "resolution": { + "count": 11200, + "medianMs": 4.804562499999999, + "p95Ms": 8.335583, + "maxMs": 37.469416 + }, + "interval": { + "count": 1082, + "medianMs": 6.5, + "p95Ms": 10.5, + "maxMs": 35.600000000034925 + }, + "gapsAbove100ms": 0 + }, + "maximumPassingWindowGapMs": 35.79999999998836, + "slowestPassingWindow": { + "fixture": "canary isolation tabs successful input", + "checkId": "T05.forward.002.unchanged", + "maxObservationGapMs": 35.79999999998836 + } + }, + { + "filename": "browser-round-2.json", + "sha256": "c028177b580c590dfb24617eb28b5412d21164839c11fb4591b2d36778cd6dcd", + "workers": 1, + "tests": 170, + "stats": { + "startTime": "2026-10-31T11:19:40.707Z", + "duration": 190669.499, + "expected": 170, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "checkedManualWindows": 57, + "healthyFixtureAggregate": { + "snapshot": { + "count": 1018, + "medianMs": 7.2221455, + "p95Ms": 13.408834, + "maxMs": 45.088916 + }, + "evaluate": { + "count": 1018, + "medianMs": 0, + "p95Ms": 0, + "maxMs": 0 + }, + "resolution": { + "count": 10180, + "medianMs": 5.342646, + "p95Ms": 10.340583, + "maxMs": 43.064708 + }, + "interval": { + "count": 980, + "medianMs": 7.299999999930151, + "p95Ms": 13, + "maxMs": 45.20000000006985 + }, + "gapsAbove100ms": 0 + }, + "maximumPassingWindowGapMs": 45.20000000006985, + "slowestPassingWindow": { + "fixture": "tabs pass manual Enter", + "checkId": "T05.forward.002.unchanged", + "maxObservationGapMs": 45.20000000006985 + } + }, + { + "filename": "browser-round-3.json", + "sha256": "279a42d02b2a128617a915f850411c11675495d0026c7e413aad97e37279f703", + "workers": 1, + "tests": 170, + "stats": { + "startTime": "2026-10-31T11:22:52.395Z", + "duration": 177047.023, + "expected": 170, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "checkedManualWindows": 57, + "healthyFixtureAggregate": { + "snapshot": { + "count": 1324, + "medianMs": 5.617729000000001, + "p95Ms": 7.963583, + "maxMs": 31.052792 + }, + "evaluate": { + "count": 1324, + "medianMs": 0, + "p95Ms": 0, + "maxMs": 0 + }, + "resolution": { + "count": 13240, + "medianMs": 4.2112289999999994, + "p95Ms": 6.374709, + "maxMs": 29.834708 + }, + "interval": { + "count": 1286, + "medianMs": 5.599999999976717, + "p95Ms": 8, + "maxMs": 31 + }, + "gapsAbove100ms": 0 + }, + "maximumPassingWindowGapMs": 31, + "slowestPassingWindow": { + "fixture": "tabs pass vertical manual Home End", + "checkId": "T05.backward.003.unchanged", + "maxObservationGapMs": 31 + } + } + ], + "totalExecutions": 510, + "testsPerRound": 170, + "journeysPerRound": 161, + "lastRoundStats": { + "startTime": "2026-10-31T11:22:52.395Z", + "duration": 177047.023, + "expected": 170, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + }, + "lastRoundRawReportSha256": "279a42d02b2a128617a915f850411c11675495d0026c7e413aad97e37279f703", + "lastRoundHealthyFixtureAggregate": { + "snapshot": { + "count": 1324, + "medianMs": 5.617729000000001, + "p95Ms": 7.963583, + "maxMs": 31.052792 + }, + "evaluate": { + "count": 1324, + "medianMs": 0, + "p95Ms": 0, + "maxMs": 0 + }, + "resolution": { + "count": 13240, + "medianMs": 4.2112289999999994, + "p95Ms": 6.374709, + "maxMs": 29.834708 + }, + "interval": { + "count": 1286, + "medianMs": 5.599999999976717, + "p95Ms": 8, + "maxMs": 31 + }, + "gapsAbove100ms": 0 + } + } + ], + "workflowConclusion": "success", + "uniqueJourneyRunIds": 644, + "totalExecutions": 680, + "localChecks": { + "checkedAt": "2026-10-31T11:16:55.538904+00:00", + "sourceCommit": "7a60938057a322e3088fcbd3ab5e70149f2f9173", + "focused": { + "file": "continuous-focused.json", + "sha256": "40ba069d024f91e34415303ab5e4baa4d381285c753f8b7311e5af4ba7f10cc6", + "stats": { + "startTime": "2026-10-31T11:12:33.672Z", + "duration": 15052.51, + "expected": 6, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + } + }, + "mutationControl": { + "file": "continuous-mutation.json", + "sha256": "705df7733020f598630a16653533c8802692871021d313e754f7b46925980be5", + "stats": { + "startTime": "2026-10-31T11:13:14.243Z", + "duration": 2296.554, + "expected": 0, + "skipped": 0, + "unexpected": 1, + "flaky": 0 + } + }, + "mutationExpected": "Restored 10 ms pause fails nextReadWasImmediate assertion; original source restored in finally.", + "benchmarkPilot": { + "file": "continuous-benchmark-pilot.json", + "sha256": "0ea01ccdf3390dc616b9601b3e019947b5bfb1a9944a06ca19b7332be63c10b0", + "stats": { + "startTime": "2026-10-31T11:15:51.466Z", + "duration": 13749.175, + "expected": 6, + "skipped": 0, + "unexpected": 0, + "flaky": 0 + } + }, + "benchmarkMeasurements": false, + "finalAcceptance": false, + "final100RoundsStarted": false + }, + "priorFailure": { + "sourceCommit": "02ee0953b79ad706746f66019b257aeb3908f075", + "runId": 41194618651, + "url": "https://github.com/PerchAnton/keytrail/actions/runs/41194618651", + "linuxPassed": 169, + "armPassed": 168, + "armFailed": 1, + "armRoundsCompleted": 1, + "armPlannedRounds": 3, + "fixture": "tabs pass manual Home End", + "checkId": "T05.backward.003.unchanged", + "messageCode": "OBSERVATION_GAP", + "gapMs": 109.8, + "snapshotMs": 98.514, + "rawReportSha256": "488dc6f53383f76ec4880f4e2f3c8b7f6b11a7464a822be26baa9c94d297b249", + "rerun": false + }, + "final100RoundsStarted": false, + "newLocalIsolationRun": false, + "validationMethod": "Re-read four raw reports; validate report schema and relationships, zero retries/skips, unique test and journey identities, environments, semantic signatures, observation intervals and 100 ms bound. Verify current source hashes, all 52 guard subprocess exit codes per platform, actual tarball bytes/checksums and both clean consumers." +} diff --git a/docs/evidence/ci-guard.json b/docs/evidence/ci-guard.json index 282519f..f4de184 100644 --- a/docs/evidence/ci-guard.json +++ b/docs/evidence/ci-guard.json @@ -1,5 +1,5 @@ { - "recordedAt": "2026-10-30T20:54:38.884Z", + "recordedAt": "2026-10-31T11:16:46.055Z", "version": "0.1.0-alpha.6", "node": "v24.22.1", "platform": "linux", @@ -15,7 +15,7 @@ "src/contracts/tabs.ts": "73d387a8040df26e07d7f1f9138e18bb522578b5806b1a4cdf818d3b43ac11e9", "src/contracts/types.ts": "78cef4b95bed88ac622170a8a8e92b43f8ecaf5ea91571384d602f126c060432", "src/engine/form-errors-plan.ts": "c094e2acf0e5665b4b3400d8fb980ed8dbbb46ef4839692810caeddc6219c44a", - "src/engine/observation-window.ts": "4b2452fdb9b876bc3efb893b32042a961d2340fa804f30ffa5c9f3ada9e9cf97", + "src/engine/observation-window.ts": "5f165904842f33e170f6f8f38fd53789c3124b39a1149335430e1ecbd1bd46b9", "src/engine/plan.ts": "cab99a7e19fea3fb1f5b80ba2136ae24bf867ba2920162e4d439ff7ec85b8f53", "src/engine/tabs-plan.ts": "1add41b1bc5500a28fd65d196e84ac58ae60b898db47825db0990226e44e5f34", "src/index.ts": "db30784e5f37a98070cd0c5b7ba1f172274031a253abfc850a11874de7029a4d", @@ -24,7 +24,7 @@ "src/reporting/validate.ts": "70e38e30858af50c29b785619c9f42ea6515251ddc9c4fe8d30f3134417e2dc6", "src/scenarios/dialog.ts": "ef7c163b05542c44b119639602d910e86b2581d9fd256ba8857c7f143b057b00", "src/scenarios/form-errors.ts": "78cb7de2c9130105b9259060a6ae8d57f9a3473dd9b8a90fff6fe7e5c9546c7b", - "src/scenarios/tabs.ts": "345bbbba97c1b51a156a895066af75de4e58a61f81c0fa11541d5c40893661ac", + "src/scenarios/tabs.ts": "b8bdedb38e3c0642da9ad242dca79c1bbd9458013cccda3fd9ec32904853fd76", "src/version.ts": "1d8ad83fca6e82ceb3adfddd60d35f681a650646b7e5af0428e94267d819b894", "tests/guard/fault-reporter.mjs": "1d71672317608ea4356c94eb52a6c0c87942cd1b4f104efe87f90a278fc67391", "tests/guard/fixture.spec.mjs": "d5cb1caf78222537f88196d69146827cff7e325f1f9b0fb841a98ca67314297b", diff --git a/docs/performance.md b/docs/performance.md index 33a2223..9fc213b 100644 --- a/docs/performance.md +++ b/docs/performance.md @@ -4,7 +4,7 @@ **Development verification:** The default repeatability check runs four full rounds and a separate four-worker comparison. Final 100-round acceptance remains deferred until the candidate is frozen; [protocol and retained results](reliability.md). Ordinary CI checks the real package and clean consumers without claiming final acceptance. -These measurements describe current main `da7e663`, recorded on 31 October 2026. +These measurements describe the historical main snapshot `da7e663`, recorded on 31 October 2026. All 108 benchmark tests passed without retries. The raw report, all warmup and measured pairs, environment, source hashes and derived statistics were independently validated; [validation record](evidence/benchmark-validation.json). diff --git a/docs/release-checklist.md b/docs/release-checklist.md index 6d0e3bf..e0768ea 100644 --- a/docs/release-checklist.md +++ b/docs/release-checklist.md @@ -1,6 +1,6 @@ # First alpha release checklist -**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. CI at `7a60938` passed three ARM rounds (510/510), one Linux round (170/170), and both package consumers per platform, with zero retries. Maximum ARM gaps were 35.8 / 45.2 / 31.0 ms. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). **Development verification:** The default repeatability check runs four full rounds and a separate four-worker comparison. Final 100-round acceptance remains deferred until the candidate is frozen; [protocol and retained results](reliability.md). Ordinary CI checks the real package and clean consumers without claiming final acceptance. @@ -8,7 +8,7 @@ Candidate: **0.1.0-alpha.6**, ruleset **0.4.0**, schema **1**. The earlier alpha numbers were source checkpoints, not published packages. This document prepares the first publication; it does not assert that a release exists. -## Current preparation snapshot +## Historical preparation snapshot (`da7e663`) The [handoff guide](release-handoff.md) and [readiness record](evidence/release-readiness.json) bind the review archive to merged commit `da7e663`. Main CI passed Linux 169/169 @@ -18,7 +18,7 @@ handoff. The browser examples and saved HTML failure report were inspected throu their interface. Owner sign-off remains separate. This is **development-review-ready**, with `releaseReady: false` and -`finalAcceptance: false`. The full current-source benchmark has passed; final 100-round evidence, +`finalAcceptance: false`. The benchmark for that recorded source passed; the consecutive-read candidate needs a refresh of its benchmark and repeatability evidence. final 100-round evidence, the release package gate and publication remain deferred. Do not repeat already sufficient development runs merely to update these documents. @@ -88,7 +88,7 @@ Neither command claims final acceptance or requires a five-hour series. ## Deferred final acceptance Once final acceptance is explicitly requested for the frozen candidate, run -`pnpm verify:reliability --final`. The current-source benchmark is already recorded; +`pnpm verify:reliability --final`. The earlier benchmark is preserved; repeat `pnpm benchmark` if its input hashes change. Independently validate the raw outputs, refresh source-bound evidence, then run `node scripts/check-package.mjs --release`. That gate requires 100 rounds and complete benchmark evidence. Short runs and diff --git a/docs/release-handoff.md b/docs/release-handoff.md index 630e9e4..271ada8 100644 --- a/docs/release-handoff.md +++ b/docs/release-handoff.md @@ -1,13 +1,13 @@ # Review the first release candidate -**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. CI at `7a60938` passed three ARM rounds (510/510), one Linux round (170/170), and both package consumers per platform, with zero retries. Maximum ARM gaps were 35.8 / 45.2 / 31.0 ms. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). -The reviewed development snapshot is `da7e66378619816cd9c7e065df95f0e2a6e67661` +The historical reviewed development snapshot is `da7e66378619816cd9c7e065df95f0e2a6e67661` for **KeyTrail 0.1.0-alpha.6**. It is not a published release or final acceptance. The [readiness record](evidence/release-readiness.json) identifies completed checks, the exact package archive and the work still deferred. -## What is already verified +## What was verified for the preserved snapshot [Main CI](https://github.com/PerchAnton/keytrail/actions/runs/41172735137) passed one Linux round (169 tests) and three macOS ARM rounds (507 tests). ARM passing-window @@ -17,7 +17,7 @@ checks in separate vanilla and React consumers. The [local development record](evidence/development-atomic-observations.json) contains four rounds (676 tests), a four-worker comparison (169 tests) and 800 -unique journey IDs. Its input hashes match the merged source. Main CI has its own +unique journey IDs. Its input hashes match the historical merged source. Main CI has its own 640 unique journey IDs; these verification sets are not a final 100-round series. The earlier `8f119df` [browser review](evidence/browser-review.json) exercised the standalone dialog, @@ -60,7 +60,7 @@ saved evidence checks, not publication readiness; see the [checklist](release-ch 1. Select and freeze the final reviewed source. 2. When explicitly requested, collect its 100-round final repeatability evidence. - The full [current-source benchmark](performance.md) now passes; + The full [historical benchmark](performance.md) passed for `da7e663`; remeasure if its input hashes change. The earlier `0300552` reliability evidence remains historical and cannot satisfy final acceptance. 3. Pass `node scripts/check-package.mjs --release` against fresh final evidence. diff --git a/docs/releases/0.1.0-alpha.6.md b/docs/releases/0.1.0-alpha.6.md index 6d206e7..4982e0c 100644 --- a/docs/releases/0.1.0-alpha.6.md +++ b/docs/releases/0.1.0-alpha.6.md @@ -1,6 +1,6 @@ # KeyTrail 0.1.0-alpha.6 — draft first-release notes -**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](../ci-concurrency.md#consecutive-window-reads). +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. CI at `7a60938` passed three ARM rounds (510/510), one Linux round (170/170), and both package consumers per platform, with zero retries. Maximum ARM gaps were 35.8 / 45.2 / 31.0 ms. Final 100-round acceptance remains deferred. [Diagnosis and scope](../ci-concurrency.md#consecutive-window-reads). **Draft: final acceptance deferred.** Development uses four rounds and independent package-consumer checks. The historical 100-round counts refer to `0300552` and cannot certify the changed release candidate. Fresh benchmark evidence is recorded separately. @@ -21,7 +21,7 @@ Playwright: custom ARIA dialogs, automatic/manual tabs and form-error recovery. - Retain ESM/CJS exports, TypeScript declarations, standard Playwright attachments, HTML/JUnit integration, vanilla examples and the React StrictMode portal example. - See the [audit cases](../release-audit.md), [verification record](../verification.md) - and [current measured overhead](../performance.md) for the tested scope. + and [historical measured overhead](../performance.md) for the tested scope. Historical verification of `0300552` completed on 29 October 2026 UTC (30 October in Kyiv): 100 × 163 sequential test executions, a matching 163-case four-worker comparison, diff --git a/docs/reliability.md b/docs/reliability.md index 3e0e531..c98c277 100644 --- a/docs/reliability.md +++ b/docs/reliability.md @@ -1,6 +1,6 @@ # Full-suite repeatability protocol -**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. CI at `7a60938` passed three ARM rounds (510/510), one Linux round (170/170), and both package consumers per platform, with zero retries. Maximum ARM gaps were 35.8 / 45.2 / 31.0 ms. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). **Development verification:** The default repeatability check runs four full rounds and a separate four-worker comparison. Final 100-round acceptance remains deferred until the candidate is frozen; [protocol and retained results](reliability.md). Ordinary CI checks the real package and clean consumers without claiming final acceptance. diff --git a/docs/roadmap.md b/docs/roadmap.md index 266941e..d3a4d97 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -1,6 +1,6 @@ # Milestones -**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. CI at `7a60938` passed three ARM rounds (510/510), one Linux round (170/170), and both package consumers per platform, with zero retries. Maximum ARM gaps were 35.8 / 45.2 / 31.0 ms. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). The supplied development specification v1.0 (28 October 2026) defines a full 0.1.0 target. This repository starts with its DEV01–DEV05 dialog checkpoint, designated @@ -16,7 +16,7 @@ These checkpoints are not full 0.1.0 acceptance. | DEV06 | Horizontal/vertical tabs, automatic/manual activation, Home/End and exit | Implemented; see [tabs contract](tabs.md) | | DEV07 | Form errors, IDREF relationships, focus policies and declarative correction | Implemented; see [form errors contract](form-errors.md) | | DEV08 | CI completeness guard and subprocess failure tests | Implemented; see [CI guard](ci-guard.md) | -| DEV09 | Repeatability, worker comparison, canaries, equivalent native benchmark | Historical `0300552`: 100 rounds, four-worker comparison and 108 benchmark cases passed; current `da7e663` benchmark: 108/108 passed; changed source uses four development rounds until final acceptance; [scope and evidence](reliability.md) | +| DEV09 | Repeatability, worker comparison, canaries, equivalent native benchmark | Historical `0300552`: 100 rounds, four-worker comparison and 108 benchmark cases passed; historical `da7e663` benchmark: 108/108 passed; changed source uses four development rounds until final acceptance; [scope and evidence](reliability.md) | | DEV10 | Full API docs, vanilla + React portal consumers, release checklist | Implemented for the alpha checkpoint; [release checklist](release-checklist.md); [review snapshot prepared](release-handoff.md); final acceptance and publication pending | No performance, superiority or adoption claim follows from passing the teaching fixtures. diff --git a/docs/verification.md b/docs/verification.md index 7ffc1ef..16adf71 100644 --- a/docs/verification.md +++ b/docs/verification.md @@ -1,6 +1,6 @@ # Verification -**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. Short CI validation is pending. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). +**Observation follow-up (31 October 2026):** main `02ee0953` failed macOS ARM with a 109.8 ms gap. The candidate now starts consecutive browser reads without a host timer inside manual windows. Earlier repeatability and benchmark records remain historical for their recorded sources; they do not certify this scheduler change. CI at `7a60938` passed three ARM rounds (510/510), one Linux round (170/170), and both package consumers per platform, with zero retries. Maximum ARM gaps were 35.8 / 45.2 / 31.0 ms. Final 100-round acceptance remains deferred. [Diagnosis and scope](ci-concurrency.md#consecutive-window-reads). **Development verification:** The default repeatability check runs four full rounds and a separate four-worker comparison. Final 100-round acceptance remains deferred until the candidate is frozen; [protocol and retained results](reliability.md). Ordinary CI checks the real package and clean consumers without claiming final acceptance. @@ -13,17 +13,17 @@ component is accessible. | --- | --- | | TypeScript | Strict library, integration and benchmark checks passed | | Unit tests | 39 passed, including verification-mode and resume-boundary checks | -| Browser suite | 169/169 in each of four local rounds at `7e48291`; hosted results separated below; no retries | +| Browser suite | Current `7a60938`: Linux 170/170 and ARM 3 × 170 = 510; no retries or skips | | Worker isolation | 169/169 on four local workers; matching semantic signatures; 800 distinct journey IDs across all five runs | | Canary isolation | Six cases: successful and exceptional paths for each scenario; five distinct markers | | Observation lifetime | Coherent focus, detached replacement, changed locator bindings, absent targets, late sibling cleanup and final map disposal | -| CI guard | 52 actual subprocess exit-code cases; [current guard record](evidence/ci-guard-atomic-observations.json) | -| Performance | Current `da7e663`: 108/108 tests; median paired overhead: dialog 4.1%, manual tabs -0.8%, forms (`insertText`) 2.5%; [samples and validation](performance.md) | +| CI guard | 52 actual subprocess exit-code cases; [current guard record](evidence/ci-guard.json) | +| Performance | Historical `da7e663`: 108/108 tests; median paired overhead: dialog 4.1%, manual tabs -0.8%, forms (`insertText`) 2.5%; [samples and validation](performance.md) | | Repeatability | `7e48291`: 4 × 169 = 676 sequential checks plus 169 four-worker checks; [development proof](evidence/development-atomic-observations.json). Final 100-round acceptance remains deferred; [historical proof](evidence/reliability.json) | -| Package consumers | Current `7e48291`: two clean offline installations verified locally and on Linux/ARM CI; ESM/CJS declarations; vanilla: 6 browser tests + 3 guarded journeys; React: 3 browser tests + 1 guarded journey + expected exit-1 control. [Archive hashes and results](evidence/ci-atomic-observations.json); final acceptance remains false | -| Hosted platforms | At `7e48291`: 3 × 169 macOS ARM and 169 Linux checks; all stages and clean package consumers passed. [Validated record](evidence/ci-atomic-observations.json). Earlier main ARM 126.7 ms and Intel 370 ms failures remain recorded. | +| Package consumers | Historical `7e48291`: two clean offline installations verified locally and on Linux/ARM CI; ESM/CJS declarations; vanilla: 6 browser tests + 3 guarded journeys; React: 3 browser tests + 1 guarded journey + expected exit-1 control. [Archive hashes and results](evidence/ci-atomic-observations.json); final acceptance remains false | +| Hosted platforms | Current `7a60938`: 3 × 170 ARM and 170 Linux, plus actual package consumers; [validated record](evidence/ci-consecutive-observations.json). Earlier failures remain recorded. | -## Current performance (`da7e663`) +## Historical performance (`da7e663`) ![Paired overhead and median/p95 timing results](assets/performance.svg) @@ -62,8 +62,8 @@ The source now resolves locators into a private browser map on every observation reads focus and containment together, and clears stored nodes before returning. It waits for sibling reads even on failure and disposes the map at journey end. No target binding is cached; [mechanism and regressions](ci-concurrency.md). -The atomic-registration four-round proof independently validates this runtime. Earlier -repeatability records remain historical for their own source hashes. +The atomic-registration four-round proof validates its recorded runtime, before the +consecutive-read change. Repeatability records remain tied to their own source hashes. ## Reproduction