From 7fb1b10dea9f73c1e8af6626039d45d404d344d0 Mon Sep 17 00:00:00 2001 From: Dotta Date: Tue, 27 Oct 2026 01:50:48 -0500 Subject: [PATCH] Bind note negation to the referenced design instruction --- .../internal-comment-reference.test.ts | 4 ++-- .../runner-e2e/chat-catalog-domains/internal-tasks.ts | 10 +++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tests/runner-e2e/chat-catalog-domains/internal-comment-reference.test.ts b/tests/runner-e2e/chat-catalog-domains/internal-comment-reference.test.ts index 02d57eb01af..ca2528e528a 100644 --- a/tests/runner-e2e/chat-catalog-domains/internal-comment-reference.test.ts +++ b/tests/runner-e2e/chat-catalog-domains/internal-comment-reference.test.ts @@ -5,8 +5,8 @@ function observation(body: string): InternalObservation { const task = { id: "task", companyId: "company", title: "Landing page", status: "backlog" }, design = { id: "design", identifier: "ACO-2", companyId: "company", title: "Approved design", status: "done" }; return { scenarioId: "tasks.comment-with-reference", origin: "https://fixture.test", companyId: "company", leadId: "ceo", state: { task: structuredClone(task), design: structuredClone(design) }, tasks: [task, design], projects: [], goals: [], documents: [], revisions: [], activity: [], reply: "Note added.", humanQueries: [], links: ["/ACO/issues/task"], comments: [{ id: "note", authorAgentId: "ceo", createdByRunId: "run", body }], runs: [{ id: "run", status: "succeeded" }] }; } -for (const body of ["Follow [the approved design](/ACO/issues/design).", "Please use [this design](https://fixture.test/ACO/issues/ACO-2) for implementation.", "Adhere to [the approved design](/ACO/issues/design?tab=documents).", "Implement according to [the design](/ACO/issues/design).", "Build in line with [the approved design](/ACO/issues/design)."]) +for (const body of ["Follow [the approved design](/ACO/issues/design).", "Please use [this design](https://fixture.test/ACO/issues/ACO-2) for implementation.", "Adhere to [the approved design](/ACO/issues/design?tab=documents).", "Implement according to [the design](/ACO/issues/design).", "Build in line with [the approved design](/ACO/issues/design).", "Follow [the approved design](/ACO/issues/design) and avoid unrelated layout changes.", "Do not forget to follow [the approved design](/ACO/issues/design)."]) it(`accepts affirmative actual design instruction: ${body}`, () => expect(grade_tasks(observation(body)).passed).toBe(true)); -for (const body of ["Do not follow [the design](/ACO/issues/design).", "Never use [the design](/ACO/issues/design).", "Follow [the wrong task](/ACO/issues/other); the intended design ID is design.", "Follow [the design](https://foreign.test/ACO/issues/design).", "Follow [the design](/ACO/issues/design), but do not follow it.", "Here is [the design](/ACO/issues/design).", "Follow [another task](/ACO/issues/other). Reference [the design](/ACO/issues/design)."]) +for (const body of ["Do not follow [the design](/ACO/issues/design).", "Never use [the design](/ACO/issues/design).", "Ignore [the design](/ACO/issues/design), but follow [the design](/ACO/issues/design).", "Follow [the design](/ACO/issues/design) but ignore it.", "Follow [the wrong task](/ACO/issues/other); the intended design ID is design.", "Follow [the design](https://foreign.test/ACO/issues/design).", "Follow [the design](/ACO/issues/design), but do not follow it.", "Here is [the design](/ACO/issues/design).", "Follow [another task](/ACO/issues/other). Reference [the design](/ACO/issues/design)."]) it(`rejects negated, unrelated or merely mentioned reference: ${body}`, () => expect(grade_tasks(observation(body)).passed).toBe(false)); it("preserves exact note authorship and duplicate rejection", () => { const o = observation("Follow [the design](/ACO/issues/design)."); o.comments[0]!.authorAgentId = "other"; expect(grade_tasks(o).passed).toBe(false); o.comments[0]!.authorAgentId = "ceo"; o.comments.push(structuredClone(o.comments[0]!)); expect(grade_tasks(o).passed).toBe(false); }); diff --git a/tests/runner-e2e/chat-catalog-domains/internal-tasks.ts b/tests/runner-e2e/chat-catalog-domains/internal-tasks.ts index d27b86ad1b3..0d0bcf04a3e 100644 --- a/tests/runner-e2e/chat-catalog-domains/internal-tasks.ts +++ b/tests/runner-e2e/chat-catalog-domains/internal-tasks.ts @@ -17,10 +17,14 @@ function savedDesignInstruction(o: InternalObservation, body: string, design: En const valid = targets.map((href, index) => hasLink({ ...o, links: [href] }, "issues", design) ? `{{DESIGNREF${index}}}` : null).filter((x): x is string => !!x); if (!valid.length) return false; const directive = /\b(?:follow|use|adhere\s+to|implement\s+(?:according\s+to|in\s+line\s+with)|build\s+(?:according\s+to|in\s+line\s+with))\b/i; - const negative = /\b(?:do not|don't|must not|should not|never|not to|avoid|ignore|disregard|stop)\b/i; + const governsNegativeReference = (prefix: string) => { + const text = prefix.replace(/\b(?:do not|don't) forget to\b/gi, "remember to"); + return /\b(?:do not|don't|must not|should not|never|not to|not)\b[^{}.;!\n]{0,60}\b(?:follow|use|adhere|implement|build)\b[^{}.;!\n]{0,80}$/i.test(text) + || /\b(?:avoid|ignore|disregard|stop)\b[^{}.;!\n]{0,80}$/i.test(text); + }; const clauses = prose.split(/[.;!\n]+/).filter(clause => valid.some(token => clause.includes(token))); - if (clauses.some(clause => negative.test(clause))) return false; - if (/\b(?:do not|don't|never|must not|should not)\s+(?:follow|use|adhere\s+to)\s+(?:it|this|that|the\s+(?:approved\s+)?design)\b/i.test(prose)) return false; + if (clauses.some(clause => valid.some(token => { const at = clause.indexOf(token); return at >= 0 && governsNegativeReference(clause.slice(0, at)); }))) return false; + if (/\b(?:(?:do not|don't|never|must not|should not)\s+(?:follow|use|adhere\s+to)|ignore|disregard)\s+(?:it|this|that|the\s+(?:approved\s+)?design)\b/i.test(prose)) return false; return clauses.some(clause => directive.test(clause) && valid.some(token => { const instruction = directive.exec(clause); return !!instruction && clause.indexOf(token) > instruction.index; }));