Commit graph Ghostlight/deployment
Author SHA1 Message Date
Meta Vens
c5bf090d62 Stop declaring Heimdall as an Idunn dependency
Odin (96a55ec) now computes Ready with an external-operator-binding
dependency not ready, but CultLib's shared contract
(runtime_authority_contracts.rs:797-805) refuses any correlation claiming
Ready while a non-optional dependency is not ready, so Odin rejected every
Ghostlight Active presence (30/30 in the last deploy). The external kind
existed only because Heimdall isn't v2-managed; that reason doesn't survive
contact with Odin's own Ready computation.

Ghostlight's deploy stops declaring Heimdall as an Idunn dependency. The
daemon discovers it through Odin at use instead: HeimdallClient already took
Option<HeimdallDependencyBinding> with None as the non-managed path, so
runtime.rs now passes None directly rather than computing it from a
dependency_bindings field that no longer exists, and the loopback-only,
non-secret-bearing, app-bound HMAC+AES envelope enforcement is unchanged.
When Heimdall becomes a v2 target the dependency returns as `required`
managed.

- deployment/idunn/recipe.toml: deleted the heimdall.command-boundary
  [[dependencies]] block. Ghostlight's own required_environment for
  GHOSTLIGHT_HEIMDALL_APP_SECRET_FILE/GHOSTLIGHT_HEIMDALL_BASE_URL is
  unrelated (Heimdall's HTTP app integration, not the Idunn dependency) and
  stays.
- idunn_health.rs: runtime_dependency_bindings now requires exactly the Odin
  dependency (one, not two). Deleted HEIMDALL_CAPABILITY,
  required_external_dependency and its doc comment, the `heimdall` field on
  RuntimeDependencyBindings, the fixture's external_dependency helper and
  its Heimdall entry, and the recipe-drift test's Heimdall block/assertion
  (now asserts exactly one [[dependencies]] block and fails if a Heimdall
  dependency reappears without the daemon changing to expect it again).
  HeimdallDependencyBinding itself moved to heimdall.rs (see below) rather
  than being deleted outright: it's still the shape
  require_expected_heimdall_boundary checks a discovered boundary against
  when Idunn does supply one, which stays true the moment Heimdall returns
  as a managed dependency.
- heimdall.rs: now owns HeimdallDependencyBinding (moved from
  idunn_health.rs, which no longer has any use for it). No behavior change:
  HeimdallBoundaryLocator::Odin's `expected: Option<HeimdallDependencyBinding>`
  and its None-tolerant checking logic were already exactly the
  "discover through Odin, verify against a managed binding when one exists"
  shape this ruling asks for.
- runtime.rs: expected_heimdall is gone; `HeimdallClient::from_env` now
  takes `None` directly instead of a value computed from a
  dependency_bindings field that no longer exists, with a comment on why.

Mutation: re-added the heimdall.command-boundary [[dependencies]] block to
the recipe -> recipe_matches_the_daemon_it_deploys fails (asserts exactly
one dependency block). Restored; deployment/idunn/recipe.toml is
git-diff-clean after, one clean 7-line deletion.

Verification: cargo test -p ghostlight-dungeon --bin ghostlight-dungeon ->
192 passed, 0 failed, 4 ignored (unchanged count: removed a test helper, not
a test).

Structural delta: 4 files changed, 42 insertions(+), 138 deletions(-) in
Ghostlight (net -96 lines) — a genuine subtraction, not a relocation with
padding; the only addition of substance is the doc comment on the relocated
HeimdallDependencyBinding explaining why it still exists.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 20:29:00 +02:00
Meta Vens
9a000e9a30 Declare the build cache environment on every Idunn recipe step
Idunn passes a runner container only the variables its step declares, and
the image's own CARGO_HOME is read-only, so the first v2 build failed
writing cargo's git database for the codex-connector dependency. Rust
steps declare CARGO_HOME and HOME, web steps HOME and NPM_CONFIG_CACHE, as
Odin and Heimdall do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 16:34:16 +02:00
Meta Vens
4ed5b26688 Retire the Raven-hosted Dungeon launch script
Dungeon runs on Yggdrasil under Idunn v2; Raven hosts only Bonsai and the
link. The scheduled task is unregistered and the secret copies removed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-23 16:27:19 +02:00
Meta Vens
c716b57730 Cut CodexConnector out of managed admission; fix Heimdall's dependency kind and recipe/binary drift
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>
2026-09-23 15:59:09 +02:00
Meta Vens
22ec118d72 Swap the real cognition acceptance test to the local Bonsai transport
CodexConnector is not a real option for Dungeon inference (operator ruling
2026-09-23): Bonsai 2 reaches Yggdrasil over a restricted reverse SSH tunnel
at loopback 127.0.0.1:18080. Rename
real_codex_connector_cognition_modes_commit_speech to
real_local_model_cognition_modes_commit_speech, open inference with
LocalBinding instead of ConnectorBinding, and read
GHOSTLIGHT_LOCAL_ENDPOINT/GHOSTLIGHT_LOCAL_MODEL_PREFIX in place of the
connector endpoint and credential. Update the Idunn recipe's acceptance step
and service required_environment to match (drop the connector env, add the
elaborator model var the test already required but the recipe omitted), and
drop the gamecult.codex.subscription-inference dependency: Dungeon no longer
depends on CodexConnector for inference. Update the remaining live references
to the old test name in notes/map.

CodexConnector's transport code and the v1 actuator are untouched; both are
separate follow-up cuts.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 15:13:45 +02:00
Meta Vens
3a56bf3389 Record the Raven playtest bring-up script
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 13:27:45 +02:00
Meta Vens
f859d2c4e3 Give the world library a sealed public boundary
Completes the move begun in the previous commit, which does not build on its
own. `ghostlight` is now a library crate with an explicit public surface;
`ghostlight-dungeon` is a consumer that reaches the kernel through it and
cannot reach past it.

Deleted first: `mod world;`, the nine unused re-exports, the `#[cfg(test)]`
re-export block, `fixture_controller_opportunities`, the five inference
`fixture_*` items, Dungeon's own `VerifiedPrincipalEvidence`, and Dungeon's
direct `ghostlight-persona-projection` dependency.

The seal. `WorldKernel`, `WorldState`, `reduce`, `apply_effect`,
`CommandEnvelope`, `AuthenticatedCaller`, the journal writer, every ID
`issue()`, and `ScopeDigest::fixture` carry no `pub` of any kind and no
feature gate; the crate declares no `[features]`, so no build configuration
can lift them. Ten `compile_fail` doc-tests stand outside the crate and pin
each one to its error code.

The principal seam. The library owns `VerifiedPrincipalEvidence` with a public
`new`; `mailbox` still bounds it by `valid_until` at ingress. A Dungeon test
counts the minters in production source and fails at anything but one.

The port contract (Q1-7). `PreparedInference::prepare` (renamed from the free
`prepare_invocation`), `InferenceOutput::new`, and
`InferenceFault::{retryable, recovery_required, integrity_violation}` are now
the port's public constructors, so a consumer-implemented `InferencePort` can
answer without test-only wrappers. `TracingInferencePort` is an ungated
decorator.

The tick-ordering test (Q1-8) derives its cover from a real active world
through `derive_cover` and asserts two cells; its ordering and shared-tick
assertions are unchanged.

Behaviour is unchanged. The library's 420 unit tests are the base `world::`
set with the prefix stripped — the names diff empty. Dungeon keeps all 49 of
its names and gains two Soul tests the boundary requires. No schema string,
digest preimage, or store layout is touched.

Windows verification only; the Linux release is Idunn's build.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 02:06:07 +02:00
Meta Vens
751b5c4150 Take runtime identity, bind, and state root from Idunn
The daemon declared its own GHOSTLIGHT_RUNTIME_ID, GHOSTLIGHT_DUNGEON_BIND,
and GHOSTLIGHT_DUNGEON_ROOT. Under the managed contract Idunn owns all three:
the runtime id arrives inside the activation bundle, the bind is a candidate
socket Idunn hands down, and the state root is an admitted workload path.
A service that also names them from its own environment is a second opinion
about facts it does not own.

runtime.rs already resolved the runtime id from the admission and kept
GHOSTLIGHT_RUNTIME_ID only as the unmanaged fallback. This is the caller side
catching up: main.rs accepts --state-root and passes it through, and the recipe
declares the state_root argument binding plus the three GAMECULT_IDUNN_*
variables while dropping the three the daemon no longer reads.

The binding is required, not cosmetic. Idunn refuses a stateful workload with
no state_root argument binding and refuses one whose binding disagrees with
the admitted root, so the recipe could not have deployed without it.

The acceptance harness kept its own GHOSTLIGHT_RUNTIME_ID; it is renamed to
GHOSTLIGHT_ACCEPTANCE_RUNTIME_ID so a test-supplied identity cannot be mistaken
for the managed one.

The mesh surface test compared the published record against a freshly built
surface, including updatedAtUtc, which is a live timestamp. It now asserts the
structural fields, parses the timestamp, and compares surface and commands.

cargo test --workspace: 89 passed, 0 failed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 01:24:08 +02:00
Meta Vens
1569d3f141 Declare Ghostlight Idunn deployment recipe 2026-09-02 21:43:26 +02:00