Conformance for the rules added in SPEC 0.2.0, 236 checks in all: - C5 (§5.1–§5.2): for the published response-time vectors (conformance/v1/scan_rate.json, 10 cases) the rate is at least the nearest-rank P95 and ⌊100·M/65⌋, within 300..5000 ms; nothing adapts before 10 responses or without opt-in; a proposal never applies itself; the 10% proposal rule is pinned at both edges. - C6 (§5.1, §5.3): dwell vectors (conformance/v1/dwell.json, 24 cases) — nothing changes without opt-in, shorter proposals respect the 300 ms floor, both directions are reachable, clean selections alone change nothing, and an opted-in engine applies exactly its proposal, once. A restored 30-selection ratchet fails. - C7 (§4.1): stable CoreStatus wire names, a record without a status reads as GlossOnly, and only English carries a natively studied core. C5 and C6 recompute every expected value from the raw inputs with an independent oracle (cross-checked with exact fractions) before comparing the engine, so the engine is held to the rule, not to itself. gen-vectors takes an output directory and regenerates all three vector files byte-for-byte; the harness takes a vector directory. A missing or unparseable vector is a FAIL. Co-Authored-By: Claude Opus 5.5 <[email protected]>
246 lines
6.5 KiB
JSON
246 lines
6.5 KiB
JSON
{
|
|
"cases": [
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_direction": "longer",
|
|
"expected_proposal_ms": 897,
|
|
"glances": 0,
|
|
"late_abandons": 0,
|
|
"max_dwell_ms": 2000,
|
|
"name": "30% undone: one rung longer",
|
|
"selections": 20,
|
|
"undos": 6
|
|
},
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_direction": "longer",
|
|
"expected_proposal_ms": 897,
|
|
"glances": 0,
|
|
"late_abandons": 0,
|
|
"max_dwell_ms": 2000,
|
|
"name": "5 of 24 undone, just over 20%: longer",
|
|
"selections": 24,
|
|
"undos": 5
|
|
},
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_direction": "none",
|
|
"expected_proposal_ms": null,
|
|
"glances": 0,
|
|
"late_abandons": 0,
|
|
"max_dwell_ms": 2000,
|
|
"name": "exactly 20% undone: nothing",
|
|
"selections": 20,
|
|
"undos": 4
|
|
},
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_direction": "shorter",
|
|
"expected_proposal_ms": 736,
|
|
"glances": 0,
|
|
"late_abandons": 8,
|
|
"max_dwell_ms": 2000,
|
|
"name": "8 of 28 attempts abandoned late, no undos: one rung shorter",
|
|
"selections": 20,
|
|
"undos": 0
|
|
},
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_direction": "none",
|
|
"expected_proposal_ms": null,
|
|
"glances": 0,
|
|
"late_abandons": 5,
|
|
"max_dwell_ms": 2000,
|
|
"name": "exactly 20% abandoned late: nothing",
|
|
"selections": 20,
|
|
"undos": 0
|
|
},
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_direction": "none",
|
|
"expected_proposal_ms": null,
|
|
"glances": 0,
|
|
"late_abandons": 8,
|
|
"max_dwell_ms": 2000,
|
|
"name": "late abandons, but 5% undone: nothing",
|
|
"selections": 20,
|
|
"undos": 1
|
|
},
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_direction": "longer",
|
|
"expected_proposal_ms": 897,
|
|
"glances": 0,
|
|
"late_abandons": 8,
|
|
"max_dwell_ms": 2000,
|
|
"name": "undos and late abandons both high: longer wins",
|
|
"selections": 20,
|
|
"undos": 6
|
|
},
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_direction": "none",
|
|
"expected_proposal_ms": null,
|
|
"glances": 30,
|
|
"late_abandons": 0,
|
|
"max_dwell_ms": 2000,
|
|
"name": "glances are not abandons: nothing",
|
|
"selections": 20,
|
|
"undos": 0
|
|
},
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_direction": "none",
|
|
"expected_proposal_ms": null,
|
|
"glances": 0,
|
|
"late_abandons": 0,
|
|
"max_dwell_ms": 2000,
|
|
"name": "nine selections: too few for any proposal",
|
|
"selections": 9,
|
|
"undos": 5
|
|
},
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_direction": "none",
|
|
"expected_proposal_ms": null,
|
|
"glances": 0,
|
|
"late_abandons": 0,
|
|
"max_dwell_ms": 2000,
|
|
"name": "ninety clean selections: nothing",
|
|
"selections": 90,
|
|
"undos": 0
|
|
},
|
|
{
|
|
"current_dwell_ms": 2000,
|
|
"expected_direction": "none",
|
|
"expected_proposal_ms": null,
|
|
"glances": 0,
|
|
"late_abandons": 0,
|
|
"max_dwell_ms": 2000,
|
|
"name": "at the ceiling: nothing longer",
|
|
"selections": 20,
|
|
"undos": 6
|
|
},
|
|
{
|
|
"current_dwell_ms": 1900,
|
|
"expected_direction": "longer",
|
|
"expected_proposal_ms": 2000,
|
|
"glances": 0,
|
|
"late_abandons": 0,
|
|
"max_dwell_ms": 2000,
|
|
"name": "one rung past the ceiling: the ceiling",
|
|
"selections": 20,
|
|
"undos": 6
|
|
},
|
|
{
|
|
"current_dwell_ms": 320,
|
|
"expected_direction": "shorter",
|
|
"expected_proposal_ms": 300,
|
|
"glances": 0,
|
|
"late_abandons": 8,
|
|
"max_dwell_ms": 2000,
|
|
"name": "one rung below the proposal floor: the floor",
|
|
"selections": 20,
|
|
"undos": 0
|
|
},
|
|
{
|
|
"current_dwell_ms": 300,
|
|
"expected_direction": "none",
|
|
"expected_proposal_ms": null,
|
|
"glances": 0,
|
|
"late_abandons": 8,
|
|
"max_dwell_ms": 2000,
|
|
"name": "at the proposal floor: nothing shorter",
|
|
"selections": 20,
|
|
"undos": 0
|
|
},
|
|
{
|
|
"current_dwell_ms": 200,
|
|
"expected_direction": "longer",
|
|
"expected_proposal_ms": 235,
|
|
"glances": 0,
|
|
"late_abandons": 0,
|
|
"max_dwell_ms": 2000,
|
|
"name": "the person chose 200 ms and often undoes: one rung up, still under 300",
|
|
"selections": 20,
|
|
"undos": 6
|
|
}
|
|
],
|
|
"opt_in": [
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_dwell_ms": 897,
|
|
"late_abandons": 0,
|
|
"max_dwell_ms": 2000,
|
|
"name": "undos push one rung longer, once",
|
|
"selections": 20,
|
|
"undos_after_opt_in": 6
|
|
},
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_dwell_ms": 736,
|
|
"late_abandons": 12,
|
|
"max_dwell_ms": 2000,
|
|
"name": "late abandons pull one rung shorter at the first undo, once",
|
|
"selections": 40,
|
|
"undos_after_opt_in": 1
|
|
},
|
|
{
|
|
"current_dwell_ms": 800,
|
|
"expected_dwell_ms": 800,
|
|
"late_abandons": 0,
|
|
"max_dwell_ms": 2000,
|
|
"name": "ninety clean selections change nothing",
|
|
"selections": 90,
|
|
"undos_after_opt_in": 0
|
|
}
|
|
],
|
|
"rule": {
|
|
"absolute_floor_ms": 150,
|
|
"adaptation_default": false,
|
|
"ladder": "DT(X) = 300 * e^(X / 12) - 150 ms; rung X = round(12 * ln((dwell + 150) / 300)); a step is round(DT(X +/- 1))",
|
|
"late_abandon": "gaze leaves a target after at least half the dwell time",
|
|
"longer": "5 * undos > selections: one rung up, capped at max_dwell_ms; nothing at the ceiling",
|
|
"min_events": 10,
|
|
"proposal_floor_ms": 300,
|
|
"set_dwell": "clamp(requested, absolute_floor_ms, max_dwell_ms)",
|
|
"shorter": "20 * undos < selections and 5 * late_abandons > selections + late_abandons: one rung down, never below proposal_floor_ms; nothing at or below it",
|
|
"window": "counts restart whenever the dwell changes; nothing is proposed before min_events selections"
|
|
},
|
|
"set_dwell": [
|
|
{
|
|
"expected_dwell_ms": 150,
|
|
"max_dwell_ms": 2000,
|
|
"requested_ms": 50
|
|
},
|
|
{
|
|
"expected_dwell_ms": 150,
|
|
"max_dwell_ms": 2000,
|
|
"requested_ms": 149
|
|
},
|
|
{
|
|
"expected_dwell_ms": 150,
|
|
"max_dwell_ms": 2000,
|
|
"requested_ms": 150
|
|
},
|
|
{
|
|
"expected_dwell_ms": 1234,
|
|
"max_dwell_ms": 2000,
|
|
"requested_ms": 1234
|
|
},
|
|
{
|
|
"expected_dwell_ms": 2000,
|
|
"max_dwell_ms": 2000,
|
|
"requested_ms": 2000
|
|
},
|
|
{
|
|
"expected_dwell_ms": 2000,
|
|
"max_dwell_ms": 2000,
|
|
"requested_ms": 10000
|
|
}
|
|
],
|
|
"spec": "SPEC.md §5.1, §5.3",
|
|
"standard": "aac",
|
|
"vector": "dwell",
|
|
"version": "0.2.0"
|
|
}
|