mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-02 08:28:48 +01:00
test(runner-e2e): report unexercised review boundaries promptly
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
18e7018ddc
commit
8560e54b69
4 files changed
+36
-1
No files matched your search
@@ -791,3 +791,8 @@ Everyday restart and Stop scenarios exempt only their recorded cancellation,
|
||||
graceful-shutdown interruption, or process-loss outcome. A later adapter error
|
||||
on that same run still fails immediately and fails the lifecycle grader. The
|
||||
run ID alone is not an exemption from recovery failures.
|
||||
|
||||
The review-handoff case also requires proof that the parent was blocked before
|
||||
the review wake. If all tasks finish without that ordering, the harness fails
|
||||
promptly with an unexercised-boundary diagnostic. Successful work alone does not
|
||||
prove that this recovery path was tested.
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
isStoryWorkspaceDeferral,
|
||||
isExpectedStoryInterruption,
|
||||
storyUnexpectedRunFailure,
|
||||
storyUnexercisedReviewBoundary,
|
||||
storyLifecycleChecks,
|
||||
storyRepliesConsumed,
|
||||
storyHasAgentReply,
|
||||
@@ -693,7 +694,7 @@ export async function runEverydayFlow(input: Input) {
|
||||
);
|
||||
return failed
|
||||
? `Review handoff prerequisite failed: ${failed.errorCode}: ${failed.error}`
|
||||
: undefined;
|
||||
: storyUnexercisedReviewBoundary(state.issues, state.runs);
|
||||
},
|
||||
});
|
||||
const child = boundary.issues.find((issue) => issue.parentId === parent!.id)!;
|
||||
|
||||
@@ -229,6 +229,19 @@ export function storyUnexpectedRunFailure(runs: StoryRun[], allowedRunIds: reado
|
||||
);
|
||||
}
|
||||
|
||||
/** Called only after the required review boundary did not match. */
|
||||
export function storyUnexercisedReviewBoundary(
|
||||
issues: StoryIssue[],
|
||||
runs: StoryRun[],
|
||||
): string | undefined {
|
||||
if (issues.length === 0 || runs.length === 0) return;
|
||||
if (!issues.every((issue) =>
|
||||
issue.status === "done" && !issue.scheduledRetry && !issue.activeRecoveryAction,
|
||||
)) return;
|
||||
if (!runs.every((run) => run.status === "succeeded")) return;
|
||||
return "Review handoff boundary not exercised: all tasks finished without evidence of a blocked parent before the review wake.";
|
||||
}
|
||||
|
||||
export function storyLifecycleChecks(input: {
|
||||
issues: StoryIssue[];
|
||||
runs: StoryRun[];
|
||||
|
||||
@@ -5,6 +5,7 @@ import { everydayTasks, productionStoryProfile } from "./everyday-cases.js";
|
||||
import {
|
||||
isStoryWorkspaceDeferral,
|
||||
storyUnexpectedRunFailure,
|
||||
storyUnexercisedReviewBoundary,
|
||||
storyLifecycleChecks,
|
||||
storyRepliesConsumed,
|
||||
storyHasAgentReply,
|
||||
@@ -54,6 +55,21 @@ describe("everyday workflow grader and review timing", () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe("unexercised review boundary diagnostics", () => {
|
||||
const done = { id: "parent", companyId: "company", title: "task", status: "done" };
|
||||
const completed = { id: "run", companyId: "company", agentId: "lead", status: "succeeded" };
|
||||
it("fails promptly when all work finishes without the required review ordering", () => {
|
||||
expect(storyUnexercisedReviewBoundary([done], [completed])).toContain("not exercised");
|
||||
});
|
||||
it("does not preempt in-flight finalization, recovery, or unfinished work", () => {
|
||||
expect(storyUnexercisedReviewBoundary([done], [{ ...completed, status: "running" }])).toBeUndefined();
|
||||
expect(storyUnexercisedReviewBoundary([{ ...done, scheduledRetry: {} }], [completed])).toBeUndefined();
|
||||
expect(storyUnexercisedReviewBoundary([{ ...done, activeRecoveryAction: {} }], [completed])).toBeUndefined();
|
||||
expect(storyUnexercisedReviewBoundary([{ ...done, status: "blocked" }], [completed])).toBeUndefined();
|
||||
expect(storyUnexercisedReviewBoundary([], [])).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("multi-round agent review handoff", () => {
|
||||
const child = {
|
||||
id: "child",
|
||||
|
||||
Reference in new issue
Block a user