Stop interpreter prose leaking into face speech

This commit is contained in:
Meta Vens 2026-05-26 12:34:46 +01:00
commit f1ed70867a
8 changed files with 15 additions and 52 deletions

View file

@ -77,8 +77,8 @@ REPO_FACE_HEARTBEAT_IDLE_COOLING_ENABLED=true
REPO_FACE_HEARTBEAT_IDLE_AFTER_MINUTES=180
REPO_FACE_HEARTBEAT_IDLE_RECOVERY_MINUTES=120
REPO_FACE_HEARTBEAT_IDLE_NAP_AFTER_MINUTES=360
REPO_FACE_HEARTBEAT_CODEX_MODEL=gpt-5.3-codex-spark
REPO_FACE_HEARTBEAT_CODEX_MODELS=gpt-5.3-codex-spark,gpt-5.4-mini
REPO_FACE_HEARTBEAT_CODEX_MODEL=gpt-5.4
REPO_FACE_HEARTBEAT_CODEX_MODELS=gpt-5.4
REPO_FACE_TURN_CODEX_MODEL=gpt-5.4
REPO_FACE_HEARTBEAT_CODEX_REASONING_EFFORT=low
EPIPHANY_AGENT_ROOT=E:/Projects/EpiphanyAgent

View file

@ -676,16 +676,6 @@ function parseRepoFaceParentInterpretation(
attempt: 1 | 2,
): RepoFaceParentInterpretation {
const block = parseInterpretationBlock(interpretationText);
if (Object.keys(block).length === 0) {
const speechFallback = repoFaceInterpreterPlainSpeechFallback(interpretationText);
if (speechFallback) {
return {
decision: "route",
reasons: ["parent interpreter returned compact plain speech; wrapped it as SAY current_room"],
routedOutput: speechFallback,
};
}
}
const decision = block.decision?.trim().toLowerCase();
const parsedDecision =
decision === "route" || decision === "retry" || decision === "drop"
@ -706,35 +696,6 @@ function parseRepoFaceParentInterpretation(
};
}
function repoFaceInterpreterPlainSpeechFallback(interpretationText: string): string | undefined {
const content = interpretationText.trim();
if (!content || content.length > 500) {
return undefined;
}
if (content.includes("\n\n") || parseRepoFaceActionBlocks(content).length > 0) {
return undefined;
}
if (/^(private thought|what should stick|work\/proposal|article draft|state note|interpretation)\s*:/i.test(content)) {
return undefined;
}
if (/\b(nothing public|would say nothing|stay private|hold silence|no public action|not worth routing)\b/i.test(content)) {
return undefined;
}
if (/\S(?:\.\.\.|…)$/.test(content)) {
return undefined;
}
return [
"SAY",
"identity: current_face_id",
"channel: current_room",
"reply_to:",
"content:",
` ${content}`,
"END",
].join("\n");
}
function collectForbiddenRepoFaceChildTools(artifacts: ProviderArtifact[]): string[] {
const forbidden = new Set<string>();
for (const artifact of artifacts) {
@ -1211,7 +1172,7 @@ async function postRepoIdentityIntent(job: JobRecord, intent: RepoIdentityPostIn
`Repo identity ${identity.id} SAY content is too long for one Discord message (${content.length} characters).`,
);
}
if (/\S(?:\.\.\.|…)$/.test(content)) {
if (/\S(?:\.\.\.|\u2026)$/.test(content)) {
throw new Error(`Repo identity ${identity.id} SAY content appears mechanically truncated.`);
}
const contentFile = await writeBifrostPayloadFile(job, `${identity.id}-discord-post.md`, content);

View file

@ -16,8 +16,8 @@ Git history and smoke artifacts carry routine proof. `state/evidence.jsonl` shou
## Current Shape
- Discord bot and worker are live.
- The unattended repo Face / CTB swarm is live again as of 2026-05-21 after the teardown/restart pass. `GameCult Local Orchestrator` is enabled and owns the single hidden pulse for repo Face CTB turns, Void mood drift, Void moderation rumination, and the watchdog. Bifrost dispatch is present but disabled by default behind `BIFROST_DISPATCH_ENABLED=false`.
- Discord bot and worker may be live, but the unattended repo Face / CTB swarm brake is active as of 2026-05-26.
- The swarm was paused because live Face turns leaked owner-reply/Interpreter scaffolding into public Discord: Mind was being wrapped by the owner Discord reply prompt, then a worker fallback treated plain malformed Mind prose as public `SAY`. The fixed worker stack was restarted on 2026-05-26, typecheck/build pass, `agents:interpreter-loop-smoke` passes, and `agents:heartbeat-model-smoke -- --model gpt-5.4 --reasoning-effort none` passes. Keep `state/agent-swarm-paused.json` active until the operator explicitly asks to thaw; before thawing, run one controlled current-room turn and inspect model-output logs for `INTERPRETATION` plus explicit DSL actions only. Bifrost dispatch remains disabled by default behind `BIFROST_DISPATCH_ENABLED=false`.
- The teardown authority remains `notes/agent-swarm-teardown-plan-2026-05-21.md`, but it is now a restart checklist and smell ledger rather than a stop sign. Keep using it when a Face/Bifrost/CTB boundary smells like prompt/parser/transport Jenga.
- The repo-controlled pause flag is `state/agent-swarm-paused.json`. While it is missing or has `"paused": false`, swarm runners may operate. While it has `"paused": true` or is malformed, the Face heartbeat runner skips and the orchestrator skips agent-swarm organs. This is the brake. Do not route around it.
- Postgres owns jobs, audit events, interaction memory, and rate-limit state.

View file

@ -122,8 +122,8 @@ const envSchema = z.object({
REPO_FACE_HEARTBEAT_IDLE_NAP_AFTER_MINUTES: z.coerce.number().positive().default(360),
REPO_FACE_HEARTBEAT_SPEED_OVERRIDES: z.string().default(""),
REPO_FACE_HEARTBEAT_HEAT_OVERRIDES: z.string().default(""),
REPO_FACE_HEARTBEAT_CODEX_MODEL: z.string().min(1).default("gpt-5.3-codex-spark"),
REPO_FACE_HEARTBEAT_CODEX_MODELS: z.string().default("gpt-5.3-codex-spark,gpt-5.4-mini"),
REPO_FACE_HEARTBEAT_CODEX_MODEL: z.string().min(1).default("gpt-5.4"),
REPO_FACE_HEARTBEAT_CODEX_MODELS: z.string().default("gpt-5.4"),
REPO_FACE_IMAGINATION_CODEX_MODEL: z.string().min(1).default("gpt-5.4"),
REPO_FACE_IMAGINATION_CODEX_MODELS: z.string().default("gpt-5.4"),
REPO_FACE_MIND_CODEX_MODEL: z.string().min(1).default("gpt-5.4"),

View file

@ -86,7 +86,7 @@ export function buildDiscordReplyPrompt(
]
: [];
if (isRepoFaceTurn) {
if (isRepoFaceTurn || isRepoFaceParentInterpreter) {
return context.prompt;
}

View file

@ -1,5 +1,5 @@
{
"paused": false,
"reason": "Unpaused after stack restart restored ready bot/worker runtime and operations check passed live-service gates; keep watching Face prompts, interpreter routing, and memory maintenance output.",
"updatedAt": "2026-05-25T17:29:11Z"
"paused": true,
"reason": "Paused after live Face turns leaked owner-Codex/bridge artifact text into public Discord despite Face stdout choosing private silence. Fix side-effect extraction/routing before thawing.",
"updatedAt": "2026-05-26T11:29:00Z"
}

View file

@ -347,3 +347,5 @@
{"ts":"2026-05-25T21:28:29Z","type":"implementation","status":"ok","note":"Fixed repo Face CTB wake/ready split: operator-absence naps now end when operator absence ends, and the swarm dashboard includes Face rest state so napping Faces are not shown as ready. Verified build and a forced repo-face heartbeat queued Fensalir, Norn, and Nibu."}
{"ts":"2026-05-26T10:53:11Z","type":"implementation","status":"ok","note":"Fixed repo Face speech loss at the Mind-to-worker crossing: if the parent interpreter returns a compact plain public sentence instead of DSL, the worker now wraps it as SAY current_room, and the interpreter prompt explicitly forbids plain-speech-only output. Verified live worker parsed say=1 and posted Mimir/Aqua webhook messages after restart."}
{"ts":"2026-05-26T11:17:58Z","type":"research","status":"ok","note":"Distilled CotSC Praxis doctrine from Tao Te Ching, Bakunin, Malatesta, Rocker, Kropotkin, Goldman, and GameCult history into notes/cotsc-praxis-worldview-2026-05-26.md; repo Face prompts now carry a concise Praxis fragment emphasizing unity of means and ends, federation, mutual aid, consent, inspectability, local stewardship, Taoist non-coercive effectiveness, and rejection of Marxism-Leninist vanguard custody."}
{"ts":"2026-05-26T11:31:11Z","type":"implementation","status":"ok","note":"Paused swarm after live Face turns leaked owner-reply/Interpreter text into Discord. Root cause: parent Mind prompts were wrapped by owner-discord-reply prompt, and worker fallback converted malformed plain Interpreter output into SAY. Fixed by passing repo-face-turn-interpreter prompts through unchanged and deleting the plain-speech fallback; Spark heartbeat defaults now use gpt-5.4 because Spark quota is exhausted."}
{"ts":"2026-05-26T11:34:24Z","type":"verification","status":"ok","note":"After Mind/side-effect fix, restarted local stack with swarm pause still active. Verified npm run typecheck, npm run build, agents:interpreter-loop-smoke, and agents:heartbeat-model-smoke -- --model gpt-5.4 --reasoning-effort none. Spark default smoke failed earlier only because GPT-5.3-Codex-Spark quota is exhausted until 2026-05-31."}

View file

@ -253,5 +253,5 @@ rejected_paths:
reason: sleep/distillation that collapses concrete claims into generic abstraction creates memory nonsense and then forces later cleanup compensators
current_status:
summary: VoidBot's bot/worker/provider/RAG/Postgres/Qdrant/CultCache structure is live again after a 2026-05-25 stack restart restored ready bot/worker PIDs. The repo Face swarm brake is lifted through `state/agent-swarm-paused.json`, `GameCult Local Orchestrator` remains the single pulse owner, repo Face heartbeats and mood drift have run `ok`, and Norn is reconciled into the active CTB participant roster. Bifrost work routing remains paused by default.
next_action: Watch the revived swarm under idle-cooling instead of forcing chatter. Verify the next human-prompted or scheduled Face turn, especially Norn's first real turn, for prompt coherence, parent Imagination/Mind routing, human-steering priority, topic-gravity pivot behavior, and sleep-memory maintenance restraint.
summary: VoidBot's bot/worker/provider/RAG/Postgres/Qdrant/CultCache structure is live, but the repo Face swarm brake is active after live turns leaked owner-reply/Interpreter text into public Discord. The fixed worker stack was restarted on 2026-05-26, parent Mind prompts now bypass the owner-reply wrapper, malformed plain Mind output no longer becomes SAY, and gpt-5.4 smoke checks pass. Bifrost work routing remains paused by default.
next_action: Keep the swarm paused until the operator explicitly asks to thaw it. Before thawing, run one controlled live repo Face turn or dry-run against the current room and confirm the latest model-output logs show an `INTERPRETATION` block plus explicit DSL actions, with no owner-reply/owner-question language crossing into Discord.