mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-11-06 23:20:53 +01:00
Bind note negation to the referenced design instruction
This commit is contained in:
1 parent
2545a5d534
commit
7fb1b10dea
2 files changed
+9
-5
No files matched your search
@@ -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); });
|
||||
@@ -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;
|
||||
}));
|
||||
|
||||
Reference in new issue
Block a user