mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-13 23:39:21 +02:00
Wait for signoff fixture runs before stage decisions
This commit is contained in:
1 parent
0421a3b8c0
commit
9c678b2d90
1 file changed
+27
@@ -270,6 +270,29 @@ async function getIssueRunLockState(board: APIRequestContext, issueId: string):
|
||||
};
|
||||
}
|
||||
|
||||
async function waitForFixtureRun(
|
||||
board: APIRequestContext,
|
||||
agentId: string,
|
||||
issueId: string,
|
||||
runId: string,
|
||||
) {
|
||||
// Negative authorization cases deliberately invoke a non-participant. Leave
|
||||
// their API rejection intact instead of waiting for a run they cannot own.
|
||||
if ((await getIssueRunLockState(board, issueId)).assigneeAgentId !== agentId) return;
|
||||
const waitBudgetMs = wakeupWaitBudgetMs();
|
||||
const deadline = Date.now() + waitBudgetMs;
|
||||
let status: string | null = null;
|
||||
do {
|
||||
const run = await fetchVerifiedRun(board, runId, agentId, issueId);
|
||||
expect(run, "Fixture run must belong to the acting agent and issue").not.toBeNull();
|
||||
status = run!.status;
|
||||
if (status === "succeeded") return;
|
||||
expect(["queued", "running"], `Fixture run ${runId} ended as ${status}`).toContain(status);
|
||||
await new Promise((resolve) => setTimeout(resolve, WAKEUP_POLL_INTERVAL_MS));
|
||||
} while (Date.now() < deadline);
|
||||
throw new Error(`Fixture run ${runId} did not succeed within ${waitBudgetMs}ms (last status: ${status})`);
|
||||
}
|
||||
|
||||
async function retryAgentPatchWithCurrentLockOnConflict(
|
||||
board: APIRequestContext,
|
||||
agent: AgentAuth,
|
||||
@@ -325,6 +348,9 @@ async function agentPatch(
|
||||
}: { maxAttempts?: number; backoffMs?: number; maxBackoffMs?: number } = {},
|
||||
) {
|
||||
const runId = await invokeHeartbeat(board, agent.agentId, issueId);
|
||||
// The fixture process only prints "done". Let its startup and cleanup settle
|
||||
// before a simulated decision reassigns the issue and cancels that process.
|
||||
await waitForFixtureRun(board, agent.agentId, issueId, runId);
|
||||
const patchWith = (patchRunId: string) =>
|
||||
agent.request.patch(`${BASE_URL}/api/issues/${issueId}`, {
|
||||
headers: { "X-Paperclip-Run-Id": patchRunId },
|
||||
@@ -353,6 +379,7 @@ async function agentCheckoutAndPatch(
|
||||
patchData: Record<string, unknown>,
|
||||
) {
|
||||
const runId = await invokeHeartbeat(board, agent.agentId, issueId);
|
||||
await waitForFixtureRun(board, agent.agentId, issueId, runId);
|
||||
const directPatchRes = await agent.request.patch(`${BASE_URL}/api/issues/${issueId}`, {
|
||||
headers: { "X-Paperclip-Run-Id": runId },
|
||||
data: patchData,
|
||||
|
||||
Reference in new issue
Block a user