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>
234 lines
13 KiB
Markdown
234 lines
13 KiB
Markdown
# Ghostlight Instructions
|
|
|
|
## Project Purpose
|
|
|
|
Ghostlight is a research and implementation home for socially persistent
|
|
generative agents. The core problem is not "make an LLM sound like a person."
|
|
The core problem is building an architecture where personality, culture,
|
|
memory, masks, perception, and incentives can actually survive contact with
|
|
time, relationships, routine, tonal variation, and pressure.
|
|
|
|
This repo exists so those organs can live somewhere cleaner than a side chamber
|
|
inside another project.
|
|
|
|
## Canonical State
|
|
|
|
- Treat `state/ghostlight-state.cultcache.jsonl` as the CultCache-backed
|
|
persistence spine for machine-managed state records that have migrated.
|
|
- Treat `state/map.yaml` as the canonical human-readable project map.
|
|
- Treat `state/scratch.md` as disposable working memory for one bounded
|
|
subgoal.
|
|
- Treat `state/evidence.jsonl` and `state/branches.json` as readable export
|
|
surfaces during the persistence migration, not as the long-term direct-write
|
|
API. A direct write to either is silently reverted: every `add-evidence`
|
|
regenerates `evidence.jsonl` from the CultCache evidence document, so edits
|
|
and deletions that do not go through `tools/ghostlight_state_store.py` look
|
|
applied until the next append restores what you removed. Compaction means
|
|
replacing the store's evidence document through
|
|
`ghostlight_state.py compact-evidence --replacement <distilled.jsonl>`,
|
|
which archives every current record verbatim to
|
|
`state/evidence.archive.jsonl` first; the export follows.
|
|
- Treat `state/evidence.jsonl` as the distilled durable ledger of what was
|
|
learned, verified, rejected, or accepted.
|
|
- Treat `notes/ghostlight-implementation-plan.md` as the current implementation
|
|
plan for the larger organs.
|
|
- Update `state/map.yaml` when project understanding changes.
|
|
- Add evidence after meaningful research, implementation, verification, or
|
|
rejected paths, but keep it distilled. Routine "I just did this" proof
|
|
belongs in git history, commits, smoke artifacts, or targeted logs unless it
|
|
changes what the next session should believe.
|
|
- Do not turn notes, map, handoff, and evidence into four versions of the same
|
|
brain. Distinct jobs or bust.
|
|
|
|
## Important Paths
|
|
|
|
- Project root: `F:\Projects\Ghostlight`
|
|
- Canonical map: `F:\Projects\Ghostlight\state\map.yaml`
|
|
- Scratch surface: `F:\Projects\Ghostlight\state\scratch.md`
|
|
- Distilled evidence ledger: `F:\Projects\Ghostlight\state\evidence.jsonl`
|
|
- Branch ledger: `F:\Projects\Ghostlight\state\branches.json`
|
|
- Handoff summary: `F:\Projects\Ghostlight\notes\fresh-workspace-handoff.md`
|
|
- System map: `F:\Projects\Ghostlight\notes\ghostlight-current-system-map.md`
|
|
- Implementation plan: `F:\Projects\Ghostlight\notes\ghostlight-implementation-plan.md`
|
|
- Architecture rationale: `F:\Projects\Ghostlight\notes\architecture-rationale.md`
|
|
- State CLI: `F:\Projects\Ghostlight\tools\ghostlight_state.py`
|
|
- CultCache state seam: `F:\Projects\Ghostlight\tools\ghostlight_state_store.py`
|
|
- CultCache-Py dependency: pinned `cultcache-py==0.2.0` from PyPI, declared in
|
|
`F:\Projects\Ghostlight\tools\requirements.txt`
|
|
- CultCache state store: `F:\Projects\Ghostlight\state\ghostlight-state.cultcache.jsonl`
|
|
- Pre-compaction helper: `F:\Projects\Ghostlight\tools\ghostlight_prepare_compaction.py`
|
|
|
|
## Useful Commands
|
|
|
|
Use the bundled Python runtime if `python` is not on PATH. `npm run state:status`
|
|
and `npm run state:prepare-compaction` install the pinned `cultcache-py`
|
|
dependency automatically (a `pre*` npm hook runs `state:bootstrap` first, an
|
|
idempotent `pip install -r tools/requirements.txt`). A direct
|
|
`ghostlight_state.py` invocation does not go through npm, so run
|
|
`state:bootstrap` once per session before the first direct call:
|
|
|
|
```powershell
|
|
npm run state:bootstrap
|
|
npm run state:status
|
|
npm run state:prepare-compaction
|
|
& 'C:\Users\Meta\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe' '.\tools\ghostlight_state.py' add-evidence --type research --status ok --note '...'
|
|
& 'C:\Users\Meta\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe' '.\tools\ghostlight_state.py' add-branch --id branch-id --hypothesis '...'
|
|
& 'C:\Users\Meta\.cache\codex-runtimes\codex-primary-runtime\dependencies\python\python.exe' '.\tools\ghostlight_state.py' compact-evidence --replacement '.\distilled.jsonl'
|
|
```
|
|
|
|
## Build And Deploy Target
|
|
|
|
Ghostlight Dungeon ships to Linux on Yggdrasil. Yggdrasil is its build, test,
|
|
and production body: Idunn freezes an exact commit, runs the locked native
|
|
Linux tests, builds the daemon and web projection in pinned Linux containers,
|
|
and seals the release. Owning runbook:
|
|
`gamecult-ops/runbooks/ghostlight-dungeon-yggdrasil.md`.
|
|
|
|
You are almost certainly reading this on a Windows workstation. That is where
|
|
the shell is, not where the artifact runs. A Windows compile of a commit is not
|
|
evidence about the Linux release — toolchain, linker, filesystem semantics and
|
|
path handling all differ — and it is not the build the deploy path will use.
|
|
Build for the target, or let the deploy path's own builder do it, and say which
|
|
one you used.
|
|
|
|
## Session Bootstrap And Re-entry Protocol
|
|
|
|
On fresh session load, do this before wandering off into implementation:
|
|
|
|
1. read:
|
|
- `state/map.yaml`
|
|
- `notes/fresh-workspace-handoff.md`
|
|
- `notes/ghostlight-current-system-map.md`
|
|
- `notes/ghostlight-implementation-plan.md`
|
|
2. run:
|
|
- `npm run state:bootstrap` (installs the pinned `cultcache-py` dependency;
|
|
idempotent, safe to rerun)
|
|
- `npm run state:status`
|
|
3. restate the current next action from the persisted state before starting
|
|
edits
|
|
4. if the user only asked to rehydrate or reorient, stop after orientation and
|
|
wait for an explicit continue instruction instead of treating the persisted
|
|
next action as permission to start coding
|
|
|
|
After compaction, resume, or suspicious continuity loss:
|
|
|
|
1. rerun `npm run state:status`
|
|
2. reread `state/map.yaml` and `notes/fresh-workspace-handoff.md`
|
|
3. treat the persisted next action as authoritative unless fresh repo evidence
|
|
contradicts it
|
|
|
|
When context pressure is clearly rising:
|
|
|
|
1. stop broad exploration
|
|
2. narrow the active move to one bounded organ
|
|
3. persist map or handoff updates, plus distilled evidence only when the lesson
|
|
changes future belief, before the blackout lands
|
|
|
|
When the user says to prepare for imminent compaction:
|
|
|
|
1. immediately write hot live context from memory into a new
|
|
`state/scratch-compaction-<guid>.md` file before reading files, running
|
|
status checks, or doing tidy persistence work
|
|
2. run `tools/ghostlight_prepare_compaction.py` before editing persistence
|
|
surfaces
|
|
3. use its warnings as the checklist for map, handoff, scratch, evidence, and
|
|
git hygiene
|
|
4. update only the state that actually needs to change
|
|
5. after hot context has been folded into canonical persisted state, delete the
|
|
`state/scratch-compaction-<guid>.md` file so stale emergency memory does not
|
|
linger
|
|
6. run `tools/ghostlight_prepare_compaction.py` again after edits and scratch
|
|
cleanup
|
|
7. fix errors, address warnings, and commit the completed persistence pass
|
|
unless the work is deliberately mid-surgery
|
|
|
|
## Operating Discipline
|
|
|
|
- Steward persistent state as part of the work. If a lesson changes future
|
|
behavior, update the smallest correct memory surface before moving on; if a
|
|
memory surface is stale, duplicated, or making re-entry slower, cut or
|
|
consolidate it.
|
|
- Before substantial edits, restate the current mechanism and intended change.
|
|
- Prefer one clear hypothesis per iteration.
|
|
- Verify with checks that reflect the real goal, not just proxy success.
|
|
- Revert or discard changes that do not clearly improve the target.
|
|
- If the diff grows while understanding shrinks, stop implementation and switch
|
|
to diagnosis.
|
|
- Keep maps and prose together; do not replace useful maps with prose-only
|
|
explanations.
|
|
- Commit completed work before it rots in the worktree unless the task is
|
|
deliberately mid-surgery or the user asked to leave changes uncommitted.
|
|
- Push after major completed passes when a remote exists, unless the user asked
|
|
not to or there is a concrete reason to keep the commit local for a moment.
|
|
- Before handoff, compaction, or phase boundaries, sync `state/map.yaml`, add
|
|
distilled evidence when the lesson changes future belief, refresh
|
|
`notes/fresh-workspace-handoff.md`, and make the next action explicit.
|
|
- Treat `state/map.yaml` as a working memory map, not an archive. Preserve
|
|
current mission, live seams, boundaries, and next action; let git history,
|
|
evidence, and artifact files carry chronology.
|
|
- In documentation, describe the live system and current rule directly. Do not
|
|
write victory laps, scar tours, clever autopsies, or contrastive little
|
|
boasts about what the project no longer does. If a sentence congratulates the
|
|
design for not being a previous wrong design, cut it or rewrite it as a plain
|
|
current rule. If rejected history matters, keep it short, explicit, and
|
|
decision-relevant; otherwise cut it. The docs are not a trophy case for
|
|
yesterday's wrong machine.
|
|
|
|
## Aetheria Grounding Doctrine
|
|
|
|
- Before writing or generating Aetheria scenes, check AetheriaLore for the
|
|
factions, movements, institutions, species or body types, location, and time
|
|
period involved.
|
|
- Before drafting story prose, choose an intentional tonal mode or blend for the
|
|
scene. Aetheria should support wit-with-stakes, warmth, absurdity, domestic
|
|
texture, ritual quiet, wonder, horror, noir, dour poetry, and dry systems
|
|
prose as needed. Do not default to constant crisis or procedural severity.
|
|
- Use Adams/Pratchett-style comic precision and humane levity as a useful
|
|
default touchstone when no stronger scene-specific style is called for:
|
|
jokes and absurdity should reveal stakes, not dissolve them.
|
|
- Establish ordinary life before interruption when the fixture calls for it:
|
|
routines, work texture, relationships, private jokes, rituals, small desires,
|
|
and local accommodations are part of worldbuilding, not filler.
|
|
- For illustrated Ink fixtures, segment prose into click-through visual
|
|
sections. Distinct places, focal areas, object closeups, arrivals, alarms,
|
|
pivotal one-sentence beats, and aftermath states need stable visual scene ids
|
|
and imagegen-ready prompts.
|
|
- Treat visual artifacts as illustrated replay and website collateral, not core
|
|
social-model training signal. Visual review judges the playable Ink
|
|
experience plus the visual plan, not clean-run prose receipts.
|
|
- Write visual prompts for a general image model, not a lore expert. Explain
|
|
fictional objects and body affordances in visible terms: geometry, materials,
|
|
lighting, stance, interfaces, tools, supports, cables, fluids, screens, and
|
|
crowd positions.
|
|
- Do the same for environments. A location label like "manifold line," "cavity
|
|
yard," "supervisor glass," or "anchor rail" is not a drawable scene until the
|
|
prompt describes its visible geometry, materials, interfaces, lights, and
|
|
scale.
|
|
- If a fixture has a target visual style, store that style cue once in the
|
|
sidecar and include it in every assembled image prompt. Do not rely on memory
|
|
or unstated website context to carry the look.
|
|
- Do not treat a character name as a visual description. Illustrated fixtures
|
|
need stable character visual refs for every recurring named character, and
|
|
scene prompts should either include those refs during prompt assembly or carry
|
|
enough appearance detail to stand alone.
|
|
- Include visual character refs only for characters actually visible in the
|
|
rendered frame. Do not feed imagegen refs for absent, off-frame, merely
|
|
mentioned, or object-represented characters.
|
|
- Treat visual continuity notes as tool/reviewer constraints, not prompt text.
|
|
If imagegen needs the fact, rewrite it as concrete visible description in the
|
|
base prompt, character ref, or branch/state modifier.
|
|
- Treat generated environment images as concept and material reference, not
|
|
spatial truth. Multi-angle or branch-consistent illustrated IF needs a durable
|
|
scene-set source such as a hand-built blockout, procedural scene file, layout
|
|
asset, or camera map. Imagegen can paint over camera-specific visual input;
|
|
it should not be asked to preserve room topology from a prior generated
|
|
image or text memory.
|
|
- Ground scene writing in the source's material details: habitat form,
|
|
infrastructure, law, class pressure, money, route access, surveillance,
|
|
communication channels, body affordances, and local failure costs.
|
|
- If the source is too vague for a concrete scene detail, do not bluff. Mark
|
|
the lore gap, patch the AetheriaLore source with a narrow elaboration, then
|
|
regenerate or revise the Ghostlight artifact from that patched source.
|
|
- Treat this as part of data generation. Ghostlight is expected to stress-test
|
|
Aetheria at room scale, find missing granularity, and push useful
|
|
elaborations back into the lore vault.
|