feat: paired review system overhaul — unified service, configurable agents, silent output removal

- Remove UNIFIED_MODE legacy: single service manages all 3 Discord bots
- Add OWNER_AGENT_TYPE / REVIEWER_AGENT_TYPE env vars for configurable agent selection
- Fix Discord channel routing: reviewer output goes through correct bot (discord/discord-review)
- Fix channel name assignment: explicit names prevent agentTypeFilter collision
- Remove silent output suppression system: harness-level protections replace prompt workarounds
- Add reviewer approval detection: DONE marker on first line stops ping-pong
- Include user's original message in reviewer prompt for context
- Fix round_trip_count auto-reset on new user message
- Fix session ID conflict: reviewer doesn't reuse owner's session
- Fix pending progress text flush in runner on close sentinel
- Promote buffered intermediate text to final result when result event has no text
- Remove legacy files: .env.codex.example, .env.codex-review.example, migrate-unify.cjs
- Update CLAUDE.md: server-side build deployment, unified architecture docs
This commit is contained in:
Eyejoker
2026-03-29 20:50:32 +09:00
parent 8a4d83e2c1
commit 16d20fe627
19 changed files with 325 additions and 642 deletions

View File

@@ -122,14 +122,9 @@ export class MessageTurnController {
}
const raw = getAgentOutputText(result);
const silentOutput = isSilentAgentOutput(result);
const suppressState =
raw && this.options.suppressToken
? classifySuppressTokenOutput(raw, this.options.suppressToken)
: raw
? classifySuppressTokenOutput(raw, undefined)
: 'none';
const text = raw && suppressState === 'none' ? formatOutbound(raw) : null;
const silentOutput = false;
const suppressState = 'none' as const;
const text = raw ? formatOutbound(raw) : null;
if (raw) {
logger.info(
@@ -144,31 +139,6 @@ export class MessageTurnController {
},
`Agent output: ${raw.slice(0, 200)}`,
);
if (suppressState === 'exact') {
logger.info(
{
chatJid: this.options.chatJid,
group: this.options.group.name,
groupFolder: this.options.group.folder,
runId: this.options.runId,
resultStatus: result.status,
resultPhase: result.phase,
},
'Suppressed exact-match silent output token',
);
} else if (suppressState === 'mixed') {
logger.warn(
{
chatJid: this.options.chatJid,
group: this.options.group.name,
groupFolder: this.options.group.folder,
runId: this.options.runId,
resultStatus: result.status,
resultPhase: result.phase,
},
'Blocked malformed output that mixed the silent output token with visible text',
);
}
}
const phase: AgentOutputPhase = normalizeAgentOutputPhase(result.phase);