test(runner-e2e): require durable review ordering evidence

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-09-19 10:07:44 -05:00
1 parent 8560e54b69
commit 4d2c918694
4 files changed
+66 -14

No files matched your search

+5 -3
View File
@@ -793,6 +793,8 @@ on that same run still fails immediately and fails the lifecycle grader. The
run ID alone is not an exemption from recovery failures. 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-handoff case also requires proof that the parent was blocked before
the review wake. If all tasks finish without that ordering, the harness fails the review wake. When all tasks finish and persisted timestamps prove that the
promptly with an unexercised-boundary diagnostic. Successful work alone does not accepted review started before any parent run finished, the harness fails
prove that this recovery path was tested. promptly with an unexercised-boundary diagnostic. Missing evidence in separately
fetched snapshots does not trigger this rejection. Successful work alone does
not prove that this recovery path was tested.
+1 -1
View File
@@ -694,7 +694,7 @@ export async function runEverydayFlow(input: Input) {
); );
return failed return failed
? `Review handoff prerequisite failed: ${failed.errorCode}: ${failed.error}` ? `Review handoff prerequisite failed: ${failed.errorCode}: ${failed.error}`
: storyUnexercisedReviewBoundary(state.issues, state.runs); : storyUnexercisedReviewBoundary(state.issues, state.runs, parent!.id, fixtures.agent.id);
}, },
}); });
const child = boundary.issues.find((issue) => issue.parentId === parent!.id)!; const child = boundary.issues.find((issue) => issue.parentId === parent!.id)!;
+23 -2
View File
@@ -229,17 +229,38 @@ export function storyUnexpectedRunFailure(runs: StoryRun[], allowedRunIds: reado
); );
} }
/** Called only after the required review boundary did not match. */ /** Called after the boundary matcher; reject only with durable proof of the wrong ordering. */
export function storyUnexercisedReviewBoundary( export function storyUnexercisedReviewBoundary(
issues: StoryIssue[], issues: StoryIssue[],
runs: StoryRun[], runs: StoryRun[],
parentId: string,
leadId: string,
): string | undefined { ): string | undefined {
if (issues.length === 0 || runs.length === 0) return; if (issues.length === 0 || runs.length === 0) return;
if (!issues.every((issue) => if (!issues.every((issue) =>
issue.status === "done" && !issue.scheduledRetry && !issue.activeRecoveryAction, issue.status === "done" && !issue.scheduledRetry && !issue.activeRecoveryAction,
)) return; )) return;
if (!runs.every((run) => run.status === "succeeded")) 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."; const child = issues.find((issue) => issue.parentId === parentId);
const accepted = child?.interactions?.flatMap((interaction) => {
const review = storyAcceptedAgentReview(child, interaction.id, leadId, runs);
return review ? [review] : [];
})[0];
const reviewRun = accepted && runs.find((run) => run.id === accepted.resolvedByRunId);
const reviewStartedAt = Date.parse(reviewRun?.startedAt ?? "");
const parentRuns = runs.filter((run) =>
run.nativeIssueId === parentId ||
run.contextSnapshot?.issueId === parentId ||
run.contextSnapshot?.taskId === parentId,
);
// Snapshots are fetched separately. Missing review evidence is not proof that it
// never happened; wait unless persisted timestamps rule out the required order.
if (!Number.isFinite(reviewStartedAt) || parentRuns.length === 0) return;
if (!parentRuns.every((run) => {
const finishedAt = Date.parse(run.finishedAt ?? "");
return Number.isFinite(finishedAt) && finishedAt > reviewStartedAt;
})) return;
return "Review handoff boundary not exercised: the accepted review started before any parent run finished, so the blocked-parent-before-review ordering was not tested.";
} }
export function storyLifecycleChecks(input: { export function storyLifecycleChecks(input: {
+37 -8
View File
@@ -24,6 +24,7 @@ import {
storyParentCompletionPrecedesReview, storyParentCompletionPrecedesReview,
storyAcceptedAgentReview, storyAcceptedAgentReview,
type StoryRun, type StoryRun,
type StoryIssue,
} from "./everyday-observations.js"; } from "./everyday-observations.js";
describe("everyday workflow grader and review timing", () => { describe("everyday workflow grader and review timing", () => {
@@ -57,16 +58,44 @@ describe("everyday workflow grader and review timing", () => {
describe("unexercised review boundary diagnostics", () => { describe("unexercised review boundary diagnostics", () => {
const done = { id: "parent", companyId: "company", title: "task", status: "done" }; const done = { id: "parent", companyId: "company", title: "task", status: "done" };
const completed = { id: "run", companyId: "company", agentId: "lead", status: "succeeded" }; const completed = {
it("fails promptly when all work finishes without the required review ordering", () => { id: "run", companyId: "company", agentId: "lead", status: "succeeded",
expect(storyUnexercisedReviewBoundary([done], [completed])).toContain("not exercised"); nativeIssueId: "parent", finishedAt: "2026-09-19T14:47:48.134Z",
};
const child = {
...done, id: "child", parentId: "parent", interactions: [{
id: "card", issueId: "child", kind: "request_confirmation", status: "accepted",
addresseeAgentId: "lead", resolvedByAgentId: "lead", resolvedByRunId: "review",
createdAt: "2026-09-19T14:47:04.000Z", resolvedAt: "2026-09-19T14:47:21.876Z",
payload: { target: { type: "custom", key: "native_completion_review", revisionId: "decision" } },
result: { version: 1, outcome: "accepted" },
}],
};
const review = {
...completed, id: "review", nativeIssueId: "child", startedAt: "2026-09-19T14:47:05.802Z",
contextSnapshot: { nativeReviewInteractionId: "card", nativeReviewDecisionId: "decision" },
};
const diagnose = (issues: StoryIssue[] = [done, child], runs: StoryRun[] = [completed, review]) =>
storyUnexercisedReviewBoundary(issues, runs, "parent", "lead");
it("fails promptly with persisted proof that review preceded parent completion", () => {
expect(diagnose()).toContain("not exercised");
}); });
it("does not preempt in-flight finalization, recovery, or unfinished work", () => { it("does not preempt in-flight finalization, recovery, or unfinished work", () => {
expect(storyUnexercisedReviewBoundary([done], [{ ...completed, status: "running" }])).toBeUndefined(); expect(diagnose([done, child], [{ ...completed, status: "running" }, review])).toBeUndefined();
expect(storyUnexercisedReviewBoundary([{ ...done, scheduledRetry: {} }], [completed])).toBeUndefined(); expect(storyUnexercisedReviewBoundary([{ ...done, scheduledRetry: {} }, child], [completed, review], "parent", "lead")).toBeUndefined();
expect(storyUnexercisedReviewBoundary([{ ...done, activeRecoveryAction: {} }], [completed])).toBeUndefined(); expect(storyUnexercisedReviewBoundary([{ ...done, activeRecoveryAction: {} }, child], [completed, review], "parent", "lead")).toBeUndefined();
expect(storyUnexercisedReviewBoundary([{ ...done, status: "blocked" }], [completed])).toBeUndefined(); expect(diagnose([{ ...done, status: "blocked" }, child])).toBeUndefined();
expect(storyUnexercisedReviewBoundary([], [])).toBeUndefined(); expect(diagnose([], [])).toBeUndefined();
});
it("waits when separately fetched snapshots lack review evidence or timestamps", () => {
expect(diagnose([done, { ...child, interactions: [] }])).toBeUndefined();
expect(diagnose([done, child], [completed])).toBeUndefined();
expect(diagnose([done, child], [{ ...completed, finishedAt: "" }, review])).toBeUndefined();
expect(diagnose([done, child], [completed, { ...review, startedAt: "" }])).toBeUndefined();
expect(diagnose([done, child], [review])).toBeUndefined();
});
it("does not reject a completed workflow with the required timing", () => {
expect(diagnose([done, child], [{ ...completed, finishedAt: review.startedAt }, review])).toBeUndefined();
}); });
}); });