fix: todos scan task ballooned to 2.5MB and analysis produced no output
The todos pre-scan walked .output/ (Nitro) and .vercel/ (Vercel) build dirs, flagging 119 of 124 candidates inside minified bundles (single lines up to 162KB). buildTodosScanTask embedded full candidate lines in the task prompt, producing a 2.5MB prompt on freno-dev; the analysis agent settled with ok:true + empty text + no findings.md, verify failed, and resume re-ran the same oversized prompt and failed identically. - scope: exclude .output/.vercel/.netlify (shared by all checks) - todos: truncate candidate code at 160 chars in the prompt + fallback - agent-runner: a session settling with no text and no observed message/ tool events now fails the run loudly instead of reporting ok:true - agent prompts: add the three dirs to each skip list - tests: excluded-dir scan, prompt truncation, emptySessionError cases
This commit is contained in:
@@ -124,6 +124,21 @@ const MAX_CANDIDATES = 500;
|
||||
const FALLBACK_CAP = 16;
|
||||
/** Candidate list embedded in the live prompt is truncated at this many. */
|
||||
const PROMPT_CAP = 40;
|
||||
/**
|
||||
* Max characters of a candidate's code line embedded in the task prompt.
|
||||
* Generated/bundled single lines can be hundreds of KB (e.g. minified assets
|
||||
* sneaking past scope); embedding them wholesale balloons the task to
|
||||
* megabytes and chokes the sub-agent. `path:line` plus a truncated prefix is
|
||||
* enough to classify — the agent can read the file for full context.
|
||||
*/
|
||||
const CODE_DISPLAY_CAP = 160;
|
||||
|
||||
/** Truncate a candidate's code line for prompt embedding. */
|
||||
function displayCode(code: string): string {
|
||||
return code.length > CODE_DISPLAY_CAP
|
||||
? `${code.slice(0, CODE_DISPLAY_CAP)}…`
|
||||
: code;
|
||||
}
|
||||
|
||||
/** Extract the declared function name from a header line, when present. */
|
||||
function headerName(line: string): string | undefined {
|
||||
@@ -369,7 +384,7 @@ function renderFindings(
|
||||
parts.push(`## ${title}`);
|
||||
list.slice(0, FALLBACK_CAP).forEach((c, i) => {
|
||||
parts.push(
|
||||
`### ${i + 1}. ${relative(cwd, c.path)}:${c.line} — ${c.code} | snippet: ${c.snippet} | context: ${c.context || relative(cwd, c.path)}`,
|
||||
`### ${i + 1}. ${relative(cwd, c.path)}:${c.line} — ${displayCode(c.code)} | snippet: ${c.snippet} | context: ${c.context || relative(cwd, c.path)}`,
|
||||
);
|
||||
});
|
||||
if (list.length > FALLBACK_CAP) {
|
||||
@@ -434,7 +449,7 @@ export async function buildTodosScanTask(
|
||||
|
||||
const candidateList = candidates
|
||||
.slice(0, PROMPT_CAP)
|
||||
.map((c) => ` - ${relative(cwd, c.path)}:${c.line} [${c.kind}] ${c.code}`);
|
||||
.map((c) => ` - ${relative(cwd, c.path)}:${c.line} [${c.kind}] ${displayCode(c.code)}`);
|
||||
if (candidates.length > PROMPT_CAP) {
|
||||
candidateList.push(
|
||||
` - … and ${candidates.length - PROMPT_CAP} more (truncated for brevity)`,
|
||||
|
||||
Reference in New Issue
Block a user