Kover Scenario DSL & Mirror Mode
kover specs/kover/scenario-dsl.kmd
Define a captura de entradas do usuário, a serialização em uma DSL de cenários reproduzíveis, e o modo espelho (executar a operação em um programa e replicá-la automaticamente em um segundo programa similar). A DSL e o espelho são a mesma máquina vista em tempos diferentes: capturar input → serializar → reexecutar (ao vivo = espelho; de arquivo = cenário). Define o schema de input record, a injeção em tiers (T1 protocolo / T2 OS-input), a tolerância de sincronização, e o reuso como caso de regressão. Implementa kover-RFC-001 §6.
When this spec applies
Primary triggers
- Gravar/reproduzir cenário ou usar modo espelho no Kover
All triggers
- Gravar ou reproduzir um cenário no Kover
- Usar o modo espelho (A/B) entre dois programas
- Definir o schema de input record ou a DSL de cenário
Specification body
Spec — Kover Scenario DSL & Mirror Mode (v0.1)
Core insight: the reproducible-scenario DSL and mirror mode are one machine viewed at two times — capture input → serialise → re-execute. Live re-execution into a second program = mirror; later re-execution from a file = reproducible scenario. This spec fixes the input record schema, the serialisation, the tiered injection, and the regression reuse. Rules
R*, testsT*.
Scope
The L3 record/replay engine and mirror mode. Consumes capture
(capture.kmd) and the connector (protocol.kmd); is consumed by the
cockpit (KOVER-008) and regression-tests.kmd.
R1 — Input record schema
R1.1 — A captured input is a typed record:
{ seq, ts, kind, target, payload } where:
seq— monotonic ordinal within the scenario.ts— RFC3339 UTC ms (relative offsets derived for replay timing).kind ∈ { pointer, key, text, scroll, nav, wait, assert }.target— a semantic selector when available (DOM selector / a11y node / OUIAdata-ouia-component-idperspecs/testing/ouia-test-hooks.kmdwhen the target is a KDS-built UI / IPC target), falling back to a geometric one ({x,y}in a named viewport). The selector tier drives the injection tier (R3).payload— kind-specific (button/coords; keycode/modifiers; string; delta; url; duration; assertion expr).
R1.2 — Captured timing is preserved as inter-event offsets so replay can run at recorded speed, fixed speed, or as-fast-as-possible.
R2 — DSL serialisation (reuse, don't greenfield)
R2.1 — The scenario file SHOULD extend the existing
infra/observe/probe Chromium scenario format rather than invent a new
language, so a Kover scenario and a probe scenario share tooling. If a
distinct surface is needed it is a KMD profile, never an ad-hoc format.
R2.2 — A scenario file is: { meta, viewport(s), targets[], steps[] } where
steps[] is an ordered list of R1 records plus control nodes (branch,
repeat, wait-for). It is human-readable and diffable.
R2.3 — Regression reuse (the loop-closer): a recorded scenario MUST
be directly consumable as a regression-tests.kmd case (behavioural or
golden). Reproducing a bug once yields a permanent test. (Maps RFC-001 A2.)
R2.4 — Harness layer. Beyond a single linear scenario, the DSL is
harness-capable via three additive constructs: a setup/teardown
lifecycle (launch/seed/reset the target(s) + env), a matrix (run the same
steps across N targets × configs — the A/B is the 2-target case), and
reusable fixtures. Composed with the headless runner (kover-RFC-001 §7.4)
these turn a scenario into an executable test harness: the DSL authors
the harness; the runner + connector (launch/command, protocol.kmd) +
capture + budgets execute it. Reuse infra/observe/probe's runner and
stack-RFC-005 Layer-3 where they fit — do not fork a third runner.
R3 — Tiered injection
R3.1 — Replay injects each step via the highest available tier for its
target:
| Tier | Mechanism | When |
|---|---|---|
| T1 protocol-driven | semantic injection via a control protocol — CDP (Kruze CEF + Chrome), IPC (protocol.kmd, Koder apps), Koder Eye (Android gesture+tree) | target is a semantic selector and the program exposes a control protocol |
| T2 OS-input fan-out | synthesise OS input events (X11/Wayland/Win32/macOS a11y) by coordinate | no control protocol; geometric target only |
R3.2 — The engine MUST record which tier executed each step and surface
it (a T2-replayed scenario is labelled approximate —
headless-self-check honesty). A scenario MUST NOT silently downgrade
T1→T2 without recording it.
R3.3 — T1 is the supported, deterministic path (RFC-001 phase 1). T2 ships labelled best-effort.
R3.4 — Synthetic input injection SHOULD reuse the koder_test_input
primitive (stack-RFC-005), not a bespoke synthesiser; semantic selectors
SHOULD resolve via OUIA hooks (specs/testing/ouia-test-hooks.kmd) when
the target is a KDS-built UI. The headless runner (kover-RFC-001 §7.4)
consumes the same DSL unattended — one format across cockpit, mirror, and
harness.
R4 — Mirror mode (live A/B)
R4.1 — Mirror runs two targets (primary + secondary "similar program") from one input stream: the operator drives the primary; each captured input (R1) is also injected into the secondary via R3.
R4.2 — Sync tolerance: mirror MUST NOT assume lockstep. Each step
carries a settle policy (wait-for selector/idle/timeout) so the
secondary can lag and re-converge. A step whose secondary injection fails is
recorded (not fatal) and flagged in the diff.
R4.3 — Mirror produces, per run: the shared scenario (R2), a capture per
target (capture.kmd), a trace per target, and a diff (R5).
R4.4 — Canonical case: primary = Kruze (CEF/CDP), secondary = Chrome (CDP). Both T1, so the A/B is deterministic — this is the RFC-001 phase-1 seed.
R5 — Diff
R5.1 — The diff aligns the two runs by seq/scenario step and reports, per
step: wall-time delta, key trace-phase deltas (paint/layout/script/network
for web targets), and resource deltas (protocol.kmd R5). It is the primary
artifact handed to Kortex (capture.kmd R2 diff).
Test cases
| # | Check | Severity |
|---|---|---|
| T1 | A recorded scenario replays deterministically into a single CDP target and reproduces the captured navigation. | hard |
| T2 | The same scenario file is accepted by the regression-tests.kmd runner as a case (R2.3). | hard |
| T3 | Mirror drives Kruze + Chrome from one input stream; each step is injected into both via T1/CDP. | hard |
| T4 | Every replayed step records its injection tier; a T2 step is labelled approximate (R3.2). | hard |
| T5 | A secondary-injection failure in mirror is recorded and flagged in the diff, not fatal (R4.2). | hard |
| T6 | The diff aligns by step and surfaces a per-step wall-time + trace-phase delta (R5.1). | hard |
| T7 | Replay honours recorded timing, fixed-speed, and as-fast modes (R1.2). | soft |
Non-goals
- The injection backends themselves (CDP client, IPC client, OS-input synthesiser) — implementation, tracked by KOVER-006/007.
- Capture storage —
capture.kmd. - Cross-program semantic equivalence of selectors (when primary and secondary have different DOMs/UI) — best-effort mapping; out of v0.1.
Open questions
- Selector mapping when primary and secondary are not the same app (e.g. Kruze vs Chrome render the same URL but expose different chrome): the web content DOM is shared (same page), so content selectors map; browser chrome actions need a per-target alias table. Scope the alias table at KOVER-007.
- Whether
wait-forpredicates should reuse the probe assertion grammar verbatim (R2.1 alignment) — likely yes; confirm at KOVER-006.
References
meta/docs/stack/policies/regression-tests.kmdmeta/docs/stack/rfcs/stack-RFC-005-full-headless-testability.kmdmeta/docs/stack/specs/testing/ouia-test-hooks.kmdmeta/docs/stack/policies/headless-first.kmdengines/sdk/koder_test_inputinfra/observe/probeproducts/dev/eyeproducts/horizontal/kruzemeta/docs/stack/specs/kover/protocol.kmdmeta/docs/stack/rfcs/kover-RFC-001-foundations.kmd