feat: add post-compaction read audit (Layer 3)

This commit is contained in:
康熙
2026-02-16 21:41:03 +08:00
committed by Peter Steinberger
parent 3296a25cc6
commit 811c4f5e91
3 changed files with 337 additions and 0 deletions

View File

@@ -37,6 +37,12 @@ import { appendUsageLine, formatResponseUsageLine } from "./agent-runner-utils.j
import { createAudioAsVoiceBuffer, createBlockReplyPipeline } from "./block-reply-pipeline.js";
import { resolveBlockStreamingCoalescing } from "./block-streaming.js";
import { createFollowupRunner } from "./followup-runner.js";
import {
auditPostCompactionReads,
extractReadPaths,
formatAuditWarning,
readSessionMessages,
} from "./post-compaction-audit.js";
import { readPostCompactionContext } from "./post-compaction-context.js";
import { enqueueFollowupRun, type FollowupRun, type QueueSettings } from "./queue.js";
import { createReplyToModeFilterForChannel, resolveReplyToMode } from "./reply-threading.js";
@@ -80,6 +86,9 @@ function appendUnscheduledReminderNote(payloads: ReplyPayload[]): ReplyPayload[]
});
}
// Track sessions pending post-compaction read audit (Layer 3)
const pendingPostCompactionAudits = new Map<string, boolean>();
export async function runReplyAgent(params: {
commandBody: string;
followupRun: FollowupRun;
@@ -562,6 +571,9 @@ export async function runReplyAgent(params: {
.catch(() => {
// Silent failure — post-compaction context is best-effort
});
// Set pending audit flag for Layer 3 (post-compaction read audit)
pendingPostCompactionAudits.set(sessionKey, true);
}
if (verboseEnabled) {
@@ -576,6 +588,25 @@ export async function runReplyAgent(params: {
finalPayloads = appendUsageLine(finalPayloads, responseUsageLine);
}
// Post-compaction read audit (Layer 3)
if (sessionKey && pendingPostCompactionAudits.get(sessionKey)) {
pendingPostCompactionAudits.delete(sessionKey); // Delete FIRST — one-shot only
try {
const sessionFile = activeSessionEntry?.sessionFile;
if (sessionFile) {
const messages = readSessionMessages(sessionFile);
const readPaths = extractReadPaths(messages);
const workspaceDir = process.cwd();
const audit = auditPostCompactionReads(readPaths, workspaceDir);
if (!audit.passed) {
enqueueSystemEvent(formatAuditWarning(audit.missingPatterns), { sessionKey });
}
}
} catch {
// Silent failure — audit is best-effort
}
}
return finalizeWithFollowup(
finalPayloads.length === 1 ? finalPayloads[0] : finalPayloads,
queueKey,