Skip to content

Answer busy local agent writes once saved (part of PRD-7398) (#5844) - #35

Merged
inkeep-oss-sync[bot] merged 1 commit into
mainfrom
copybara/sync
Oct 7, 2026
Merged

inkeep-oss-sync[bot] merged 1 commit into
mainfrom
copybara/sync

Conversation

@inkeep-oss-sync

Copy link
Copy Markdown

Copybara-translated 1 Inkeep OSS change. Rebase-merge this PR so the prepared commit lands directly on public main.

Linear: this mirror replays a change that already merged upstream, so it must not drive ticket status.
skip PRD-7398

* PRD-7398 Answer busy-project agent writes once they are saved

On a large local project under an agent write storm, agent-write-md
spent 50 to 110 seconds after the disk write waiting on post-write
advisories. Orphan hints, the broken-link advisory and the lint link
validator all query the derived document index, whose operations run
on one serial queue, and each write queued four to six reads behind the
backlog one after another. Clients timed out on writes that then
committed, and the long tail held agent sessions open until new writes
were refused with a 503 that did not say whether anything was saved.

The three index-dependent advisories now go through a write advisory
gate. Each waits at most 1.5 seconds; while an earlier advisory is
still waiting past that deadline, new ones are not started, so a
backlogged index costs at most one deadline per write instead of
growing the queue. A missed orphan hint or lint link check is omitted.
A missed link advisory returns the existing link-check-deferred warning
with a busy message, so an empty brokenLinks is never read as an
all-clear. The CRDT apply, flush and durability checks are unchanged,
and content-rule lint and mermaid validation still run, since neither
touches the index.

Every too-many-agent-sessions refusal (agent-write, agent-write-md,
frontmatter-patch, agent-patch, lint-fix and each batch entry) now
carries committed: false, retryAfterSeconds and a detail saying the
write was not applied, keeping the 503 status and Retry-After header.
The session is acquired before any mutation on all of these paths.

On the 7,501-file fixture at host load 20 to 33, burst-3x request
p95 fell from 48 s to 4.6 s, and 300 concurrent writes went from 0
accepted (256 client timeouts that later committed, 44 unlabeled 503s)
to 300 accepted with no timeouts. MCP brief, tool descriptions, the
MCP reference and the linking skill now say a deferred link check can
also mean the server was busy.

* PRD-7398 Address review of busy-project agent writes

Every MCP path that can receive the agent-session limit refusal now
shows its detail and retry interval: edit find/replace and frontmatter,
the frontmatter follow-up of a write from a template, and lint fix. They
share one writeRefusalText helper with the main write path. The MCP
reference documents the too-many-agent-sessions refusal next to
concurrent-overwrite-refused: 503, nothing written, committed false,
retryAfterSeconds with Retry-After, and the batch entry shape.

The docs and the project skill now name both causes of
link-check-deferred, a server still starting or an index busy with other
writes, and no longer tie the busy re-check to startup. The agentic
search page no longer presents a missing orphan hint as proof that a doc
is linked.

The advisory gate now logs a deferred advisory that fails after its
deadline, with its kind and error, and logs the gate closing at most
once a minute, so both are visible without OpenTelemetry.

A link-check index query that fails after the write is on disk now
degrades to the link-check-deferred warning with the error logged, on
single and batch writes, instead of answering a saved write with a 500.
The busy warning now says the index did not answer, usually because it
is busy with other writes.

The link projection that lint validation runs on every agent write now
schedules the debounced backlink cache save, as durable stores do,
instead of a full save on the serial index queue. That save added to the
same backlog the gate bounds.

Tests cover two advisories overdue at once, which keep the gate closed
until both settle and fail against a boolean flag. The stalled-write
fixture now has a hub doc, so the healthy write proves a hint would
appear before the stalled write asserts it does not. The suite timeout
now covers its own response bounds.

The changeset now says skipped link checks carry the warning. The
committed field keeps its name, because the hosted runtime's
project-busy problem uses the same field.

* PRD-7398 Log the advisory gate reopening and clarify partial template writes

A write from a template whose frontmatter patch is refused now says the
document was created and only the frontmatter patch was refused. It
keeps the refusal reason and retry interval, and names the recovery: an
edit of the existing document's frontmatter, not a repeat of the
templated write.

The write advisory gate now logs when it reopens, with how long it was
closed and how many advisories it skipped as busy, so a stuck gate can
be told apart from one that recovered. Gate lines stay at one per
minute: a change inside that window is reported by a single line at its
end, which carries the closings and skips counted meanwhile instead of
dropping them when no later closing arrives.

The MCP tools now render a failed request through one helper,
requestFailureText, with errorTextWithDetail as its prefixed form. An
empty detail is now omitted everywhere; install and skill tool errors
used to print it as an empty pair of parentheses. Their retry suffix
only appears when the server sends retryAfterSeconds, which those
endpoints never do, so their text is otherwise unchanged.

* PRD-7398 Only call a template frontmatter failure refused when nothing applied

A write from a template whose frontmatter patch fails used to say the
patch was refused and the document lacks that frontmatter for any
failure. Some failures arrive after the patch was applied: a disk
persistence failure, a stale external-write conflict, or a client
timeout, whose own text says the edit was applied or may have been.

The refused wording and the frontmatter-only edit recovery now apply
only when the response proves nothing was applied: a body with
committed false, such as the session-limit refusal, or a request or
frontmatter validation rejection, keyed off the problem type. Any other
failure says the document exists, that the response does not show
whether the frontmatter was applied, and to re-read the document,
alongside the server's own text. Both forms still say not to repeat the
templated write.

The MCP reference no longer ends the session-limit paragraph by telling
callers to repeat the write; it says to repeat the request, and that a
templated write whose frontmatter step failed should be finished with
edit or re-read, not repeated.

GitOrigin-RevId: b7773845d58bd50ab84d97dcf129e1848ffa13ca
@inkeep-oss-sync
inkeep-oss-sync Bot merged commit dce5d77 into main Oct 7, 2026
@inkeep-oss-sync
inkeep-oss-sync Bot deleted the copybara/sync branch October 7, 2026 09:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant