nmarshall commited on
Commit
50db15e
·
1 Parent(s): 42b012c

qvm: timers dispatch

Browse files
docs/ASSET_PIPELINE_TODO.md CHANGED
@@ -270,3 +270,5 @@ Research progress: [QVM animation helpers and contacts](research/QVM_ANIMATION_C
270
  Research progress: [QVM animation assets and tables](research/QVM_ANIMATION_TABLES.md) completes bounded RE-449–451: verified variants/symbols/model selectors, loader records/partial EOF and source-derived timed-helper bridges. RE-448/452 retain native preprocessing/live tables/playback/contact/full-state/runtime/platform work; broad game/rendering milestones remain open.
271
 
272
  Research progress: [QVM resource update and consumers](research/QVM_RESOURCE.md) completes bounded RE-453–455: reset/drain/recovery/counter policy, selected caller arguments and resource/posture/scale bridges. RE-444/448/452/456 retain native effects/semantic producers/live animation/contact/full-state/runtime/platform work; broad game/rendering milestones remain open.
 
 
 
270
  Research progress: [QVM animation assets and tables](research/QVM_ANIMATION_TABLES.md) completes bounded RE-449–451: verified variants/symbols/model selectors, loader records/partial EOF and source-derived timed-helper bridges. RE-448/452 retain native preprocessing/live tables/playback/contact/full-state/runtime/platform work; broad game/rendering milestones remain open.
271
 
272
  Research progress: [QVM resource update and consumers](research/QVM_RESOURCE.md) completes bounded RE-453–455: reset/drain/recovery/counter policy, selected caller arguments and resource/posture/scale bridges. RE-444/448/452/456 retain native effects/semantic producers/live animation/contact/full-state/runtime/platform work; broad game/rendering milestones remain open.
273
+
274
+ Research progress: [QVM timer aging and main routing](research/QVM_TIMERS_DISPATCH.md) completes bounded RE-457–459: countdown policy, main request/mode ordering and clock/posture/animation bridges. RE-456/460 retain actual helpers/producers/full environment-state composition/runtime/platform work; broad game/rendering milestones remain open.
docs/FINDINGS.md CHANGED
@@ -540,3 +540,9 @@ Bounded qagame paths recover bomb-plant/inactivity correction requests, direct f
540
  **F-200 — Recovery/counter asymmetry:** fallback resource change can be replaced by a negative change above105, applies only the health-derived upper cap and can remain negative. Drain instead applies a zero floor without that upper cap. Normal zero-speed clears PS+224; nonzero adds dt capped1700, while early paths leave it alone. Runtime/legal domains remain open. [RESOURCE-002](research/QVM_RESOURCE.md).
541
 
542
  **F-201 — Resource arguments and consumers:** selected helper55465 tail requests a full3D norm for39595; helper43626 slice passes a retained scalar after velocity rescaling. Fourteen caller probes and16 scalar bridges connect resource results to earlier posture and scale arithmetic without claiming full movement ordering/state/collision equivalence. [RESOURCE-003](research/QVM_RESOURCE.md).
 
 
 
 
 
 
 
540
  **F-200 — Recovery/counter asymmetry:** fallback resource change can be replaced by a negative change above105, applies only the health-derived upper cap and can remain negative. Drain instead applies a zero floor without that upper cap. Normal zero-speed clears PS+224; nonzero adds dt capped1700, while early paths leave it alone. Runtime/legal domains remain open. [RESOURCE-002](research/QVM_RESOURCE.md).
541
 
542
  **F-201 — Resource arguments and consumers:** selected helper55465 tail requests a full3D norm for39595; helper43626 slice passes a retained scalar after velocity rescaling. Fourteen caller probes and16 scalar bridges connect resource results to earlier posture and scale arithmetic without claiming full movement ordering/state/collision equivalence. [RESOURCE-003](research/QVM_RESOURCE.md).
543
+
544
+ **F-202 — Timer expiry asymmetry:**53048 expires nonzero PS+16 at dt>=timer and clears flag mask192, but already-zero preserves flags. PS+72/+80 age only when positive and floor at0; negative animation timers remain untouched. Semantic/legal domains remain open. [TIMER-001](research/QVM_TIMERS_DISPATCH.md).
545
+
546
+ **F-203 — Main mode priority:** child53418 requests content/posture/ground before timer aging and54981(0); saved/current state220 bit1024 and a supplied56639 result control flag2/event23. Flag128, mask12, level>1, current bit1024 and walk word select one of six helpers before a common suffix. Other callee effects remain omitted. [ROUTE-001](research/QVM_TIMERS_DISPATCH.md).
547
+
548
+ **F-204 — Clock/posture timer connection:**36 selected bridges pass actual clock elapsed and recovered posture animation/timer results into53048, then direct animation guards. New timer200 can age to184 in the same selected16-unit step, conditional on omitted intervening effects; complete state and actual animation-request policy remain open. [TIMER-002](research/QVM_TIMERS_DISPATCH.md).
docs/PROVISIONAL_TODO.md CHANGED
@@ -582,3 +582,5 @@ Research progress: [QVM animation helpers and contacts](research/QVM_ANIMATION_C
582
  Research progress: [QVM animation assets and tables](research/QVM_ANIMATION_TABLES.md) completes bounded RE-449–451: verified variants/symbols/model selectors, loader records/partial EOF and source-derived timed-helper bridges. RE-448/452 retain native preprocessing/live tables/playback/contact/full-state/runtime/platform work; broad game/rendering milestones remain open.
583
 
584
  Research progress: [QVM resource update and consumers](research/QVM_RESOURCE.md) completes bounded RE-453–455: reset/drain/recovery/counter policy, selected caller arguments and resource/posture/scale bridges. RE-444/448/452/456 retain native effects/semantic producers/live animation/contact/full-state/runtime/platform work; broad game/rendering milestones remain open.
 
 
 
582
  Research progress: [QVM animation assets and tables](research/QVM_ANIMATION_TABLES.md) completes bounded RE-449–451: verified variants/symbols/model selectors, loader records/partial EOF and source-derived timed-helper bridges. RE-448/452 retain native preprocessing/live tables/playback/contact/full-state/runtime/platform work; broad game/rendering milestones remain open.
583
 
584
  Research progress: [QVM resource update and consumers](research/QVM_RESOURCE.md) completes bounded RE-453–455: reset/drain/recovery/counter policy, selected caller arguments and resource/posture/scale bridges. RE-444/448/452/456 retain native effects/semantic producers/live animation/contact/full-state/runtime/platform work; broad game/rendering milestones remain open.
585
+
586
+ Research progress: [QVM timer aging and main routing](research/QVM_TIMERS_DISPATCH.md) completes bounded RE-457–459: countdown policy, main request/mode ordering and clock/posture/animation bridges. RE-456/460 retain actual helpers/producers/full environment-state composition/runtime/platform work; broad game/rendering milestones remain open.
docs/RESEARCH_LEDGER.md CHANGED
@@ -339,3 +339,7 @@ Completed bounded RE-449–451 with `analyze_qvm_animation_tables.py`: verifies
339
  ## 2026-10-15 — Game-QVM resource update, argument tails and scalar consumers
340
 
341
  Completed bounded RE-453–455 with `analyze_qvm_resource.py`: verifies complete shipped qagame helper39595,856 resource probes,14 selected caller probes and16 consumer bridges. RESOURCE-001–003/F-199–201 recover configuration>=2 resource reset, initial negative clamp before frame+244 bypass, signed button/forward/right and mask/speed drain guards, capped local argument and16-word low-byte17 scan with0.9/0.5 factors; exact rounded recovery/replacement change, drain zero floor versus recovery health-derived upper cap, potential negative recovery stores/oversized drain stores and zero/nonzero counter reset/add/cap1700. Helper has no calls. Selected helper55465 tail records full3D-norm/supplied-sqrt-to-resource argument; helper43626 tail rescales supplied velocity using a retained scalar and passes that scalar. Evaluated resource transfers into earlier scale/posture/scale fixtures without claiming complete frame/state or real ordering. Native sqrt and previous caller/collision/normalization effects remain supplied/omitted; no original executable/full QVM/native collision/physics/rendering executes. Semantic meanings, live configuration/resource/health/item/counter/time producers and legal/exceptional/overflow/alias domains remain open. Eight independent tests verify all resource path/arithmetic outputs and immutable words, reset/bypass precedence, drain thresholds/cap/scan bounds, recovery cap/negative asymmetry/counter,14 caller arguments/velocity results,16 scalar handoffs with prior posture/scale oracles, source/constants/partitions and scope. All519 tests pass. Direct posture/acceleration reports regenerate byte-identically; new resource report reproduces twice byte-identically (1223307 bytes). Storage/filter setup, documentation links and whitespace checks pass. No assets or existing analyzer/evaluator code changed. RE-444/448/452 remain open; RE-456 tracks producer/semantic/legal domains, retained scalar/native sqrt/complete callers, consecutive-frame resource behavior/exceptional arithmetic and full movement state/ordering/gameplay/macOS/Linux/Rust/Bevy/Solari validation; packet/entity/player/snapshot/rendering milestones remain open.
 
 
 
 
 
339
  ## 2026-10-15 — Game-QVM resource update, argument tails and scalar consumers
340
 
341
  Completed bounded RE-453–455 with `analyze_qvm_resource.py`: verifies complete shipped qagame helper39595,856 resource probes,14 selected caller probes and16 consumer bridges. RESOURCE-001–003/F-199–201 recover configuration>=2 resource reset, initial negative clamp before frame+244 bypass, signed button/forward/right and mask/speed drain guards, capped local argument and16-word low-byte17 scan with0.9/0.5 factors; exact rounded recovery/replacement change, drain zero floor versus recovery health-derived upper cap, potential negative recovery stores/oversized drain stores and zero/nonzero counter reset/add/cap1700. Helper has no calls. Selected helper55465 tail records full3D-norm/supplied-sqrt-to-resource argument; helper43626 tail rescales supplied velocity using a retained scalar and passes that scalar. Evaluated resource transfers into earlier scale/posture/scale fixtures without claiming complete frame/state or real ordering. Native sqrt and previous caller/collision/normalization effects remain supplied/omitted; no original executable/full QVM/native collision/physics/rendering executes. Semantic meanings, live configuration/resource/health/item/counter/time producers and legal/exceptional/overflow/alias domains remain open. Eight independent tests verify all resource path/arithmetic outputs and immutable words, reset/bypass precedence, drain thresholds/cap/scan bounds, recovery cap/negative asymmetry/counter,14 caller arguments/velocity results,16 scalar handoffs with prior posture/scale oracles, source/constants/partitions and scope. All519 tests pass. Direct posture/acceleration reports regenerate byte-identically; new resource report reproduces twice byte-identically (1223307 bytes). Storage/filter setup, documentation links and whitespace checks pass. No assets or existing analyzer/evaluator code changed. RE-444/448/452 remain open; RE-456 tracks producer/semantic/legal domains, retained scalar/native sqrt/complete callers, consecutive-frame resource behavior/exceptional arithmetic and full movement state/ordering/gameplay/macOS/Linux/Rust/Bevy/Solari validation; packet/entity/player/snapshot/rendering milestones remain open.
342
+
343
+ ## 2026-10-15 — Game-QVM timer aging, main movement routing and consumer bridges
344
+
345
+ Completed bounded RE-457–459 with `analyze_qvm_timers_dispatch.py`: verifies complete helper53048 and child53418 main body54244–54474,600 timer probes,250 main routing probes and36 selected producer/consumer bridges. TIMER-001/ROUTE-001/TIMER-002/F-202–204 recover nonzero movement-timer equality expiry/mask192 clear versus already-zero preservation; positive-only leg/torso timer aging and negative-timer asymmetry; main content/saved-level/posture/ground/type3/timer/action ordering, saved/current state220 query/event23 policy, six-mode priority and exact common suffix/native-43 pointer request. Timer53048 effects are applied at its actual caller boundary; other main callees are recorded with omitted effects, supplied level/walk/PS words and explicit hypothetical state220 edits after54981/56639. Query return is supplied; no helper mutation is inferred from the edits. Bridges transfer actual clock elapsed, selected evaluated posture animation children/caller timer stores, timer results and direct animation-setter guards; intervening ground/type3/action/physics/native effects and complete shared-state composition remain omitted. Separate clock synthetic addresses are explicitly respected during scalar transfer. No original executable/full QVM/native collision/physics/rendering executes. Eight independent tests verify all timer results/immutable canaries, negative-zero-equality differences,250 exact request/argument sequences and routes, expiry priority, saved/current bit distinctions,36 clock/posture/timer/animation handoffs, provenance/partitions and scope. All527 tests pass. Direct step-state/animation-contact reports regenerate byte-identically; new report reproduces twice byte-identically (1241534 bytes). Storage/filter setup, documentation links and whitespace checks pass. No assets or existing analyzer/evaluator code changed. RE-456 and earlier broad tasks remain open; RE-460 tracks actual action/query/mode/suffix/native effects, timer/flag producers/legal domains, intervening ground/type3 mutations,47884 request policy and full environment/posture/timer/mode/state/gameplay/macOS/Linux/Rust/Bevy/Solari validation. Contact/resource/playback/packet/entity/player/snapshot/rendering milestones remain open.
docs/REVERSE_ENGINEERING_TODO.md CHANGED
@@ -552,3 +552,8 @@ Purpose: turn the supplied installation into an evidence-backed specification of
552
  - [x] RE-454 Recover exact finite recovery/replacement change, asymmetric lower/upper resource caps and zero/1700 counter policy with independent arithmetic checks ([RESOURCE-002](research/QVM_RESOURCE.md)).
553
  - [x] RE-455 Recover selected full3D-norm/retained-scalar caller argument tails and bridge evaluated resource into earlier posture/command-scale probes ([RESOURCE-003](research/QVM_RESOURCE.md)).
554
  - [ ] RE-456 Recover configuration/health/resource/array/counter/timestep semantic producers/legal ranges, retained-scalar producer/native sqrt/complete caller effects, consecutive-frame behavior/exceptional-overflow-alias domains and actual movement ordering/full shared state. Validate gameplay/macOS/Linux/Rust/Bevy/Solari; packet/entity/player/snapshot/rendering work remains open.
 
 
 
 
 
 
552
  - [x] RE-454 Recover exact finite recovery/replacement change, asymmetric lower/upper resource caps and zero/1700 counter policy with independent arithmetic checks ([RESOURCE-002](research/QVM_RESOURCE.md)).
553
  - [x] RE-455 Recover selected full3D-norm/retained-scalar caller argument tails and bridge evaluated resource into earlier posture/command-scale probes ([RESOURCE-003](research/QVM_RESOURCE.md)).
554
  - [ ] RE-456 Recover configuration/health/resource/array/counter/timestep semantic producers/legal ranges, retained-scalar producer/native sqrt/complete caller effects, consecutive-frame behavior/exceptional-overflow-alias domains and actual movement ordering/full shared state. Validate gameplay/macOS/Linux/Rust/Bevy/Solari; packet/entity/player/snapshot/rendering work remains open.
555
+
556
+ - [x] RE-457 Recover complete bounded helper53048 movement/animation timer guards, equality expiry/mask192 cleanup and negative/zero timer asymmetry ([TIMER-001](research/QVM_TIMERS_DISPATCH.md)).
557
+ - [x] RE-458 Recover main child environment/posture/ground/timer request ordering, saved/current bit query/event policy, six-mode priority and common suffix with supplied omitted effects ([ROUTE-001](research/QVM_TIMERS_DISPATCH.md)).
558
+ - [x] RE-459 Bridge evaluated child elapsed/posture animation children/timer outputs into direct animation guards with independent clock/posture/timer/animation checks ([TIMER-002](research/QVM_TIMERS_DISPATCH.md)).
559
+ - [ ] RE-460 Recover actual54981/56639/mode/suffix/native-43 effects, timer/flag producers/legal domains, intervening ground/type3 mutations and47884 animation requests; compose complete environment/posture/timer/mode/state and validate gameplay/macOS/Linux/Rust/Bevy/Solari. Continue contact/resource/playback and packet/entity/player/snapshot/rendering work.
docs/research/QVM_POSTURE.md CHANGED
@@ -47,3 +47,5 @@ Follow-up: [animation-helper recovery](QVM_ANIMATION_CONTACTS.md) evaluates39525
47
  Follow-up: [shipped animation definitions](QVM_ANIMATION_TABLES.md) name25 as LEGS_SWIM and36/37 as LEGS_STANDCR/LEGS_CRSTAND. The loader derives480/360 for those transition rows; this does not change the posture caller's explicit timer200 stores. Full state/playback remains open.
48
 
49
  Follow-up: [resource producer recovery](QVM_RESOURCE.md) evaluates helper39595 and transfers selected resource outputs into posture and command-scale fixtures (RE-453–455). This recovers one producer of PS+184; complete ordering, semantic/configuration producers and native/state effects remain open under RE-456.
 
 
 
47
  Follow-up: [shipped animation definitions](QVM_ANIMATION_TABLES.md) name25 as LEGS_SWIM and36/37 as LEGS_STANDCR/LEGS_CRSTAND. The loader derives480/360 for those transition rows; this does not change the posture caller's explicit timer200 stores. Full state/playback remains open.
48
 
49
  Follow-up: [resource producer recovery](QVM_RESOURCE.md) evaluates helper39595 and transfers selected resource outputs into posture and command-scale fixtures (RE-453–455). This recovers one producer of PS+184; complete ordering, semantic/configuration producers and native/state effects remain open under RE-456.
50
+
51
+ Follow-up: [timer/main-path recovery](QVM_TIMERS_DISPATCH.md) places53048 after posture/ground in the main body and ages selected posture/animation timer outputs using recovered clock elapsed. A new200 timer becomes184 with dt16, conditional on omitted intervening effects. Complete composition remains open under RE-460.
docs/research/QVM_STEP_STATE.md CHANGED
@@ -71,3 +71,5 @@ Eight independent tests cover gate ordering/packed bytes, clock writes versus cl
71
  RE-420 remains open for full child behavior and runtime work. RE-424 must recover scratch reset and native trap effects, omitted angle/trigonometric helpers, early-dispatch callee semantics and real clock/vector mutations, remaining action/weapon/physics/collision branches, packed selectors/flags/types through producers and consumers, complete step/outer-loop composition and actual gameplay/macOS/Linux behavior before Rust/Bevy/Solari compatibility claims. Packet/entity/player/snapshot/rendering work also remains open.
72
 
73
  Follow-up: [view and position tails](QVM_VIEW_MOTION.md) recovers helper53186 angle conversion, conditional basis algebra and two position tails. Native trig, omitted callee/physics effects and real composition/runtime validation remain open.
 
 
 
71
  RE-420 remains open for full child behavior and runtime work. RE-424 must recover scratch reset and native trap effects, omitted angle/trigonometric helpers, early-dispatch callee semantics and real clock/vector mutations, remaining action/weapon/physics/collision branches, packed selectors/flags/types through producers and consumers, complete step/outer-loop composition and actual gameplay/macOS/Linux behavior before Rust/Bevy/Solari compatibility claims. Packet/entity/player/snapshot/rendering work also remains open.
72
 
73
  Follow-up: [view and position tails](QVM_VIEW_MOTION.md) recovers helper53186 angle conversion, conditional basis algebra and two position tails. Native trig, omitted callee/physics effects and real composition/runtime validation remain open.
74
+
75
+ Follow-up: [main routing/timer recovery](QVM_TIMERS_DISPATCH.md) continues beyond54244, evaluates53048 countdowns and records ordered main requests/six-mode priority. Selected real clock elapsed words feed timer/animation fixtures; full child/environment/physics/state remains open (RE-457–460).
docs/research/QVM_TIMERS_DISPATCH.md ADDED
@@ -0,0 +1,63 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Game-QVM timer aging, main routing and selected consumer bridges
2
+
3
+ RE-457–459 / F-202–204. [qvm-timers-dispatch.json](qvm-timers-dispatch.json) retains complete helper53048 and the main body54244–54474 of child53418,600 timer probes,250 main-path probes and36 clock/posture/timer/animation bridges. Reproduce with `python3 scripts/analyze_qvm_timers_dispatch.py`; check with `python3 scripts/test_qvm_timers_dispatch.py`.
4
+
5
+ This continues [child clock and early dispatch](QVM_STEP_STATE.md), [posture](QVM_POSTURE.md) and [animation helpers](QVM_ANIMATION_CONTACTS.md). Bounded synthetic instruction evaluation does not execute the original executable, complete QVM, native collision, physics or rendering. Timer helper53048 is evaluated; other main-body callees record requests with omitted effects. Supplied level/walk/PS words stand in for those effects, and explicit state220 changes model possible omitted mutations without proving any helper actually produces them. These are conditional caller-policy and selected-value compositions, not complete simulation.
6
+
7
+ ## TIMER-001 — Three countdown fields and expiry flags (RE-457)
8
+
9
+ Helper53048 reads integer timestep global35023932 and reaches PS through the movement frame at global35024032. Its policy differs across the three timer fields:
10
+
11
+ | Field | Guard | Update |
12
+ | --- | --- | --- |
13
+ | PS+16 movement timer | Nonzero | If timestep >= timer, clear PS+12 mask192 and set timer0; otherwise subtract timestep |
14
+ | PS+72 leg animation timer | Positive | Subtract timestep, then floor a negative result to0 |
15
+ | PS+80 torso animation timer | Positive | Same subtraction/floor policy |
16
+
17
+ Mask192 is bits64 and128. An **already-zero** movement timer does not clear those flags. A negative movement timer is nonzero and expires for the sampled nonnegative timesteps; negative leg/torso timers instead remain untouched because those guards require positive values. Other flag bits remain unchanged, and no helper requests occur in this body.
18
+
19
+ The600 fixtures combine flags0/192/0x123456ff, movement timers-1/0/1/16/17, leg timers-1/0/16/17/200, torso timers-1/0/16/17 and timestep0/16. Independent integer/branch oracles verify every result, unchanged origin canary and empty call sequence. These inputs include synthetic guard states, not claims that all combinations occur during play. Overflow, negative timestep and live semantic/producer domains remain open.
20
+
21
+ ## ROUTE-001 — Main movement ordering, query and six-way priority (RE-458)
22
+
23
+ The source main path records this initial sequence:
24
+
25
+ 1.47217 content sampling, then copy frame level+212 into global35024028.
26
+ 2.47422 posture, then46773 ground classification.
27
+ 3.For PS type+4 equal3 only,45201.
28
+ 4.53048 timer aging, then54981(0).
29
+
30
+ The analyzer applies the evaluated timer child's flag/countdown mutations at its actual call boundary. Earlier content/posture/ground/type3 effects are omitted; their input/output-relevant fields are explicitly supplied. Main probes use timestep16, leg timer200 and torso timer17 at that boundary. Thus these caller fixtures do not compose the real initial environment queries or posture mutations.
31
+
32
+ After54981, when PS+12 mask12 is clear, the caller saves a Boolean of PS+220 bit1024 and requests56639(). A supplied nonzero return plus a set **saved** bit sets PS+12 bit2. If that saved bit was clear but the **current** PS+220 bit1024 is now set, the caller requests39238(23). This transition request does not require a nonzero query return. Supplied state edits after54981 and after56639 exercise the distinction between saved and current words; they are assumptions about omitted effects, not recovered helper implementations. If mask12 is nonzero, the query and this transition check are skipped.
33
+
34
+ Movement selection then uses this priority:
35
+
36
+ | First matching condition | Requested helper |
37
+ | --- | --- |
38
+ | PS+12 bit128 | 41768 |
39
+ | PS+12 mask12 | 55465 |
40
+ | Frame level+212 >1 | 41848 |
41
+ | Current PS+220 bit1024 | 57312 |
42
+ | Global35023936 nonzero | 43626 |
43
+ | Otherwise | 42838 |
44
+
45
+ Exactly one mode helper is requested. For example, supplied flags132 (128|4) choose41768 with timer17 and timestep16. Timer16 expires, clears128 while retaining4, and the caller chooses55465. With supplied flags128 alone and otherwise grounded/low-level inputs, timer16 expiry can instead select43626. Initial timer0 retains128 and still selects41768. This recovers branch control and ordering without establishing which combinations the runtime permits.
46
+
47
+ After every selected mode, the common suffix records46773,47217,49652(1),49918,50746,49117,47884,48716 and encoded target-43(PS+32 velocity pointer), in that order. These callees/native effects remain omitted. The stored global35024028 is the earlier supplied first level; it is written before posture and the later environment queries. Neither real level changes nor full before/after state are composed.
48
+
49
+ The250 main fixtures cover five flag patterns, timers0/16/17, levels0/2, state220 bit0/1024, walk0/1, supplied query returns0/1, type3 requests and explicit state edits. Independent tests check every flag/current-state result, query gate, saved level, exact ordered target/argument list, all six mode targets and equality-expiry priority.
50
+
51
+ ## TIMER-002 — Clock, posture and animation guard bridges (RE-459)
52
+
53
+ Thirty-six bridges combine six requested times999/1000/1001/1016/1200/1201 against old time1000 with six selected posture variants. The recovered child clock prefix produces elapsed1–200, which becomes the actual integer timestep input to53048. The posture helper's recorded39525 requests have their recovered animation children evaluated first, and the posture caller's timer200 assignment is applied, as in the earlier animation batch. Its resulting leg timer/animation and flags feed timer aging; movement timer16 and torso timer17 are supplied independently.
54
+
55
+ This selected order follows the main path's posture-before-timer calls. A new posture timer200 becomes199/184/0 for elapsed1/16/200 respectively, conditional on the omitted intervening ground/type3 effects. Blocked stand-up, existing timer suppression and early type3 variants are included. The source clock result writes the requested timestamp separately from its clamped elapsed; the previous independent clock oracle checks that distinction.
56
+
57
+ Evaluated timer values then feed the previously recovered **direct** leg/torso setter guards with supplied requests36/45. Their results are checked by the independent animation oracle. This demonstrates how timer expiry controls those setters; it does not establish that the later caller47884 requests these particular setters/animations during the same real step. Intervening content/ground/action/physics effects, native sqrt and complete state preservation remain supplied or omitted. Clock, posture and animation analyzers use their own synthetic addresses; only reported words are transferred between those fixtures.
58
+
59
+ ## Validation and next tasks
60
+
61
+ Eight tests independently verify600 timer outcomes/negative-zero-equality asymmetries,250 exact main call sequences and routes, expiry priority, saved/current state distinctions and event request,36 clock/posture/timer/animation bridges, source hash/instruction boundaries and explicit scope. Direct step-state/animation-contact dependencies regenerate unchanged; the new report reproduces twice byte-identically. Full-suite/storage/link/whitespace outcomes are recorded in the research ledger.
62
+
63
+ RE-456 and earlier broad tasks remain open. RE-460 tracks actual54981/56639 and mode/suffix/native-43 effects, movement/animation timer and flag producers/legal ranges, intervening ground/type3 mutations, actual47884 animation request policy, complete environment/posture/timer/mode/state composition and gameplay/macOS/Linux/Rust/Bevy/Solari validation. Contact/resource/animation playback and packet/entity/player/snapshot/rendering milestones remain open.
docs/research/README.md CHANGED
@@ -183,3 +183,5 @@ The extension collector adds five focused tests for native tail calls, command-r
183
  [QVM animation assets, table loader and duration consumers](QVM_ANIMATION_TABLES.md) adds RE-449–451. Reproduce with `python3 scripts/analyze_qvm_animation_tables.py`; check with `python3 scripts/test_qvm_animation_tables.py`. Verified assets supply token integer values; complete native preprocessing, live playback and runtime remain open.
184
 
185
  [QVM resource update, caller arguments and consumer bridges](QVM_RESOURCE.md) adds RE-453–455. Reproduce with `python3 scripts/analyze_qvm_resource.py`; check with `python3 scripts/test_qvm_resource.py`. Resource helper is evaluated completely within its bounded body; native sqrt/collision, preceding callers, full state and runtime remain open.
 
 
 
183
  [QVM animation assets, table loader and duration consumers](QVM_ANIMATION_TABLES.md) adds RE-449–451. Reproduce with `python3 scripts/analyze_qvm_animation_tables.py`; check with `python3 scripts/test_qvm_animation_tables.py`. Verified assets supply token integer values; complete native preprocessing, live playback and runtime remain open.
184
 
185
  [QVM resource update, caller arguments and consumer bridges](QVM_RESOURCE.md) adds RE-453–455. Reproduce with `python3 scripts/analyze_qvm_resource.py`; check with `python3 scripts/test_qvm_resource.py`. Resource helper is evaluated completely within its bounded body; native sqrt/collision, preceding callers, full state and runtime remain open.
186
+
187
+ [QVM timer aging, main routing and consumer bridges](QVM_TIMERS_DISPATCH.md) adds RE-457–459. Reproduce with `python3 scripts/analyze_qvm_timers_dispatch.py`; check with `python3 scripts/test_qvm_timers_dispatch.py`. Timer body is evaluated; other main helpers/native effects are omitted, with selected producer/consumer words transferred.
docs/research/qvm-timers-dispatch.json ADDED
The diff for this file is too large to render. See raw diff
 
scripts/analyze_qvm_timers_dispatch.py ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Bounded timer aging, main movement routing and clock/posture/animation bridges."""
3
+ import itertools
4
+ import json
5
+ from pathlib import Path
6
+ from analyze_bsp_references import trace_fields
7
+ from analyze_deferred_auth import trace_slice
8
+ from analyze_qvm import decode,write_json
9
+ from analyze_qvm_acceleration import FRAME,PS
10
+ from analyze_qvm_step_state import clock_effect,FRAME as CLOCK_FRAME,PS as CLOCK_PS
11
+ from analyze_qvm_animation_contacts import animation_probe,posture_bridge
12
+ from analyze_vm_extensions import verified
13
+
14
+ TIMER_LOCAL=0x4c000000
15
+ MAIN_LOCAL=0x4d000000
16
+ MODES={41768,55465,41848,57312,43626,42838}
17
+
18
+
19
+ def timer_probe(ins,flags=192,movement_timer=16,leg_timer=200,torso_timer=17,dt=16):
20
+ m={35024032:FRAME,FRAME:PS,35023932:dt,PS+12:flags,PS+16:movement_timer,PS+72:leg_timer,PS+80:torso_timer,PS+20:0x12345678};t=trace_slice(ins,53049,53184,m,{},local_base=TIMER_LOCAL,limit=256);m=t['memory']
21
+ return {'initial_flags_word':flags,'initial_movement_timer_word':movement_timer,'initial_leg_timer_word':leg_timer,'initial_torso_timer_word':torso_timer,'dt_word':dt,'result_flags_word':m[PS+12]&0xffffffff,'result_movement_timer_word':m[PS+16],'result_leg_timer_word':m[PS+72],'result_torso_timer_word':m[PS+80],'canary_word':m[PS+20],'calls':t['calls'],**trace_fields(t,False)}
22
+
23
+
24
+ def main_probe(ins,flags=0,movement_timer=0,level=0,state220=0,walk=1,query_result=0,kind=0,after_action=None,after_query=None):
25
+ timer=timer_probe(ins,flags,movement_timer);m={35024032:FRAME,FRAME:PS,PS+4:kind,PS+12:flags,PS+16:movement_timer,PS+72:200,PS+80:17,PS+220:state220,FRAME+212:level,35023936:walk};calls=[];trace=[]
26
+ def segment(start,stop,stops=()):
27
+ nonlocal m
28
+ t=trace_slice(ins,54244,54473,m,{104:FRAME},resume_at=start,stop_targets=stops or [stop],local_base=MAIN_LOCAL,call_results={54313:query_result},limit=512);m=t['memory'];calls.extend(t['calls']);trace.extend(t['trace']);return t['stop']
29
+ segment(54244,54274)
30
+ for o,key in [(12,'result_flags_word'),(16,'result_movement_timer_word'),(72,'result_leg_timer_word'),(80,'result_torso_timer_word')]:m[PS+o]=timer[key]
31
+ segment(54274,54279);m[PS+220]=state220 if after_action is None else after_action
32
+ stopped=segment(54279,54438,[54315,54438]);queried=stopped==54315
33
+ if queried:
34
+ if after_query is not None:m[PS+220]=after_query
35
+ segment(54315,54438)
36
+ segment(54438,54473)
37
+ selected=[c['target'] for c in calls if c['target'] in MODES]
38
+ if len(selected)!=1:raise ValueError('unexpected movement dispatch count')
39
+ return {'initial_flags_word':flags,'initial_movement_timer_word':movement_timer,'level_word':level,'initial_state220_word':state220,'walk_word':walk,'supplied_query_result_word':query_result,'type_word':kind,'supplied_after_action_state220_word':state220 if after_action is None else after_action,'supplied_after_query_state220_word':after_query,'query_reached':queried,'timer_probe':timer,'result_flags_word':m[PS+12]&0xffffffff,'result_state220_word':m[PS+220],'saved_first_level_word':m[35024028],'selected_mode':selected[0],'calls':calls,**trace_fields({'trace':trace},False)}
40
+
41
+
42
+ def bridge_probe(ins,requested,kwargs):
43
+ _,_,clock=clock_effect(ins,{CLOCK_PS:1000,CLOCK_FRAME+4:requested},{});posture=posture_bridge(ins,kwargs);p=posture['posture_probe'];timer=timer_probe(ins,p['result_ps_flags_word'],16,posture['result_leg_timer_word'],17,clock['elapsed_word']);leg=animation_probe(ins,39383,kind=p['type_word'],legs=posture['result_legs_word'],leg_timer=timer['result_leg_timer_word'],request=36);torso=animation_probe(ins,39338,kind=p['type_word'],torso_timer=timer['result_torso_timer_word'],request=45)
44
+ return {'clock_probe':clock,'posture_bridge':posture,'timer_probe':timer,'leg_animation_probe':leg,'torso_animation_probe':torso}
45
+
46
+
47
+ def main():
48
+ q=json.loads(Path('docs/research/qvm/qagame.json').read_text());raw=verified(Path(q['source']['member']['output']).read_bytes(),q['sha256']);_,ins=decode(raw)
49
+ timers=[timer_probe(ins,*v) for v in itertools.product([0,192,0x123456ff],[-1,0,1,16,17],[-1,0,16,17,200],[-1,0,16,17],[0,16])]
50
+ dispatch=[main_probe(ins,*v) for v in itertools.product([0,4,128,132,192],[0,16,17],[0,2],[0,1024],[0,1],[0,1])]
51
+ dispatch += [main_probe(ins,kind=3,movement_timer=t) for t in [0,16]]
52
+ dispatch += [main_probe(ins,after_action=a,after_query=b,query_result=r) for a,b,r in itertools.product([0,1024],[0,1024],[0,1])]
53
+ variants=[{'up':-1},{'flags':1},{'flags':1,'allsolid':1},{'flags':1,'timer':16},{'up':-1,'timer':1},{'kind':3,'up':-1}]
54
+ out={'source':q['source'],'sha256':q['sha256'],'timer_instructions':ins[53048:53186],'main_instructions':ins[54244:54475],'timer_probes':timers,'dispatch_probes':dispatch,'clock_posture_animation_bridges':[bridge_probe(ins,*v) for v in itertools.product([999,1000,1001,1016,1200,1201],variants)],'limitations':'Bounded synthetic shipped-QVM instruction evaluations only; no original executable/full QVM/native collision/physics/rendering executes. Timer53048 is evaluated; main caller other callees only record requests with omitted effects. Content level/walk/PS fields are supplied, and explicit supplied state220 edits after54981/56639 model possible omitted mutations without proving those effects. Query56639 return supplied; main captures request ordering and caller routing, not complete simulation. Bridges evaluate clock prefix, selected posture animation children, timer and direct animation setters; intervening content/ground/action/physics/native sqrt effects remain supplied or omitted. Scalar/selected-word transfer is not full shared-state composition. Semantic flag/type/time meanings, invalid/overflow/alias/legal domains and gameplay/macOS/Linux/Rust/Bevy/Solari compatibility remain open.'};write_json(Path('docs/research/qvm-timers-dispatch.json'),out);print('Recovered timer aging, main-path mode selection and bounded clock/posture/animation bridges')
55
+
56
+
57
+ if __name__=='__main__':main()
scripts/test_qvm_timers_dispatch.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """Independent timer, main-route and selected producer/consumer oracles."""
3
+ import hashlib
4
+ import json
5
+ from pathlib import Path
6
+ import unittest
7
+ from test_qvm_step_state import check_clock
8
+ from test_qvm_animation_contacts import animation_oracle
9
+ from test_qvm_posture import oracle as posture_oracle
10
+
11
+
12
+ def timer_oracle(p):
13
+ flags=p['initial_flags_word'];move=p['initial_movement_timer_word'];leg=p['initial_leg_timer_word'];torso=p['initial_torso_timer_word'];dt=p['dt_word']
14
+ if move:
15
+ if dt>=move:move=0;flags&=~192
16
+ else:move-=dt
17
+ if leg>0:leg=max(0,leg-dt)
18
+ if torso>0:torso=max(0,torso-dt)
19
+ return flags,move,leg,torso
20
+
21
+
22
+ def dispatch_oracle(p):
23
+ flags=timer_oracle(p['timer_probe'])[0];state=p['supplied_after_action_state220_word'];calls=[(47217,{}),(47422,{}),(46773,{})]
24
+ if p['type_word']==3:calls.append((45201,{}))
25
+ calls += [(53048,{}),(54981,{'8':0})];queried=not flags&12
26
+ if queried:
27
+ old=bool(state&1024);calls.append((56639,{}))
28
+ if p['supplied_after_query_state220_word'] is not None:state=p['supplied_after_query_state220_word']
29
+ if p['supplied_query_result_word'] and old:flags|=2
30
+ if not old and state&1024:calls.append((39238,{'8':23}))
31
+ mode=41768 if flags&128 else 55465 if flags&12 else 41848 if p['level_word']>1 else 57312 if state&1024 else 43626 if p['walk_word'] else 42838
32
+ calls += [(mode,{}),(46773,{}),(47217,{}),(49652,{'8':1}),(49918,{}),(50746,{}),(49117,{}),(47884,{}),(48716,{}),(-43,{'8':0x10020})]
33
+ return flags,state,queried,mode,calls
34
+
35
+
36
+ class QvmTimerDispatchTests(unittest.TestCase):
37
+ @classmethod
38
+ def setUpClass(cls):cls.r=json.loads(Path('docs/research/qvm-timers-dispatch.json').read_text())
39
+
40
+ def test_all_timer_mutations_exactly_match_independent_policy(self):
41
+ self.assertEqual(len(self.r['timer_probes']),600)
42
+ for p in self.r['timer_probes']:
43
+ self.assertEqual([p['result_flags_word'],p['result_movement_timer_word'],p['result_leg_timer_word'],p['result_torso_timer_word']],list(timer_oracle(p)));self.assertEqual(p['canary_word'],0x12345678);self.assertEqual(p['calls'],[])
44
+
45
+ def test_equality_expiry_zero_nonexpiry_and_negative_timer_asymmetry(self):
46
+ rows=self.r['timer_probes']
47
+ for move,expected_flags in [(0,192),(16,0),(17,192),(-1,0)]:self.assertTrue(any(p['initial_flags_word']==192 and p['initial_movement_timer_word']==move and p['dt_word']==16 and p['result_flags_word']==expected_flags for p in rows))
48
+ for p in rows:
49
+ if p['initial_leg_timer_word']<0:self.assertEqual(p['result_leg_timer_word'],p['initial_leg_timer_word'])
50
+ if p['initial_torso_timer_word']<0:self.assertEqual(p['result_torso_timer_word'],p['initial_torso_timer_word'])
51
+
52
+ def test_every_main_route_request_order_arguments_and_saved_level(self):
53
+ self.assertEqual(len(self.r['dispatch_probes']),250)
54
+ for p in self.r['dispatch_probes']:
55
+ flags,state,queried,mode,calls=dispatch_oracle(p);self.assertEqual([p['result_flags_word'],p['result_state220_word'],p['query_reached'],p['selected_mode']],[flags,state,queried,mode]);self.assertEqual([(c['target'],c['args']) for c in p['calls']],calls);self.assertEqual(p['saved_first_level_word'],p['level_word'])
56
+ self.assertEqual({p['selected_mode'] for p in self.r['dispatch_probes']},{41768,55465,41848,57312,43626,42838})
57
+
58
+ def test_timer_expiry_changes_mode_at_exact_dt_boundary(self):
59
+ rows=self.r['dispatch_probes']
60
+ for timer,mode in [(0,41768),(16,43626),(17,41768)]:self.assertTrue(any(p['initial_flags_word']==128 and p['initial_movement_timer_word']==timer and p['level_word']==0 and p['initial_state220_word']==0 and p['walk_word']==1 and p['selected_mode']==mode for p in rows))
61
+ self.assertTrue(any(p['initial_flags_word']==132 and p['initial_movement_timer_word']==16 and p['selected_mode']==55465 for p in rows))
62
+
63
+ def test_supplied_state_edits_saved_bit_and_current_bit_are_distinct(self):
64
+ rows=self.r['dispatch_probes'];events=[p for p in rows if any(c['target']==39238 for c in p['calls'])];self.assertTrue(events)
65
+ for p in events:self.assertEqual(p['supplied_after_action_state220_word']&1024,0);self.assertTrue(p['supplied_after_query_state220_word']&1024)
66
+ changed=next(p for p in rows if p['supplied_after_action_state220_word']==1024 and p['supplied_after_query_state220_word']==0 and p['supplied_query_result_word']==1);self.assertTrue(changed['result_flags_word']&2);self.assertEqual(changed['selected_mode'],43626)
67
+
68
+ def test_clock_posture_timer_and_animation_guards_compose_selected_values(self):
69
+ self.assertEqual(len(self.r['clock_posture_animation_bridges']),36)
70
+ for b in self.r['clock_posture_animation_bridges']:
71
+ clock,pb,t=b['clock_probe'],b['posture_bridge'],b['timer_probe'];check_clock(self,clock);p=pb['posture_probe'];self.assertEqual(t['dt_word'],clock['elapsed_word']);self.assertEqual(t['initial_flags_word'],posture_oracle(p)[0]);self.assertEqual(t['initial_leg_timer_word'],pb['result_leg_timer_word']);self.assertEqual(pb['result_leg_timer_word'],posture_oracle(p)[1]);self.assertEqual([t['result_flags_word'],t['result_movement_timer_word'],t['result_leg_timer_word'],t['result_torso_timer_word']],list(timer_oracle(t)))
72
+ for key,timer_key in [('leg_animation_probe','result_leg_timer_word'),('torso_animation_probe','result_torso_timer_word')]:
73
+ a=b[key];self.assertEqual(a['initial_leg_timer_word'] if key=='leg_animation_probe' else a['initial_torso_timer_word'],t[timer_key]);self.assertEqual([a['result_legs_word'],a['result_torso_word'],a['result_leg_timer_word'],a['result_torso_timer_word']],list(animation_oracle(a)[:4]))
74
+ self.assertEqual(b['leg_animation_probe']['initial_legs_word'],pb['result_legs_word'])
75
+ self.assertTrue(any(b['clock_probe']['elapsed_word']==16 and b['timer_probe']['initial_leg_timer_word']==200 and b['timer_probe']['result_leg_timer_word']==184 for b in self.r['clock_posture_animation_bridges']))
76
+
77
+ def test_source_hash_complete_timer_and_main_body_boundaries(self):
78
+ q=json.loads(Path('docs/research/qvm/qagame.json').read_text());self.assertEqual(self.r['source'],q['source']);self.assertEqual(self.r['sha256'],hashlib.sha256(Path(q['source']['member']['output']).read_bytes()).hexdigest());self.assertEqual(self.r['timer_instructions'][0]['index'],53048);self.assertEqual(self.r['timer_instructions'][-1]['index'],53185);self.assertEqual(self.r['main_instructions'][0]['index'],54244);self.assertEqual(self.r['main_instructions'][-1]['index'],54474)
79
+
80
+ def test_omitted_effects_and_conditional_composition_are_explicit(self):
81
+ for text in ['no original executable/full QVM/native collision/physics/rendering executes','other callees only record requests with omitted effects','without proving those effects','not full shared-state composition']:self.assertIn(text,self.r['limitations'])
82
+
83
+
84
+ if __name__=='__main__':unittest.main()