Block ambiguous repo Face current-room routing
This commit is contained in:
parent
b76f6c54a7
commit
6773f21341
4 changed files with 26 additions and 12 deletions
|
|
@ -692,7 +692,7 @@ async function interpretRepoFaceTurnOutput(
|
|||
const response = await executeProviderForJob(provider, job, interpreterContext, "interpreter");
|
||||
const interpretationText = normalizeModelText(response.outputText ?? response.summary);
|
||||
return {
|
||||
...parseRepoFaceParentInterpretation(interpretationText, input.attempt, outputText),
|
||||
...parseRepoFaceParentInterpretation(interpretationText, input.attempt, outputText, job),
|
||||
artifacts: prefixProviderArtifacts(`interpreter-attempt-${input.attempt}`, response.artifacts ?? []),
|
||||
};
|
||||
}
|
||||
|
|
@ -784,9 +784,10 @@ function parseRepoFaceParentInterpretation(
|
|||
interpretationText: string,
|
||||
attempt: 1 | 2,
|
||||
faceOutputText: string,
|
||||
job?: JobRecord,
|
||||
): RepoFaceParentInterpretation {
|
||||
const block = parseInterpretationBlock(interpretationText);
|
||||
const fallback = buildBareInterpreterSayFallback(interpretationText, faceOutputText);
|
||||
const fallback = buildBareInterpreterSayFallback(interpretationText, faceOutputText, job);
|
||||
if (!block.decision && fallback) {
|
||||
return {
|
||||
decision: "route",
|
||||
|
|
@ -814,10 +815,17 @@ function parseRepoFaceParentInterpretation(
|
|||
};
|
||||
}
|
||||
|
||||
function buildBareInterpreterSayFallback(interpretationText: string, faceOutputText: string): string | undefined {
|
||||
function buildBareInterpreterSayFallback(
|
||||
interpretationText: string,
|
||||
faceOutputText: string,
|
||||
job?: JobRecord,
|
||||
): string | undefined {
|
||||
if (!faceOutputHasUnconditionalWouldSay(faceOutputText)) {
|
||||
return undefined;
|
||||
}
|
||||
if (job && repoFaceHasMultipleActiveConversationChannels(job)) {
|
||||
return undefined;
|
||||
}
|
||||
if (parseRepoFaceActionBlocks(interpretationText).length > 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
|
@ -955,7 +963,9 @@ function normalizeInterpretedRepoFaceSpeechDestinations(
|
|||
}
|
||||
|
||||
function repoFaceHasMultipleActiveConversationChannels(job: JobRecord): boolean {
|
||||
return repoFaceHasMultipleActiveConversationChannels(job);
|
||||
const activeThreads = job.contextBundle.repoFaceConversationThreads ?? [];
|
||||
const representedChannels = new Set(activeThreads.map((thread) => thread.channelId));
|
||||
return representedChannels.size > 1;
|
||||
}
|
||||
|
||||
function repoFaceOutputHasExplicitSayDestination(outputText: string): boolean {
|
||||
|
|
@ -1386,7 +1396,7 @@ async function postRepoIdentityIntent(job: JobRecord, intent: RepoIdentityPostIn
|
|||
}
|
||||
if (repoIdentityRequiresExplicitConversationContext(job, intent) && !conversationContext) {
|
||||
console.warn(
|
||||
`Rejected repo identity ${identity.id} speech for job ${job.id}: multiple active conversation contexts require context, reply_to, or channel.`,
|
||||
`Rejected repo identity ${identity.id} speech for job ${job.id}: multiple active conversation contexts require context, reply_to, or a concrete channel id.`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
|
@ -3098,13 +3108,15 @@ function repoIdentityRequiresExplicitConversationContext(
|
|||
job: JobRecord,
|
||||
intent: RepoIdentityPostIntent,
|
||||
): boolean {
|
||||
if (intent.channelId || intent.replyToMessageId || intent.contextId) {
|
||||
if (intent.replyToMessageId || intent.contextId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const activeThreads = job.contextBundle.repoFaceConversationThreads ?? [];
|
||||
const representedChannels = new Set(activeThreads.map((thread) => thread.channelId));
|
||||
return representedChannels.size > 1;
|
||||
if (intent.channelId && !isCurrentRoomChannelAlias(intent.channelId)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return repoFaceHasMultipleActiveConversationChannels(job);
|
||||
}
|
||||
|
||||
function resolveRepoIdentityReplyTargetChannel(
|
||||
|
|
|
|||
|
|
@ -175,6 +175,7 @@ Git history and smoke artifacts carry routine proof. `state/evidence.jsonl` shou
|
|||
- The overnight 2026-05-23 run showed a softer version of the previous loop: Faces did not collapse into nonsense, but the Aquarium room stayed captured by the Nibu-origin/faction lore seam for hours. Existing `saturationScore` lived on private thought/incubation surfaces, and the repetition prompt mostly caught copied openings/endings, not semantic topic attractors. The heartbeat prompt now projects current-room topic saturation from repeated raw-transcript terms and estimates whether the attractor is home-adjacent or another steward's gravity well from each Face's identity/jurisdiction text. The state projector should turn foreign attractors into character-specific crowding, neglect, boredom, rivalry, handoff, or pivot pressure; the Interpreter diagnoses non-owner same-topic politeness as missing personal stake, ownership, freshness, handoff, or pivot rather than applying a topic ban or token blacklist.
|
||||
- Void's broader moderation authority had become venue leakage: recent-history projection stripped `channelId`, leaving the configured `publicSpeechTarget` as the obvious place for replies, so Aquarium-shaped talk could land in `#general`. The rumination context now preserves message `channelId` and projects `recentConversationTarget`; prompt doctrine says source-channel replies belong in that source channel, while `publicSpeechTarget` is for unanchored herald/artifact announcements.
|
||||
- Repo Face speech routing now uses active conversation contexts instead of one room-focus guess. Heartbeat prompts project up to six `ctx_<channel>_<message>` records across current and nearby channels; the Interpreter can emit `context:` on a `SAY`; the worker resolves that context to the source channel/message and rejects unknown contexts or ambiguous bare SAY blocks when multiple active channels are visible. A Persona can carry separate #aquarium/#pics/#general conversations at once, but public speech has to keep its context attached.
|
||||
- Follow-up leak found on 2026-06-14: `channel: current_room` still counted as an explicit destination, and bare parent-Interpreter text could still be wrapped into a `SAY channel: current_room`. Those were obsolete owners. They are now blocked when multiple active conversation channels are visible; multi-context speech needs `context`, `reply_to`, or a concrete channel id. The swarm pause flag is currently set true while this repair is verified live.
|
||||
- The Nibu/Void turf-crossing discussion exposed a social-state projection gap: existing bonds/status reads project well once typed state already contains them, but the live pipeline did not own "this recent event should become relationship/status pressure." The repair adds bounded raw relationship-pressure evidence to the state packet before the projector: recent messages that touch the Face, peer Faces, existing social targets, jurisdiction/domain terms, or status/territory/consultation language. The projector may turn that evidence into tentative felt pressure, and the Interpreter may persist a bond/status/mood note only when the projected memory or Face output shows a character-specific reaction. This should let resentment, rivalry, consultation offense, and territorial tension emerge without manual state edits.
|
||||
- The swarm brake currently reads `state/agent-swarm-paused.json` with `"paused": false`. If scheduled Face turns start overrunning again, use that brake rather than letting the orchestrator churn. The known 2026-06-09 timeout source was the model state-projector child; local runtime currently keeps it disabled while the deterministic fallback and Interpreter/worker speech rails are watched.
|
||||
- Direct Face `UPDATE REQUEST` and `BIFROST TOPIC` packets are ignored while `REPO_FACE_BIFROST_ENABLED=false`. Do not debug missing Bifrost jobs as a live failure unless that flag has been deliberately enabled again.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"paused": false,
|
||||
"reason": "Resumed by Codex on 2026-06-09 after local runtime config disabled the expensive repo Face state-projector pass and reduced heartbeat selection to one job per tick. Watch scheduled pulses for clean exits before raising cadence.",
|
||||
"updatedAt": "2026-06-09T15:00:00.0000000Z"
|
||||
"paused": true,
|
||||
"reason": "Paused by Codex on 2026-06-14 after repo Faces still routed source-channel context through channel: current_room into Aquarium. Keep paused until current_room is no longer accepted as explicit context when multiple active conversation contexts are visible.",
|
||||
"updatedAt": "2026-06-14T18:55:00.0000000Z"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -364,3 +364,4 @@
|
|||
{"ts":"2026-06-14T12:26:21Z","type":"implementation","status":"ok","note":"Made repo Face self-maintenance grievances public-first: prompt projection now surfaces Persona/system substrate, tools, voice/avatar/access, state-projection, semantic-memory, and agency-path pressure under a Self-maintenance public advocacy section; Face and Interpreter prompts now require a compact public-safe SAY for body/mind/substrate asks instead of burying them as private state. Detector was narrowed after prompt verification so sensitive human body/home trauma does not get auto-promoted by this machinery."}
|
||||
{"ts":"2026-06-14T12:43:35Z","type":"implementation","status":"ok","note":"Fixed repo Face cross-channel reply routing: prompt transcripts now include source channel ids for current, nearby, and chronology messages; Face prompts explicitly forbid answering nearby-room posts in the current room; worker post routing now derives the destination channel from reply_to message ids and also infers a non-current room when a bare Face output names that room label (e.g. general thread). Verified against Libby prompt showing Metacrat general messages followed by the bad Aquarium post."}
|
||||
{"ts":"2026-06-14T17:40:23Z","type":"implementation","status":"ok","note":"Repo Face speech routing now carries typed active conversation contexts across current and nearby Discord channels. Heartbeat prompts emit ctx_<channel>_<message> records; SAY can include context; worker resolves context to source channel/reply target and rejects unknown or ambiguous unqualified SAY when multiple channels are active."}
|
||||
{"ts":"2026-06-14T20:01:05Z","type":"implementation","status":"ok","note":"Closed the surviving repo Face context leak: channel: current_room no longer counts as explicit routing when multiple active conversation channels are visible, and bare parent-interpreter text is no longer wrapped into SAY fallback under multi-context jobs. Swarm paused while this fix is verified live."}
|
||||
|
|
|
|||
Loading…
Reference in a new issue