acdream/docs/plans/2026-07-26-modern-runtime-slice-j3-hardening.md
Erik 84954c8b77 docs(runtime): close J3.5 and plan J3.6
Record the canonical entity/object delta cutover, full Release and exact-binary connected evidence, rollback, and the adversarial zero-owner J3.6 execution contract. Synchronize architecture, roadmap, milestones, and agent guidance.

Co-authored-by: Codex <codex@openai.com>
2026-07-26 06:54:47 +02:00

196 lines
7.5 KiB
Markdown

# Modern runtime J3.6 — adversarial lifetime hardening and closeout
**Status:** READY
**Parent:** `2026-07-25-modern-runtime-slice-j3.md`
**Required production base:** `ce3ac310d92722ffb637e81cb1957458874dd220`
**Prior closeout:** `../research/2026-07-26-slice-j3-5-canonical-delta-stream.md`
## Objective
Close the canonical entity/object lifetime group under failure, re-entrancy,
reset, and disposal before J4 moves another gameplay owner.
This slice adds no feature, queue, retry timer, renderer fallback, or gameplay
behavior. It proves that Runtime's canonical identity/object owner and App's
exact-key graphical projection either complete each transaction or retain one
explicitly retryable suffix, and that every terminal path converges to zero.
## Fixed boundary
- Runtime remains the sole GUID/incarnation/local-ID, accepted-wire,
parent-relation, object-table, direct-view, and entity/object-event owner.
- App remains an exact-key projection and resource host.
- The server remains authoritative.
- Existing synchronous retail ordering remains unchanged.
- J4 chat, vitals, enchantments, spells/components, cooldowns, and
ViewModel-facing revisions do not enter this slice.
- A failure test may expose a production ownership defect. Fix the owning
transaction at its commit/acknowledgement boundary; do not add a suppression
flag, timer, retry loop, or symptom guard.
## Execution
### 1. Pin the complete ownership ledger
Create one assertion helper that reports every J3 owner:
- active Runtime records;
- teardown Runtime records and claimed local IDs;
- accepted snapshot/timestamp and parent-relation entries;
- active and teardown App projections;
- materialized world entities and graphical resource registrations;
- spatial loaded/pending projection keys;
- animation, remote-motion, projectile, root-object, effect, light, script,
and equipped-child bindings;
- object-table objects, containers, pending moves, and replacement state;
- Runtime stream subscriptions, dispatch failures, and pending work.
The helper must distinguish an intentionally retained retry receipt from a
leak. A stable terminal checkpoint permits neither.
### 2. Failure-inject canonical registration and hydration
Exercise failures and re-entry:
- before and after Runtime active-record/local-ID commit;
- same-incarnation refresh;
- generation replacement while prior App teardown succeeds or fails;
- projection sidecar creation;
- world-entity factory;
- resource registration before commit and after partial commit;
- resource rollback before and after commit;
- animation/physics/effect/relationship/ready publication stages;
- observer replacement, delete, and session clear during each callback.
Prove that a still-active Runtime incarnation never loses its key, a failed
partial owner remains reachable by one exact teardown receipt, and retry
cannot replay create-time resources already committed.
### 3. Failure-inject accepted updates and placement
Cover ObjDesc, motion, vector, state, position, parent, pickup, explicit
rebucket, withdrawal, and child-NoDraw:
- stale/equal/new/wrapped timestamps;
- loaded-to-loaded, loaded-to-pending, pending-to-loaded, and cellless
transitions;
- projection callback failure before and after the graphical mutation;
- observer delete/recreate or same-record newer update;
- parent event before the parent, before the child, and across GUID reuse;
- malformed or missing-object updates.
Assert the shared stream publishes only committed canonical facts, consumes
no sequence for rejected packets, never emits renderer visibility as a
withdrawal, and never applies a displaced callback to a replacement
incarnation.
### 4. Failure-inject object-table transactions
Run the exact object-table behavior through the Runtime stream:
- create/add versus update;
- optimistic container move;
- confirmation;
- rejection rollback;
- wield/container replacement;
- stack/value/property refresh;
- unknown-object move;
- authoritative entity delete;
- dormant/offscreen delete;
- clear and next-generation reuse;
- callback mutation of the same object or containing container.
Verify callback order, exact removed generation, immediate borrowed-view
visibility, and no second retained inventory collection.
### 5. Prove reset, retry, and disposal convergence
Inject a failure at every App teardown stage, then repeatedly invoke the
existing retryable teardown entry until it completes. Exercise:
- ordinary authoritative delete;
- delete/recreate with the same GUID;
- session reset during create, update, object callback, and teardown callback;
- logout;
- transport replacement;
- mid-portal disconnect;
- Runtime and App disposal;
- repeated subscription disposal and disposal from inside dispatch.
At convergence assert the complete ownership ledger is zero, the retired
generation cannot publish, the next generation starts at sequence one, and
later object-table mutations cannot reach disposed observers.
### 6. Runtime-only end-to-end fixture
Without loading App, UI, Silk.NET, OpenAL, Arch, or ImGui:
1. construct Runtime;
2. bind a generation and frame clock;
3. register several conflicting entity/object shapes;
4. apply properties, motion/vector/state/position, parent/container moves,
Hidden, pickup, delete/recreate, and clear;
5. visit direct views after each commit;
6. record the exact shared delta stream;
7. reset and reconnect;
8. dispose.
Run the same normalized input script through the graphical harness and require
exact equality. Assert the Runtime assembly load closure remains backend-free.
### 7. Closeout gates
Run, in order:
1. focused Runtime lifetime/stream failure matrix;
2. Core `ClientObjectTable*` and `ObjectTableWiring*`;
3. focused App hydration, projection, update, parent, rebucket, delete,
session-reset, selection, inventory, and paperdoll suites;
4. Runtime-only versus graphical normalized parity;
5. all Runtime tests;
6. all App tests;
7. `dotnet build AcDream.slnx -c Release`;
8. `dotnet test AcDream.slnx -c Release --no-build`;
9. exact-binary connected lifecycle/reconnect;
10. canonical nine-stop connected world route;
11. documentation, divergence, dependency, and source-ownership audit.
A user visual pause is required only if automated or connected evidence shows
a visible inventory, selection, radar, paperdoll, portal, or world-object
symptom.
## Acceptance
J3 is complete only when:
- every canonical mutation and terminal path has adversarial coverage;
- direct and graphical traces remain exact;
- rejected/stale work consumes no event sequence;
- no callback can mutate a superseded incarnation;
- every partial acquisition remains reachable and retryable;
- every stable reset/disposal checkpoint has zero records, tombstones, keys,
projections, resources, container entries, parent candidates,
subscriptions, and pending deltas;
- Runtime-only construction and lifecycle load no presentation/backend
assembly;
- full Release and both exact-binary connected routes pass;
- architecture, roadmap, milestones, AGENTS/CLAUDE, durable memory, and exact
rollback are synchronized.
## Rollback
J3.5 remains independently reversible:
```text
git revert ce3ac310d92722ffb637e81cb1957458874dd220
```
Record J3.6's exact production commit before its connected gates. Never revert
J3.4 or J3.3 to mask a J3.6 failure.
## Next boundary
After J3.6 closes J3, execute J4 from
`docs/plans/2026-07-25-modern-runtime-slice-j.md`: move the remaining
presentation-independent gameplay-state owners in coherent lifetime groups,
with direct/graphical parity and zero-mirror deletion after every group.