docs(tool-fs): state apply_patch's whole-patch preflight in the model guidance

The guidance described only the commit phase ("stop at the first failure,
not rolled back"), so a model inferred that an invalid hunk would leave
earlier operations applied. The sentence now says the whole patch is checked
first and a rejected patch changes nothing before describing commit order.
This commit is contained in:
sjw1231 committed 2026-10-28 15:37:36 +08:00
1 parent 1f1a9cda72
commit 5711d3aae7
5 files changed
+7 -6

No files matched your search

+1 -1
View File
@@ -266,7 +266,7 @@ The `apply_patch` schema requires one `input` string (the Codex parameter name,
##### System guidance
```markdown
Prefer apply_patch over separate edit calls for changes across files or separated regions. Give every hunk enough surrounding context lines to match one place in the current file. Operations run in order, stop at the first failure, and are not rolled back; re-read affected files before retrying when needed.
Prefer apply_patch over separate edit calls for changes across files or separated regions. Give every hunk enough surrounding context lines to match one place in the current file. The whole patch is checked first (syntax, hunk matching, missing files) and a rejected patch changes nothing; once applying starts, operations run in order, stop at the first failure, and are not rolled back, so re-read affected files before retrying when needed.
```
##### Result examples
+1 -1
View File
@@ -266,7 +266,7 @@ Read a file before editing it (the default fs-observation-policy requires it), u
##### 系统提示
```markdown
Prefer apply_patch over separate edit calls for changes across files or separated regions. Give every hunk enough surrounding context lines to match one place in the current file. Operations run in order, stop at the first failure, and are not rolled back; re-read affected files before retrying when needed.
Prefer apply_patch over separate edit calls for changes across files or separated regions. Give every hunk enough surrounding context lines to match one place in the current file. The whole patch is checked first (syntax, hunk matching, missing files) and a rejected patch changes nothing; once applying starts, operations run in order, stop at the first failure, and are not rolled back, so re-read affected files before retrying when needed.
```
##### 结果示例
+2 -1
View File
@@ -27,7 +27,8 @@ export function applyApplyPatchTool(ctx: Context, sandbox: FsSandboxController,
text: ({ scope }) => ctx.tools.get('apply_patch', scope) === undefined ? ''
: 'Prefer apply_patch over separate edit calls for changes across files or separated regions. '
+ GUARD_GUIDANCE[guard]
+ 'Operations run in order, stop at the first failure, and are not rolled back; re-read affected files before retrying when needed.',
+ 'The whole patch is checked first (syntax, hunk matching, missing files) and a rejected patch changes nothing; '
+ 'once applying starts, operations run in order, stop at the first failure, and are not rolled back, so re-read affected files before retrying when needed.',
})
ctx.tools.register(defineTool({
name: 'apply_patch',
@@ -12,7 +12,7 @@ import { add, move, patch, remove, setup, update } from './patch/harness.ts'
const guidance = 'Prefer apply_patch over separate edit calls for changes across files or separated regions. '
+ 'Read a file before updating, deleting, or moving it (the default fs-observation-policy requires it), unless you just created or edited it in this session. '
+ 'Operations run in order, stop at the first failure, and are not rolled back; re-read affected files before retrying when needed.'
+ 'The whole patch is checked first (syntax, hunk matching, missing files) and a rejected patch changes nothing; once applying starts, operations run in order, stop at the first failure, and are not rolled back, so re-read affected files before retrying when needed.'
type Fixture = Awaited<ReturnType<typeof setup>>
function call(t: Fixture, text: string) {
@@ -48,7 +48,7 @@ it('drops the read-first guidance and schema sentence when the guard is off', as
const section = (await t.ctx.systemPrompt.assemble()).sections.find(section => section.name === 'tool:apply_patch')
expect(section?.text).toBe('Prefer apply_patch over separate edit calls for changes across files or separated regions. '
+ 'Give every hunk enough surrounding context lines to match one place in the current file. '
+ 'Operations run in order, stop at the first failure, and are not rolled back; re-read affected files before retrying when needed.')
+ 'The whole patch is checked first (syntax, hunk matching, missing files) and a rejected patch changes nothing; once applying starts, operations run in order, stop at the first failure, and are not rolled back, so re-read affected files before retrying when needed.')
const guarded = await setup()
const description = (fixture: Fixture) => (fixture.ctx.tools.get('apply_patch')?.parameters as { properties: { input: { description: string } } }).properties.input.description
expect(description(guarded)).toContain('Read existing files before updating, deleting, or moving them.')
@@ -10,7 +10,7 @@ Read an existing file before overwriting it with write (the default fs-observati
Read a file before editing it (the default fs-observation-policy requires it), unless you just created or edited it in this session.
Prefer apply_patch over separate edit calls for changes across files or separated regions. Read a file before updating, deleting, or moving it (the default fs-observation-policy requires it), unless you just created or edited it in this session. Operations run in order, stop at the first failure, and are not rolled back; re-read affected files before retrying when needed.
Prefer apply_patch over separate edit calls for changes across files or separated regions. Read a file before updating, deleting, or moving it (the default fs-observation-policy requires it), unless you just created or edited it in this session. The whole patch is checked first (syntax, hunk matching, missing files) and a rejected patch changes nothing; once applying starts, operations run in order, stop at the first failure, and are not rolled back, so re-read affected files before retrying when needed.
Use the glob tool — not shell find — to discover files by path pattern.