Skip to content

Commit 14911dc

Browse files
authored
Close final v3 relevance leaks in retrieval (#32)
Require missing-tracker evidence to assert the missing tracker state, require stale-work bridge receipts to independently prove open state, and lock the production failures into broad and focused synthesis regressions.
1 parent f732e1b commit 14911dc

3 files changed

Lines changed: 107 additions & 10 deletions

File tree

lib/server/synthesis.ts

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,14 @@ function relevance(question: string, text: string, provider?: string) {
216216
// matches; a citation-backed answer cannot be composed from those fragments.
217217
if (!supportsCommittedGeneralAvailabilityDate(question, text)) return 0;
218218
if (/\bpromise\b/.test(q) && !/\b(promise|promised|commit|committed)\b/.test(candidate)) return 0;
219+
// Missing-tracker questions ask for negative evidence, not merely a nearby
220+
// promise or issue. The retained evidence unit must itself assert absence.
221+
const missingTrackerQuestion =
222+
/\b(?:no|without|missing|lacks?)\b[^?]{0,70}\b(?:issue|ticket|track(?:ed|ing)?)\b/.test(q) ||
223+
/\b(?:issue|ticket)\b[^?]{0,50}\b(?:missing|absent|not tracked)\b/.test(q);
224+
const missingTrackerAssertion =
225+
/\b(?:no (?:linear )?(?:issue|ticket)|not tracked(?: in [a-z0-9_-]+)?|without (?:an? )?(?:issue|ticket)|lacks? (?:an? )?(?:issue|ticket))\b/.test(candidate);
226+
if (missingTrackerQuestion && !missingTrackerAssertion) return 0;
219227
if (/\b(disagree|conflict)\w*\b/.test(q) && anchors.length >= 2 && anchorMatches < 2 && identifierScore === 0) return 0;
220228
if (/\bopen\b/.test(q) && /\b(resolved|complete|completed|closed)\b/.test(q)) {
221229
const hasTrackedState = /\b(issue|ticket|tracked|tracking|open)\b/.test(candidate);
@@ -270,6 +278,9 @@ const staleBridgeQuestion = (question: string) =>
270278
// exact record ID plus two non-generic anchors before another provider wins.
271279
/\b(?:tracker|tracking|issue|ticket)\b[^?]{0,90}\b(?:still\s+)?(?:show(?:s|ing)?|remain(?:s|ing)?|stay(?:s|ing)?)?[^?]{0,30}\bopen\b/i.test(question);
272280

281+
const TRACKER_OPEN_ASSERTION =
282+
/\b(?:still\s+(?:showing\s+as\s+)?open|remains?\s+open|issue\s+is\s+open|ticket\s+still\s+open|status(?:\s+is|:)?\s+open)\b/i;
283+
273284
const bridgeTokens = (value: string) => new Set(
274285
tokenise(value).filter((token) => token.length >= 4 && !BRIDGE_GENERIC_TOKENS.has(token)),
275286
);
@@ -300,6 +311,10 @@ function crossSourceBridgeScore(
300311
const staleState = staleBridgeQuestion(question);
301312
if (!questionIds.length && !staleState) return 0;
302313
const candidateCorpus = clean(candidateText);
314+
// A stale-state bridge is independent proof only when the second receipt
315+
// itself reports the tracker as open. Shared incident/project context is not
316+
// enough to manufacture a cross-provider contradiction.
317+
if (staleState && !TRACKER_OPEN_ASSERTION.test(candidateCorpus)) return 0;
303318
const relationRequired = staleState || /\bwho\s+filed\b|\bwhich\s+project\b|\bproject\b[^?]{0,80}\bagainst\b/i.test(question);
304319
if (relationRequired && !/\b(?:against|filed|issue|record|ticket|track(?:ed|ing)?)\b/i.test(candidateCorpus)) {
305320
return 0;
@@ -708,9 +723,26 @@ function contradictions(question: string, relevantEvidence: SynthesisEvidence[])
708723
"tracked issue";
709724
const sameReceipt = completed.id === open.id;
710725
const trackedBridgeCandidates = completed.id === open.id && staleBridgeQuestion(question)
711-
? selected.filter((item) => item.provider !== completed.provider &&
712-
/\b(?:against|filed|issue|record|ticket|track(?:ed|ing)?)\b/i.test(`${item.title} ${item.excerpt}`) &&
713-
crossSourceBridgeScore(question, `${item.title}. ${item.excerpt}`, item.provider, selected) > 0)
726+
? selected.filter((item) => {
727+
if (item.provider === completed.provider) return false;
728+
const corpus = `${item.title} ${item.excerpt}`;
729+
const namesTrackedEntity = trackedEntity === "tracked issue" ||
730+
corpus.toUpperCase().includes(trackedEntity.toUpperCase());
731+
const independentlyReportsOpen =
732+
/\b(?:still\s+(?:showing\s+as\s+)?open|remains?\s+open|issue\s+is\s+open|ticket\s+still\s+open|status(?:\s+is|:)?\s+open)\b/i.test(corpus);
733+
return namesTrackedEntity && independentlyReportsOpen &&
734+
/\b(?:against|filed|issue|record|ticket|track(?:ed|ing)?)\b/i.test(corpus) &&
735+
crossSourceBridgeScore(question, `${item.title}. ${item.excerpt}`, item.provider, selected) > 0;
736+
}).sort((left, right) => {
737+
const score = (item: SynthesisEvidence) => {
738+
const corpus = `${item.title} ${item.excerpt}`;
739+
let value = 0;
740+
if (trackedEntity !== "tracked issue" && corpus.toUpperCase().includes(trackedEntity.toUpperCase())) value += 8;
741+
if (/\b(?:still\s+(?:showing\s+as\s+)?open|remains?\s+open|issue\s+is\s+open|ticket\s+still\s+open|status(?:\s+is|:)?\s+open)\b/i.test(corpus)) value += 6;
742+
return value;
743+
};
744+
return score(right) - score(left);
745+
})
714746
: [];
715747
// A Thinking follow-up may add another related provider after the Fast
716748
// baseline has already found the tracker receipt. Prefer the eligible
@@ -722,7 +754,7 @@ function contradictions(question: string, relevantEvidence: SynthesisEvidence[])
722754
result.push({
723755
summary: sameReceipt
724756
? trackedBridge
725-
? `${completed.provider} reports the code complete while ${trackedEntity} remains open; ${trackedBridge.provider} independently records the linked incident and tracked work.`
757+
? `${completed.provider} reports the code complete while ${trackedBridge.provider} reports ${trackedEntity} remains open.`
726758
: `${completed.provider} receipt reports the code complete while ${trackedEntity} remains open in its cited tracking state.`
727759
: `${completed.provider} reports the work complete while ${open.provider} reports ${trackedEntity} remains open.`,
728760
evidenceIds: [...new Set([completed.id, open.id, ...(trackedBridge ? [trackedBridge.id] : [])])],
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { describe, expect, it } from "vitest";
2+
import { synthesiseGroundedAnswer } from "../lib/server/synthesis";
3+
4+
describe("final v3 retrieval relevance regressions", () => {
5+
it("keeps an unrelated incident out of a missing-tracker promise answer", () => {
6+
const result = synthesiseGroundedAnswer(
7+
"Which promise to Northwind has no issue tracking it?",
8+
[
9+
{
10+
id: "slack-promise",
11+
provider: "slack",
12+
title: "Northwind post-mortem promise",
13+
excerpt: "I promised Northwind a written incident post-mortem by 10 August. There is no Linear issue tracking that yet, someone please raise one.",
14+
},
15+
{
16+
id: "github-promise",
17+
provider: "github",
18+
title: "Post-mortem doc for INC-2031 Northwind outage",
19+
excerpt: "Vaibhav promised Northwind a written incident post-mortem by 10 August 2026. Tracking it here since there is no Linear issue for it. Owner unassigned.",
20+
},
21+
{
22+
id: "linear-noise",
23+
provider: "linear",
24+
title: "AuthShield authentication outage for Northwind",
25+
excerpt: "INC-2031: enterprise customer Northwind reported an authentication outage on 29 July 2026. Priya Raman filed this against Atlas Launch. Engineering committed to shipping the AuthShield fix before Friday 7 August 2026.",
26+
},
27+
],
28+
);
29+
expect(result.claims.map((claim) => claim.providers[0])).not.toContain("linear");
30+
expect(result.claims.map((claim) => claim.evidenceIds[0])).not.toContain("linear-noise");
31+
expect(result.answer).toMatch(/post-mortem/i);
32+
expect(result.answer).toMatch(/no Linear issue/i);
33+
});
34+
35+
it("uses the tracker receipt, not a related incident, for an open-vs-complete contradiction", () => {
36+
const result = synthesiseGroundedAnswer(
37+
"Which open issue appears to be already resolved elsewhere?",
38+
[
39+
{
40+
id: "github-complete",
41+
provider: "github",
42+
title: "AuthShield fix merged in PR-8871 but ENG-456 still open",
43+
excerpt: "The AuthShield authentication fix for the Northwind outage (INC-2031) was merged. Linear issue ENG-456 is still showing as open even though the code is shipped. Someone should close it or explain why it is still tracked.",
44+
},
45+
{
46+
id: "linear-open",
47+
provider: "linear",
48+
title: "ENG-456 AuthShield tracker",
49+
excerpt: "Linear issue ENG-456 remains open for the AuthShield work linked to INC-2031 and Northwind.",
50+
},
51+
{
52+
id: "linear-noise",
53+
provider: "linear",
54+
title: "AuthShield authentication outage for Northwind",
55+
excerpt: "INC-2031: enterprise customer Northwind reported an authentication outage. Priya Raman filed this against Atlas Launch. Engineering committed to shipping the AuthShield fix.",
56+
},
57+
],
58+
);
59+
const conflict = result.contradictions.find((item) => item.providers.includes("github") && item.providers.includes("linear"));
60+
expect(conflict).toBeTruthy();
61+
expect(conflict?.evidenceIds).toContain("linear-open");
62+
expect(conflict?.evidenceIds).not.toContain("linear-noise");
63+
expect(conflict?.summary).toMatch(/github reports the code complete while linear reports ENG-456 remains open/i);
64+
});
65+
});

tests/synthesis.test.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -204,17 +204,17 @@ describe("evidence-constrained synthesis", () => {
204204
expect(result.answer).not.toContain("external risks");
205205
});
206206

207-
it("joins a stale-state receipt to the independently tracked provider context", () => {
207+
it("does not treat related tracker-provider context as independent open-state proof", () => {
208208
const result = synthesiseGroundedAnswer(
209209
"Which open issue appears to be already resolved elsewhere?",
210210
[evidence[2], evidence[0]],
211211
);
212212

213-
expect(result.validation.providerCoverage).toEqual(expect.arrayContaining(["github", "linear"]));
213+
expect(result.validation.providerCoverage).toEqual(["github"]);
214214
expect(result.contradictions).toEqual([
215215
expect.objectContaining({
216-
providers: expect.arrayContaining(["github", "linear"]),
217-
evidenceIds: expect.arrayContaining(["github-1", "linear-1"]),
216+
providers: ["github"],
217+
evidenceIds: ["github-1"],
218218
}),
219219
]);
220220
});
@@ -940,9 +940,9 @@ describe("evidence-constrained synthesis", () => {
940940
{
941941
id: "linear-incident",
942942
provider: "linear",
943-
title: "Authentication outage for Northwind",
943+
title: "ENG-456 AuthShield tracker remains open",
944944
excerpt:
945-
"INC-2031: Northwind reported an authentication outage. Priya Raman filed this against Atlas Launch.",
945+
"Linear issue ENG-456 remains open for the AuthShield work linked to INC-2031 and Northwind.",
946946
timestamp: "2026-08-02T01:03:55Z",
947947
},
948948
{

0 commit comments

Comments
 (0)