Commit graph

1,083 commits

Author SHA1 Message Date
Meta Vens
ab95d7897c Name the library's test subject human, not player
Players are a Dungeon concept. The library's own term for a
human-controlled subject is ControllerMode::Human, so its test code now
says so: the principal fixture player() becomes human_principal() (a
local `human` subject binding in action.rs would shadow a bare human()),
and the genesis subject handle, labels, principal address, variables and
one test name follow:

- "player" handle -> "human"; "The Player" -> "The Human";
  "Another Player" -> "Another Human";
  "player@example.test" -> "human@example.test"
- player_opportunity, after_player, genesis_player ->
  human_opportunity, after_human, genesis_human
- draft_activation_player_and_autonomous_actions_share_one_reducer ->
  draft_activation_human_and_autonomous_actions_share_one_reducer

Test code only: no production code, schema string, serde name, pinned
digest or fixture file carried any of these values. The library test
count stays 419 passed and 1 ignored.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 12:19:04 +02:00
Meta Vens
b14507c894 Pin the scope digest comparison to exact case and label
The stale-digest admission test now submits, besides the one-digit
forgery, the current issued digest with one hex letter uppercased, its
bare 64-hex value, and the same hex under a blake3: label. Each forgery
asserts its own premise before submission, and each must be refused as
ScopeChanged with revision, state digest, last commit digest and
operator-log length unchanged.

This kills the case-insensitive, hex-only (rsplit) and sha256:-stripping
mutants of the comparison in the kernel, which the previous eight tests
admitted, while the length, 7-character prefix and all-but-last mutants
stay killed. The cases extend the existing stale-digest test; the
external admission test count stays eight.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 12:14:52 +02:00
Meta Vens
af9c95a5bf Name the consumer, not Dungeon's session type, in library docs
SeedPort's evidence is minted by the consumer authenticating a live
principal, and a quarantined controller leaves WorldMailbox and its
consumer authoritative. Neither comment needs to know the consumer is
Dungeon's AppSession.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 11:56:55 +02:00
Meta Vens
9e514ebf15 Close InferenceRequest::provider_model to the crate
Its only caller is the SDK inference router inside the library, and no
consumer names it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 11:56:55 +02:00
Meta Vens
bde05de4e3 Refuse a digest shaped exactly like the real one
Both existing scope-digest forgeries differ in length from a real
`sha256:` + 64-hex digest, so a length-only comparison in
`exact_opportunity` passed every external admission test.

The new test takes two genuinely issued controller opportunities, lets
one subject speak (genesis places every subject in the commons, so the
telling lands as knowledge on the other and moves its scope digest), then
submits the listener's now-stale opportunity. It asserts the stale and
current digests differ and share a length, and that the submission is
refused with ScopeChanged and commits nothing.

A stale SHA-256 digest differs from the current one almost everywhere, so
it cannot catch a comparison that skips the last character. The test also
submits the current digest with only its final hex digit changed.

Mutants on the comparison, each killed: length-only, first seven
characters only, all but the last character.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 11:56:55 +02:00
Meta Vens
89eb75b6a7 Record the Cut 1 fix batch and Soul's verdict
The fix batch landed at 7c1d1e9..2865ea7: external rejection tests,
the minter check by name, Eve removed from library text, and a narrower
public surface. Soul confirmed the rejection tests drive the real kernel
path from outside the crate, that the unchanged-state assertions are
sound, and that Hands was right about what holds three types public.

Soul also found the digest check is pinned only by forgeries of the wrong
length, so a stale same-length digest from an earlier revision is going to
a fix. The minter scanner is still evadable five ways; since every text
scanner in this migration has lost to a short evasion, Q1-10 asks whether
Clippy's disallowed-methods should replace it.

Recorded, not fixed: rustc on stable does not enforce compile_fail error
codes, the world_id check is redundant by construction, and the decline
path is not reachable from an external test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 11:47:08 +02:00
Meta Vens
2865ea738d Close the two snapshot rows Dungeon never reads
An item stays pub only when the compiler requires it for an API Dungeon
calls. WorldSnapshot's resources and routes fields were pub, which forced
ResourceSnapshot and RouteSnapshot pub; Dungeon reads neither field and only
the library's own controllers do. The fields and both types are now
pub(crate). The workspace builds with the same unique warning set.

Every other bare-pub identifier Dungeon never names was closed one at a time
under cargo check --workspace --all-targets. Each either fails to compile
because Dungeon or the admission tests use it through a public path, or adds
a private_interfaces warning from a public enum variant field or method that
Dungeon does use (KernelError, CommandBody, CausalBoundary, RefKind,
ControllerWorkCustody, NarrativeCheckpoint, WorldMailbox), or strands library
code as dead. Those stay pub.

ScopeDigest, WorkLane and ScopeComponents are in the second group: the
warnings come from KernelError::ScopeChanged, ControllerWorkCustody::Uncertain
and the NarrativeCheckpoint variants. NarrativeInterruption's
bound_scope_digest and fresh_scope_digest return &str, so they never forced
ScopeDigest open, and Dungeon calls both at runtime.rs:1286-1287 and
2022-2023, so they stay pub too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 11:13:56 +02:00
Meta Vens
7cbb9e37a6 Say what the library means, not who consumes it
Four error strings and four comments named Eve, which is a consumer's
interface and not a concept the kernel has. The errors now say what they
refuse — a command ID, an opportunity, persisted controller work — and the
comments name an operator interface or a consumer's payload.

Nothing pins these strings: the four `#[error(...)]` literals appear only at
their definitions, and no test reads a `Display` of them.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 10:59:31 +02:00
Meta Vens
fac90e6f4b Follow the minter by name, not by one literal
The old count read one non-recursive directory, split each file at one exact
`#[cfg(test)]\nmod tests {` marker, and counted one literal. Soul walked past
it with an alias; a qualified `<T>::new(`, a file in a subdirectory, and a
production item placed after the test module walked past it too.

The check now walks `src` recursively and removes what each `#[cfg(test)]`
attribute guards by its own extent — balanced braces for an item with a body,
the first `;` or `,` outside parentheses for one without — so a renamed test
module is stripped and nothing after it is hidden. Construction is recognised
by scanning what follows the type's name, which admits `<T>::new(` and any
whitespace, and the one site found must be this owner's file.

Following the type by name means production may not give it a second name: an
`as` import or a type alias is refused outright rather than counted. What the
check still cannot see is a call that never spells the type, such as a macro
expansion or a generic instantiated elsewhere.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 10:59:31 +02:00
Meta Vens
a8d3377072 Prove admission from outside the crate
Q1-9 rules the seal as unforgeable admission rather than unconstructible
values, so the proof belongs where a consumer stands. An integration test
compiles as its own crate against the public API alone; these seven mint
their forgeries through serde, which visibility does not gate, and assert on
the typed error rather than on any message.

Six rejections — a forged scope digest, the digest string the deleted
ScopeDigest::fixture used to produce, a forged controller ID, a minted
SubjectId, a minted AffordanceId, and a wholly deserialized opportunity —
each assert that revision, state digest, last commit digest and the operator
log's length are unchanged. One control commits through the same port with an
issued opportunity, so the rejections cannot be an inert harness.

No manifest change: serde_json, uuid, chrono and tokio are already library
dependencies, and Cargo gives test targets a package's dependencies as well
as its dev-dependencies. No new production dependency and no feature.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 10:50:35 +02:00
Meta Vens
7c1d1e96fa Rule Q1-9: sealing means unforgeable admission
External code may hold a syntactically valid ID, digest or opportunity,
because Dungeon's Eve payloads deserialize them. What must hold is that
the kernel rejects every one it did not issue, proven by rejection tests
written from outside the crate. The compile_fail set stays for the
genuinely private items, with its limit stated: it pins a path name and
cannot see constructibility.

The target's first invariant now says that, so the claim matches what the
boundary does.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 10:42:25 +02:00
Meta Vens
af63b0cd13 Record Soul's verdict on the Cut 2 fix batch
The batch holds: whole-invocation pinning survives image swaps, line
swaps, re-indentation, continuation splits and appended flags; the order
checks catch a move into the reuse branch; the runbook is tied in both
directions; and a fail inside a command substitution does abort.

Soul then found the limit of the approach. An exact-line pin proves the
lines exist, not that they run: wrapping the block in `if false`, chaining
it behind `true ||`, or swallowing it in a heredoc keeps every pinned line
intact and the checker green. Abort on failure rests on an unpinned
`set -euo pipefail`, and a duplicated block passes unnoticed.

All three are recorded, not fixed. The script is a legacy actuator under a
do-not-invoke warning, retired at the deployment gate, and the authority
that really runs the tests is Ghostlight's Idunn recipe. Revisit only if
the gate keeps the script.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 02:57:01 +02:00
Meta Vens
8ddc1e86f3 Record the Cut 2 fix batch and its follow-ups
gamecult-ops 803f2c7 pins each of the four cargo steps as a whole
docker invocation, asserts the recipe order, and brings the runbook into
the wiring test. The four mutations that previously passed silently now
fail, and no pre-existing assertion was weakened.

The same defect class survives in three places outside this migration:
the web build container, the Codex Connector's cargo steps, and a fixed
18-line search window. All three are recorded as follow-ups.

Soul has not yet passed on the fix batch.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 02:47:28 +02:00
Meta Vens
e7d21013b9 Record Soul's Cut 2 verdict
The assertions Cut 2 added pin text, not invocations. Deleting the two
lines above the pinned cargo line turns it into trailing arguments on the
previous container: the kernel tests never run and the wiring test still
passes. Nothing pins the order of the four cargo steps, and the wiring
test never reads the runbook.

Those three are going to a fix batch. Two more are recorded, not fixed: a
redeploy of an already-sealed commit runs no cargo steps at all, which is
pre-existing deploy behaviour the operator owns, and the dated census docs
still show the old single-crate paths.

What held: the library step runs in the right branch with the same image
and mounts, its failure aborts the deploy, and the acceptance test path
resolves under the library crate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 02:40:45 +02:00
Meta Vens
1b409b3121 Record Cut 2 and the two spec defects it exposed
Cut 2 landed at gamecult-ops 6aba281: the library test step now runs in
the deploy script, is documented in the runbook, and is asserted by the
wiring test. Without it a deploy would run 50 tests and skip the 420
kernel tests that moved to the library crate.

Two defects in this map's own spec, reported by Hands rather than worked
around:
- the assertion it specified was vacuous, because require_text is a
  substring match and the given string is a substring of the
  persona-projection line;
- the acceptance test path lives in a variable the spec did not list,
  pinned by the wiring test and repeated in the runbook prose.

Changing the acceptance binding means sealed acceptance witnesses from
before this commit will miss and regenerate.

Soul has not passed on Cut 2 yet.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 02:35:06 +02:00
Meta Vens
880c9656ad Record Cut 1 and Soul's verdict; sync the stale surfaces
Cut 1 landed at 108b691..f859d2c. Soul reran the builds, tests, census and
mutations itself and confirmed the behavior-unchanged claim; it found six
defects.

F1 is the one that matters: the seal is name-based. Public ID types,
ScopeDigest and DecisionOpportunity all derive Deserialize, so an external
crate can mint them from JSON and rebuild the fixture path ruling Q1-4
said must be unreachable. The reducer still rejects forged opportunities,
so kernel integrity holds while the invariant's wording does not. Q1-9 asks
the operator whether sealing means unforgeable admission or unconstructible
types.

F2 (bypassable minter count) and F3 (71 unused public items) are queued for
the fix batch. F4 names Eve in library error strings. F5 and F6 are
recorded, not fixed.

The map, map.yaml and the handoff now say the kernel is the ghostlight
crate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 02:27:09 +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
108b691015 Move the world module to crates/ghostlight
Pure `git mv` of the thirteen files under
`crates/ghostlight-dungeon/src/world/` into `crates/ghostlight/src/`, with
`mod.rs` becoming `lib.rs`. No byte of any file changes; all thirteen are
detected as renames so history follows.

This commit does not build. The crate graph has no `ghostlight` package yet
and `ghostlight-dungeon` still declares `mod world;`. The next commit adds
the manifest, the public boundary, and the consumer rewrite; the two are
pushed together.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 01:32:21 +02:00
Meta Vens
6ddabcad33 Record the L0 rulings; close the fixture question
Rulings Q1-1 through Q1-6 are in the map's status header. The crate is
`ghostlight`. The Vault reader and the SDK port go in the library. The
library owns the principal evidence type. The persona projection crate
stays separate. The gamecult-ops cargo lines are edited, not retired,
and editing them is not an endorsement to run those helpers.

Ruling Q1-4 asked for the Dungeon tests that need sealed fixtures to move
into the library. Classification found none to move: all five are Dungeon
runtime tests. Two further rulings close it instead:
- Q1-7: the inference port's value constructors become the port's public
  contract and the five fixtures are deleted.
- Q1-8: the cover ordering test derives its cover from a real world, and
  the last fixture reaching a sealed ID constructor is deleted.

The sealed ID issuers and ScopeDigest::fixture stay private under every
configuration, with no feature gate anywhere.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 01:27:37 +02:00
Meta Vens
02bbf62eb1 Map the library extraction cuts
The Imagination pass maps plan step 15 L0 against d83534c:
- Cut 0: base captures (469 bin tests, and a world.cc written at base).
- Cut 1: a single Ghostlight commit that moves world/ into a library
  crate with the exact public boundary (compile_fail doc tests prove the
  sealed items) and a test-support feature for cross-boundary fixtures.
- Cut 2: the gamecult-ops cargo invocations.

The map was probed with scratch cargo checks on the Windows workstation,
so it proves Windows only. Six operator questions are open. No code has
moved.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 23:27:03 +02:00
Meta Vens
d83534cf38 Write the library extraction target; merge conflicting boundary records
Plan step 15 pass L0 extracts the world kernel from crates/ghostlight-dungeon
into its own library crate. The new target document lists the invariants
that must survive:
- sealed kernel visibility at the crate boundary;
- no change in behavior, schemas, or stores;
- no Dungeon concepts or dependencies in the library;
- a working release path;
- unaffected pins;
- bounded build fan-out.

It also lists the questions Imagination must bring back.

Two evidence records from 2026-09-15 disagreed about focus and whether the
extraction and title decisions were settled. They are now one boundary
record. The title correction now points at the ontology doc's lens section.
The compaction archived the previous records verbatim.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 22:57:01 +02:00
Meta Vens
e19c9d9bda Replace focus with typed detail rules; ship titles as stock lenses
A detail rule is a function from place to detail level. Each consumer
chooses its own level-of-detail rule. Dungeon uses ByDistance anchored on
important subjects, the player first. Delvehold starts from Uniform.

Rules are typed world data that the library evaluates, not consumer code.
The deficit a rule produces is an admission input, and journal replay
re-runs reduce, so a changed consumer function would break committed
history. WorldScaleIntent per-kind targets remain the ceiling a rule
distributes.

The eight titles move into the library doc as the stock lens set. The
kernel extraction is ordered as plan step 15 pass L0, ahead of every
library pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 22:55:18 +02:00
Meta Vens
3d5fe83708 Keep Session Zero in Dungeon; spec the library capabilities it consumes
Ghostlight Dungeon is a consumer of the Ghostlight library. Session Zero,
Vault choice, players, sliders and starting locations are Dungeon authority
and do not shape the library.

The ontology doc gains consumer-neutral library targets: elaboration
lenses with weights, focus-weighted demand with a consumer-supplied detail
profile, one evidence source bound per world, and elaborator sessions in
Draft. The Session Zero doc now carries only Dungeon policy that consumes
those capabilities.

The map records the boundary as a hard rule. The plan splits into library
passes L1-L4 and Dungeon passes D1-D3. Two decisions stay open: extracting
the kernel from crates/ghostlight-dungeon, and whether the eight titles ship
as a library stock lens set.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 22:46:54 +02:00
Meta Vens
038632d1dd Align remaining doc lines with titled lenses and Session Zero
The memory steward found four leftover lines. The plan and the ontology
doc now describe elaborators as lensed sessions, not eight fixed
instances. The handoff no longer says there is no Session Zero. The
ontology doc notes that Session Zero stops declaring the human at the
genesis commons.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 22:34:39 +02:00
Meta Vens
25ff91f08d Restore the titled elaborators as lenses and design Session Zero
The eight titles (Patina, Charter, Ledger, Hearth, Tangle, Veil, Ember,
Numen) were deleted with their titled verifier and quotas, and no operator
decision covered them. The ontology doc and evidence record 6 now say the
tribunal was the verifier and the quotas, not the titles. A new correction
record carries the history and the 2026-09-15 direction.

Session Zero is the player's path through a world's Draft phase. The player
chooses a Vault, describes the experience, and sets title weights. The seed
lane sketches the world and the player chooses a start. A swarm then draws a
title by weight for each session and elaborates by travel distance from the
player, before and after activation. It is plan step 15, and its fifth pass
closes the playtest gate.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 22:33:21 +02:00
Meta Vens
705d298f91 Make the local playtest the next gate; correct stale map claims
The playtest gate goes ahead of the outbound consumer batch. The handoff
defines it and lists the walls found in source. The map no longer claims
co-op for up to eight players on the rebuilt kernel. It points the economy
spec at GameCult/Njordr and says CultCache comes from CultLib, not a
vendored copy.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 22:10:52 +02:00
Meta Vens
a306feda4d Clarify connector constraint in map
The Claude SDK sidecar is the only live provider. Backends share one
standardized CultNet connector API with Epiphany; CodexConnector is isolated
and not live here; a generic OpenAI-compatible connector gates third-party use.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-14 23:06:40 +02:00
Meta Vens
cc016ffb55 Name CultLib as the home of the TypeScript CultNet client
The contract doc still pointed at the standalone GameCult/cultnet-ts repo,
which is being removed. The client is the cultnet-ts package in CultLib.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 16:47:39 +02:00
Meta Vens
59bbe85875 Keep the world elaboration record and first-generation world fixtures in Ghostlight
The elaborator swarm's GitHub branches were removed after verified bundling,
but its output is still wanted: the operator will integrate ideas into the
lore vaults as time allows. The durable record now lives in the repository
that owns the obligation instead of a Codex task folder and deleted branches.

experiments/elaboration/ carries the reviewed additions packet (A2 and D1-D3
approved, A1 demoted, K1/K2/Z1-Z3 pending), the per-world reviews, the
2026-09-05 shortlist with its 20 full candidates, and the 92 per-pass idea
ledgers, with a README naming where the bundled vault additions are and how
to restore one. The four reviewer-accepted first-generation world fixtures
return from their deleted codex/world-* branches to examples/ and
prompts/image-generation/ beside the existing fixtures. The map and handoff
point at the new home.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-13 16:35:03 +02:00
Meta Vens
22937b71f0 Replace vendor/cultcache-py submodule with published PyPI dependency
CultLib's packages/cultcache-py is now published as cultcache-py==0.2.0 on
PyPI (MIT), so the standalone GameCult/cultcache-py fork that Ghostlight
vendored as a submodule is retired. Symbol-for-symbol and on-disk-format
verification against the pinned submodule commit 9b4bbb8 found no
incompatibility: every symbol tools/ghostlight_state_store.py imports
(CultCache, JsonLinesBackingStore, define_document_type) and every method it
calls kept its signature, and JsonLinesBackingStore's on-disk JSONL envelope
fields and sort order are unchanged, confirmed by a real round-trip against
Ghostlight's production state/ghostlight-state.cultcache.jsonl.

tools/ghostlight_state_store.py no longer pushes vendor/cultcache-py/src onto
sys.path; it imports cultcache_py directly. Since Ghostlight's session
bootstrap previously depended on the submodule needing no install step,
tools/requirements.txt now pins cultcache-py==0.2.0 and npm run
state:bootstrap (pip install -r tools/requirements.txt, idempotent) runs as a
pre-hook ahead of state:status and state:prepare-compaction; AGENTS.md's
Session Bootstrap protocol and Useful Commands section call it out explicitly
for the direct ghostlight_state.py CLI invocations that don't go through npm.

Verified for real: `python tools/ghostlight_state.py status` and `python
tools/ghostlight_prepare_compaction.py`, run from a venv with cultcache-py
installed from PyPI, against Ghostlight's actual production state file (22 ok
findings, 2 pre-existing unrelated warnings, exit 0 both times).

Idunn's deployment/idunn/recipe.toml never declared vendor/cultcache-py in
required_gitlinks (only vendor/eve) and its build/test/service steps never
touch Python state tooling, so no recipe change is needed for admission.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-13 16:08:19 +02:00
Meta Vens
9574bf53d7 Point the economy spec at GameCult/Njordr
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 18:29:10 +02:00
Meta Vens
78e54554b8 Njordr: discovery as a producer policy, retooling as a recipe, catalog generation plan
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 18:15:15 +02:00
Meta Vens
4d1040ece0 Njordr: sources are finite deposits, materialized as mining
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 17:58:46 +02:00
Meta Vens
cc85db847c Njordr: roles are filled by lots, properties may be curves over conditions
The heat spreader is a role; copper, a vapour-chamber part, or anything
else fills it by its properties alone. A property value may be a curve over
an operating condition, so a part that fails hot fills a cool recipe and
not a hot one. No optional roles, no alternate recipes.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 17:44:08 +02:00
Meta Vens
b6c2ccd697 Njordr: demand as rates, derived intermediate demand, admission over provenance, producer policies
Player activity moves prices both up and down the recipe graph: consumption
is a lot sink so floods find a floor; producers' planned inputs are derived
demand so crashes propagate to inputs; markets admit or refuse lots by
provenance so a diverted shipment re-enters through a black market; corners
are bounded by the scoring rule and answered by supply. Seeding guarantees
every market is served or marked unserved as a fact.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 17:31:42 +02:00
Meta Vens
c077174264 Njordr: market maker settled, no Delvehold surface to cut against
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 17:19:49 +02:00
Meta Vens
e2aeb972bd Njordr owns the economy whole, Delvehold interior included
Greathold recipes, facilities, inventories, orders, and prices are Njordr
lots, recipes, markets, and quotes; Delvehold civic organs author policy as
demand rows and carrier policies. Unity embedding settled as the Rust engine
over a C ABI. The integration note's Delvehold-owner line is marked
superseded.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 15:54:23 +02:00
Meta Vens
d415101fa1 Njordr: engine and shell, seeded single-player mode
The engine is a pure deterministic step function over a state document and
an exogenous event stream it cannot attribute; the shell is the daemon.
Single-player Aetheria hands over the engine state and an event script,
never precalculated prices, so player choices stay live against the story.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 15:45:24 +02:00
Meta Vens
ced6d89b98 Njordr: name the repository spelling
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 15:28:50 +02:00
Meta Vens
b1167cce67 Njordr: shipments, two consumer profiles, dimensions settled
Economic flow is materialized as shipments a player can meet. Aetheria's
interspersed profile adds materialization, interception against a revision,
and per-zone cadence; Delvehold keeps the boundary profile. One ledger, one
quote function; only the subscription grain differs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 15:28:26 +02:00
Meta Vens
6133461d8e Spec the GameCult economy daemon
Dimensions, materials, lots with provenance, recipes as roles, products as
property vectors; markets as Ghostlight mirrors; prices as a pure function
of committed state; both directions through the consumer contract. The
economy owner is the consumer that owns a world's market mirrors.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 15:04:28 +02:00
Meta Vens
d5cbc45a87 Map: name the span rule beside its schema pin
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 14:34:35 +02:00
Meta Vens
4406008b3c Record run 12: every cited span lands
Runbook row 12, evidence record, schema pins in map and handoff moved to
controller_work.v15.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 14:34:20 +02:00
Meta Vens
855727f8a4 Take a turn's address as its spans in prose order
The Interpreter was citing correctly and the fold was discarding: an
utterance split by narration lost its second half and a turn's second
visible act became an ambiguity gap. Every span cited for a kind now joins
that kind's one statement in prose order; only an overlapping span is an
ambiguity. NarrativeCapture carries the spans, the invocation still carries
one utterance and one display. controller_work.v15.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 14:20:27 +02:00
Meta Vens
d0c047f375 Record run 11: the interrupted cell, logged per cell
Runbook row 11 and the interrupted-cell section, evidence record, map and
handoff advanced: next is the outbound consumer batch.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 14:12:26 +02:00
Meta Vens
81a1f53c2e Report the interrupted cell: subject and both scope digests
A committed turn that re-lowered once carries its pair of scope digests on
the receipt; the cover tick logs it per cell and keeps it on the tick
summary, and the smoke harness prints one "interrupted cell" line per
re-lowered cell after the tick line. The operator feed line shows a display
beside or instead of speech.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 14:00:40 +02:00
Meta Vens
4ef5f71397 Record run 10: the first displays and the first live interrupted cell
Runbook row 10 and the interrupted-cell section; plan step 14 landed;
evidence record; map, handoff, and scratch reconciled (schemas v4/v14,
thirteen components, next action is the per-cell interrupted log line).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 13:34:09 +02:00
Meta Vens
0582321e2c Let a person be seen: nonverbal display by quote
An invocation may carry a display, the actor's own visible sentence, beside
or instead of its utterance. The kernel lowers it as speech's twin: an
AssertClaim and a Display whose room is re-derived at apply, landing
Seen { by } on everyone standing in the actor's place and on nobody else,
never over a channel. A speech-carrying entry given a display alone is an
address, not SpeechRequired; an empty display is EmptyDisplay; a placeless
actor has no room. The Interpreter gains a display tool quoting the visible
clause alone; the narrative capture carries both spans; the fold allows one
of each. Overheard rows and Projector knowledge rows say how a thing was
perceived: said by, seen doing, or known. The journal's event-shape rule
counts both lowerings. Kernel-only lowering: no patch tool, catalog stays
thirty. Schemas: world_state.consumer.v4, world_commit.consumer.v4,
controller_work.v14. Six tests pin the room, the silence, the refusals,
replay, the fold, and the interruption block.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 13:21:53 +02:00
Meta Vens
29ecae7613 Give plan step 13 its own heading
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 12:59:45 +02:00
Meta Vens
5885eff5b6 Map step 14: nonverbal display by quote
A visible act becomes Seen { by } knowledge on the co-located, kernel-lowered
from the invocation beside speech, quoted by the Interpreter as the visible
clause alone. Intent stays private. Authority map, cut line, budgets,
verification, and the three operator decisions are in the plan; map,
handoff, and scratch point at it. Not built.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-11 12:51:33 +02:00