mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-09 07:10:34 +01:00
Merge commit '499afce285c429f814f5cd22fd437bafabf530e7' into codex/sleep-final-qualified-18388
* commit '499afce285c429f814f5cd22fd437bafabf530e7': test: align deferred recovery clocks with real execution Keep recovery acceptance timers on their owning clock fix(server): recheck reactive sources after status summary commit test: measure retention page fairness on a controlled clock fix(heartbeat): resume saved chat work on feature enablement test: await resolved interaction execution before outcome assertions Wake saved conversation assignments when Agent Chat becomes enabled
This commit is contained in:
commit
96b516dcb6
10 files changed
+519
-87
No files matched your search
@@ -1,3 +1,4 @@
|
||||
import { instanceSettingsService } from "../instance-settings.js";
|
||||
import { writeDeferredExecutionWait } from "../deferred-execution-wait.js";
|
||||
import type { DeferredReceiptRecoveryOptions } from "../deferred-execution-notifications.js";
|
||||
import { observeStoppedWorkspaceRecovery } from "../workspace-recovery.js";
|
||||
@@ -777,7 +778,8 @@ export function createHeartbeatRunControl(db: Db, dependencies: HeartbeatRunCont
|
||||
async function resumeExecutionWaitComments(scope: DeferredReceiptRecoveryOptions = {}) {
|
||||
if ((await getSchedulingSuppression()).suppressed) return;
|
||||
await reconcileTaskChatRetryReceipts(db, scope);
|
||||
const retries = await db.select({ id: agentWakeupRequests.id, companyId: agentWakeupRequests.companyId })
|
||||
const retries = await db.select({ id: agentWakeupRequests.id, companyId: agentWakeupRequests.companyId,
|
||||
conversationAgentId: issues.conversationAgentId })
|
||||
.from(agentWakeupRequests).innerJoin(issues, and(eq(issues.companyId, agentWakeupRequests.companyId),
|
||||
sql`${issues.id}::text = ${agentWakeupRequests.payload}->>'issueId'`,
|
||||
eq(issues.assigneeAgentId, agentWakeupRequests.agentId)))
|
||||
@@ -788,8 +790,13 @@ export function createHeartbeatRunControl(db: Db, dependencies: HeartbeatRunCont
|
||||
sql`${agentWakeupRequests.payload}->'taskRetry'->>'chatActionId' is null`,
|
||||
notInArray(issues.status, ["done", "cancelled"])))
|
||||
.orderBy(asc(agentWakeupRequests.updatedAt)).limit(50);
|
||||
const chatEnabled = !retries.some(retry => retry.conversationAgentId)
|
||||
|| (await instanceSettingsService(db).getExperimental()).enableAgentChat;
|
||||
for (const retry of retries) {
|
||||
// Accepted chat work waits for the flag's committed eligibility signal.
|
||||
// Public Retry still rejects new requests while the feature is disabled.
|
||||
await db.update(agentWakeupRequests).set({ updatedAt: new Date() }).where(eq(agentWakeupRequests.id, retry.id));
|
||||
if (retry.conversationAgentId && !chatEnabled) continue;
|
||||
await resumeTaskRetry(retry.companyId, retry.id).catch(err => {
|
||||
scope.onError?.(err); logger.warn({ err, requestId: retry.id }, "Task retry dispatch deferred");
|
||||
});
|
||||
|
||||
@@ -626,12 +626,16 @@ export function instanceSettingsService(db: Db, options: InstanceSettingsService
|
||||
}
|
||||
}
|
||||
}
|
||||
const chatBecameEnabled = !toExperimentalView(current.experimental).enableAgentChat
|
||||
&& toExperimentalView(nextExperimental).enableAgentChat;
|
||||
const now = new Date();
|
||||
const [updated] = await db.transaction(async tx => {
|
||||
if (patch.enableStatusCards !== undefined) await notifyStatusCardEvaluation(tx);
|
||||
if (chatBecameEnabled) await notifyDeferredExecutionEligibility(tx);
|
||||
await notifyDeliveryWork(tx, DELIVERY_QUEUES.mcpEvents, "*");
|
||||
await notifyDeliveryWork(tx, DELIVERY_QUEUES.dotEvents, "*");
|
||||
await notifyDeliveryWork(tx, DELIVERY_QUEUES.grokDispatch);
|
||||
if (chatBecameEnabled) await notifyDeliveryWork(tx, DELIVERY_QUEUES.strandedAssignments, "*");
|
||||
if (patch.enableWorktreeRunExecution !== undefined) await notifyScheduledRetryCancellation(tx);
|
||||
if (patch.enableWorktreeRunExecution !== undefined) {
|
||||
await notifyRunDispatch(tx);
|
||||
|
||||
@@ -969,12 +969,8 @@ export function statusCardService(
|
||||
pendingChangeCount: 0,
|
||||
pendingChangeHash: null,
|
||||
lastChangeAt: null,
|
||||
nextEvalReason: current.refreshPolicy.mode === "reactive" &&
|
||||
filterStatusCardChanges(diffStatusCardFingerprint(snapshot, watchedNow), current.refreshPolicy).length > 0
|
||||
? "refresh" : membershipAt ? "membership" : null,
|
||||
nextEvalAt: current.refreshPolicy.mode === "reactive" &&
|
||||
filterStatusCardChanges(diffStatusCardFingerprint(snapshot, watchedNow), current.refreshPolicy).length > 0
|
||||
? now : nextEvaluationAt(current, membershipAt, now),
|
||||
nextEvalReason: current.refreshPolicy.mode === "reactive" ? "refresh" : membershipAt ? "membership" : null,
|
||||
nextEvalAt: current.refreshPolicy.mode === "reactive" ? now : nextEvaluationAt(current, membershipAt, now),
|
||||
updatedAt: now,
|
||||
}).where(and(eq(statusCards.id, current.id), eq(statusCards.generatingIssueId, input.generationIssueId))).returning();
|
||||
if (!next) throw conflict("Status-card generation was superseded by a newer task");
|
||||
|
||||
Reference in new issue
Block a user