docs(runtime): close J3.3 and hand off J3.4

Record exact projection-store ownership, automated and connected evidence, rollback chain, and the executor-ready canonical object-table plan. Reconcile milestones, roadmap, architecture, divergence pointers, AGENTS/CLAUDE, and durable handoff state.

Co-authored-by: Codex <codex@openai.com>
This commit is contained in:
Erik 2026-07-25 22:29:34 +02:00
parent e937cc36df
commit d9bf4c4960
15 changed files with 757 additions and 114 deletions

View file

@ -1687,8 +1687,14 @@ port in any phase — no separate listing here.
> tombstone, local-ID/reverse, accepted-wire, parent, and operation-version
> maps. Its 110 Runtime tests, 3,758 App tests / 3 skips, 8,441-test / 5-skip
> complete Release suite, and exact-binary seven-checkpoint connected gate pass
> with graceful exits and zero render-shadow mismatch. J3.3 exact-key App
> projection storage is next.
> with graceful exits and zero render-shadow mismatch. J3.3 is complete at
> `420e5eea` plus `e937cc36`: App's materialized sidecars, presentation
> worksets, spatial residence, quiescence, and visibility edges now carry the
> exact `RuntimeEntityKey`; the compatibility GUID view is deleted. Its 3,761
> App tests / 3 skips, 8,444-test / 5-skip complete Release suite, and exact-
> binary seven-checkpoint gate pass with two graceful exits, zero failures,
> zero render-shadow mismatches, and zero pending deltas. J3.4 canonical object-
> table ownership is next.
> The historical exact cutover
> rollback remains
> `git revert ef1d263337997bb030eadb7b8e71d73dc659907a`. Slice H is complete:

View file

@ -162,8 +162,14 @@ residency is `0/0/0` at every stable checkpoint and teardown converges. Slice I
local-ID/reverse, accepted-wire, parent, and operation-version maps in
Runtime. Its 110 Runtime tests, 3,758 App tests / 3 skips, 8,441 full Release
tests / 5 skips, and exact-binary seven-checkpoint connected gate pass with
graceful exits and zero render-shadow mismatch. J3.3 exact-key App projection
storage is next under
graceful exits and zero render-shadow mismatch. J3.3 is complete at
`420e5eea` plus exact-spatial correction `e937cc36`:
`LiveEntityProjectionStore` and every materialized presentation/spatial
workset now use exact `RuntimeEntityKey`; the GUID-shaped compatibility view
is deleted. Its 3,761 App tests / 3 skips, 8,444 full Release tests / 5 skips,
and exact-binary seven-checkpoint connected gate pass with two graceful
exits, zero failures, zero render-shadow mismatches, and zero pending deltas.
J3.4 canonical `ClientObjectTable` ownership is next under
[`2026-07-25-modern-runtime-slice-j.md`](2026-07-25-modern-runtime-slice-j.md).
Slice-I closeout evidence is
[`../research/2026-07-25-slice-i7-closeout.md`](../research/2026-07-25-slice-i7-closeout.md).
@ -171,6 +177,8 @@ Slice-J2 closeout evidence is
[`../research/2026-07-25-slice-j2-session-lifetime-closeout.md`](../research/2026-07-25-slice-j2-session-lifetime-closeout.md).
Slice-J3.2 closeout evidence is
[`../research/2026-07-25-slice-j3-2-canonical-entity-directory-closeout.md`](../research/2026-07-25-slice-j3-2-canonical-entity-directory-closeout.md).
Slice-J3.3 closeout evidence is
[`../research/2026-07-25-slice-j3-3-exact-projection-store.md`](../research/2026-07-25-slice-j3-3-exact-projection-store.md).
The historical exact G4 visual rollback remains
`git revert ef1d263337997bb030eadb7b8e71d73dc659907a`.

View file

@ -2,12 +2,14 @@
**Date:** 2026-07-24
**Status:** Slices AI and J0J2 are complete. Flat-authoritative collision, zero-
**Status:** Slices AI and J0J3.3 are complete. Flat-authoritative collision, zero-
allocation resolve scratch, parsed-graph removal, connected correctness/
lifetime acceptance, and Slice-I closeout landed 2026-07-25. Slices FL were
explicitly approved 2026-07-24. Slice J0J1 established the enforced Runtime
boundary and borrowed contract seam; J2 moved canonical session/transport
lifetime and ordered inbound routing. J3 is the active execution point.
lifetime and ordered inbound routing; J3.1J3.3 moved canonical entity identity
to Runtime and exact graphical projection identity to App. J3.4 is the active
execution point.
**Scope:** Reconcile and sequence the existing Modern Pipeline (`MP`) and
Linux/headless (`LH`) tracks using the 2026-07-24 connected performance audit.
@ -19,8 +21,9 @@ world detail, or retail behavior.
This plan refines rather than replaces
[`docs/superpowers/specs/2026-07-05-modern-pipeline-design.md`](../superpowers/specs/2026-07-05-modern-pipeline-design.md).
It preserves the shipped N.5 bindless/MDI renderer, the completed `GameWindow`
decomposition, canonical `LiveEntityRuntime` ownership, the retail PView/cell
visibility ports, and all behavior already accepted by the user.
decomposition, canonical Runtime entity ownership with exact-key App
projections, the retail PView/cell visibility ports, and all behavior already
accepted by the user.
---
@ -1246,9 +1249,12 @@ proved exact flat traversal, strict dual publication, and flat-authoritative
gameplay before removing every production parsed collision graph. Slice I7
passes 8,413 Release tests / 5 skips plus both exact-binary connected routes;
every stable checkpoint reports zero retained parsed collision graphs. J1 is
complete with borrowed contracts, and J2 now owns canonical session/transport
lifetime plus ordered inbound routing in Runtime. J3 is the current execution
point.
complete with borrowed contracts, and J2 owns canonical session/transport
lifetime plus ordered inbound routing in Runtime. J3.1J3.3 are complete:
Runtime owns the only entity GUID/incarnation/local-ID directory, and App's
materialized sidecars plus spatial/presentation worksets carry exact
`RuntimeEntityKey`. J3.4 canonical `ClientObjectTable` ownership is the current
execution point.
Evidence:
[`../research/2026-07-25-slice-g5-production-profile.md`](../research/2026-07-25-slice-g5-production-profile.md)
and
@ -1262,6 +1268,8 @@ and
and
[`../research/2026-07-25-slice-j2-session-lifetime-closeout.md`](../research/2026-07-25-slice-j2-session-lifetime-closeout.md)
and
[`../research/2026-07-25-slice-j3-3-exact-projection-store.md`](../research/2026-07-25-slice-j3-3-exact-projection-store.md)
and
[`2026-07-25-modern-runtime-slice-j.md`](2026-07-25-modern-runtime-slice-j.md).
The intended order is therefore:
@ -1276,7 +1284,7 @@ honest metrics + committed baselines (A — exit criteria block C)
-> delta GPU submission (G)
-> residual frame cleanup (H-a, H-b, H-c)
-> flat collision assets (I — COMPLETE)
-> presentation-independent runtime (J — CURRENT at J3)
-> presentation-independent runtime (J — CURRENT at J3.4)
-> Linux/headless/multi-session (K)
-> evidence-gated GPU jobs (L)
```

View file

@ -1,7 +1,7 @@
# Modern runtime Slice J — presentation-independent runtime
**Status:** J0J2 COMPLETE — boundary, borrowed contracts, and canonical
session/transport lifetime; J3 is ACTIVE
**Status:** J0J2 COMPLETE; J3.1J3.3 COMPLETE; J3.4 canonical object-table
ownership is next
**Parent:** `2026-07-24-modern-runtime-architecture.md`, Slice J
**Authorization:** the user approved Slices FL, including the otherwise-frozen
Slice J gameplay-owner moves, on 2026-07-24
@ -15,8 +15,9 @@ deletes the replaced App production path before the next group moves.
## 1. Fixed invariants
1. `LiveEntityRuntime` remains the sole server-GUID/incarnation owner. There is
never a second GUID map or synchronized gameplay world.
1. `RuntimeEntityDirectory` is the sole server-GUID/incarnation/local-ID owner.
`LiveEntityRuntime` is the exact-key App projection host. There is never a
second GUID map or synchronized gameplay world.
2. Runtime types do not reference `AcDream.App`, either UI assembly, Silk.NET,
OpenAL, Arch, ImGui, a native window, or an OpenGL resource.
3. App projection state is keyed by runtime-issued local entity identity plus
@ -182,6 +183,15 @@ git revert 75930787741db40a83eab8663e4464dce8d687ba
**Detailed execution plan:**
[`2026-07-25-modern-runtime-slice-j3.md`](2026-07-25-modern-runtime-slice-j3.md).
**Current checkpoint:** J3.1J3.3 are complete. Runtime owns accepted entity
wire state and the only canonical identity/incarnation/local-ID directory.
App's `LiveEntityProjectionStore` and every materialized presentation/spatial
workset are keyed by exact `RuntimeEntityKey`; the temporary GUID-shaped
compatibility view is deleted. The final J3.3 binary `e937cc36` passes 8,444
Release tests / 5 skips and the exact seven-checkpoint connected gate at
`logs/connected-world-gate-20260725-221008/report.json`. J3.4 now moves the
existing `ClientObjectTable` under the Runtime entity/object lifetime root.
- Strip renderer, particle, Wb, and streaming components from the canonical
record into an App projection store keyed only by local identity/incarnation.
- Move `LiveEntityRuntime`, accepted spawn/state/property timestamps,

View file

@ -0,0 +1,237 @@
# Modern runtime J3.4 — canonical object-table ownership
**Status:** READY
**Parent:** `2026-07-25-modern-runtime-slice-j3.md`
**Required production base:** `e937cc36df39cf6ea1eaba2f9c0243d1929da702`
**Prior closeout:** `docs/research/2026-07-25-slice-j3-3-exact-projection-store.md`
## Objective
Make one presentation-independent Runtime lifetime-group root own both:
- the canonical `RuntimeEntityDirectory`; and
- the existing canonical `ClientObjectTable`.
App, retained UI, interaction controllers, and the graphical projection host
must borrow those exact same instances. There must be no copied inventory
model, second object table, asynchronous delivery seam, extra input frame, or
change to retail event order.
This slice moves ownership and transaction boundaries, not the
`ClientObjectTable` implementation out of `AcDream.Core`. The type is already
presentation-free and has extensive Core conformance coverage.
## Current ownership inventory
At the required base:
- `LiveEntityRuntime` constructs its own `RuntimeEntityDirectory`.
- `GameWindow` constructs a public readonly `ClientObjectTable Objects`.
- App composition records pass that table to retained UI, selection,
interaction, magic, combat, paperdoll, appraisal, cooldown, and diagnostics.
- Runtime `LiveSessionEventRouter` already applies property, stack, inventory,
player-description, container, and appraisal traffic directly to the
borrowed table through `ObjectTableWiring`.
- App `LiveEntityHydrationController` applies CreateObject to the table only
after canonical Runtime create acceptance and revalidates
`CreateIntegrationVersion`.
- App `LiveEntityDeletionController` applies logical DeleteObject before the
exact App projection teardown suffix.
- App `LiveSessionResetManifest` clears the object table before clearing live
graphical projections.
- Optimistic moves, confirmations, rollback, stack updates, container
replacement, and every table event are synchronous on the current thread.
Retail behavior and citations already live in:
- `src/AcDream.Core/Items/ClientObjectTable.cs`;
- `src/AcDream.Core.Net/ObjectTableWiring.cs`;
- `docs/research/2026-07-13-retail-give-item-pseudocode.md`;
- the named-retail symbols cited beside `ACCObjectMaint::CreateObject`,
`ACCObjectMaint::DeleteObject`, and
`ACCWeenieObject::ServerSaysMoveItem`.
J3.4 does not reinterpret those algorithms.
## Fixed target
Add a presentation-free Runtime owner equivalent to:
```csharp
public sealed class RuntimeEntityObjectLifetime
{
public RuntimeEntityDirectory Entities { get; }
public ClientObjectTable Objects { get; }
}
```
The concrete name may change, but these invariants do not:
1. The owner constructs each canonical instance exactly once.
2. `LiveEntityRuntime` receives `Entities`; it may not construct a directory.
3. Runtime session routing receives `Objects` from the same owner.
4. App projection, UI, and interaction composition receive borrowed references
only.
5. Accepted CreateObject/DeleteObject object-table mutation is implemented by
the Runtime group and revalidates the exact canonical record/version.
6. Reset preserves the current order: object-table clear before graphical live
projection teardown, with completed stages never replayed.
7. Studio/sample-data object tables remain independent fixture owners and are
not part of the live session.
## Execution
### 1. Pin parity traces and construction identity
- Capture normalized traces for:
- initial player description and equipment manifest;
- item CreateObject add/update;
- same-incarnation refresh;
- new-generation replacement;
- property Int/Int64/String/Float/DataID updates;
- stack-size update;
- optimistic move, authoritative confirm, and rejection rollback;
- wield/unwield;
- ViewContents replacement and close;
- logical delete, GUID reuse, and session clear.
- Add a construction-identity test proving the router, App projection host,
retained UI source, and interaction source all receive one table instance.
- Preserve current synchronous event order in the golden trace.
### 2. Introduce the Runtime lifetime-group root
- Add the owner under `src/AcDream.Runtime/Entities/`.
- Construct `RuntimeEntityDirectory` and `ClientObjectTable` there.
- Expose borrowed properties only; no collection mirror or event repeater.
- Add Runtime-only tests that instantiate it without loading App, UI, Silk,
OpenAL, Arch, or ImGui assemblies.
- Keep mutable state instance-scoped so two roots can hold conflicting GUIDs
and inventory contents without interference.
### 3. Inject canonical identity into the App projection host
- Change `LiveEntityRuntime` to require the exact
`RuntimeEntityDirectory` instance from the group.
- Remove its internal `new RuntimeEntityDirectory(...)`.
- Preserve the existing local-ID start override for focused wraparound tests
through an explicit fixture/group construction seam, not a second production
allocator.
- Assert that App cannot replace the directory after projection construction.
- Preserve J3.3 `RuntimeEntityKey` identity and teardown behavior unchanged.
### 4. Replace the `GameWindow` object-table owner
- Construct the Runtime group before retained UI and live presentation
composition.
- Delete `GameWindow`'s public readonly `ClientObjectTable Objects` field.
- Pass `runtimeGroup.Objects` through the existing typed composition records.
- Keep App controllers as direct synchronous borrowers; do not wrap every read
in a copied DTO or event bus.
- Add source guards rejecting a production App `new ClientObjectTable()` and a
second Runtime entity directory. Exempt Studio/sample-data and tests.
### 5. Move accepted object mutation to the Runtime group
- Move the generation/version-sensitive
`ObjectTableWiring.ApplyEntitySpawn/Delete` transaction boundary out of App.
- Runtime must apply a CreateObject only after the canonical directory accepts
that exact incarnation and while its create-integration version remains
current.
- New-generation replacement must remove the old object generation and publish
the same add/update/removal sequence as today.
- Logical delete must mutate the table before App graphical teardown, exactly
as the current `beforeTeardown` callback does.
- Pickup/parent leave-world must not delete the object-table entry.
- Dormant liveness pruning must retain the existing object-table semantics;
only an authoritative logical delete removes the retained object generation.
- Keep all callbacks synchronous and revalidate after every callback that can
replace, delete, or clear the incarnation.
### 6. Route session and reset ownership
- Bind J2 `LiveSessionEventRouter` directly from the Runtime group rather than
an App-owned table field.
- Keep the current pre-Connect subscription order.
- Keep local-player property projection to `LocalPlayerState` and the same
table instance until J4 moves the coherent player/gameplay state group.
- Replace the App reset field with a Runtime-group object-table reset
acknowledgement at the same manifest position.
- Failure injection must retain the unfinished reset suffix and never clear a
replacement session's table.
### 7. Delete superseded ownership seams
- Remove public ownership comments and aliases that describe the table as a
GameWindow state owner.
- Remove any App construction helper whose only purpose was to allocate the
live table.
- Keep direct table parameters on UI/controllers for now: they are explicit
borrowed dependencies and J4 will move higher-level inventory transactions.
- Update architecture, plans, durable memory, and exact rollback in the same
closeout commit.
## Adversarial cases
- Reentrant `ObjectAdded` deletes or replaces the same GUID.
- Reentrant `ObjectMoved` starts another optimistic move.
- Delete arrives during CreateObject callbacks.
- Same GUID with a new `INSTANCE_TS` while old projection teardown is pending.
- Unknown-object authoritative move publishes the same nullable item event.
- Equal, stale, and wrapped object/physics generations.
- Multiple in-flight optimistic moves followed by confirm/reject in either
order.
- Container replacement while item events mutate the same container.
- Reset during object-table event dispatch.
- Failed graphical teardown after canonical object removal.
- Two Runtime roots use identical GUIDs with different contents.
- No-window root executes the full entity/object lifecycle without loading App
or backend assemblies.
## Mandatory gates
Run in this order:
1. Runtime entity/object lifetime tests.
2. Core `ClientObjectTable*` and `ObjectTableWiring*` tests.
3. Focused App hydration, deletion, reset, inventory, interaction, paperdoll,
magic, cooldown, and runtime-adapter tests.
4. All Runtime tests.
5. All App tests.
6. `dotnet build AcDream.slnx -c Release`.
7. `dotnet test AcDream.slnx -c Release --no-build`.
8. Exact-binary connected lifecycle/reconnect gate.
9. At every connected checkpoint: zero render-shadow mismatches, zero pending
deltas, graceful process exit, and object/projection teardown convergence.
A user visual pause is not required unless an automated or connected gate
exposes an inventory, paperdoll, selection, or interaction symptom.
## Acceptance
- One Runtime lifetime-group root owns the exact entity directory and object
table.
- `GameWindow` owns neither instance directly.
- App and Runtime routing borrow the same object table.
- Runtime remains the only GUID/incarnation/local-ID authority.
- Create/delete/property/container ordering matches the pinned trace.
- Optimistic move/rollback and press-time UI remain synchronous.
- No App/UI/backend dependency enters Runtime.
- No mirror, queue, frame delay, or steady-state traversal allocation is added.
- Runtime-only entity/object lifecycle and multiple-instance isolation pass.
- Complete Release and exact connected gates pass on one committed binary.
## Rollback
Record the exact J3.4 production commit here before its connected gate. J3.3
remains independently reversible; do not use its rollback for a J3.4 failure.
## Final J3 goal
J3.4 is not the end of J3. J3.5 must publish one ordered per-session
entity/object delta stream and make graphical/direct hosts consume the same
committed facts without a second queue. J3.6 then failure-injects and proves
the complete no-window entity/object lifecycle, zero leaked records,
tombstones, projections, container entries, queued deltas, or subscriptions,
plus Release and connected parity. That J3.6 proof is the clean boundary before
J4 moves inventory transactions, vitals, enchantments, magic, and other
gameplay-state services.

View file

@ -1,8 +1,12 @@
# Modern runtime J3.3 — exact-key App projection store
**Status:** READY AFTER J3.2 CONNECTED GATE
**Status:** COMPLETE 2026-07-25
**Parent:** `2026-07-25-modern-runtime-slice-j3.md`
**Required base:** `f46ddb5cdb1e145752bea49aeb1d62bfe71284d3`
**Production commits:** `420e5eea70fd2c29cf9c8614e6298a1f84d64045`,
then exact-spatial correction
`e937cc36df39cf6ea1eaba2f9c0243d1929da702`
**Closeout:** `docs/research/2026-07-25-slice-j3-3-exact-projection-store.md`
## Objective
@ -131,3 +135,46 @@ Run:
- No new allocation appears in steady-state live-object traversal.
- No callback is delayed to another frame.
- All automated and connected gates pass on the exact commit.
## Completion result
All acceptance conditions pass on final exact binary `e937cc36`.
- `LiveEntityProjectionStore` is the only materialized App sidecar store and is
keyed by exact `RuntimeEntityKey`.
- The temporary `ActiveRecordView`, `_activeRecords`, detached App record
constructor, and broad materialized/visible `WorldEntity` collection
surfaces are deleted. Borrowed exact-key record views remain for hot
traversal and tests.
- Hydration, animation, effects, lights, equipped children, remote teleport,
render journal, liveness, movement observations, teardown, spatial
residence, and visibility transitions carry the exact key.
- `GpuWorldState` retains the exact key through loaded/pending rebucketing,
landblock retirement, origin recentering, quiescence, and reentrant
visibility delivery. DAT-static entities remain outside live Runtime
identity.
- Runtime remains the only current-GUID/incarnation/local-ID authority. App
resolves GUID through Runtime and never decides which incarnation is current.
- Synchronous callbacks, allocation order, render ordering, and frame timing
are unchanged.
Evidence:
- 104 focused App ownership/streaming tests passed.
- 3,761 App tests passed / 3 skipped.
- 8,444 complete Release tests passed / 5 skipped.
- Release solution build passed.
- `logs/connected-world-gate-20260725-221008/report.json` passed on exact commit
`e937cc36`: two sessions, seven checkpoints, two graceful zero-code exits,
zero failures, zero render-shadow mismatches, and zero pending deltas.
Exact rollback, newest commit first:
```text
git revert e937cc36df39cf6ea1eaba2f9c0243d1929da702
git revert 420e5eea70fd2c29cf9c8614e6298a1f84d64045
```
J3.4 is the next clean slice. It moves canonical `ClientObjectTable` ownership
under the Runtime entity/object lifetime group without moving retained UI,
icons, paperdolls, grids, cooldown drawing, or interaction presentation.

View file

@ -12,16 +12,21 @@
| J3.0 ownership inventory | complete | `b0fecc5f65ed26042c61a1651fb134aeb432c141`; `docs/research/2026-07-25-slice-j3-entity-ownership-inventory.md` |
| J3.1 accepted-wire owners | complete | `f7442d13e9ae7d5b077ffecb1f8a10899ad46edd`; 110 Runtime tests and complete Release parity remain green after J3.2 |
| J3.2 canonical Runtime entity directory | complete | `f46ddb5cdb1e145752bea49aeb1d62bfe71284d3`; 8,441 Release tests / 5 skips and `logs/connected-world-gate-20260725-200749/report.json` pass |
| J3.3 App projection store | next | [`2026-07-25-modern-runtime-slice-j3-projection-store.md`](2026-07-25-modern-runtime-slice-j3-projection-store.md): key every graphical sidecar/workset by `RuntimeEntityKey` and remove the compatibility view |
| J3.3 App projection store | complete | `420e5eea70fd2c29cf9c8614e6298a1f84d64045` + `e937cc36df39cf6ea1eaba2f9c0243d1929da702`; 8,444 Release tests / 5 skips and `logs/connected-world-gate-20260725-221008/report.json` pass |
| J3.4 canonical object-table ownership | next | [`2026-07-25-modern-runtime-slice-j3-object-table.md`](2026-07-25-modern-runtime-slice-j3-object-table.md): move the existing `ClientObjectTable` into the Runtime entity/object lifetime group while App remains a synchronous borrower |
J3.2 passes the Release solution build and 8,441 complete tests with five
expected skips. Its exact-binary seven-checkpoint connected
lifecycle/reconnect route also passes with graceful exits, zero render-shadow
mismatches, and zero pending deltas. It adds no frame queue, backend
dependency, or gameplay behavior change. The exact rollback for J3.2 is:
J3.3 passes the Release solution build, 3,761 App tests with three skips, and
8,444 complete tests with five expected skips. Its final exact-binary
seven-checkpoint connected lifecycle/reconnect route also passes with graceful
exits, zero render-shadow mismatches, and zero pending deltas. Runtime is now
the sole GUID/incarnation/local-ID authority; every materialized App sidecar,
presentation workset, and live spatial visibility edge uses the exact
`RuntimeEntityKey`. It adds no frame queue, backend dependency, allocation-order
change, or gameplay behavior change. The exact rollback for J3.3 is:
```text
git revert f46ddb5cdb1e145752bea49aeb1d62bfe71284d3
git revert e937cc36df39cf6ea1eaba2f9c0243d1929da702
git revert 420e5eea70fd2c29cf9c8614e6298a1f84d64045
```
## 1. Objective
@ -197,6 +202,9 @@ Source guards reject any App server-GUID authority map.
### J3.4 — canonical object-table ownership
**Detailed execution plan:**
[`2026-07-25-modern-runtime-slice-j3-object-table.md`](2026-07-25-modern-runtime-slice-j3-object-table.md).
- Add a Runtime entity/object lifetime-group root that owns the canonical
entity directory and the existing Core `ClientObjectTable`.
- Construct it before either graphical UI or live presentation; both borrow
@ -286,8 +294,12 @@ failure; record and revert only the exact failing J3 commit.
J3 sub-slices are independently reversible:
```text
git revert e937cc36df39cf6ea1eaba2f9c0243d1929da702
git revert 420e5eea70fd2c29cf9c8614e6298a1f84d64045
git revert f46ddb5cdb1e145752bea49aeb1d62bfe71284d3
git revert f7442d13e9ae7d5b077ffecb1f8a10899ad46edd
```
Revert J3.2 before J3.1 when rolling back both.
Revert J3.3's exact-spatial correction before its main projection-store
commit. Revert J3.3 before J3.2, and J3.2 before J3.1, when rolling back more
than one sub-slice.