fix: bind semantic progress to run owner

This commit is contained in:
Josh Avant
2026-08-06 04:30:35 -05:00
parent 474be1700d
commit 4ea4596617
3 changed files with 70 additions and 16 deletions
+64 -11
View File
@@ -598,7 +598,39 @@ describe("repeated request liveness", () => {
).toBeUndefined();
});
it("orders semantic progress across merged session aliases", () => {
it("keeps replacement-owner evidence across delayed semantic event delivery", async () => {
const ref = { sessionId: "queued-owner-session", sessionKey: "agent:main:queued-owner" };
startDiagnosticRunActivityTracking();
markDiagnosticEmbeddedRunStarted({ ...ref, runId: "queued-old-owner" });
emitTrustedDiagnosticEvent({
type: "run.progress",
...ref,
runId: "queued-old-owner",
reason: "delayed-old-owner-output",
progressKind: "semantic",
});
markDiagnosticEmbeddedRunStarted({ ...ref, runId: "queued-new-owner" });
for (let attempt = 0; attempt < 2; attempt += 1) {
markDiagnosticModelStartedForTest({
...ref,
runId: "queued-new-owner",
provider: "mock",
model: "request-model",
observationUnit: "request",
});
}
await waitForDiagnosticEventsDrained();
expect(getDiagnosticSessionActivitySnapshot(ref)).toMatchObject({
lastProgressReason: "delayed-old-owner-output",
repeatedRequestNoProgressAgeMs: expect.any(Number),
});
});
it("requires an owned semantic event across merged session aliases", () => {
vi.useFakeTimers();
const startedAt = Date.parse("2026-08-04T02:00:00Z");
vi.setSystemTime(startedAt);
@@ -607,24 +639,45 @@ describe("repeated request liveness", () => {
const runId = "merge-run";
markDiagnosticEmbeddedRunStarted({ sessionId, runId });
markDiagnosticModelStartedForTest({
for (let attempt = 0; attempt < 2; attempt += 1) {
markDiagnosticModelStartedForTest({
sessionId,
runId,
provider: "mock",
model: "request-model",
observationUnit: "request",
});
}
markDiagnosticRunProgress({
sessionId,
runId,
provider: "mock",
model: "request-model",
observationUnit: "request",
sessionKey,
reason: "ownerless:semantic",
progressKind: "semantic",
});
markDiagnosticRunProgress({
sessionId,
sessionKey,
reason: "reply:delivered",
runId: " ",
reason: "whitespace-owner:semantic",
progressKind: "semantic",
});
vi.setSystemTime(startedAt + 6 * 60_000);
expect(
getDiagnosticSessionActivitySnapshot({ sessionId, sessionKey })
.repeatedRequestNoProgressAgeMs,
).toBeUndefined();
expect(getDiagnosticSessionActivitySnapshot({ sessionId, sessionKey })).toMatchObject({
lastProgressReason: "whitespace-owner:semantic",
repeatedRequestNoProgressAgeMs: 6 * 60_000,
});
markDiagnosticRunProgress({
sessionKey,
runId: ` ${runId} `,
reason: "owned:semantic",
progressKind: "semantic",
});
expect(getDiagnosticSessionActivitySnapshot({ sessionId, sessionKey })).toMatchObject({
lastProgressReason: "owned:semantic",
repeatedRequestNoProgressAgeMs: undefined,
});
});
it("keeps repeated request evidence across same-logical-owner attempt rearming", async () => {
+5 -4
View File
@@ -338,16 +338,17 @@ export function markDiagnosticArgumentChurnObservation(
}
export function markDiagnosticRunProgress(params: DiagnosticRunProgressActivityEvent): void {
const activity = resolveSessionActivity({ ...params, create: true });
const runId = params.runId?.trim() || undefined;
const activity = resolveSessionActivity({ ...params, runId, create: true });
if (!activity) {
return;
}
// run.progress predates progressKind; only an explicit semantic fact may clear evidence.
if (params.progressKind !== "semantic") {
// Only an explicit fact from the current owner may clear its recovery evidence.
if (params.progressKind !== "semantic" || !runId) {
touchSessionActivity(activity, params.reason);
return;
}
touchSemanticSessionActivity(activity, params.reason, { runId: params.runId });
touchSemanticSessionActivity(activity, params.reason, { runId });
}
function recordRunCompleted(