fix: sub-agent hang/crash stranding runs mid-phase with no save
Some checks failed
port-to-omp / port (push) Failing after 2s
Some checks failed
port-to-omp / port (push) Failing after 2s
A stalled sub-agent (provider stream never settling after the final tool call, or a throwing session-event listener recursing through the SDK's run-failure path to stack overflow) left the phase stuck in_progress with no state save, no error, and no completion message — observed twice in freno-dev, both times after comments wrote findings.md. - agent-runner: 60-min settle watchdog on every agent phase (PYGIENIUM_AGENT_TIMEOUT_MS, env-tunable); timeout disposes the session and fails the phase loudly with a /pygienium-resume hint instead of hanging the check-runner's await forever. - agent-runner: applySessionEvent — the session.subscribe listener can no longer throw into the SDK event pipeline (guards for partial/malformed events, optional-chained message_update, throwing chat forwarder). - comments: scan no longer regenerates the full report as its final message (findings.md is the source of truth); fix phase reads findings.md with embedded fallback. - check-runner: failing state-save inside the catch path can't double- fault or escape as an unhandled rejection; completion posting is best-effort. - tests: watchdog timeout test, comments task-text regression tests, applySessionEvent malformed-shape unit tests. 146 pass, tsc clean. - README: document PYGIENIUM_AGENT_TIMEOUT_MS.
This commit is contained in:
@@ -30,6 +30,8 @@ import {
|
||||
commentsCheck,
|
||||
findingsPath,
|
||||
changesPath,
|
||||
buildCommentsScanTask,
|
||||
buildCommentsFixTask,
|
||||
} from "../src/checks/comments.js";
|
||||
import type { CheckScope } from "../src/checks/registry.js";
|
||||
|
||||
@@ -256,4 +258,31 @@ describe("comments check (end-to-end)", () => {
|
||||
expect(check!.findings).toBeDefined();
|
||||
expect(check!.changes).toBeDefined();
|
||||
});
|
||||
|
||||
it("scan task keeps the full report in findings.md, not the final message", () => {
|
||||
// Regression: the scan task used to demand the agent regenerate the
|
||||
// whole report as its final message right after writing findings.md —
|
||||
// a second huge output that stalled the phase transition (observed in
|
||||
// freno-dev twice). The final message must stay a one-line summary.
|
||||
const scope: CheckScope = {
|
||||
cwd,
|
||||
target,
|
||||
fix: false,
|
||||
rest: [],
|
||||
};
|
||||
const task = buildCommentsScanTask(cwd, scope);
|
||||
expect(task).toContain("ONE-LINE summary");
|
||||
expect(task).toContain("do NOT regenerate the report text");
|
||||
expect(task).not.toContain(
|
||||
"Return the findings report text as your final message",
|
||||
);
|
||||
expect(task).not.toContain("same content as the file");
|
||||
|
||||
// The fix phase must read the detailed findings from the artifact so a
|
||||
// one-line scan summary can't starve it.
|
||||
const fixTask = buildCommentsFixTask(cwd, scope, "fallback-findings-text");
|
||||
expect(fixTask).toContain("Read the detailed per-file findings");
|
||||
expect(fixTask).toContain(findingsPath(scope));
|
||||
expect(fixTask).toContain("fallback-findings-text");
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user