Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions docs/content/agent-notes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ npx diffsplain \
The default batch size is 12 files. Smaller batches add the first notes to
the open page sooner.

## File limits and failed notes

Diffsplain sends a file鈥檚 full patch when it is at most 180,000 bytes. For a
larger patch, it sends the short patch excerpt shown in the page. If that
excerpt still makes the file input larger than 2,000,000 bytes, Diffsplain
rejects the file without starting an agent for it.

A bad file note or a failed agent pass does not remove valid notes from other
files. Diffsplain publishes each complete note, marks the run as failed, exits
with an error, and lists each failed path and reason in `meta.failedFiles`.
It ignores notes for paths outside the requested batch and reports those paths
as failures.

## Run one note pass

Generate or revise notes without starting the page:
Expand Down
32 changes: 32 additions & 0 deletions scripts/build-diff-data.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,22 @@ const completeChangeSummary = (value) =>
completeText(value.why) &&
completeList(value.highlights) &&
completeList(value.risks);
const failedFileRecords = (value) =>
Array.isArray(value)
? value
.filter(
(item) =>
item &&
typeof item.path === 'string' &&
item.path.trim() &&
typeof item.reason === 'string' &&
item.reason.trim(),
)
.map((item) => ({
path: item.path.trim(),
reason: item.reason.trim(),
}))
: [];

function fileSummary(path, value) {
return {
Expand Down Expand Up @@ -931,8 +947,19 @@ function build() {
: undefined;
const summariesAreFresh = !generatedFor || generatedFor === reviewFingerprint;
const sourceSummaries = summariesAreFresh ? summaryDoc : {};
const failedFiles = summariesAreFresh
? failedFileRecords(summaryDoc.meta?.failedFiles)
: [];
const summaryErrors = summariesAreFresh
? cleanList(summaryDoc.meta?.errors)
: [];
const failureByPath = new Map(
failedFiles.map((failure) => [failure.path, failure.reason]),
);
const summariesAreComplete =
summariesAreFresh &&
failedFiles.length === 0 &&
summaryErrors.length === 0 &&
completeChangeSummary(sourceSummaries.change) &&
filesWithoutSummaries.every((file) =>
completeFileSummary(sourceSummaries.files?.[file.path]),
Expand All @@ -954,6 +981,9 @@ function build() {
noteReady: Boolean(
completeFileSummary(sourceSummaries.files?.[file.path]),
),
...(failureByPath.has(file.path)
? { noteFailure: failureByPath.get(file.path) }
: {}),
}));
const change = changeSummary(sourceSummaries.change, target.changeDefaults);
const content = {
Expand All @@ -979,6 +1009,8 @@ function build() {
status: noteStatus,
completedFiles,
totalFiles: filesWithoutSummaries.length,
...(failedFiles.length ? { failedFiles } : {}),
...(summaryErrors.length ? { errors: summaryErrors } : {}),
...(typeof summaryDoc.meta?.model === 'string'
? { model: summaryDoc.meta.model }
: {}),
Expand Down
Loading
Loading