Commit graph

945 commits

Author SHA1 Message Date
Meta Vens
40e4efcc18 Make the affordance grant structural in exercise
`action::exercise` read `invocation.affordance` and looked the entry up
itself, with the grant check standing beside it in each caller. Pass 5 adds
a third caller, so the check becomes the type: `require_granted` now returns
a `GrantedAffordance` carrying the verified id and its catalog entry, and
`exercise` takes that instead of the raw id. Nothing in the pipeline reads
`invocation.affordance`, and no caller can reach it ungated.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 22:03:15 +02:00
Meta Vens
d589ea0578 Record pass 4 in the ontology doc and handoff
Current mechanism now describes passes 1 through 4; plan invariant 10
follows the scope-digest rule; steward folded the pipeline state into
the handoff and map. Emergency compaction scratch deleted.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 20:59:26 +02:00
Meta Vens
0f21a4900c Soul: falsify pass-4 bands, the shared catalog id, and journal-side forgery
Four test-only additions, plus one two-slot fixture entry:

- `soul_only_the_selected_bands_effects_are_committed` closes verification
  contract 10's discriminating case. The existing tests prove an empty band
  commits nothing and a one-slot entry lowers what it declares; neither
  separates a slot the proposer offered from a slot the draw admitted. The new
  `carry_split` entry declares two slots on disjoint bands, both proposed
  within ceiling, and each band is reached by searching for a command id
  before the envelope is built rather than by retrying commits.
- `soul_a_forged_band_or_effect_in_the_journal_dies_at_replay` names the layer.
  `verify_state_shape` bounds a band index and refuses effects under an empty
  band; it does not re-derive the draw. The forgery is re-digested into a
  contiguous chain and dies at `apply_committed_command`'s effect equality.
- `soul_a_shared_catalog_id_is_gated_by_the_scope_grant` pins that an
  affordance id names a catalog entry every grantee shares, so grant
  membership per scope is what gates: the same `convene` id commits for its
  grantee and is denied for a controller-driven scope that does not hold it.
- `soul_a_stored_role_spec_over_an_optional_subject_kind_round_trips` proves
  the adjacently tagged `RefKind` survives the `to_vec_named` path that a
  stored `RoleSpec { kind: Subject(None) }` writes through.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 20:40:41 +02:00
Meta Vens
f9cd0177e7 Affordances become world-authored catalog entries with preconditions, ceilings, and bands
An action stops being an enum the kernel understands and becomes a lookup into
world-authored data: preconditions over live state, magnitudes under declared
ceilings, one deterministic band, lowered into the same ResolvedOps the patch
path already applies.

Cut first, with no compatibility path: DecisionAction and its kind(),
AffordanceKind, the AffordanceGrant struct and the (scope, kind) uniqueness
scan, affordance_slug, validated_invocation and its three call sites,
KernelError::EmptySpeech and ::AffordanceMismatch, the seven-clause equality
chain in apply_effect's DecisionExercised arm, the grant-kind comparison in
replay, speak_invocation's parallel constructor, and all three hand-written
claims about what a subject may do (the available_tools prose, the
operational_tools schemas, and the typed view's speak permission literal).

WorldState gains affordance_catalog, the sole store of what an affordance is,
written only by admit_resolved from a resolved patch and validated only by
resolve_patch. affordance_grants collapses to a set per scope, so a duplicate
grant is unrepresentable rather than checked and derive_opportunities is a map
lookup. Declaration::Affordance authors an entry; a subject grants entries by
reference, so one genesis patch declares a catalog and grants from it
atomically. Speak is the kernel-built entry under an ordinary draft handle:
zero preconditions, zero slots, one empty band, one utterance.

world/action.rs owns the pipeline behind one entry point, exercise(), called
from both reduce and apply_effect so a forged effect is re-derived by the
function that produced the honest one. It binds roles, evaluates Present,
Reachable, and Holds, checks every slot against its ceiling, draws one band
through the existing digest() owner over a named BandPreimage, lowers the
selected band's slots through the bindings, and admits them through the same
resolver. Effects ride on the event and apply through apply_operations, so an
affordance's Transfer meets the same conservation equation as a declaration.
ActionMismatch is a sibling of Mismatch, complete, sorted, and never
serialized; it surfaces as KernelError::ActionRejected.

Binding and admission are two checks, not one. Binding is scope-digest
equality, and the digest now reads the granted entries' definitions. Admission
runs at commit against live state, so a route closing mid-flight is
TargetUnreachable rather than ScopeChanged, and a proposal is not invalidated
by distant traffic.

The OperationalAgent tool catalog, its prose signature line, and the typed
view's permission block are three projections of the granted entries, naming
affordance kinds and role parameters and never an affordance id.

State, commit, and controller-work schemas bump; a pre-pass store is refused.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 20:40:41 +02:00
Meta Vens
0ca51cf90a Extract apply_operations as the one owner of operation application and conservation
The seed/apply/accumulate/check_ledger sequence was inlined in the tail of
admit_resolved, which made declaration admission the only lane able to prove
custody conservation. Lift it verbatim into apply_operations, taking the
operations and the evidence list; admit_resolved calls it after its declaration
loops. No behaviour change.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 20:40:41 +02:00
Meta Vens
138ff69034 Bank compaction scratch; point the handoff at the Epiphany workflow lessons
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 20:40:02 +02:00
Meta Vens
94a87a8733 Hand the elaborator swarm to a successor; this session focuses on the kernel
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 20:10:49 +02:00
Meta Vens
9f0e417774 Name pass 10 (consumer ingress) and record the design pipeline for re-entry
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 20:05:18 +02:00
Meta Vens
bec8004bd9 Record pass 3 as landed on every steering surface
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 19:14:46 +02:00
Meta Vens
6a4f42a0bb Boundary doc: Ghostlight owns a conserved narrative ledger, Delvehold owns the economy
Pass 3 implemented Custody and conservation per the ontology; the Delvehold
consumer profile still assigned both to Delvehold. Transform at one-to-one
with no unit or rate field makes prices and recipes unrepresentable here,
which is the structural form of the boundary the profile wanted.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 19:06:43 +02:00
Meta Vens
d2805fe70d Soul: falsify pass-3 conservation, the apply-side ledger, overflow, and counterparty scope
Six test-only additions, no source change.

- soul_a_mixed_patch_conserves_every_resource_it_touches: the ledger equation as
  arithmetic over committed totals across transfer + transform + consume in one
  patch, plus the admit-only opening balance. Absence stays absent.
- soul_a_forged_sequence_dies_at_the_per_operation_check_not_the_ledger: answers
  the reachability question for the apply-side check_ledger. A forged
  PatchAdmitted carrying two transfers whose second exceeds what the first left
  dies at apply_operation's own precondition, one operation early. A conserving
  forged sequence applies. from == to and from_resource == into_resource are
  refused by their arms. A forged Admit still needs its receipt.
- soul_a_holding_cannot_overflow_silently: QuantityOverflow had no landed test.
  Two admissions summing past u64::MAX are the complete verdict; nothing mints.
- soul_an_incoming_transfer_changes_only_the_counterpartys_scope: the receiver's
  bound proposal is refused with ScopeChanged; an unrelated subject's commits.
- soul_replay_is_exact_after_every_custody_operation: replay covered only
  transfer. Transform, consume, and both bind targets now ride the same restart.
- soul_a_dependency_on_an_absent_or_wrong_kind_target_is_corrupt: the dependency
  shape clauses refuse a wrong-kind target, an empty target set, and an orphan
  holder key.

cargo test -p ghostlight-dungeon --bin ghostlight-dungeon world::
  97 passed, 0 failed, 1 ignored.
cargo test -p ghostlight-dungeon: 132 passed + 1, 0 failed, 1 ignored.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 19:03:59 +02:00
Meta Vens
48de96b0a4 ghostlight-dungeon: cut the duplicated incident-route scan, add Custody, Dependency, conservation, and evidenced admission
The cut first. `controllers.rs::typed_incident_routes` recomputed by hand the
same incident-route set `scope_digest` computed in `mod.rs`, two scans in two
modules held together by a comment. Both are gone. `mod.rs::scope_components`
is now the single owner of "what components does this subject's verification
read"; `scope_digest` and `snapshot` both consume it, and the controller view
reads `SubjectSnapshot.incident_routes` and resolves IDs against the snapshot.
`ScopePreimage`'s `position` and `routes` fields fold into one `components`
field. Three candidate mismatch names are refused before they exist:
`CustodyNotHeld` (absence is zero, so it is the boundary case of
`InsufficientCustody`), `DependencyTargetKind` (a target of the wrong kind is
`WrongKind`), and `DependencyDuplicate` / `DependencyNotBound` (an operation
that changes nothing is `NoOperationEffect`, which pass 2 already owns).

The addition.

- `WorldState` gains `holdings: BTreeMap<SubjectId, BTreeMap<EntityId,
  Quantity>>` and `dependencies: BTreeMap<SubjectId, BTreeSet<
  DependencyTarget>>`: subject-keyed partitions following `positions`, not
  `EdgeRecord` variants. `EdgeRecord`, `EdgeKind`, `ResolvedRoute`, and the
  seven accessors are untouched. Absence is zero at both levels, so no stored
  `Quantity(0)`, no empty inner map, and a duplicate holding is unrepresentable
  because a map key is unique.
- `Quantity(u64)`: unsigned, no unit, no maximum. Subtraction is `checked_sub`
  and fails as `InsufficientCustody`; addition is `checked_add` and fails as
  `QuantityOverflow`. No saturating arithmetic.
- `ComponentOp` and `ResolvedOp` gain `Transfer`, `Transform`, `Consume`,
  `Admit`, `Bind`, `Release`. `Transform` is 1:1 by construction: one `qty`
  spent and gained, so a ratio has nowhere to be written. No `ResolvedOp`
  carries a resulting balance; every arm re-derives its precondition from the
  committed partitions at apply time.
- `Mismatch` gains `InsufficientCustody`, `ZeroQuantity`, `QuantityOverflow`,
  `AdmitWithoutEvidence`, `SelfDependency`, and `CustodyNotConserved`, appended
  after the pass-2 variants so single-item assertions keep their ordering.
- `patch::check_ledger` is the one statement of conservation:
  `after == before + admitted + gained - consumed - spent`, over `u128`
  accumulators. `resolve_patch` seeds a fourth candidate map beside containers,
  routes, and positions, records each admitted operation's terms, and verdicts
  the ledger after the operation loop and before the emptiness gate.
  `admit_resolved` re-derives the same equation over the committed partitions,
  so a forged `PatchAdmitted` that reaches `apply_effect` without passing the
  resolver dies with `Invariant("custody does not conserve")`. `Transfer`
  contributes to no term: the equation proves it.
- Evidenced admission. `EvidenceRef` gains a constructor and crosses the
  facade. An `Admit` is valid when its ref is canonical text and the identical
  ref appears in the same patch's `evidence` list; otherwise
  `AdmitWithoutEvidence`. The kernel checks no store and no digest — retrieval
  and receipt authenticity belong to the retrieval organ — but the ref rides
  inside the digested, hash-chained commit, so it cannot be altered or dropped
  afterwards. There is no holdings declaration field: `Admit` with evidence is
  the only creation path, in every lane including genesis. Evidence is
  Draft-only, so `Admit` is Draft-only in this pass, with no second gate.
- Replay shape. Every `holdings` key names a canonical subject, every inner key
  a `Resource` entity at a nonzero quantity, no inner map empty; every
  `dependencies` key names a canonical subject with a non-empty set of
  canonical, distinct targets.
- Snapshot and typed view. `WorldSnapshot` gains `resources`;
  `SubjectSnapshot` gains `holdings`, `dependencies`, and `incident_routes`,
  all the acting subject's own. `typed_view` gains a `holdings` block with
  labels resolved only for what this subject holds, and a `dependencies` block
  carrying target kind and ID with no label and no target state. The
  hand-written `available_tools` string is unchanged; the derived tool catalog
  is a later pass.
- Schema bump to `ghostlight.world_state.custody.v1` /
  `ghostlight.world_commit.custody.v1` and the matching journal rows. A
  pre-pass store fails `recover` with an unadmitted row type. No migration
  adapter.

Deviations from the Imagination spec, each decided here:

- `resolve_place` generalizes into `resolve_entity(expected_kind)` rather than
  gaining a `resolve_resource` sibling. Two eight-line wrappers around one body
  bought nothing; the four place call sites pass the kind.
- Spec test 1 asks for a forged `Transfer` whose debit and credit differ.
  `ResolvedOp::Transfer` carries one `qty`, so that is unrepresentable — which
  is the outcome the shape was chosen for. The test proves the reachable
  forgery (a transfer the holder cannot cover leaves `holdings` byte-identical)
  and falsifies `check_ledger` directly beside it.
- Spec test 14 asserts against `verify_state_shape` rather than
  `verify_history`. Mutating a committed holding also breaks replay equality,
  so routing through `verify_history` would pass even with the shape clauses
  deleted.
- Spec test 11's visible half lives in `controllers.rs`, where
  `SelectedDecision` is, extending the existing typed-view non-leakage test;
  its kernel half is the world-level test of the same name.
- `EvidenceRef::new` is `#[cfg(test)]`. No `AdmitPatch` ingress exists yet, so
  every caller that builds a patch today is a test; the gate comes off in the
  same commit as the first production patch author. The type itself crosses the
  facade, as `ComponentOp::Admit` requires.

No external-owner field, no unit, rate, or recipe field anywhere, no new crate
or dependency, no compatibility shim.

cargo test -p ghostlight-dungeon --bin ghostlight-dungeon world::
  91 passed, 0 failed, 1 ignored (75 before this commit).
cargo test -p ghostlight-dungeon: 126 passed + 1, 0 failed, 1 ignored.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 19:03:59 +02:00
Meta Vens
db8eb0b2a7 Pass-2 follow-ups: dead presence check, RefKind derives, stamped world_id, stale imports and comment
Four cuts Soul named on pass 2, none of them behaviour changes.

- runtime.rs: delete the `source_version` presence check in
  `admit_controller_command`. It called `.ok_or_else(...)?` and discarded the
  value, so it validated nothing. The `expected_revision = source_version - 1`
  computation on the approve/activate path is untouched; that one still needs a
  caller-supplied binding.
- world/patch.rs: drop `Serialize`/`Deserialize` from `RefKind`.
  `RefKind::Subject(Option<SubjectKind>)` is an internally tagged newtype over a
  non-map, which serde refuses at runtime, so the derives were unexercised
  weight. `RefKind` is never persisted: it appears only in `Mismatch` (not
  serializable), the resolution index, and the three kind constants. Soul's
  `soul_ref_kind_is_not_a_serializable_shape` cannot compile as a negative
  without the derives it falsifies, so it is deleted; the doc comment on
  `RefKind` now carries the rule it was proving.
- world/mailbox.rs: document that `submit_stamped` stamps `world_id` as well as
  `revision`, and why — the mailbox owns exactly one world, so there is no other
  world a controller runner could mean. The consequence is that
  `WorldKernel::submit`'s `WorldMismatch` check is unreachable on this path;
  `soul_a_stamped_submission_still_fails_closed_on_a_foreign_scope` stays as the
  proof that scope still fails closed.
- world/mod.rs: `ComponentOp` and `RouteDeclaration` are test-only, so their
  import moves behind `#[cfg(test)]`.
  ghostlight-persona-projection: `opportunity_digest` no longer claims to bind
  "world state as one value"; pass 2 made it bind the scope digest.

cargo test -p ghostlight-dungeon --bin ghostlight-dungeon world::
  75 passed (76 minus the deleted RefKind test), 1 ignored.
cargo test -p ghostlight-dungeon: 110 passed + 1, 1 ignored.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 19:03:59 +02:00
Meta Vens
53f35afc31 Record pass 2 as landed on every steering surface
Handoff, map, scratch, and the ontology doc's current-mechanism section now
describe e99af63. The elaborator witness is corrected to 26 finished slot
passes. The worktree the steward saw at 8cad6b9 is the pass-3 Hands tree
before its reset to the tip, not an orphan.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 18:15:30 +02:00
Meta Vens
e99af63f9a Soul: falsify the pass-2 scope binding, topology admission, and replay
Ten test-only additions, no production source touched.

- mailbox: the end-to-end proof the kernel-level test does not give — a
  controller turn bound at revision N commits through the mailbox after an
  unrelated commit at N+1, and a stamped body still fails closed on a
  foreign scope.
- world: the scope preimage excludes revision, phase, a place declared
  elsewhere, a non-incident route, and another subject's Position, across
  real commits; a forged affordance list cannot widen authority.
- patch: RouteSelfLoop, UnplacedSubject, and NoOperationEffect are each
  reachable; a forged relocate effect dies at apply time on all three
  preconditions; RefKind is not a serializable shape.
- journal: forged store rows carrying a self-loop, an out-of-range cost, a
  non-place endpoint, or a stray position are refused by recover, and a
  pre-topology row type is refused outright.
- controllers: the typed view carries only the actor's own place and the
  routes incident to it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 18:10:34 +02:00
Meta Vens
24addfb21e ghostlight-dungeon: cut authority_scope and whole-world binding, add topology and scope digests
Cut: SubjectDeclaration.authority_scope and SubjectState.authority_scope with
their four production readers; DecisionOpportunity.state_digest and every reader
of it, including the kernel's whole-world gate, ControllerRunner::select's
struct-equality filter, PersonaTurnBinding.state_digest, the two runtime.rs
surface-freshness comparisons, and the caller-supplied envelope revision for
opportunity-bearing commands; EdgeKind's Relation, Commitment, and Pressure arms.

Add: a positions partition and Position, EntityRecord.container with containment
acyclicity over the complete candidate graph, Route written into the existing
edges partition with AccessKind, Cost, and an open flag, the four inhabited
ComponentOp variants, and resolve_patch as the one owner of declarations,
references, topology admission, and operation preconditions, closing the complete
mismatch set before the first ID mints. A proposal now binds the digest of the
components its verification reads -- controller assignment, grants, Position, and
incident routes -- so an unchanged scope commits at a later revision and a changed
one is refused with KernelError::ScopeChanged. Schema bumps to topology.v1.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 18:10:34 +02:00
Meta Vens
489913f171 Scheduling paragraph states scope-digest binding, not stale-discard
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 17:50:59 +02:00
Meta Vens
0f010de431 Record the four first-generation fixtures and the pass-2 worktree
Handoff and map carry the four world-branch tips and fixture commits, the
retired single-loop launcher, the live 32-slot scheduler, ontology tip
5e53beb with its follow-ups landed, and pass 2 in flight.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 17:22:45 +02:00
Meta Vens
5e53beb353 ghostlight-dungeon: one schema owner, genesis mismatch not journal fault, named ref fields
- Promote world::STATE_SCHEMA/COMMIT_SCHEMA to pub(crate) and add
  state_schema_compatibility_tag(), derived from STATE_SCHEMA, so mesh.rs and
  idunn_health.rs stop hand-copying "ghostlight.world_state.foundation.v0" and
  "foundation-v0" as second literals that had already drifted from the v1
  kernel schema.
- A CreateWorld patch that declares only entities now fails inside
  resolve_declarations with Mismatch::NoDecisionSubject instead of surviving
  admission and dying in journal::verify_state_shape as a
  CorruptJournal(requires_owner_restart) fault. Collapse the two hardcoded
  admits_human literals in prepare_creation and WorldState::genesis onto the
  same admits_human predicate the AdmitPatch lane uses (reshaped to take
  revision/subjects directly, since the genesis lane resolves before any
  WorldState exists).
- Mismatch::UnresolvedDraft and the draft-branch WrongKind now name their
  DraftHandle field referent; Mismatch::UnknownCanonical and the
  canonical-branch WrongKind now name theirs referrer. WrongKind carries both
  referrer: DraftHandle and referent: Ref<EntityId> so every construction site
  states which end each field names instead of overloading one `handle`
  field with two different meanings.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 17:13:10 +02:00
Meta Vens
f447f585ca Record pass 1 as landed on every steering surface
Handoff, map, scratch, and the ontology doc's current-mechanism section now
describe HEAD: patch.rs owns identity and closed resolution, AdmitPatch is
the Draft ingress, schemas are v1/v2, and the three Soul follow-ups are named
with their exact lines. Evidence records the sandbox lesson that supersedes
the clone-plus-network one: .git is read-only inside the writable root, so a
supervisor outside the sandbox commits and pushes per slot.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 17:05:48 +02:00
Meta Vens
4d95bb8cbd Ignore agent worktrees 2026-09-04 17:02:53 +02:00
Meta Vens
9ddc21f048 Soul: prove the store and apply_effect halves of closed resolution
Two falsification tests the pass-1 suite did not carry.

a_rejected_patch_leaves_no_row_and_no_id_in_the_store checks the durable
store, not the in-memory head: after the Run 115 rejection it scans the
.cc bytes for the three IDs the patch would have derived, then reopens
the world and re-asserts the snapshot, commit count, and empty entity
partition.

apply_effect_rejects_a_forged_stale_unauthorized_or_active_patch_effect
drives the PatchAdmitted arm directly. journal::a_forged_patch_effect_
does_not_apply dies earlier, at apply_committed_command's reduce
equality ("committed effect is not the deterministic reduction of its
command"), so nothing exercised admit_resolved's own re-validation. This
does: a jurisdiction naming an absent place, the honest effect replayed,
a non-owner caller, and the Active phase each return Invariant with the
candidate state untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 17:00:45 +02:00
Meta Vens
d74d6ad3d7 Close patch resolution before any canonical ID allocates
Cut: DraftSubjectHandle, validate_handle, NewDecisionSubject,
GenesisSubjectBinding, canonicalize_subjects, issue_genesis,
normalize_label, assignment_matches_new, the 116-line zip-and-compare
body of WorldState::genesis, the non-test SubjectId/ControllerId/
AffordanceId::issue bodies, and the KernelError variants NoSubjects,
EmptySubjectHandle, EmptySubjectLabel, DuplicateSubjectHandle, and
NoAffordances.

Add world/patch.rs: typed EntityId/EdgeId namespaces beside SubjectId,
Ref<Id> with draft handles, WorldPatch declarations, uninhabited
ComponentOp and PatchAnswer, and resolve_declarations as the one owner
of handle indexing, kind checking, reference resolution, and allocation
for both admission lanes. It returns the complete deterministic
Vec<Mismatch> and allocates only after that set is empty, so a rejected
patch mints nothing. IDs derive from sha256 over namespace, world ID,
command ID, and handle, which is what lets journal replay recompute
reduce() and require effect equality.

CommandBody::AdmitPatch and WorldEffect::PatchAdmitted join the reducer;
WorldCreated now carries the same ResolvedPatch payload, and both lanes
mutate through one admit_resolved. WorldState gains entities and edges
partitions, SubjectState gains authority_scope, and the state and commit
schema strings move to foundation.v1 and foundation.v2, which refuses a
pre-pass store rather than migrating it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 16:47:15 +02:00
Meta Vens
807ba24a89 Eight elaborators; the earlier line was already nine passes 2026-09-04 16:23:26 +02:00
Meta Vens
09a48ba191 Nine passes, not eight, in the handoff gate 2026-09-04 16:23:15 +02:00
Meta Vens
1e18c4f8e0 Record the pass-1 fan-out and the live test baseline
Handoff and map say pass 1 is in progress through faculty workers with maps
in the session scratchpad and nothing landed in crates; the baseline is
Speak-only with 43 world tests and 83 crate-wide at d87cad8.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 16:23:06 +02:00
Meta Vens
d87cad84c6 Record the clone-not-worktree lesson for Codex fan-outs
Linked worktrees put .git outside the Codex sandbox's writable roots; the
four world workers all died on index.lock. Handoff, map, and one evidence
record now carry the clone-plus-network rule and the relaunch witnesses.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 16:19:17 +02:00
Meta Vens
5599c164f3 Carry the scale directive into every steering surface
Handoff, map hard boundaries and scale checkpoint, and plan invariant 8 now
all state both truths: structural validity never waits on a count, and the
seed's WorldScaleIntent with its cover-budget choke is the operator's design
the elaborators pursue. The handoff carries the dated operator directive so a
future session cannot re-cut it as fixture noise.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 16:15:58 +02:00
Meta Vens
4ae1d6181d Restore the scale target as design, not load fixture
The operator's design is detail first, then a ten-percent choke: generate
goal-bearing actors at every level, then budget cells so attention is scarce
and selection is forced. The mvp doc's teardown-era sentence calling the
2,400-subject profile "test data, not a production elaboration target"
contradicted that and is amended. The ontology now carries an authored
WorldScaleIntent with a structurally counted deficit that elaborators pursue
after boundaries, a budgeted connected cover every tick with singleton detail
cells and grouped coarse cells, partitioned views and per-constituent
attribution in groups, and debt rotation. Gestalt as canonical identity,
arena knowledge union, and semantic qualification stay deleted. Plan step six
is nine passes; two proofs added; evidence records the correction.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 16:14:44 +02:00
Meta Vens
362c7539cc Name the scale mechanisms the gestalt cut kept
The multiresolution demotion undersold what survives. Coarse-by-construction
populations, deterministic clocks, debt-ordered scheduling, and batched
runner-owned representation with per-constituent attribution all carry many
subjects on few inferences without a second identity layer. Routine
commitments auto-fulfill on Time.advance so unattended ordinary life does not
default into spurious pressure. Two proofs added.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 16:08:01 +02:00
Meta Vens
dd23d7fcec Retire the revision-bound rule from active steering
The steward found stale-means-discard still asserted as the opportunity rule
in map.yaml live_architecture and plan invariant 11. Both now state
scope-digest binding as the adopted rule and name foundation.v0 as still
revision-bound until plan step 6 pass 2. Handoff and next_action carry the
v2 shape and the live worker witnesses.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 16:03:42 +02:00
Meta Vens
34ce8c8a63 Unify elaboration and action under one deterministic verifier
Ontology v2. Affordances become world-authored data over a closed
twenty-nine-operation kernel set: preconditions read the actor's own typed
components, effect slots bound what an invocation may propose, and kernel
entropy selects the outcome band so no model ever decides success. That
deletes the legacy wave-level outcome resolver along with the reconciler.
Proposals bind to the scope digest of the components their verification
reads instead of the whole state digest, so eight elaborator loops and many
subjects stop serializing on one revision. Elaborator tools are a projection
of the operation set and cannot drift from the reducer.

Demotes the multiresolution agency doc to teardown evidence, keeping only
resumable sessions, compact drafts, and the complete mismatch set. Plan step
six now lists eight passes with the affordance pipeline fourth.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 16:01:27 +02:00
Meta Vens
dc474be660 Correct re-entry steering after the fan-out
The steward found the handoff pointing at legacy Persona runners that do not
exist and a next gate that no longer matched the operator's orders; both
surfaces now carry the elaboration-ontology order, the world fan-out layout,
and the deferred deployment gate. The BFL script defaulted to a key path on
the lost E: drive. The consumer API doc is marked as drift pending rewrite
against the ontology.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-04 15:58:55 +02:00
Meta Vens
9c662bda23 Design the elaboration ontology
Run 115 died on a dangling reference, and the vocabulary is why. Legacy
transition.rs took caller-supplied SubjectRef{kind,id:String}, admitted
entities in two phases, and permitted mutations one at a time in a flat
batch, so a plausible-looking id was indistinguishable from a referent until
reduction. Reconciliation existed to repair that class and exhausted after
four steps. Depth lived in free strings, so the previous attempt to fix
shallowness grew model tribunals instead of structure.

The closed vocabulary: reducer-issued typed ID namespaces, draft-handle
references resolved inside one closed WorldPatch before any ID allocates,
twelve components that each constrain a decision, four derived CausalBoundary
kinds, and one AdmitPatch command shared by seed admission and boundary
elaboration. Twenty component kinds become twelve, eighteen mutation variants
become one primitive, five qualification and verification types become none,
and waves and quotas become derived boundaries.

Demotes the transition algebra doc to teardown evidence and slots the stage
into the implementation plan ahead of the deferred deployment cutover.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 15:39:17 +02:00
Meta Vens
99dc8b0ef9 Record the swarm triage
Every repo is clean and pushed. Two findings matter for the deployment gate:
Odin's recipe and the gamecult-ops operator bindings still declared gitlinks for
submodules the consolidation removed, so Idunn would have refused to admit those
targets. Both corrected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 15:17:04 +02:00
Meta Vens
cbb8a5c95a Odin consumes CultLib
27cc815 lands the repoint. The in-flight CultMesh work came with it because the
old CultMesh calls a CultNet method CultLib does not have, so it could not build
against CultLib at all -- established by reverting and watching it fail, not
assumed.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 14:56:04 +02:00
Meta Vens
d324da18bb CultLib main carries the consolidation
Landed by fast-forward at 8cb3b72. All four consumer pins verified as ancestors
of origin/main, so the revisions Ghostlight, Epiphany, CodexConnector and Odin
depend on resolve from a fresh clone.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 13:02:22 +02:00
Meta Vens
de8c5d327f Record the publishing decision for the non-Rust consumers
The TypeScript and Python forks existed because nothing was publishable, not
because the code diverged. CultLib now has a publish workflow, and the licensing
that would have blocked it is uniform.

Ghostlight's own repoint has a catch worth remembering: the state tooling puts
the vendored source on sys.path so it runs from a clone with no install step,
and session bootstrap depends on that.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 04:42:08 +02:00
Meta Vens
3f66a83869 Record the swarm-wide core-stack consolidation
Epiphany and CodexConnector now consume CultLib and carry no submodules, so
GameCult/cultcache-rs and GameCult/cultnet-rs have no readers left anywhere.

The survey's main finding is that the forks held far less than their number
suggested. Four of them held nothing CultLib lacks. What they mostly held was
reach: things CultLib had but did not expose. Each had simply pinned a different
branch of the standalone repos, which is the explosion that made separate repos
untenable in the first place.

The two remaining non-Rust forks are blocked on distribution, not divergence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 04:27:22 +02:00
Meta Vens
37dfb25929 Record the Odin repoint and the closed cultnet-rs gate
Odin no longer reads GameCult/cultnet-rs. Its CultNet submodule and CultCache
copy are gone; both come from CultLib, and vendor/cultmesh-rs is the only fork
left, itself consuming CultLib so one crate version spans the graph.

The forks were not pure duplication. A whole-file symbol comparison -- not a
diff of recent changes, which is what misled me the first time -- found four
capabilities CultLib lacked, all now ported with tests.

The Odin side is verified but uncommitted. Its one-line edit to
vendor/cultmesh-rs/src/lib.rs cannot be separated from 433 lines of in-flight
CultMesh work and an untracked module, so committing the repoint would mean
committing that feature on the operator's behalf.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 04:03:44 +02:00
Meta Vens
c80c323022 Re-anchor contract citations on CultLib 85f7024
Every live CultNet contract citation named `f4ab237`, which is not an ancestor
of CultLib main and survives only on the retiring standalone repo's branch.
They now name CultLib `85f7024`, which is both CultLib's current main head and a
permanent ancestor of it, so the citation survives every future advance --
something a branch SHA in a repo queued for deletion could never do.

Verified rather than assumed. At `85f7024`, packages/cultnet-rs carries
IDUNN_LIFECYCLE_BRAKE_* distinct from IDUNN_DEPLOYMENT_BRAKE_*,
IdunnProcessWriteLeaseRecord, GameCultRuntimeCapability, OdinTopologyDisagreement
with disagreements() and into_undisputed_present separating presence from
readiness, a generation-bound IdunnRuntimeActivationRecord with its own
activation-proof signing purpose, and IdunnExpectedRoute refusing non-rudp://
endpoints for RUDP routes. All six cited contracts hold.

Two of the eight citations were instructions, not descriptions, and a mechanical
swap would have been wrong. map.yaml's next action and the handoff's next gate
both said to advance Odin to CultNet `f4ab237` -- advancing it deeper into the
repo we intend to delete. Both now say to repoint Odin off its vendored CultNet
fork onto CultLib `85f7024`, as Ghostlight did at `d0510ac`.

Evidence records keep their pre-consolidation SHAs. They are dated statements of
what was believed, and the new record is the key for reading them.

This closes the citation half of the cultnet-rs retirement gate. Odin's vendored
CultNet gitlink is now the last reader of that repo.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 01:51:44 +02:00
Meta Vens
a338567230 Record the landed drift and the cultnet-rs retirement gate
Evidence for 751b5c4 and the provenance finding behind it.

While citing revisions I checked whether they resolve. CultNet `f4ab237` and its
predecessor `e542225` are not ancestors of CultLib main. Their content is on
CultLib `85f7024` -- verified by symbol, and Ghostlight compiles against it --
but the SHAs are not, because the consolidation ported commits forward instead
of merging them. They survive only on GameCult/cultnet-rs branch
codex/idunn-runtime-authority-contract.

That changes the retirement gate. Deleting GameCult/cultnet-rs was previously
gated on its content living somewhere else, which is now satisfied. It is also
gated on citation: every contract reference in this map, the handoff, both notes
and the evidence ledger points into that repo. Either re-anchor them on CultLib
`85f7024` or keep the branch.

Odin `65cf2b2` and `d527d72` are likewise off Odin main but sit on a pushed
branch, so they resolve from a clone and need nothing.

The vendor-retirement record carried a hand-written timestamp ten hours in the
future, which sorted it after work that actually came later. Corrected through
the store to 7e73504's commit time; the export follows. All 27 records intact.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 01:28:04 +02:00
Meta Vens
322cc116b0 Land the Idunn bootstrap rules and retire two superseded revisions
The system map and implementation plan carried uncommitted prose describing
Idunn's independent bootstrap, the Odin-outage freeze rule, and the nine-phase
durable transaction. That content is good and is landed here.

It cited CultNet `e542225` and Odin `d527d72`, which map.yaml and the handoff had
already advanced past to `f4ab237` and `65cf2b2`. A bare SHA bump would have been
wrong: both successors own strictly more. `f4ab237` adds routed RUDP incarnation
admission, and `65cf2b2` already lands the durable three-record transaction and
admitted-generation engine that this prose still described as the remaining cut,
along with the systemd isolation, Ready-provider selection, and protected
activation delivery it called uncommitted. The claims are corrected, not just
renumbered.

map.yaml carried the same superseded pair on its Idunn foundation line while its
contract line named the successors, so the canonical map disagreed with itself.

Evidence records keep their original revisions. That ledger says what was
believed when it was written, and editing it would falsify the history it exists
to preserve.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 01:26:08 +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
7e73504819 Record the vendored fork retirement
Ghostlight consumes the core stack from CultLib 85f7024 rather than holding
its own generation of the wire contracts outside the parity harness.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 01:13:55 +02:00
Meta Vens
d0510ac85b Consume the core stack from CultLib instead of forking it
vendor/README.md declared cultcache-rs, cultnet-rs and cultmesh-rs "a locally
owned compatible protocol generation". That charter is the defect. A consumer
holding its own generation of the wire stack sits outside the only harness that
checks cross-runtime agreement, and the fork behaved exactly as that predicts:
runtime_authority_contracts.rs drifted to e542225 while this repo's own
authority map named f4ab237, and the Rust CultMesh implementation existed
nowhere else in GameCult.

All three now come from CultLib pinned at 85f7024, and 19,604 lines of forked
substrate are deleted. Nothing was lost on the way out. The vendored cultnet
tree was compared file by file against CultLib: ten of twelve matched, lib.rs
differed only in module declarations, and transport.rs carried one guard that
existed nowhere else -- a framed length checked against the advertised maximum
before allocating. That guard is now CultLib 85f7024 with a test.

The migration this was expected to need does not exist. RuntimePresenceCorrelation
changing from enum to struct is Odin's side of the contract and no file here
touches it; with line endings normalised the two contract copies differ by 132
lines, and the only production change that reaches a provider is
IdunnExpectedRoute requiring rudp:// schemes for rudp transport, which this
service does not use. The code compiles unchanged.

89 tests pass across the workspace against the pinned rev.

vendor/ still holds the cultcache-py and eve submodules. cultcache-py is the
same pattern -- a runtime-specific repo CultLib also carries as
packages/cultcache-py -- but it backs the state tooling rather than the
daemon, so it is left for its own change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 01:13:24 +02:00
Meta Vens
5d852b76b0 Warn that evidence.jsonl edits are silently reverted
The existing rule said evidence.jsonl is an export surface rather than the
direct-write API, which is true but understates the failure. A hand edit does
not fail loudly; it survives until the next add-evidence regenerates the file
from the CultCache evidence document and restores whatever was removed.

An agent compacting the ledger would see a clean result, commit it, and have
it silently undone by the next append. Say so where the rule already lives,
since AGENTS.md is read before anyone reaches the store.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-04 00:28:50 +02:00
Meta Vens
79911a9ecc Record core stack ownership and the vendored fork
CultLib owns CultCache, CultNet and CultMesh for every runtime because wire
parity conformance lives only there. Ghostlight's vendor/README.md charters a
locally owned protocol generation, which is duplicate authority over the wire
stack held outside the harness that checks it -- and is why
runtime_authority_contracts.rs forked on whether Present may coexist with a
disagreement.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 22:45:59 +02:00
Meta Vens
ca7d7366e9 Wire AGENTS.md into Claude Code memory
Claude Code reads CLAUDE.md, not AGENTS.md, so this repo's doctrine was
invisible to it. This one-line import makes the existing AGENTS.md load
without duplicating or renaming it. Codex is unaffected.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 22:22:51 +02:00
Meta Vens
138b459ff8 Compact the Mind and purge the workspace
The evidence ledger had drifted from distilled to accumulated at 258 records.
235 were per-release and per-run receipts, self-consuming falsification chains,
and May fixture doctrine already owned by docs/architecture and map
hard_boundaries. They move to state/evidence.archive.jsonl.

evidence.jsonl is a regenerated export, not a writer: _export_evidence rewrites
it from the CultCache evidence document on every append. Compacting the export
alone would resurrect every archived record on the next add-evidence, so the
deletion goes through the store and the export follows.

Twenty-three records remain: the still-binding contracts (CultCache wire
format, agent_state.v0, cognition ceiling, image-geometry authority, sandboxed
coordinator, VoidBot appraisal, multiplayer extension, the Delvehold boundary
set, newspaper-as-Persona) and the whole rebuild era from Run 108 forward. A
multiplayer note recorded twice under different timestamp encodings is reduced
to one.

map.yaml and the handoff carried stale frontiers naming 13d5136 and a0b16b9.
Both now name 6a79cb0 and record what 9256648 and 6a79cb0 landed.

The worktree sheds 87MB of untracked debris: three Git bundles whose commits
are all ancestors of HEAD, ~60 legacy live-fire run scripts and sftp batches,
the forbidden redeploy helpers, downloaded run61-63 acceptance copies whose
authoritative roots remain on Yggdrasil and whose frozen copy stays digest-bound
in output/tex, a redb file created by a stray --help argument, and 71MB of tmp/
legacy campaign caches and newspaper renders. .gitignore now refuses all of it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-03 21:56:19 +02:00