Distinguish file delivery references from inline contents

Co-authored-by: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-10-03 03:18:08 -05:00
1 parent fef9e84562
commit 062902cea2
4 files changed
+28 -4

No files matched your search

@@ -431,6 +431,13 @@ prices are estimates. Unpriced usage must stay unpriced in the ledger and UI.
in chat do not. All 76 completion tests pass; the exact failed agent-files
objective still needs no download. Wait for clean source review before
rebuilding public packages again.
- At `fef9e8456`, review identifies a missing explicit "send it" delivery
requirement. Preserve delivery references to the preceding file, including
across sentences, while explicit inline/chat content remains inline.
Attachment/export directives always retain publication requirements. All 84
completion tests pass, including both delivery and inline instructions. The
exact failed agent-files objective still needs no download; no paid retry runs
on these intermediate candidates.
- The `0d65753fe` broad local suite is terminal with 736 passed files, four
skipped files, 14,982 passed tests and three failures: a Git scan load
single-flight count (497 versus 498) and two HTTP socket resets. One associated
@@ -22,6 +22,11 @@ describe("explicit file output requirements", () => {
"Write report.txt and attach it. This is an internal verification file, not a deliverable.",
"Attach it.",
"Write report.txt and return it as an attachment. This is an internal verification file, not a deliverable.",
"Write report.txt and send it to me. This is an internal verification file, not a deliverable.",
"Write report.txt. This is an internal verification file, not a deliverable. Send it to me.",
"Write report.txt and provide it to me. This is an internal verification file, not a deliverable.",
"Write report.txt and give me it. This is an internal verification file, not a deliverable.",
"Write report.txt and return it. This is an internal verification file, not a deliverable.",
])("recognizes an explicit output request: %s", objective => {
expect(explicitlyRequestsFileOutput(objective)).toBe(true);
});
@@ -50,6 +55,8 @@ describe("explicit file output requirements", () => {
"Write internal-proof.txt; do not attach it. This is an internal verification file, not a deliverable.",
"Write a reply and return it in chat.",
"Write internal-proof.txt and return it in chat. This is an internal verification file, not a deliverable.",
"Write internal-proof.txt and send it in chat. This is an internal verification file, not a deliverable.",
"Write internal-proof.txt. This is an internal verification file, not a deliverable. Return it inline.",
])("does not require a file for a text or source-review request: %s", objective => {
expect(explicitlyRequestsFileOutput(objective)).toBe(false);
});
@@ -64,6 +64,7 @@ async function hasCurrentPublicationReceipt(db: Db, companyId: string, receipts:
*/
export function explicitlyRequestsFileOutput(objective: string): boolean {
const sentences = objective.replaceAll("\\_", "_").split(/(?:[.!?](?:\s|$)|\n)/iu);
let precedingFileOutput = false;
return sentences.some((sentence, index) => {
const file = /\b(?:files?|attachments?|downloads?|pdf|spreadsheets?|workbooks?|slide decks?|powerpoints?|docx|xlsx|csv)\b|\b[^\s/]+\.(?:md|txt|pdf|docx?|xlsx?|csv|pptx?|png|jpe?g|svg|zip)\b/giu;
const outputs = sentence.split(/(?:[;,]|\bbut\b)/iu).flatMap(clause => {
@@ -89,15 +90,19 @@ export function explicitlyRequestsFileOutput(objective: string): boolean {
});
// An explicit attachment/export request can refer to the file by
// pronoun. It still requires publication when its name is omitted.
const referencedAttachment = /^(?:attach|export)$/iu.test(create[0])
const referencesOutput = /^(?:attach|export|send|provide|give|return)$/iu.test(create[0])
&& /^\s+(?:me\s+)?(?:it|them|this|that)\b/iu.test(output);
const referencedAttachment = referencesOutput && /^(?:attach|export)$/iu.test(create[0]);
const inline = /\b(?:in (?:the )?chat|inline|as (?:a |the )?(?:chat )?(?:reply|message)|(?:its|the) contents)\b/iu.test(output);
const downloadable = referencedAttachment || (!/\b(?:no|without)\s+(?:downloadable|attached)/iu.test(output)
&& /\b(?:downloadable|attached)\s+(?:file|report|document|checklist|draft)\b/iu.test(output));
const publication = /\b(?:downloadable|attached|attach|export|send|provide|return|give)\b/iu.test(create[0] + output);
const deniedAttempt = create[0].toLowerCase() === "write" && objects.length === 1
&& /\b(?:attempt|try)\s+(?:the\s+)?native\s*$/iu.test(before)
&& /\b(?:must be denied|denial is (?:the )?expected|(?:this|the) negative test)\b/iu.test(objective);
return [{ objects: objects.length, downloadable, publication, deniedAttempt }];
if (objects.length === 0 && !downloadable && /^\s+(?:no|zero|without)\b/iu.test(output)) return [];
return [{ objects: objects.length, downloadable, publication, deniedAttempt,
referencesOutput, publicationReference: referencesOutput && !inline }];
});
});
// "This ..." qualifies a single requested file in the preceding sentence,
@@ -105,8 +110,12 @@ export function explicitlyRequestsFileOutput(objective: string): boolean {
// exception and separate report requests still require publication.
const internal = outputs.reduce((count, output) => count + output.objects + Number(output.downloadable && output.objects === 0), 0) === 1
&& /^\s*This is (?:an? )?(?:personal memory|internal (?:assertion|verification) file)\b[^.!?]*\bnot a (?:task )?deliverable\b/iu.test(sentences[index + 1] ?? "");
return outputs.some(output => (output.objects > 0 || output.downloadable)
&& (output.publication || (!internal && !output.deniedAttempt)));
return outputs.some(output => {
const publicationReference = output.publicationReference && precedingFileOutput;
if (!output.referencesOutput) precedingFileOutput = output.objects > 0;
return (output.objects > 0 || output.downloadable || publicationReference)
&& (output.publication || (!internal && !output.deniedAttempt));
});
});
}
@@ -354,6 +354,7 @@ describe("native runner file handoff", () => {
"Write report.pdf; write internal-proof.txt. This is an internal verification file, not a deliverable.",
"Write report.pdf and attempt native write to /outside/probe.txt; this negative test must be denied.",
"Write report.txt and attach it. This is an internal verification file, not a deliverable.",
"Write report.txt and send it to me. This is an internal verification file, not a deliverable.",
])("still requires publication when the task also asks for internal or denied writes: %s", async objective => {
await db.update(heartbeatRuns).set({ contextSnapshot: { issueId, executionContinuation: { objective } } })
.where(eq(heartbeatRuns.id, runId));