docs: #365 Opus diagnosis — three layered defects, fix plan C->measure->B->A
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
98de4f5ab3
commit
6150327ea3
1 changed files with 355 additions and 0 deletions
355
docs/research/2026-08-10-365-headless-hydration-diagnosis.md
Normal file
355
docs/research/2026-08-10-365-headless-hydration-diagnosis.md
Normal file
|
|
@ -0,0 +1,355 @@
|
|||
# #365 headless hydration — Opus diagnosis (2026-08-10, read-only pass)
|
||||
|
||||
Verbatim agent output. The fix agent works solely from this document.
|
||||
|
||||
## 0. Executive summary
|
||||
|
||||
Three distinct defects layered on top of each other. Only the middle one is
|
||||
the hydration root cause.
|
||||
|
||||
| # | Layer | Verdict |
|
||||
|---|---|---|
|
||||
| **A** | `HeadlessLocalPlayerFrameHost.CanAdvancePlayer` accepts a **dormant (unpublished)** controller; the graphical host does not. This is the crash. | **CONFIRMED by source.** Real host-asymmetry bug. |
|
||||
| **B** | The headless collision neighborhood publishes collision **as a reaction to the local-player Create**, interleaved with the Create burst. Every `TrySealCollisionEvaluationAuthority` during that window is structurally refused, and (hypothesis) the mutual `HasOldPrefixPlacementDebt` ↔ seal dependency between remote first-entry operations and the landblock commit closes a circular wait that never opens. This is why the controller never publishes. | **Mechanism CONFIRMED; the "never opens" closure is HIGH-CONFIDENCE HYPOTHESIS.** One existing probe answers it in one line. |
|
||||
| **C** | `HeadlessStaticStateAudit` unconditionally refuses to start when **any** `PhysicsDiagnostics.Probe*`/`Dump*` flag is set — including single-session runs. The exact probe built to diagnose this stall class (`ACDREAM_PROBE_PARK=1`) cannot be run headless at all. | **CONFIRMED.** Why #365 arrived with no `[rearm]`/`[pump]` evidence. |
|
||||
|
||||
**Fix C first (two-line predicate change), then use it to confirm B, then fix
|
||||
B, then fix A.** Fixing A alone is the forbidden workaround shape: it converts
|
||||
a hard crash into a silent never-moves bot.
|
||||
|
||||
## 1. Correction to the ISSUES.md evidence chain
|
||||
|
||||
**`entities: 0` in the headless JSON is NOT evidence of failed hydration.**
|
||||
`HeadlessDiagnosticWriter.Lifecycle` (`HeadlessDiagnosticWriter.cs:22-45`) is
|
||||
called at exactly four points (`HeadlessSessionHost.cs:289, 463, 551, 588`):
|
||||
`constructed` (pre-connect), `start-result` (inside `StartLive`, BEFORE the
|
||||
first `Runtime.Session.Tick()` drains a packet), `reconnect-deferred`, and
|
||||
`stopped` (AFTER teardown emptied the directory). A perfectly healthy run also
|
||||
prints `entities: 0` on every lifecycle line. `live: in world — CreateObject
|
||||
stream active` (`LiveSessionController.cs:593`) prints before any CreateObject
|
||||
routes. The periodic `resources` sampler sums real counts but defaults to a
|
||||
30 s period the quarantined run never reached.
|
||||
|
||||
**Do NOT hunt for "CreateObjects never admit."** The record almost certainly
|
||||
IS registered: `RuntimeLocalPlayerPhysicsPublicationState.Prepare`
|
||||
dereferences `record.Key!.Value.LocalEntityId` (`:214`), `CanPrepare` requires
|
||||
`_entities.IsCurrent(record)` (`:1052`), and the crash proves a controller was
|
||||
constructed. The `entityCount` datum is an artifact.
|
||||
|
||||
## 2. Q1 — inbound route and the fork points
|
||||
|
||||
Headless inbound route: `WorldSession.EntitySpawned` → `LiveSessionEventRouter`
|
||||
→ `RuntimeLiveEntitySessionController.OnSpawned` (`:129`) →
|
||||
`RegisterEntityWithInitialResidence` (`:147-152`) → `ApplyAcceptedSpawn`
|
||||
(`:158`) → `HeadlessSessionWorldProjection.ProjectSpawn` (`:627`): local player
|
||||
→ `_collision.CenterOn(position.LandblockId)` (`:644-648`) then
|
||||
`_firstEntry.DriveAll()` (`:666`) → `RuntimeFirstEntryDriveController.DriveOne`
|
||||
(`:200`) → `RuntimeLocalPlayerFirstEntryState.Advance` (`:247`).
|
||||
|
||||
Per-tick pump (`HeadlessSessionHost.Tick:333-362`): `Clock.Advance` →
|
||||
`AdvanceBeforeNetwork` → `Session.Tick()` → `PumpFirstEntry()` →
|
||||
`PumpPortalCompletion()` → `RetryPending()` → `RunPostNetworkCommandPhase()` →
|
||||
`policy.Tick`.
|
||||
|
||||
**No presentation-gated admission step, no missing subscription, no
|
||||
reveal/streaming gate on the headless admission path** — C3c (`529e0e9d`)
|
||||
unified them. The fork is downstream:
|
||||
|
||||
### Fork point 1 (the crash) — `HeadlessLocalPlayerFrameHost.cs:42-44`
|
||||
|
||||
```csharp
|
||||
public bool CanAdvancePlayer =>
|
||||
_runtime.Session.IsInWorld
|
||||
&& _runtime.MovementOwner.Controller is not null;
|
||||
```
|
||||
|
||||
Graphical host: `LocalPlayerFrameRuntime.cs:24-25` → `CanPresentPlayer` →
|
||||
`IsPlayerMode`, entered only when `PlayerModeAutoEntry.cs:100`
|
||||
`Controller is { IsRuntimePublished: true }` (the C3c-F2 fix).
|
||||
`Controller` becomes non-null at publication Commit
|
||||
(`RuntimeLocalPlayerPhysicsPublicationState.Commit:472`) in
|
||||
`RuntimeOwnedDormant`; `RuntimePublished` only arrives inside
|
||||
`TryApplyDormantLocalActivationFinalCommit` (`RuntimeSetPositionState.cs:2823`
|
||||
`controller.ActivateRuntimePublication()`). So headless runs
|
||||
`RuntimeLocalPlayerFrameController.AdvanceBeforeNetwork` (`:75`) against a
|
||||
dormant controller: `:93` LocalEntityId write (quarantine #1, neutralized by
|
||||
`ab82347d`) and `:96-99` Suspend branch → `SuspendObjectUpdate` →
|
||||
`EnsurePublishedForRuntimeOperation` throw (quarantine #2, current).
|
||||
|
||||
### Fork point 2 (the hydration stall) — `HeadlessSessionWorldProjection.cs:471-548`
|
||||
|
||||
`HeadlessCollisionNeighborhood.AdvanceWork`, called from `PumpFirstEntry`
|
||||
(`:736-742`) and `ProjectSpawn` (`:644-648`). The headless host's ONLY
|
||||
collision publisher is a 3×3 landblock plan **built and started by the local
|
||||
player's own CreateObject**. The graphical publisher
|
||||
(`LandblockPhysicsPublisher.cs`) runs on the streaming cadence, independent of
|
||||
and ahead of the Create burst. That timing difference is the whole asymmetry.
|
||||
|
||||
## 3. Q2 — the never-satisfied precondition
|
||||
|
||||
### The stall state
|
||||
|
||||
Conductor parked at `Stage.PublicationCommitted` in
|
||||
`RuntimeLocalPlayerFirstEntryState.AdvanceCore` (`:437-506`), cycling
|
||||
`EvaluateActivation` → `AwaitingActivation` forever. `MovementOwner.Controller`
|
||||
non-null (Commit ran) but `IsRuntimeOwnedDormant`; `record.PhysicsBody` set,
|
||||
`body.InWorld == false` (`Publication.Prepare:358-359`); `record.FullCellId
|
||||
== 0` → `ObjectClockDisposition` (`:78-96`) returns `Suspend`;
|
||||
`RuntimeFirstEntryDriveController.DriveOne` hits `:264-270` and returns every
|
||||
tick. 1:1 match for every symptom.
|
||||
|
||||
### The precondition
|
||||
|
||||
`EvaluateActivation` (`:496-541`) fails because
|
||||
`RuntimeSetPositionState.TryEvaluateDormantLocalActivation` (`:1989-2094`)
|
||||
returns false at the seal (`:2061` → `:2088`). `TrySealCollisionEvaluationAuthority`
|
||||
(`RuntimePhysicsState.cs:2411-2469`) requires for EVERY prefix the placement's
|
||||
ring search queried:
|
||||
|
||||
```csharp
|
||||
// RuntimePhysicsState.cs:2365-2371
|
||||
internal bool IsCollisionEvaluationPrefixAdmissible(uint exactCellId)
|
||||
{
|
||||
uint landblockId = CanonicalLandblock(exactCellId);
|
||||
return landblockId != 0u
|
||||
&& !_collisionAdmissions.ContainsKey(landblockId)
|
||||
&& !SetPosition.IsCollisionPrefixQuiescing(landblockId);
|
||||
}
|
||||
```
|
||||
|
||||
### Why headless cannot satisfy it (structural half — CONFIRMED)
|
||||
|
||||
`AdvanceWork` drains a 9-entry plan one commit poll per call, yielding on
|
||||
every non-completed `CommitCollisionGeneration` (`:540-543`,
|
||||
`HeadlessCollisionGenerationTransaction.Advance:142-156`). While it holds
|
||||
`_pendingPublication`, that landblock's `RuntimeCollisionAdmission` IS
|
||||
registered, and once `CommitCollisionGeneration` opens
|
||||
`BeginCollisionPrefixQuiescence` (`RuntimePhysicsState.cs:1866-1889`) the
|
||||
prefix IS quiescing — both admissibility terms false for the duration.
|
||||
`PumpFirstEntry` calls `DriveAll()` immediately after `IsReady` (`:739-741`),
|
||||
so the conductor evaluates exactly while the admission is open. Same in
|
||||
`ProjectSpawn` (`:648` → `:666`). The ring search touches the center + its
|
||||
neighbours — every one in the 3×3 plan. The graphical host has the identical
|
||||
seal but long admission-free windows. Same class #357 named; headless is
|
||||
strictly worse because publication is STARTED by the Create.
|
||||
|
||||
### Why it may never open (HIGH-CONFIDENCE HYPOTHESIS — must be confirmed)
|
||||
|
||||
Circular wait between the collision commit and remote first-entry operations:
|
||||
1. Committing landblock L requires `TryAcquireCollisionPrefixMutationPermission`
|
||||
(`RuntimeSetPositionState.cs:925-972`) → requires
|
||||
`!HasOldPrefixPlacementDebt(current)`.
|
||||
2. `HasOldPrefixPlacementDebt` (`:4076-4100`) walks every `_operations` entry,
|
||||
skipping only `WakeableLostCell || DormantLocalActivation`, true if the
|
||||
operation's command/result/mover-preparation accepted position or its
|
||||
record's collision residency touches L.
|
||||
3. `RuntimeInitialCreateResidenceState.Own` (`:750-780`) opens an exclusive
|
||||
authored placement operation for EVERY remote Create whose route
|
||||
`PerformsSetPosition`. Those sit in `AwaitingPreparation`, not exempt
|
||||
(they gain `WakeableLostCell` only after successfully submitting and
|
||||
parking; `0934a121` gives them a real body in prefix L, which also trips
|
||||
`IsAffectedCollisionResident`).
|
||||
4. A remote's own placement submission seals against the same prefix —
|
||||
refused while L is admitted/quiescing — so it never reaches the park that
|
||||
would exempt it.
|
||||
|
||||
→ L never commits; remotes never park; the player's dormant activation never
|
||||
wakes. The local player IS exempt from step 2 from publication-Commit onward
|
||||
(`PrepareDormantLocalActivationOwnership` sets
|
||||
`operation.DormantLocalActivation = true`, `RuntimeSetPositionState.cs:1526`)
|
||||
— exactly why the local controller gets built and then freezes.
|
||||
|
||||
Other blocking terms checked by the same probe:
|
||||
`HasPendingProjectionThrough(ProjectionBarrierSequence)` (`:4059-4062`) — note
|
||||
`HeadlessRuntimePlacementProjectionSink.TryApply` deliberately returns FALSE
|
||||
(leaves at FIFO head) for Place/Withdraw of an entity still holding an
|
||||
initial-create residence (`HeadlessRuntimePlacementProjectionSink.cs:63-81`) —
|
||||
and `HasCollisionDispatchDebt` (`:4064-4074`).
|
||||
|
||||
### The one line that settles it
|
||||
|
||||
`TryRearmDeferredDormantLocalActivation` prints a purpose-built verdict
|
||||
enumerating every term (`RuntimeSetPositionState.cs:~2200-2225`), behind
|
||||
`PhysicsDiagnostics.ProbeParkEnabled`:
|
||||
|
||||
```
|
||||
[rearm] guid=... verdict=<not-current | stage=X | not-dormant | not-wakeable
|
||||
| gen-not-ready | proj-seq | gen-mismatch(a!=b) | spawn-not-ready
|
||||
| prefix-inadmissible | OK>
|
||||
[rearm] guid=... seal-refused (transient; lease retained)
|
||||
[pump] DriveAll #N pending=K
|
||||
[wake] begin lb=0x... gen=... unboundCells=... buckets=...
|
||||
```
|
||||
|
||||
And it is unrunnable headless — defect C.
|
||||
|
||||
## 4. Q3 — when it broke
|
||||
|
||||
| Commit | Date | Headless impact |
|
||||
|---|---|---|
|
||||
| **`529e0e9d` — C3c production placement cutover (routes 1+8)** | 2026-08-02 | **Prime culprit.** Rewrote the headless local-player path wholesale; deleted `SynchronizeLocalPlayer`/`CreateController`/`ApplySetupStepHeights`; controller now only publishable through the residence→publication→activation→seal chain. Gate list: unit tests + a GRAPHICAL connected gate. **No connected headless gate.** |
|
||||
| `175ad6b0` | 2026-08-02 | Same seam, same window. |
|
||||
| `9966b531`/`2e8e09ac`/`e0f96a55` | 08-03→05 | Touched HeadlessSessionWorldProjection; graphical-gated only. |
|
||||
| `6921a027` C5a, `3aab05b0` #280 | 08-05/06 | Comment-only / shape — not causal. |
|
||||
| **`78b981cc` — #357** | 2026-08-08 | **Symptom-shape culprit.** Seal failure reclassified terminal→DeferredCell: pre-#357 headless failed SILENTLY (controller discarded, no crash); post-#357 the dormant controller persists → crash. Correct fix graphically; DO NOT revert. |
|
||||
| `ab82347d` | 2026-08-10 | Fixed quarantine #1; filed #365. |
|
||||
|
||||
Coverage gap: the one headless hydration test
|
||||
(`HeadlessSessionHostTests.WorldProjectionHydratesCanonicalMovementAndTeleportState`,
|
||||
`:347-475`) uses a `FixtureCollisionNeighborhood` fake and pre-commits
|
||||
collision by calling `SetPosition.BeginCollisionGeneration`/
|
||||
`CommitCollisionGeneration` DIRECTLY (`:372-375`) — bypassing admission
|
||||
registry, seal, and quiescence. **The production `HeadlessCollisionNeighborhood`
|
||||
has never been exercised against the first-entry conductor in any test.**
|
||||
|
||||
## 5. Q4 — Suspend / CanAdvancePlayer contract
|
||||
|
||||
- **`Suspend` is correct** for a cell-less pre-hydration player (retail's
|
||||
parent/cell-less/Frozen early gate, `PlayerMovementController.cs:1036-1041`).
|
||||
The crash is calling ANY live-movement op on an unpublished controller —
|
||||
the Advance branch would throw identically.
|
||||
- **`CanAdvancePlayer` must require publication.** Three confirmations: the
|
||||
graphical host gates on `IsRuntimePublished` (C3c-F2,
|
||||
`PlayerModeAutoEntry.cs:100`); #356 (`972c7ab3`) established
|
||||
`CanExecuteLiveMovement` (`PlayerMovementController.cs:797-805`) as the
|
||||
lifecycle-caller idiom ("including before the controller is published during
|
||||
login… neither is an error"; `MouseLookController.cs:205` is the consumer);
|
||||
and `IsActivationOwnershipEnvelopeCurrent`
|
||||
(`RuntimeLocalPlayerPhysicsPublicationState.cs:900-928`) asserts the dormant
|
||||
controller is untouched across activation — advancing it is semantically
|
||||
wrong, not merely fatal. No dormant-activation classification changes needed;
|
||||
the #357 test matrix stays untouched.
|
||||
- There is NO #357 closeout doc in docs/research; its record is commit
|
||||
`78b981cc`'s message + source comments (`RuntimeSetPositionState.cs:2073-2088`,
|
||||
`RuntimeLocalPlayerPhysicsPublicationState.cs:513-534`).
|
||||
|
||||
## 6. Q5 — fix plan (ORDERING IS LOAD-BEARING)
|
||||
|
||||
### Step 1 (enabler, ~10 lines) — make the diagnosis runnable headless
|
||||
`HeadlessStaticStateAudit.cs:15` + call site `HeadlessProcessHost.cs:45`: the
|
||||
audit's stated rationale is multi-root isolation; give `ValidateProcessIsolation`
|
||||
a `sessionCount` parameter and skip the refusal for `sessionCount == 1`
|
||||
(emit a diagnostic Message naming enabled probes). Tests: single-session +
|
||||
probe ⇒ starts (and logs); two sessions + probe ⇒ still throws naming the
|
||||
probe. Not a workaround — a correctness fix to a guard whose rationale does
|
||||
not hold for its condition.
|
||||
|
||||
### Step 2 (measurement, no code) — confirm which term is stuck
|
||||
Run the repro with `ACDREAM_PROBE_PARK=1`; read `[rearm] verdict=`:
|
||||
|
||||
| verdict | Meaning | Fix target |
|
||||
|---|---|---|
|
||||
| `prefix-inadmissible` persisting | structural claim — admission/quiescence never clears | Step 3 |
|
||||
| `gen-not-ready` / `gen-mismatch` | neighborhood commits a generation the lease isn't parked against | narrower fix in HeadlessCollisionNeighborhood |
|
||||
| `spawn-not-ready` | 3×3 plan never published the destination cell | BuildPublicationPlan / CreatePublication |
|
||||
| `proj-seq` | unacknowledged placement projection — the projection-sink residence gate wedge | drain rule in RuntimeFirstEntryDriveController |
|
||||
| `seal-refused` repeating, no verdict line | operation never re-parks; abort in pre-park evaluation | TryEvaluateDormantLocalActivation |
|
||||
|
||||
Also capture `[pump] DriveAll #N pending=K`. **This step is mandatory** (the
|
||||
C4 closeout's "inferring a fact you can observe" finding applies exactly).
|
||||
|
||||
### Step 3 (root cause) — headless collision publication quiescent-before-drive
|
||||
Do NOT relax the seal, add a retry budget, or special-case headless inside
|
||||
Runtime. The host's publication cadence violates the (correct) precondition.
|
||||
|
||||
**3a.** Never drive the conductor while the neighborhood holds an open
|
||||
admission or in-flight quiescence. Add read-only
|
||||
`IHeadlessCollisionNeighborhood.IsQuiescent`
|
||||
(`_pendingPublication is null && _publicationQueue.Count == 0 &&
|
||||
!_pendingPublicationCancellation`); gate `PumpFirstEntry` (and
|
||||
`ProjectSpawn:666`, `ProjectPosition:690`):
|
||||
|
||||
```csharp
|
||||
if (!_collision.IsQuiescent)
|
||||
return; // publication owns the authority this tick
|
||||
_firstEntry?.DriveAll();
|
||||
_acceptedPositionDrive?.Advance();
|
||||
```
|
||||
|
||||
**3b.** If Step 2 shows `HasOldPrefixPlacementDebt` (remote first-entry
|
||||
operations) is the blocker, 3a alone won't close it: hoist `CenterOn` off
|
||||
`ProjectSpawn` onto the accepted local-player position observed at
|
||||
`RegisterEntityCore`'s `Physics.ObserveLocalPlayerCreate` seam, publish the
|
||||
login window to completion BEFORE the first Create is projected, hold
|
||||
conductor driving until `IsQuiescent` — restoring the graphical ordering
|
||||
(world published, then entities placed).
|
||||
|
||||
**Explicitly rejected shapes** (workarounds): retry budget on
|
||||
AwaitingActivation; forcing `IsCollisionEvaluationPrefixAdmissible` to ignore
|
||||
the headless admission; nulling the controller on stall.
|
||||
|
||||
### Step 4 (crash guard, AFTER step 3) — `CanAdvancePlayer` requires publication
|
||||
`HeadlessLocalPlayerFrameHost.cs:42-44`:
|
||||
|
||||
```csharp
|
||||
public bool CanAdvancePlayer =>
|
||||
_runtime.Session.IsInWorld
|
||||
&& _runtime.MovementOwner.Controller is { CanExecuteLiveMovement: true };
|
||||
```
|
||||
|
||||
Use the PUBLIC `CanExecuteLiveMovement` (#356 idiom), not internal
|
||||
IsRuntimePublished. Optionally harden the shared owner:
|
||||
`RuntimeLocalPlayerFrameController.AdvanceBeforeNetwork/RunPostNetworkCommandPhase/
|
||||
TryGetPresentationAfterNetwork` (`:75, :135, :166`) add
|
||||
`|| !controller.CanExecuteLiveMovement` to the null checks (contract-preserving
|
||||
for the graphical host).
|
||||
|
||||
### Test list
|
||||
1. Runtime: `RuntimeLocalPlayerFrameControllerTests` — host reporting
|
||||
CanAdvancePlayer:true with a DORMANT controller must not throw in either
|
||||
Suspend or Advance branch (sabotage-verify both directions).
|
||||
2. `RuntimeLocalPlayerPhysicsPublicationStateTests` — assert UNCHANGED (the
|
||||
seven #357 DeferredCell tests + two terminal tests). If any needs editing,
|
||||
the fix is wrong.
|
||||
3. **The missing headless test**: sibling of
|
||||
`WorldProjectionHydratesCanonicalMovementAndTeleportState` driving the REAL
|
||||
`HeadlessCollisionNeighborhood` (or a faithful fake registering a
|
||||
RuntimeCollisionAdmission + opening prefix quiescence across ticks);
|
||||
asserts first-entry reaches Completed and
|
||||
`MovementOwner.Controller.IsRuntimePublished` within a bounded tick count.
|
||||
**Must FAIL on the current tree** — the acceptance criterion.
|
||||
4. `PumpFirstEntry` does not call DriveAll while non-quiescent; calls it on
|
||||
the first tick after quiescence.
|
||||
5. `CanAdvancePlayer`: false dormant, true published, false retired.
|
||||
6. Audit: single-session+probe allowed (logged); multi-session+probe refused.
|
||||
7. Keep `HeadlessCollisionNeighborhoodServiceWindowTests`,
|
||||
`HeadlessSessionEventRouteRetryPendingTests` green.
|
||||
|
||||
### End-to-end verification recipe
|
||||
Config on disk (content-bearing, so the content-less branch at
|
||||
`RuntimeLiveEntitySessionController.cs:147` is NOT in play):
|
||||
`<scratchpad>/jump-probe-config.json` (testaccount/+Acdream, policy
|
||||
jump-probe, credential env ACDREAM_HEADLESS_PASS).
|
||||
|
||||
```powershell
|
||||
$env:ACDREAM_HEADLESS_PASS = "testpassword"
|
||||
$env:ACDREAM_PROBE_PARK = "1" # requires Step 1
|
||||
dotnet run --project src\AcDream.Headless -c Release -- run --config <cfg> 2>&1 |
|
||||
Tee-Object -FilePath headless-365.log
|
||||
```
|
||||
|
||||
Cautions: testaccount must not be held by a running graphical client;
|
||||
terminate with Ctrl-C/SIGINT (never Stop-Process — graceful Stop() clears the
|
||||
ACE session in ~3-5 s; a hard kill costs ~3 min of exit-29).
|
||||
|
||||
Pass criteria: (1) no `kind:"failure"`; (2) `[jump-probe] local player
|
||||
present; charging jump`; (3) `[pump]` reaches pending=0 and `[rearm]
|
||||
verdict=OK` (or clean first-pass seal); (4) `[jump-probe] airborne-transition
|
||||
False -> True` — the bot actually moves (the real acceptance test); (5)
|
||||
graceful exit, converged final `disposed` sample. Second gate: run the
|
||||
`observer-movement` policy ~60 s and watch from the graphical/retail client
|
||||
that +Acdream walks — the K3/K4 gate unrun since 2026-08-02.
|
||||
|
||||
## 7. Confidence summary
|
||||
|
||||
| Claim | Confidence | Falsify cheaply |
|
||||
|---|---|---|
|
||||
| Crash = dormant controller reaching SuspendObjectUpdate via headless CanAdvancePlayer | Certain | — |
|
||||
| Graphical gates on IsRuntimePublished; headless doesn't | Certain | PlayerModeAutoEntry.cs:100 |
|
||||
| entities:0 is a logging artifact | Certain | HeadlessDiagnosticWriter call sites |
|
||||
| Conductor parked at PublicationCommitted/AwaitingActivation | Very high | [pump] probe |
|
||||
| Blocked precondition = IsCollisionEvaluationPrefixAdmissible in the seal | High | [rearm] verdict= |
|
||||
| Circular HasOldPrefixPlacementDebt ↔ seal wait makes it permanent | Hypothesis, well-supported | [rearm] verdict= + log on TryAcquireCollisionPrefixMutationPermission's four early returns |
|
||||
| 529e0e9d root cause; 78b981cc changed the symptom | High | git show 529e0e9d -- src/AcDream.Headless/ |
|
||||
| Probes unrunnable headless | Certain | HeadlessProcessHost.cs:45 |
|
||||
| Existing hydration test bypasses admission/seal | Certain | HeadlessSessionHostTests.cs:372-375 |
|
||||
Loading…
Add table
Add a link
Reference in a new issue