feat(coding-agent): made hashline seen-line guard opt-in via edit.enforceSeenLines
- Added the `enforceSeenLines` option to hashline `PatcherOptions` (defaults `true`); the seen-line guard in `Patcher` now runs only when enabled. - Added the `edit.enforceSeenLines` coding-agent setting (default off) and wired it through `edit/hashline/execute.ts` into the `Patcher`. - Stopped `file-snapshot-store` excluding column-clipped (>512-char) lines from a snapshot's seen set, so single-line edits on long lines apply without a full-width re-read. - Updated `seen-line-guard` tests and the hashline/coding-agent changelogs.
This commit is contained in:
@@ -131,27 +131,18 @@ export function recordSeenLines(
|
||||
}
|
||||
|
||||
/**
|
||||
* Attach the lines a read displayed to the snapshot it minted, so the patcher
|
||||
* can reject edits anchored on lines the model never saw. Best-effort: a no-op
|
||||
* when the body has no numbered rows or the snapshot already aged out. `tag`
|
||||
* must be the tag returned when this exact content was recorded.
|
||||
*
|
||||
* `excludedLines` prunes 1-indexed line numbers whose displayed text was
|
||||
* column-truncated (or otherwise not shown in full). A column-clipped row
|
||||
* still carries a `NN:` prefix — the parser sees the number and would
|
||||
* otherwise mark the line "seen" even though only its prefix ever reached
|
||||
* the model. Producers that apply per-line column truncation MUST supply
|
||||
* the clipped line set so the patcher's seen-line guard keeps rejecting
|
||||
* edits against those lines until a full-width read of them occurs.
|
||||
* Attach the lines a read displayed to the snapshot it minted, so the patcher's
|
||||
* (opt-in) seen-line guard can reject edits anchored on lines the model never
|
||||
* saw. Best-effort: a no-op when the body has no numbered rows or the snapshot
|
||||
* already aged out. `tag` must be the tag returned when this exact content was
|
||||
* recorded. Every displayed `NN:` row counts as seen, including column-clipped
|
||||
* rows — the guard no longer distinguishes full-width from truncated display.
|
||||
*/
|
||||
export function recordSeenLinesFromBody(
|
||||
session: FileSnapshotStoreOwner,
|
||||
absolutePath: string,
|
||||
tag: string,
|
||||
body: string,
|
||||
excludedLines?: ReadonlySet<number>,
|
||||
): void {
|
||||
const parsed = parseSeenLinesFromHashlineBody(body);
|
||||
const filtered = excludedLines && excludedLines.size > 0 ? parsed.filter(line => !excludedLines.has(line)) : parsed;
|
||||
recordSeenLines(session, absolutePath, tag, filtered);
|
||||
recordSeenLines(session, absolutePath, tag, parseSeenLinesFromHashlineBody(body));
|
||||
}
|
||||
|
||||
@@ -210,7 +210,8 @@ export async function executeHashlineSingle(
|
||||
batchRequest: options.batchRequest,
|
||||
});
|
||||
const snapshots = getFileSnapshotStore(options.session);
|
||||
const patcher = new Patcher({ fs, snapshots, blockResolver: nativeBlockResolver });
|
||||
const enforceSeenLines = options.session.settings.get("edit.enforceSeenLines");
|
||||
const patcher = new Patcher({ fs, snapshots, blockResolver: nativeBlockResolver, enforceSeenLines });
|
||||
|
||||
// Single-section fast path: prepare, commit, render.
|
||||
const inputHash = hashPatchInput(options.input);
|
||||
|
||||
Reference in New Issue
Block a user