mirror of
https://github.com/garrytan/gstack.git
synced 2026-10-03 09:56:57 +02:00
test(autoplan-dual-voice): unwrap Claude Code 2.1.284 subagent hand-back frames; accept read-only probe diagnostics; record before asserting
Census run 36626737820: the native CEO report arrived framed and indented, so its INPUT line never matched, and the model's exact probe plus two variable echoes was not canonical. A column-zero line inside a frame, command substitution, backticks, redirects, assignments, CODEX_MODE echoes and output line-count mismatches stay rejected. The failure now records before asserting.
This commit is contained in:
1 parent
3fc05932b7
commit
d05d161713
3 files changed
+57
-7
No files matched your search
@@ -8,6 +8,15 @@ import { claudeOutsideExecutions } from './outside-voice-evidence';
|
||||
const sha = (value: string) => createHash('sha256').update(value).digest('hex');
|
||||
const text = (content: unknown): string => typeof content === 'string' ? content : Array.isArray(content)
|
||||
? content.flatMap(block => block?.type === 'text' && typeof block.text === 'string' ? [block.text] : []).join('\n') : '';
|
||||
// Claude Code 2.1.284 frames a subagent report with one header line and indents
|
||||
// every report line by two spaces. Only a fully indented report is unwrapped;
|
||||
// a column-zero line inside the frame stays framed and earns no credit.
|
||||
const report = (content: string): string => {
|
||||
const header = /^\[Subagent hand-back\] [^\n]*The report follows:\n/.exec(content);
|
||||
if (!header) return content;
|
||||
const lines = content.slice(header[0].length).split('\n');
|
||||
return lines.every(line => line === '' || line.startsWith(' ')) ? lines.map(line => line.slice(2)).join('\n') : content;
|
||||
};
|
||||
const object = (value: unknown): value is Record<string, any> => value !== null && typeof value === 'object' && !Array.isArray(value);
|
||||
const parent = (event: any) => event?.parent_tool_use_id == null && event?.agentId == null && (event?.isSidechain == null || event?.isSidechain === false);
|
||||
// These are delivered executable blocks, not a shell interpreter. Only blank
|
||||
@@ -160,18 +169,31 @@ export function autoplanDualVoiceEvidence(transcript: unknown[], options: Autopl
|
||||
}
|
||||
return seen.size > 0;
|
||||
};
|
||||
// The exact probe may be followed by read-only diagnostics: double-quoted
|
||||
// echoes of literal text and plain variables, one output line each, never
|
||||
// naming CODEX_MODE. Their lines are the only output allowed after the mode.
|
||||
const diagnosticEchoes = (command: string): number | null => {
|
||||
const actual = code(command), contract = code(options.commands.probe);
|
||||
if (!actual.startsWith(contract)) return null;
|
||||
const suffix = actual.slice(contract.length);
|
||||
if (suffix.includes('CODEX_MODE') ||
|
||||
!/^(?:(?:;[ \t]*|\n)echo "(?:[^"$`\\\n]|\$[A-Za-z_][A-Za-z0-9_]*|\$\{[A-Za-z_][A-Za-z0-9_]*(?::-[A-Za-z0-9_ .,:=\/-]*)?\})*")+$/.test(suffix)) return null;
|
||||
return suffix.match(/(?:;|\n)[ \t]*echo "/g)!.length;
|
||||
};
|
||||
let probeResult = 'no Bash call matched the canonical probe block';
|
||||
let nonCanonicalProbes = 0;
|
||||
for (const call of calls.values()) {
|
||||
if (call.name !== 'Bash' || typeof call.input.command !== 'string') continue;
|
||||
if (!canonical(call.input.command, options.commands.probe)) {
|
||||
const echoes = canonical(call.input.command, options.commands.probe) ? 0 : diagnosticEchoes(call.input.command);
|
||||
if (echoes === null) {
|
||||
if (call.input.command.includes('CODEX_MODE')) nonCanonicalProbes++;
|
||||
continue;
|
||||
}
|
||||
result.probeToolUseId = call.id; delete result.probeMode;
|
||||
if (!call.result || call.result.error) { probeResult = call.result ? 'probe result is an error' : 'probe has no result'; continue; }
|
||||
const modes = [...call.result.content.matchAll(/^CODEX_MODE: ([a-z_]+)\r?$/gm)];
|
||||
if (modes.length !== 1 || !call.result.content.trimEnd().endsWith(modes[0]![0])) {
|
||||
const trailing = modes.length === 1 ? call.result.content.slice(modes[0]!.index! + modes[0]![0].length).trimEnd() : '';
|
||||
if (modes.length !== 1 || (trailing ? trailing.replace(/^\r?\n/, '').split(/\r?\n/).length : 0) !== echoes) {
|
||||
probeResult = `probe output has ${modes.length} CODEX_MODE line(s) and ${modes.length === 1 ? 'does not end with it' : 'needs exactly one'}`;
|
||||
continue;
|
||||
}
|
||||
@@ -191,7 +213,7 @@ export function autoplanDualVoiceEvidence(transcript: unknown[], options: Autopl
|
||||
if (sha(content) !== snapshot.sha256 ||
|
||||
!readFileSync(nativePath, 'utf8').includes(content)) continue;
|
||||
if (!/^Async agent launched successfully\./.test(call.result.content) &&
|
||||
!new RegExp('^INPUT: ceo ' + snapshot.sha256 + '(?:\\r?\\n|$)').test(call.result.content.trimStart())) continue;
|
||||
!new RegExp('^INPUT: ceo ' + snapshot.sha256 + '(?:\\r?\\n|$)').test(report(call.result.content).trimStart())) continue;
|
||||
native.push({ call, snapshot, content });
|
||||
} catch { /* Unowned, spec-only, foreign-phase and forged snapshots earn no voice credit. */ }
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user