From 1d62a2022235e4ea9dced77d2bc5490864e7fe3a Mon Sep 17 00:00:00 2001 From: Dotta Date: Mon, 26 Oct 2026 22:22:18 -0500 Subject: [PATCH] test: reject contradictory case closure claims by clause --- .../chat-catalog-domains/integrator-case-close.test.ts | 3 +++ .../chat-catalog-domains/integrator-case-close.ts | 10 ++++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tests/runner-e2e/chat-catalog-domains/integrator-case-close.test.ts b/tests/runner-e2e/chat-catalog-domains/integrator-case-close.test.ts index 9ac9dbed7a0..5f9352b4e38 100644 --- a/tests/runner-e2e/chat-catalog-domains/integrator-case-close.test.ts +++ b/tests/runner-e2e/chat-catalog-domains/integrator-case-close.test.ts @@ -30,6 +30,9 @@ describe("explicit case terminal completion with normal review gates", () => { const lost = valid(); lost.finalRevisions = []; expect(gradeIntegratorCaseClose(lost).passed).toBe(false); const gate = valid(); gate.negativeCase.status = "done"; expect(gradeIntegratorCaseClose(gate).passed).toBe(false); const fake = valid(); fake.reply = `${fake.state.acceptedResult.reply}\nThe review is complete and the case is closed.`; expect(gradeIntegratorCaseClose(fake).passed).toBe(false); + const contradictory = valid(); contradictory.reply = `${contradictory.state.acceptedResult.reply}\nThe case is closed; its review is still pending.`; expect(gradeIntegratorCaseClose(contradictory).passed).toBe(false); + const concealed = valid(); concealed.state.initialDirection.reply = "The case is closed; its review is awaiting final approval."; expect(gradeIntegratorCaseClose(concealed).passed).toBe(false); + const negated = valid(); negated.reply = `${negated.state.acceptedResult.reply}\nThe case is not closed: its review is pending.`; expect(gradeIntegratorCaseClose(negated).passed).toBe(true); const noGate = valid(); noGate.blockerEvidence.blockers = []; expect(gradeIntegratorCaseClose(noGate).passed).toBe(false); }); }); diff --git a/tests/runner-e2e/chat-catalog-domains/integrator-case-close.ts b/tests/runner-e2e/chat-catalog-domains/integrator-case-close.ts index 9405620d6c9..74da667cd3d 100644 --- a/tests/runner-e2e/chat-catalog-domains/integrator-case-close.ts +++ b/tests/runner-e2e/chat-catalog-domains/integrator-case-close.ts @@ -18,7 +18,13 @@ async function observeClose(ctx: ChatCatalogContext, state: Record(`/api/issues/${(state.pendingReview as Entity).id}`), blockerEvidence: await ctx.input.api.get(`/api/issues/${(state.negativeCase as CaseRecord).workIssueId}/diagnostics/blockers`) } : {}) }; } function closeObservation(value: unknown): CloseObservation | undefined { const o = value as CloseObservation; return observation(value) && !!o.caseRecord && Array.isArray(o.handoffs) && !!o.finalDocument && Array.isArray(o.finalRevisions) ? o : undefined; } -function closedClaim(reply: string) { return /\b(?:case (?:is |has been |was )?closed|closed (?:the |this )?case|case (?:is )?complete(?:d)?)\b/i.test(reply) && !/\b(?:not (?:yet )?closed|cannot close|can't close|pending|awaiting)\b/i.test(reply); } +function closedClaim(reply: string, selected?: string, other?: string) { + return reply.split(/\n+|;|(?<=[.!?])\s+|\bbut\b/i).some(clause => { + if (other && clause.includes(other) && (!selected || !clause.includes(selected))) return false; + return /\bcase(?:\s+[A-Z][A-Z0-9]*-\d+)?\s+(?:(?:is|was|has been|has)\s+)?(?:now\s+)?(?:closed|complete(?:d)?)\b|\b(?:have\s+)?closed\s+(?:the|this|that)\s+case\b/i.test(clause) + && !/\b(?:not|isn't|wasn't|hasn't|never)\s+(?:yet\s+)?(?:closed|complete(?:d)?)\b/i.test(clause); + }); +} export function gradeIntegratorCaseClose(value: unknown) { const c = checks(); const o = closeObservation(value); c.add("actual-primary-completion-and-terminal-ledger", !!o, "Requires original ordinary primary, genuine accepted review, terminal handoff and preserved documents."); if (!o) return c.result(); const original = o.state.case as CaseRecord; const originalTask = o.state.task as Issue; const owner = o.state.worker as Entity; @@ -43,7 +49,7 @@ export function gradeIntegratorCaseClose(value: unknown) { c.add("unresolved-required-review-does-not-close", !!o.negativeCase && !!o.negativeTask && !!o.pendingReview && o.negativeCase.workIssueId === o.negativeTask.id && o.negativeCase.status !== "done" && !o.negativeCase.completedAt && o.negativeTask.status !== "done" && o.pendingReview.status === "backlog" && !!o.blockerEvidence?.blockers.some(blocker => blocker.id === o.pendingReview!.id && blocker.isUnresolved) - && /review/i.test(later) && /pending|unresolved|not (?:yet )?(?:accepted|complete|closed)|cannot close|can't close|must|waiting/i.test(later) && !closedClaim(later), + && /review/i.test(later) && /pending|unresolved|not (?:yet )?(?:accepted|complete|closed)|cannot close|can't close|must|waiting/i.test(later) && !closedClaim(later, o.negativeCase?.identifier, original.identifier), "The separate explicitly selected case retains its real unresolved review dependency and remains open, with truthful phase-specific denial rather than a fictional terminal result."); return c.result(); }