# RC.2 Ghost Dojo headless-bout integration audit

Date: 2026-07-22

## Decision

Ghost Dojo stays unshipped and its Rail channel stays unregistered. V2 has a
real deterministic rollback simulation core, but this checkout does not have an
autonomous, authoritative headless bout path that can turn two ghost tendency
profiles into inputs, collisions, rounds, and a winner. Building the league on
the existing test-bot arithmetic or on a second TypeScript fight simulator would
produce canned results and violate RC.2's explicit gate.

This gate does not block the Rail or the already-shipped channels.

## What the Shakti bridge actually owns

`libs/shakti/fighting-ruleset-bridge` is an authoring transform. It maps Shakti
biomechanics into deterministic frame-data records for the seven V2 launch
rulesets. `apps/v2/shakti-ruleset-bridge` adapts those records into CSV rows and
reference-card metadata for V2 balance authoring. Both packages deliberately
keep Shakti RPCs outside rollback frames.

The production direction is therefore:

```text
Shakti biomechanics
  -> @shakti/fighting-ruleset-bridge profiles and pure transform
  -> @v2/shakti-ruleset-bridge CSV/reference-card adapter
  -> V2 authored/cooked frame data
  -> V2 runtime collision and rollback systems
```

The bridge is not a bout simulator and is not a runtime policy interface. A
Ghost Dojo implementation must consume the same cooked V2 combat data and
authoritative V2 match loop as the game; it must not call Shakti during a bout.

## What can run headlessly today

`FV2SimWorld` in `V2Netcode` is real, deterministic simulation code. It can:

- reset and snapshot fighter state, step explicit per-player
  `FV2RollbackFrameInput` records, restore snapshots, and produce state hashes;
- apply deterministic movement and a substantial set of ruleset mechanics;
- resolve explicitly supplied `FV2CombatCollisionEvent` records through the
  shared deterministic hit authority; and
- replay the 200 checked-in golden-corpus manifests and detect a hash divergence
  at the first sampled frame.

The corpus is valuable regression evidence, but it is not autonomous combat.
`GoldenReplayCorpus.spec.cpp` generates or loads each input stream itself. Its
hit-exchange and juggle scenarios also inject their collision events on fixed
frames before calling `ResolveRollbackHits`.

## What cannot simulate a Ghost Dojo bout today

No inspected path supplies all of the following:

1. a ghost/tendency policy that observes `FV2SimWorld` and emits legal
   `FV2RollbackFrameInput` for both fighters;
2. runtime move selection and collision generation from the cooked frame data;
3. an authoritative round/match loop that detects KO, time-out, draw, and a
   final winner; and
4. a runnable fighter roster/stage from which a league bout can be instantiated.

The similarly named V2 playtesting harnesses do not fill that gap:

- `UV2BotHarnessLibrary::RunBotHarnessScript` validates scripted actions, marks
  supported ones executed, and hashes their metadata. It does not boot a game
  world, load the declared script/model paths, or call `FV2SimWorld`.
- `UV2CombatBotLibrary::RunCombatBot` derives each result by subtracting an
  authored combo damage total (minus authored armor) from authored enemy health.
  It does not simulate attacks, defenses, collisions, or opponent decisions.
- the default harness map `/Game/Maps/L_BotHarness`, default pawn
  `/Game/V2/Blueprints/BP_V2BotTestPawn`, `.v2botscript`, `.onnx`, and
  `.v2input` files referenced by those abstractions are absent from
  `V2/ue/Content`.

The content gate is also concrete: `V2/ue/Content` currently contains eight
regional `.uasset` data assets, zero `.umap` files, and no checked-in cooked
`.pak`, `.utoc`, `.ucas`, or `AssetRegistry.bin` output. There is no fighter or
stage content to instantiate for the league.

## Verification performed

The source audit covered the two Shakti bridge implementations and tests, the V2
combat/determinism and build/cook architecture notes, `FV2SimWorld`, the golden
replay corpus and its regression test, and the BotHarness/CombatBot
implementations and automation specs.

A focused Unreal command was attempted with the required local UE 5.5 editor:

```text
Automation RunTests V2.Netcode.GoldenReplayCorpus.Regression
```

Automation could not start because the local engine installation is internally
build-ID mismatched: the editor reports build ID
`9729efc9-d09a-46a2-bf07-036739f64d68`, while the installed `OnlineServicesEOS`
module reports `0825d548-3e61-4aa3-bcb0-2e87affafb30`. The plugin's shared
object exists, but Unreal rejects the module before test discovery. A second
command-line attempt to disable the optional EOS plugins was ignored by plugin
mounting and failed at the same module check. This is an environment
verification blocker, not evidence that an autonomous bout path exists.

## Reopen criteria

RC.2 league and channel implementation can begin only when all of these are
true:

- a headless V2 target can load at least two real cooked fighters and a legal
  bout environment;
- a deterministic ghost policy converts persisted tendencies into both fighters'
  frame inputs;
- the normal V2 move/collision/round authorities run to a reproducible match
  outcome without injected or preselected results;
- changing a tendency produces a tested behavioral delta while identical seed,
  content version, and tendencies reproduce the same result; and
- the headless target passes on a build-compatible Unreal installation.

Only then should the persistent ladder consume those result events, and only
after that should `rail-channel-ghost-dojo` expose tiles, drips, predictions, or
video-lane bouts. Until then the tendencies mobile micro-act also has no honest
write authority and remains unavailable.
