mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-24 10:13:11 +02:00
test: identify active Stop boundary from durable provider events
This commit is contained in:
1 parent
12624d60c3
commit
2d89146adc
3 files changed
+20
-10
No files matched your search
@@ -86,9 +86,9 @@ export async function runFollowupStopResumeFlow(input: {
|
||||
load: async () => {
|
||||
await refresh();
|
||||
const run = runs[0];
|
||||
if (runs.length !== 1 || !isActiveStopCheckpointRun(run)) return false;
|
||||
if (runs.length !== 1 || !run || run.status !== "running") return false;
|
||||
const events = prpEvents(await runEvents(run.id), run.id);
|
||||
if (!events.some(event => event.eventType === "turn.started" && event.sourceKind === "runner") || events.some(event => event.eventType === "run.result.accepted")) return false;
|
||||
if (!isActiveStopCheckpointRun(run, events)) return false;
|
||||
const checkpoint = await readRegisteredArtifacts(api, issue!.id, run.id, [files.checkpoint])
|
||||
.then(([artifact]) => artifact).catch(error => {
|
||||
if (error instanceof RegisteredArtifactNotFoundError) return null;
|
||||
@@ -111,7 +111,7 @@ export async function runFollowupStopResumeFlow(input: {
|
||||
observation.followup = { commentIds: followup.commentIds, runId: active.id, runStatus: active.status,
|
||||
acceptedResults: activeEvents.filter(event => event.eventType === "run.result.accepted").length,
|
||||
providerStarted: activeEvents.some(event => event.eventType === "turn.started"), observedAt: new Date().toISOString() };
|
||||
if (runs.length !== 1 || active.status !== "running" || observation.followup.acceptedResults !== 0)
|
||||
if (runs.length !== 1 || !isActiveStopCheckpointRun(active, activeEvents))
|
||||
throw new Error("Follow-up was not recorded before the original active Stop boundary");
|
||||
await persist("followup-during-work");
|
||||
await input.capture("before-stop", "Follow-up persisted during original active work", "before-stop.png");
|
||||
|
||||
@@ -66,9 +66,15 @@ describe("one task across follow-up, Stop and explicit resumption", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("recognizes the production active-provider phase before checkpoint publication", () => {
|
||||
expect(isActiveStopCheckpointRun({ status: "running", nativePhase: "provider_running" })).toBe(true);
|
||||
for (const run of [undefined, { status: "queued", nativePhase: "provider_running" },
|
||||
{ status: "succeeded", nativePhase: "committed" }, { status: "running", nativePhase: "result_accepted" },
|
||||
{ status: "running", nativePhase: "workspace_finalizing" }]) expect(isActiveStopCheckpointRun(run)).toBe(false);
|
||||
it("observes the actual active provider through its durable turn rather than a finalization phase label", () => {
|
||||
const run = { id: "run", status: "running", nativePhase: "observed" };
|
||||
const started = { runId: "run", eventType: "turn.started", sourceKind: "runner" };
|
||||
expect(isActiveStopCheckpointRun(run, [started])).toBe(true);
|
||||
const prepared = { ...run, nativePhase: "provider_running" };
|
||||
expect(isActiveStopCheckpointRun(prepared, [started])).toBe(true);
|
||||
for (const candidate of [undefined, { ...run, status: "queued" }, { ...run, status: "succeeded" }])
|
||||
expect(isActiveStopCheckpointRun(candidate, [started])).toBe(false);
|
||||
for (const events of [[], [started, started], [{ ...started, runId: "foreign" }], [{ ...started, sourceKind: "control_plane" }],
|
||||
...["run.result.accepted", "run.terminal", "turn.completed", "turn.failed", "turn.cancelled"].map(eventType => [started, { runId: "run", eventType }])])
|
||||
expect(isActiveStopCheckpointRun(run, events)).toBe(false);
|
||||
});
|
||||
@@ -25,8 +25,12 @@ export const followupStopTask: RunnerTaskFixture = {
|
||||
].join("\n");
|
||||
}, buildMatchers: () => [],
|
||||
};
|
||||
export function isActiveStopCheckpointRun(run: { status?: string; nativePhase?: string | null } | undefined) {
|
||||
return run?.status === "running" && run.nativePhase === "provider_running";
|
||||
export function isActiveStopCheckpointRun(run: { id?: string; status?: string } | undefined,
|
||||
events: readonly { runId?: string; eventType?: string; sourceKind?: string }[]) {
|
||||
if (!run?.id || run.status !== "running") return false;
|
||||
const owned = events.filter(event => event.runId === run.id);
|
||||
return owned.filter(event => event.eventType === "turn.started" && event.sourceKind === "runner").length === 1 &&
|
||||
!owned.some(event => ["run.result.accepted", "run.terminal", "turn.completed", "turn.failed", "turn.cancelled"].includes(event.eventType ?? ""));
|
||||
}
|
||||
export function exactSyntheticJson(content: string, expected: Record<string, string>): boolean {
|
||||
let parsed: unknown;
|
||||
|
||||
Reference in new issue
Block a user