This is the current forward plan for the next larger organs. It is not a changelog and it is not allowed to become a duplicate brain for the canonical map.
Stop feature work on moderation, mood, and self-state until the state boundary is rebuilt. The live product goal still stands: Void should answer Discord, remember useful social/project context, retrieve GameCult history/source/lore, and run an unattended moderation/participation loop. The current implementation reaches that goal through JSON projection edits, legacy mirrors, and a swollen memory organ. Most of the deterministic cleanup code is recent compensator cruft: it accumulated because the live state had exploded into nonsense, and repeated "clean this file" passes preserved the mess by adding machinery around it.
The next priority is to remove JSON from the mutation loop entirely and rebuild the state model so the compensator pile is unnecessary. Agents and scheduled workers should mutate typed CultCache-backed state through explicit tools/APIs, not by editing a whole-state JSON working copy. Sleep and memory distillation must also be redesigned from first principles so they preserve meaning-bearing claims/evidence/tensions instead of collapsing them into generic slogan paste.
CultCache does not need a separate physical store per state type; it is already polymorphic. The intended split is ownership by typed document kind and mutation contract, not a herd of little stores in fake mustaches. Each durable fact still has one owner. No top-level mirrors. No editable shadow copy pretending to be a harmless view.
- Deterministic cleanup passes whose real job is compensating for whole-state JSON edits, permissive schemas, or sleep distillation that destroyed meaning.
- the scheduled moderation runner owns lifecycle through a huge prompt instead of a typed runner contract
- deterministic cleanup is mostly recent scar tissue from failed manual cleanup passes; it should be deleted as the new state boundary makes it unnecessary
- sleep/distillation currently lacks a hard meaning-preservation contract, so it can compress a concrete repo-bound thought into generic abstraction sludge
Verdict: stop feature work and rebuild this foundation. The rest of the machine can keep running, but moderation/mood/self-state work should cut toward typed state tools before adding new behavior.
## Migration Plan
### Commit 1: Name The Boundary
- Add typed self-state domain interfaces in core.
- Define document types and operation payload types.
- Keep current storage untouched.
- Verification: typecheck only.
### Commit 2: Add Read-Only Typed Projections
- Build a self-state service that reads current canonical state and renders the same summaries used by direct replies.
- Keep JSON projection for the old runner.
- Verification: compare rendered summary against current loader output on a fixture.
### Commit 3: Add Typed Mutation CLI
- Extend `scripts/moderation-state-store.mjs` or replace it with a typed command surface for cursor, open cases, receipts, candidates, sleep, speaking pressure, and distilled memories.
- The CLI writes CultCache directly.
- Verification: fixture tests for each operation.
### Commit 4: Move Repo Activity Cursor Behind The Store
- Change `scripts/export-recent-repo-activity.mjs` so it never writes `.voidbot/private/moderation-agent-state.json`.
- It should emit observed activity and call/store a typed `update_repo_activity_cursor` operation.
- Verification: run with a temp fixture store; cursor advances without JSON projection writes.
### Commit 5: Replace Agent Whole-State Editing With Operation Output
- Scheduled moderation child may propose operations and speech, not edit state.
- Runner applies operations through the typed store.
- Keep old JSON runner behind a fallback flag for one commit only.
- Verification: dry run with `-NoPost` applies only allowed operations.
### Commit 6: Delete JSON Projection Authority
- Remove routine materialization/commit of `.voidbot/private/moderation-agent-state.json`.
- Keep an explicit debug export command if humans need to inspect state.
- Remove `legacyJsonPath` from normal paths.
- Verification: mood drift and moderation dry runs pass without touching JSON.
### Commit 7: Cut Legacy Mirrors
- Remove top-level mirror reconciliation.
- Migrate any consumer to typed projections.
- Delete mirror fields from canonical state.
- Verification: projection summaries still contain required information; no code references mirror keys.
### Commit 8: Replace Compensating Cleanup With Meaning-Preserving Sleep
- Delete cleanup paths whose only job was repairing JSON projection edits, legacy mirrors, keyword sludge, or overgrown runtime residue.
- Redesign sleep/distillation around an explicit contract:
- preserve the claim/question/fascination target
- preserve the concrete subject, such as repo, room, lore seam, person, or system
- preserve evidence refs or admit when evidence is missing
- preserve the live tension/counterweight
- preserve why the memory should affect future action
- never replace a concrete thought with a prettier generic principle unless the operation records what was lost and why that loss is acceptable
- Make distillation emit typed candidate memories first; the state service applies only candidates that satisfy the contract.
- Verification: fixture memories such as `AquariumSynthCSharp: Workflow cannot own the body` survive sleep with their subject, claim, evidence, and tension intact.