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>
64 lines
2.6 KiB
Markdown
64 lines
2.6 KiB
Markdown
# Persistence Spine
|
|
|
|
Ghostlight's machine-managed state is moving behind a small CultCache-style
|
|
persistence layer instead of letting every tool paw raw files directly.
|
|
|
|
The Python port is `cultcache-py`, published by CultLib to PyPI and pinned in
|
|
`tools/requirements.txt`. It used to be vendored as the `vendor/cultcache-py`
|
|
git submodule against the now-retired standalone `GameCult/cultcache-py`
|
|
repository; PyPI distribution replaced that fork.
|
|
|
|
## Current Store
|
|
|
|
- Cache store: `state/ghostlight-state.cultcache.jsonl`
|
|
- Ghostlight seam: `tools/ghostlight_state_store.py`
|
|
- Library dependency: pinned `cultcache-py==0.2.0`, declared in
|
|
`tools/requirements.txt` and installed by `npm run state:bootstrap`
|
|
(an idempotent `pip install -r tools/requirements.txt`, wired as a `pre*`
|
|
hook ahead of `state:status` and `state:prepare-compaction`)
|
|
- Readable exports: `state/branches.json`, `state/evidence.jsonl`
|
|
|
|
The JSONL store is deliberate bootstrap plumbing. The package also exposes a
|
|
MessagePack store for environments that install the optional `msgpack`
|
|
dependency, but Ghostlight's state CLI must run on the bundled Python runtime
|
|
without global package assumptions.
|
|
|
|
For cross-runtime `DatabaseEntry` payloads, use `cultcache-py`'s
|
|
`define_database_entry_type(...)` formatter. It writes MessagePack arrays by
|
|
explicit slot key, preserves nil gaps for deleted/reserved fields, and uses
|
|
defaults for missing older slots. That is the wire-compatibility contract shared
|
|
with `cultcache-rs` and the updated CultLib MessagePack generator.
|
|
|
|
## Live Rule
|
|
|
|
New machine-managed state should go through registered document definitions in
|
|
`tools/ghostlight_state_store.py` or a successor module. Direct writes to
|
|
`state/branches.json` and `state/evidence.jsonl` are compatibility debt.
|
|
|
|
Human-readable exports remain useful because git diffs, handoff review, and
|
|
emergency recovery should not require decoding a cache file while the house is
|
|
on fire.
|
|
|
|
## Migrated Documents
|
|
|
|
- `ghostlight.branches.v0`
|
|
- global document
|
|
- exported to `state/branches.json`
|
|
- `ghostlight.evidence_record.v0`
|
|
- one record per evidence entry
|
|
- indexed by `type`, `status`, and `branch`
|
|
- exported to `state/evidence.jsonl`
|
|
|
|
## Expansion Path
|
|
|
|
Move compact control-plane state next:
|
|
|
|
- corpus coverage ledger metadata
|
|
- active fixture run manifests
|
|
- persistent reviewer receipt indexes
|
|
- compaction scratch registration
|
|
- branch and initiative run ledgers
|
|
|
|
Keep large corpora, generated artifacts, images, and full story payloads outside
|
|
the single state store unless they are represented by compact refs. A cache
|
|
file is not a warehouse just because it has pockets.
|