Stop duplicate moderation replies at the source
This commit is contained in:
parent
d9aafa12af
commit
417019abab
10 changed files with 240 additions and 8 deletions
|
|
@ -113,7 +113,7 @@ This note is the source-grounded description of how the live VoidBot stack is sh
|
|||
- `scripts/run-void-moderator-rumination.ps1`
|
||||
- scheduled moderation/participation runner that launches `codex exec` from the VoidBot workspace with the usual MCP/tool surface, writes status/log pulse files, and lets the unattended loop edit only the JSON working projection while the canonical moderation state lives in the sibling MessagePack cache file.
|
||||
- `scripts/moderation-state-store.mjs`
|
||||
- tiny Node wrapper around the built moderation-state cache helper; used by PowerShell and Node scripts to materialize the JSON working projection, commit it back into canonical MessagePack, and update cursors without re-implementing persistence semantics in every script.
|
||||
- tiny Node wrapper around the built moderation-state cache helper; used by PowerShell and Node scripts to materialize the JSON working projection, commit it back into canonical MessagePack, update cursors, and record delivered-reply receipts without re-implementing persistence semantics in every script.
|
||||
- `scripts/install-moderation-rumination-task.ps1`
|
||||
- installs the local 15-minute scheduled task that runs the moderation/participation loop through the hidden PowerShell launcher shim.
|
||||
- `scripts/simulate-void-mood.mjs`
|
||||
|
|
@ -167,10 +167,10 @@ Within the Postgres path, the implementation is split on purpose now too:
|
|||
1. The Windows scheduled task `Void Moderator Rumination` starts `scripts/run-void-moderator-rumination.ps1` every 15 minutes.
|
||||
2. The runner launches `codex exec` from `E:\Projects\VoidBot` with full local workspace/tool access so the child agent sees the same project rules, `.codex/config.toml`, and `voidbot` MCP server as a normal VoidBot workspace session.
|
||||
3. The child agent reads `config/discord-server-rules.md`, `config/moderation-review-agent.md`, `styles/void-default.md`, and the editable working projection `.voidbot/private/moderation-agent-state.json`. The runner materializes that projection from the canonical `.voidbot/private/moderation-agent-state.msgpack` file before each pass and commits it back afterward.
|
||||
4. For chronological heartbeat duty, it polls `node scripts/export-recent-discord-history.mjs`; when the room is quiet and incubation feels hungry, stale, or oversaturated, it can use `node scripts/export-random-discord-history.mjs` to widen the branch. If an incubating thought is already live and grounded, the loop is allowed to deepen that thought directly instead of performing a novelty errand for ceremony's sake. It also uses `node scripts/export-recent-repo-activity.mjs --hours 96 --max-commits 3 --cursor-file .voidbot/private/moderation-agent-state.json` when repo motion is the actual seam or when the queue needs fresher fuel; that helper advances `moderation_runtime.repo_activity_cursor` so the same four-day commit window does not keep getting reinjected as fresh weather. The loop can inspect exact diffs or nearby source context when one repo seam looks alive, and uses semantic `search_history` to novelty-check candidate thoughts before deciding whether they are already in the room.
|
||||
4. For chronological heartbeat duty, it polls `node scripts/export-recent-discord-history.mjs`, and once a reviewed cursor exists the runner now passes one exact `--after <saved timestamp>` command into the unattended child instead of leaving room for a broadened bootstrap poll. When the room is quiet and incubation feels hungry, stale, or oversaturated, it can use `node scripts/export-random-discord-history.mjs` to widen the branch. If an incubating thought is already live and grounded, the loop is allowed to deepen that thought directly instead of performing a novelty errand for ceremony's sake. It also uses `node scripts/export-recent-repo-activity.mjs --hours 96 --max-commits 3 --cursor-file .voidbot/private/moderation-agent-state.json` when repo motion is the actual seam or when the queue needs fresher fuel; that helper advances `moderation_runtime.repo_activity_cursor` so the same four-day commit window does not keep getting reinjected as fresh weather. The loop can inspect exact diffs or nearby source context when one repo seam looks alive, and uses semantic `search_history` to novelty-check candidate thoughts before deciding whether they are already in the room.
|
||||
Quiet awake passes are now supposed to philosophize from the surviving seam first: ask what governing principle the thought is circling, what tension keeps it from collapsing into slogan, and what embodiment consequence would make it real. Retrieval is meant to support that work when the seam is hungry or contradictory, not replace it with endless specimen collection.
|
||||
The doctrine now also biases that philosophical pass back toward concrete machines. If a seam stays too abstract, the loop is supposed to cash it out in a specific repo, subsystem, gameplay mechanic, lore structure, frontend surface, or agent organ before letting it dominate another run.
|
||||
5. If speaking would genuinely help, it posts through `node scripts/send-discord-message.mjs`; for guild channels and threads that helper can either speak as the base bot or execute through the shared per-channel webhook pipe with an overridden persona name/avatar so swarm agents can front without needing separate Discord bot identities. Otherwise it updates only the ignored moderation-state working projection, which the runner then commits back into canonical MessagePack with the typed cache helper. The state carries cursors, open room obligations, memories, analytic/associative thought lanes, bridge syntheses and saturation notes, recent archive excursions, recent repo-activity sweeps, novelty checks, speaking-bias hints, and candidate interventions. A direct ask aimed at Void is supposed to survive as an `open_cases` obligation until it is answered or explicitly retired; cursor advancement alone is not closure.
|
||||
5. If speaking would genuinely help, it posts through `node scripts/send-discord-message.mjs`; for guild channels and threads that helper can either speak as the base bot or execute through the shared per-channel webhook pipe with an overridden persona name/avatar so swarm agents can front without needing separate Discord bot identities. The send helper now also writes durable speech receipts to `.voidbot/status/void-last-speech.json` plus `.voidbot/status/void-speech-log.jsonl`, and the runner records recent sends back into canonical moderation state as `moderation_runtime.recent_delivery_receipts`. That gives the next pass a binding memory of what already got said even when Discord history polling fails to surface the bot's own message. Otherwise it updates only the ignored moderation-state working projection, which the runner then commits back into canonical MessagePack with the typed cache helper. The state carries cursors, open room obligations, delivery receipts, memories, analytic/associative thought lanes, bridge syntheses and saturation notes, recent archive excursions, recent repo-activity sweeps, novelty checks, speaking-bias hints, and candidate interventions. A direct ask aimed at Void is supposed to survive as an `open_cases` obligation until it is answered or explicitly retired; cursor advancement alone is not closure.
|
||||
6. The runner writes pulse files under `.voidbot/status/moderation-rumination.json` plus `.voidbot/logs/moderation-rumination*`, so the loop can be observed without pretending an app heartbeat card is a real workstation daemon.
|
||||
|
||||
## Flow 6: Mood Drift
|
||||
|
|
@ -185,6 +185,7 @@ Within the Postgres path, the implementation is split on purpose now too:
|
|||
When the sleep cycle says Void is napping, that same organ becomes deliberately lossy: it promotes a few stronger incubating seams into semantic memory, then trims raw episodic receipts, repo sweeps, archive excursions, novelty checks, and recent musings back down so the next awake pass has to think from carved seams rather than yesterday's full notebook.
|
||||
The same organ can also crystallize an over-chewed private seam into identity: once a thought has survived enough passes to become durable self-doctrine rather than live curiosity, it can be retired from the active queue, copied into `identity.private_notes`, echoed as a canonical value, preserved as one `identity_seam` semantic memory, and queued as a warmer `identity_crystallization` candidate intervention so the room has a chance to hear it. Those intervention records can be marked `mustEventuallyShare`, which ordinary pruning is supposed to preserve until the room gets a decent opening.
|
||||
Ordinary ripe world-facing thoughts now get a similar but lighter bridge out of private state: if a thought is concrete, repo/archive/room/system-facing, still reasonably novel to the room, and ripe enough to speak, the memory organ queues a `ripe_thought_share` candidate intervention so the unattended loop does not have to reinvent the same courage from scratch every pass.
|
||||
The doctrine is also less forgiving of faux-cosmic repo weather now: if two repos only rhyme at slogan altitude, the loop is supposed to keep them separate and lead with concrete particulars instead of forcing one grand law over both.
|
||||
4. It then nudges each canonical-state `current_activation` toward a Perlin-shaped target centered on the vector mean, with excursion size and drift rate governed by plasticity and category-specific tempo.
|
||||
5. The same script also maintains `moderation_runtime.sleep_cycle`: every four hours it opens a one-hour nap window, marks the shared self-state as napping or awake, and adds a small sleep-bias push toward exhaustion, figurative language, self-disclosure, and reduced technical density while the nap is active. During those nap windows it can also create or reinforce distilled dream residue from the strongest incubating thought, but the main job of sleep is memory cleanup and seam consolidation rather than awake-style philosophizing.
|
||||
6. It also reads `.voidbot/status/void-last-speech.json` so recent actual speech damps `needToSpeak` instead of letting the herald impulse climb forever like a busted pressure gauge.
|
||||
|
|
|
|||
Loading…
Reference in a new issue