F1 (critical, Soul): managed admission still bailed without
GHOSTLIGHT_CONTROLLER_CONNECTOR and required Idunn's Expected to carry a
third, connector, dependency that no longer exists anywhere upstream.
idunn_health.rs now reads no connector env, requires exactly Ghostlight's two
real dependencies (Odin, Heimdall), and RuntimeDependencyBindings/
RuntimePresencePublisher carry no connector field. runtime.rs's
open_controller no longer takes an endpoint parameter for a lane it cannot
offer: Dungeon passes None for ConnectorBinding and says why in a comment.
configured_connector_endpoint is deleted. The library's CodexConnector
transport (crates/ghostlight) is untouched, and play.rs's own use of the
codex_connector crate for transcript types is unrelated and untouched.
F3: Heimdall is not an Idunn-v2-managed incarnation (every v2 deploy has
failed; it runs as legacy heimdall.service). Idunn projects an
[[external_capabilities]]-declared provider as provider_authority =
"external-operator-binding" with no provider_expected_projection_sha256
(Idunn's DependencySelection::expected_projection), never the managed shape a
"required" dependency expects. Recipe's Heimdall dependency kind is now
"external-operator-binding"; idunn_health.rs's required_external_dependency
checks exactly that shape. Odin stays a managed shared-infrastructure
dependency.
F2: the recipe disagreed with the binary on every declared contract, so
Warming would fail even with F1/F3 fixed. schema_generation was "world-v2"
against the daemon's "world-v3"; ghostlight.world-service provided
"foundation-v0" against the binary's actual ghostlight.world_state.consumer.v6
/ consumer-v6 (STATE_SCHEMA); controller-work's slot schema was pinned at
"v3" against the code's "v17". Fixed all three against the source constants,
and recomputed idunn_health.rs's STATE_CONTRACT_SHA256 against the corrected
[state] block using Idunn's own canonical_state_contract_sha256 (msgpack +
sha256 of the recipe's StateDeclaration) run against the finalized recipe —
not guessed. Promoted CONTROLLER_WORK_SCHEMA (ghostlight) and STORE_SCHEMA
(ghostlight-dungeon's app_session) from private to pub/pub(crate) so a test
can check itself against them instead of hand-copying version numbers.
Added one Dungeon test, recipe_matches_the_daemon_it_deploys, pinning recipe
strings against the daemon's own constants: state generation, provided
schema/compatibility, all four slot schemas, the exact dependency count and
kinds, and the absence of the retired CodexConnector dependency. No TOML
parser exists in this workspace's Cargo.lock, so it string-matches the exact
values rather than parsing into a struct — it catches value drift but not
field-placement drift a real parse would also catch (documented in the test's
own comment). Mutation-verified: corrupting schema_generation fails it;
reverted (diff-clean).
Verification: cargo test -p ghostlight-dungeon --bin ghostlight-dungeon ->
185 passed, 0 failed, 4 ignored (was 184; +1 for the new test). cargo test -p
ghostlight --lib controllers:: -> 131 passed, 0 failed, 1 ignored, unchanged.
Negative grep for CONNECTOR in crates/ghostlight-dungeon/src: zero survivors.
sudo -n idunn validate on Yggdrasil against the updated recipe + binding:
both ok.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>