Commit Graph

11383 Commits

Author SHA1 Message Date
Diogo Soares Rodrigues 91b703b6af fix(cursor): resolve symlinks when confining resource downloads
A lexical containment check is not containment. `out/config` is
relative and `..`-free, so it passed - while a `ws/out -> /elsewhere`
link inside the workspace sent the write straight out. Proven before
the fix: the download landed in the link's target.

Containment now realpaths three things: the target when it exists, the
immediate link destination when it is a dangling symlink (a write still
follows it), and otherwise the deepest existing ancestor with the
not-yet-created segments re-applied. Each branch has a regression, and
all three fail the suite when individually reverted.

Also moves this branch's ai/catalog changelog entries back under
[Unreleased]; two commits had re-landed them inside the released
[17.1.5] section, which left `packages/ai/CHANGELOG.md` with two.
All three released sections are now byte-identical to upstream/main.

(cherry picked from commit e3ed4035ab8a1781c49a68c1fbe92c88bec3aa25)
2026-07-30 01:42:29 +02:00
Diogo Soares Rodrigues 7a944f1baa fix(cursor): confine MCP resource downloads to the workspace
`download_path` is workspace-relative by contract, but it arrives from
the server and `resolveToCwd` deliberately honors absolute paths, `~`,
and `..` - correct for a path a user typed, a write-anywhere primitive
for one a remote peer supplied. `/etc/cron.d/x` or `../../escape` would
have been written wherever the process can reach.

`confineToWorkspace` accepts only a non-empty relative path resolving
under the live cwd, and the download refuses anything else. The refusal
throws inside the dispatch's existing try, so it reaches the model as a
`ReadMcpResourceError` rather than a silent success or a crash.

(cherry picked from commit 963cfee21a56576033ec115db745bb18ab0a8d06)
2026-07-30 01:42:29 +02:00
Diogo Soares Rodrigues 01be80b9ea fix(cursor): honor download_path on MCP resource reads
`ReadMcpResourceExecArgs.download_path` means "write the resource to
this workspace-relative path and return no model content". The handler
I added forwarded only server and uri, so a download reported success
while creating no file and leaving `ReadMcpResourceSuccess.download_path`
unset - the model was pointed at a path that did not exist.

The path now reaches the handler, the bridge writes the bytes (decoding
a base64 blob, or the joined text) under the session cwd, and the
answer carries the path with the content oneof deliberately unset: a
host that also has the payload on hand must not have it forwarded, or
the download mode puts it right back in context.

(cherry picked from commit f0a6784533201f412529fb0ae5a6542531012197)
2026-07-30 01:42:29 +02:00
Diogo Soares Rodrigues 6d42f6e52e fix(cursor): read pi_ls's entry cap from the shape read actually sets
The bridge looked for a flat `details.resultLimitReached`. `glob` sets
that alongside the structured meta, so `pi_find` worked; `read` - the
tool serving `pi_ls` - records the cap only through `OutputMeta`, at
`details.meta.limits.resultLimit.reached`. Every capped listing
therefore reached Cursor with `entry_limit_reached` unset, which reads
as a complete listing.

Both shapes are now checked, mirroring how `piTruncation` already
handles its two producers. Covered by running the real `ReadTool`
against a directory that trips the per-directory cap and asserting the
wire field, so a move in the producer's shape fails here instead of
silently sending clipped output as whole.

(cherry picked from commit cbfe7ca9d59faa2f967e2724744b58a96a9a1839)
2026-07-30 01:42:29 +02:00
Diogo Soares Rodrigues 0601ee7324 fix(cursor): route MCP resource frames and gate native delete
`list_mcp_resources` / `read_mcp_resource` answered as though this
client hosted no MCP servers - a hardcoded empty catalog and
`not_found`. The same session reads those resources through `mcp://`
via `MCPManager.getServerResources` / `readServerResource`, so a Cursor
model could not see resources its own session was connected to.
`CursorExecHandlers` gained `listMcpResources`/`readMcpResource`, the
bridge answers them from the manager's live connections, and the
no-handler fallback is unchanged. A throwing lookup surfaces as an
error: an empty success claims "asked, none exist", which the model
cannot retry.

The native `delete` frame also bypassed approval. Unlike every other
frame it calls `fs.rmSync` directly rather than running a registry
tool, so no `ExtensionToolWrapper` sat in front of it, and
`allowNativeDelete` only answers whether a mutating tool was granted -
not whether the user's policy allows the call. It now resolves the
write tier against the session's approval mode and per-tool policies,
failing closed on `always-ask`, which this channel cannot prompt in.

(cherry picked from commit 44d36d1e8d35b0038d00e0202454d68fbcc53bce)
2026-07-30 01:42:28 +02:00
Diogo Soares Rodrigues a363f95009 fix(cursor): pair interrupted calls and gate advisor bridge approval
Two independent bugs found in review.

A stream that dies mid-turn takes the terminal-error path: `settleH2`
rejects when the transport closes without `turnEnded`, so the flush on
the success path never runs. `connect_scm` and native todo blocks are
stamped `kCursorExecResolved` at start, so `agent-loop.ts` synthesizes
no placeholder and only their completion frame pairs a result - the call
was left unpaired and its card animating, and `buildSessionContext`
strips a dangling call from every rebuilt transcript. The catch path now
closes open blocks and pairs those server-owned calls with an
interrupted result. Exec-settled MCP blocks are excluded: the dispatch
that ran them owns their result and `drainInFlightDispatches` awaits it,
so pairing here would duplicate against the same id.

Separately, the advisor bridge supplied no `getToolContext`.
`ExtensionToolWrapper` reads the approval mode, per-tool policies and
`autoApprove` only from that execute-time context, so every wrapped
advisor bridge tool resolved as `yolo` with empty policies - a
configured `ask` or `deny` on `edit`/`grep` did not apply to native
frames. Advisors now get the same `ToolContextStore` as the primary
bridge.

Both are covered against the real paths: the interrupted call through
the HTTP/2 fixture server (a helper-level test passes even with the
catch-path flush removed), and approval through real deny policies.

(cherry picked from commit 5ace682578af96708caf88db2d44b9077a1c0e74)
2026-07-30 01:42:28 +02:00
Diogo Soares Rodrigues 5779c762de fix(cursor): give advisors the replace-mode edit pi_edit needs
The primary bridge builds a `replace`-mode `EditTool` because
`PiEditExecArgs` carries `old_text`/`new_text` pairs that no other mode
accepts. The advisor roster passed its own instances straight through,
and those follow the session's configured `edit.mode` - `hashline` by
default, whose schema is a single `input` string - so every native
advisor edit failed validation instead of touching the file.

Both bridge-only tools now come from `cursor-bridge-tools.ts`:
`createBridgeEditTool` builds the wrapped `replace` instance, and
`bridgeToolMap` substitutes it into a granted map. The substitution is
gated on `edit` actually having been granted, since the tool is
constructed rather than looked up - handing one to a read-only roster is
the #5680 escalation. The advisor's own loop keeps its instance; only
the exec map is swapped.

(cherry picked from commit e6cf9f8046c595cab9793b4b2a5795d8488d8d22)
2026-07-30 01:42:28 +02:00
Diogo Soares Rodrigues a4e714279c docs(changelog): move this branch's entries out of released 17.1.5
The rebase onto a tree where 17.1.5 had been cut landed this branch's
entries inside that released section. Released sections are immutable,
so they belong under [Unreleased] — the release script folds them into
whatever version ships next.

Both released sections are now byte-identical to upstream/main, no
bullet was dropped in the move, and the `Added` heading the
coding-agent entry needs came back with it.

(cherry picked from commit c1c6566dccb7255395e463c940cca6c76a707a9d)
2026-07-30 01:42:28 +02:00
Diogo Soares Rodrigues 8737987398 fix(cursor): gate bridge-only edit and grep on the granted tool set
Both are constructed rather than looked up, and `executeTool` prefers a
constructed override over the registry — so a session that withheld
either still got a working frame. Native `pi_edit`/`pi_grep` arrive
regardless of the advertised catalog, so a restricted agent
(`toolNames` without them, or `restrictToolNames: true`) could modify
and search files it was never granted.

Both now check the registry for the grant before building. The edit
check reads it before the Cursor-specific delete, since that delete is
about not advertising the tool, not about revoking it. This is the same
escalation the `delete` frame already guards against (#5680); the
advisor path got the grep gate in the previous commit and the primary
session was missed.

(cherry picked from commit 68f82b0ce08bb93db941e0fbe1bd2a515d45c2cb)
2026-07-30 01:42:28 +02:00
Diogo Soares Rodrigues f785d76bc9 fix(cursor): honor an explicit zero pi_bash timeout
`timeout` is `optional int32` and `bash` documents `0` as "disables the
command deadline". Both the bridge and the provider's synthesized block
gated on `timeout && timeout > 0`, folding a supplied `0` into unset —
so the 300s default applied and the long-running command that asked not
to be killed was killed.

The expression was duplicated across the two sides, which is the drift
the shared translation exists to prevent, so it moves into
`cursor-pi-args` as `piTimeout` alongside the other presence-sensitive
mappings. Negatives have no local meaning and would clamp to `bash`'s 1s
floor, so those still fall back to the default.

Verified against a real BashTool: `timeout: 0` yields
`timeoutDisabled: true`, omitted yields the default, `42` passes
through, and `-5` matches the omitted case rather than the 1s clamp.
Mutation-checked on both branches.

(cherry picked from commit db442ae5aed90dc2268b2d898ef99ef4e0961c10)
2026-07-30 01:42:27 +02:00
Diogo Soares Rodrigues 6eaf090ccc fix(cursor): repair pi_edit and close the scoped-grep approval bypass
Three defects the exec bridge shipped with, all found by review.

`pi_edit` never worked. The session removes `edit` from the tool
registry for Cursor so the model is steered to full-file `write`
(8ba0498eb), but that same registry is the bridge's tool source, so the
native frame — which the server sends regardless of the advertised
catalog — resolved nothing and answered `Tool "edit" not available`.
Retaining the instance is not enough either: `PiEditExecArgs` carries
`old_text`/`new_text` pairs, which only `replace` accepts, while the
default mode is `hashline` (`{ input: string }`). `EditTool` now takes
an optional mode, and the bridge resolves a pinned `replace` instance
through its fallback resolver.

A `pi_grep` frame carrying `context` or `limit` escaped the approval
gate. Honoring those needs a per-call tool, and the per-call instance
was built raw while every registry tool is wrapped — so exactly those
calls skipped `tools.approval.grep` and the exec-tier SSH check. Both
callsites now go through one `createBridgeGrepFactory`.

Advisors ignored the same two fields: only the primary session supplied
the factory. They now get it too, gated on the advisor actually holding
`grep` so the factory cannot grant a denied tool.

Also moves the pure Pi arg translation to `providers/cursor-pi-args`.
The legacy shim shares it and is compiled into the bundled virtual
registry, where `./providers/*` cannot match a nested specifier — it
fell through to `Bun.resolveSync`, unsatisfiable under bunfs (#3442) —
and the exec module would have dragged the protobuf graph along.

Verified against real files and the real module graph: `pi_edit` mutates
a temp file, the bundled probe executes the shim's shared module in a
subprocess, and the grep test drives the shared factory. Mutation-
checked: returning a raw tool from the factory, ignoring the pinned edit
mode, dropping the `getTool` fallback, or moving the helpers back to a
nested path each fails a test.

(cherry picked from commit e46ba22b634e449005f7c22b6d0efd19a45ce1f8)
2026-07-30 01:42:23 +02:00
Diogo Soares Rodrigues ab7b457af0 fix(cursor): read pi_bash truncation from the shape BashTool emits
Two truncation records exist locally. `read`/`grep` set
`details.truncation` (`TruncationResult`), which carries an explicit
`truncated` boolean. `bash` sets `details.meta.truncation`
(`TruncationMeta`), which has no such flag — its presence is the signal.

`piTruncation` read only the first and required the boolean, so every
real Bash truncation was dropped: Cursor got clipped output with no
indication it was clipped. Both shapes now translate; `TruncationResult`
stays authoritative when present so an explicit `false` still suppresses.

Also drops the legacy pi shim's copies of the regex-literal escaper and
the path/glob join. Both were verbatim duplicates of the modern bridge's
helpers, which is the drift the shared translation exists to prevent.

Verified producer-to-consumer, not against a hand-built bag: the test
runs a real `BashTool`, asserts its output has no top-level `truncation`
and no `truncated` flag under `meta`, then feeds those exact details to
`piTruncation`. Typed against the producer's own `TruncationMeta`, so a
renamed field fails compilation rather than silently reverting the bug.
Mutation-checked: reverting to the top-level lookup, restoring the flag
requirement, or dropping the null guard each fails a test.

(cherry picked from commit 6699672d52061b832677dd45315f4aba8d330db1)
2026-07-30 01:42:11 +02:00
Diogo Soares Rodrigues 9436fb5640 feat(cursor): honor pi_grep's context and limit
`pi_grep` carries a context width and a total match cap. Neither is
expressible in the model-facing `grep` schema — context comes from
`grep.contextBefore`/`grep.contextAfter`, fixed when the shared tool is
constructed — so both were dropped.

`GrepTool` now takes them as constructor options. The model-facing
schema is unchanged: this is a seam for wire bridges whose protocol
supplies the values, mirroring `GlobTool`'s existing options bag. The
bridge builds a per-call `grep` only for frames that supply them;
everything else keeps the shared instance and session defaults.

`pi_ls`'s `limit` stays unmapped, now deliberately and documented. It
caps directory entries, while the local `read` renders a depth-2 tree
and slices rendered lines — nested rows, headers and elision summaries
all count — so `:1+K` would cap a different unit while looking honored.

Verified against real files in a temp dir, not captured arguments:
match counts and context lines are asserted from actual search output.
Mutation-checked — ignoring either option, or dropping the scoped tool
in the bridge, fails a test.

(cherry picked from commit 299ded5a274427c2c2d5de27c00a2056a709581c)
2026-07-30 01:42:06 +02:00
Diogo Soares Rodrigues 7b62fef366 fix(cursor): honor Pi frame arguments and preserve open-block args
Review of the modern exec wire protocol surfaced defects the committed
suite did not pin.

The Pi bridge dropped frame arguments: `pi_read`'s offset/limit (ranged
reads returned whole files), `pi_grep`'s literal (fixed strings ran as
regexes), and the path/glob join emitted `./`-prefixed specs. These are
`optional int32`, so a present `0` is a value, not "unset" — `limit: 0`
now answers empty rather than reading everything, and `pi_find` clamps
to 1 like the reference client.

The provider synthesized its transcript block from a second, divergent
translation of the same frame, so the displayed operation differed from
the executed one. Both sides now share one mapper in `exec-modern.ts`.

End-of-transport cleanup reparsed every open block's streamed argument
buffer; blocks whose args arrive whole never set that buffer, and
`parseStreamingJson(undefined)` is `{}`, so a truncated turn erased
their arguments.

All fixes are mutation-verified: reverting each one fails a test.

(cherry picked from commit bb7bcfebce4200d436e17d6e39320da13fc85ca8)
2026-07-30 01:41:55 +02:00
Diogo Soares Rodrigues b6e01c8a3c feat(ai): handle Cursor's modern exec wire protocol
Current Cursor CLI builds emit exec frames this client did not model. A
frame whose oneof number is absent from `agent.proto` decodes with
`message.case` unset, so the dispatcher found no handler, ran no tool and
sent no result — the server was left waiting on an execution that never
happened.

Every recognised frame now gets a typed answer:

- The seven Pi tools (45-51) run their local equivalents. They are a
  separate wire family from the legacy args, not aliases: `pi_grep`'s
  `ignore_case` is the inverse of the local `case` flag, `pi_find`
  searches filenames (so it routes to `glob`, not `grep`), and
  `pi_edit`'s replacements are renamed to snake_case pairs.
- Hooks, subagents, prechecks, MCP state, smart-mode, canvas,
  conversation search and agent-store answer with the error, not-found or
  empty-but-valid variant that is true of this client.
- Unnameable frames raise `ExecClientControlMessage.throw`
  (`unknown_exec_variant`); recognised frames with no truthful answer —
  `git_diff_request`, whose `GetDiffResponse` has no error variant —
  raise `exec_variant_unsupported`.

Four frames previously answered `create(XSchema, {})`. In proto3 that is
not an empty result: the oneof is unset and the server reads it as "the
tool ran and produced nothing", indistinguishable from success. They now
send real variants.

`connect_scm` lost its repository (the target rides in a oneof, so the
flat property was always undefined) and settled on a fixed failure at the
announcement, before the server's `success`/`error`/`rejected` verdict
arrived on the completion frame.

The stream decoder tracked a single "current" tool-call block and settled
it on any `toolCallCompleted`, ignoring the envelope `call_id`: an
unrelated completion paired the wrong block, and `start A, start B`
orphaned A so nothing ever paired it — which strips the whole interaction
from every rebuilt transcript. Blocks are now retained per envelope id.

`lsp` is advertised as MCP again; the native `diagnostics` frame covers
one of ~10 actions.

(cherry picked from commit 4d269724a3a448886d13b4323ac02aadbfe38de3)
2026-07-30 01:41:55 +02:00
can1357 091f670ea0 style: apply biome formatting to merged changes 2026-07-30 01:28:07 +02:00
can1357 038d8372d7 chore: normalize changelogs after merging open fixes 2026-07-30 01:27:44 +02:00
can1357 55ac64679e Merge PR #6652: feat(ai): add Exa API key login (@will-bogusz) 2026-07-30 01:26:50 +02:00
can1357 4a05d02f01 test(extensions): cover session async job wiring
(cherry picked from commit e79cc9e79a68b53332eb6ca04f2e555e25d1b7e0)
2026-07-30 01:26:50 +02:00
can1357 5486c8fd1d Merge PR #6939: feat(extensions): expose session async job snapshots (@usr-bin-roygbiv) 2026-07-30 01:26:50 +02:00
can1357 da794ebb24 Merge PR #6938: feat(coding-agent): allow checkpoint/rewind/learn/manage_skill in subagents when explicitly requested (@szavadsky) 2026-07-30 01:26:49 +02:00
can1357 0249fa4715 Merge PR #7036: feat(rpc): expose live fast-mode control and token throughput (@fredluz) 2026-07-30 01:26:49 +02:00
can1357 07ed00ae22 Merge PR #7028: fix(ai): bound Anthropic retry-after waits (@metaphorics) 2026-07-30 01:26:49 +02:00
can1357 65f3743622 feat(coding-agent/session): supported importing session compactions in Codex session store
- Support parsing compacted records with replacement history and conversion to compaction entries.
- Add test coverage for foreign session import of Codex session compactions.
2026-07-30 01:13:37 +02:00
can1357 f11641d5a8 feat(coding-agent): enabled importing foreign sessions from claude and codex
- Implemented session stores and metadata converters to import Claude and Codex sessions into OMP.
- Added `--from-claude` and `--from-codex` CLI flags and `/resume` command arguments for foreign session resolution.
- Updated session selector components and controllers to support listing and picking external agent sessions.
- Added comprehensive unit tests and documentation covering foreign session import functionality.
2026-07-30 00:28:40 +02:00
can1357 93eb95b3b1 chore: rewrite changelogs 2026-07-29 23:34:04 +02:00
can1357 f2251b7d59 chore: normalize changelogs and formatting after merging open fixes 2026-07-29 23:09:40 +02:00
can1357 6527671c3a fix(lsp): sanitize expanded generic output
(cherry picked from commit 1260d0633a5fb533c492f272ee500fec60c46e22)
2026-07-29 23:09:14 +02:00
can1357 2adf484ef1 Merge PR #7042: fix(lsp): handle quick exits before reader teardown (@roboomp) 2026-07-29 23:09:13 +02:00
roboomp dca8f44b73 fix(lsp): handled quick exits before reader teardown
Waited briefly for process exit publication after clean stdout EOF so the process handler preserves the real exit code and stderr, while genuine reader errors still tear down immediately.

Cleared only the matching initialization failure for explicit reloads and added regressions for quick exits, reader errors, ordinary backoff, and immediate reload retries.

Fixes #7041

(cherry picked from commit a76522b759f14421202d4cc437ec611b78be20d1)
2026-07-29 23:09:13 +02:00
can1357 672857d238 Merge PR #7025: fix(coding-agent): coalesce models config resource probe (@paralin) 2026-07-29 23:09:10 +02:00
Christian Stewart a43c7a4d36 fix(coding-agent): coalesce models config resource probe
The models config resource regression started two cold child processes inside one five-second test. Under parallel CI chunk load, the second child could still be waiting for pipe drain or process exit after the validator had completed.

Keep the process boundary as the owner of the lifecycle measurement and run the missing and custom phases in one child. The missing phase closes its storage and registry before the baseline snapshot, while the custom phase proves schema identity and retention without changing config loading or validator cleanup semantics.

Signed-off-by: Christian Stewart <christian@aperture.us>
(cherry picked from commit 81fa98491544c7fbcbf075922889e0a9e1a0a3b4)
2026-07-29 23:09:10 +02:00
can1357 1b3f01d197 Merge PR #7019: test(ai,catalog): give spawn-based lazy tests explicit timeouts (@roboomp) 2026-07-29 23:09:07 +02:00
roboomp cc04600a64 test(ai,catalog): give spawn-based lazy tests explicit timeouts
Spawn-based lazy-loading tests assert exitCode===0 on a child process but
set no per-test timeout, so bun's 5s default kills the child under CPU
contention and the assertion reports a dead child rather than a regression.

Give each spawn test an explicit 60s per-test timeout, matching the
existing precedent in auth-gateway-anthropic-caching.test.ts.

Fixes #7018

(cherry picked from commit 00e5ec8855eb8ba31c1bdf571bd7c16f2405d679)
2026-07-29 23:09:06 +02:00
can1357 1b4c9d7d1a Merge PR #7015: perf(prompts): streamline tool guidance (@usr-bin-roygbiv) 2026-07-29 23:09:05 +02:00
usr-bin-roygbiv 066a3239f8 fix(prompts): preserve supported tool routes
(cherry picked from commit 0b02fb9219f07e212d7a0f67dacd7747b622ee45)
2026-07-29 23:09:05 +02:00
usr-bin-roygbiv 1e0d352a72 perf(tools): streamline shell guidance
(cherry picked from commit 9039728d89f07852904962685581c752ffebcdc6)
2026-07-29 23:09:05 +02:00
can1357 def7c5fadd test(task): exercise bundled budget through subprocess
(cherry picked from commit 6e023cfcebebc429cc020f0f823604eb64eb9c18)
2026-07-29 23:09:03 +02:00
can1357 d2d9c81c84 Merge PR #7012: fix(task): let task.softRequestBudget lower bundled subagent budgets (@terrxo) 2026-07-29 23:09:03 +02:00
can1357 adad262ba9 fix(xdev): include truncation marker in summary byte cap
(cherry picked from commit aa2067bf7952191beab85b71002aafe812f544bc)
2026-07-29 23:09:01 +02:00
Nik Divjak c3011fff3c fix(task): let task.softRequestBudget lower bundled subagent budgets
The soft request budget resolved to `SOFT_REQUEST_BUDGET[agent.name] ??
configured`, so the bundled entries for scout and sonic replaced the
configured value outright. Lowering `task.softRequestBudget` to tighten
the guard therefore did nothing for exactly the two agents that spawn
most often: a scout kept its 100-request budget no matter how small the
user set the knob. Only 0 (disable) and raising the value for
non-bundled agents had any effect.

Treat both numbers as upper bounds and take the smaller one. The bundled
entries stay ceilings, so a runaway scout is still stopped at 100 by
default and existing behavior is unchanged for anyone who has not
lowered the setting; a configured 0 still disables the guard entirely.
Resolution moves into `resolveSoftRequestBudget`, which also normalizes
negative and fractional inputs, so the rule is testable without standing
up a subprocess run.

This composes with `task.maxEffort` on a separate axis: effort caps how
hard each request thinks, this caps how many requests a run may spend.

(cherry picked from commit f0db29f8f725f11390b64ca9342300c482ff5c5d)
2026-07-29 23:09:01 +02:00
can1357 4666b1ae41 Merge PR #7010: fix(xdev): bound device summaries in UTF-8 bytes and flag untrusted metadata (@terrxo) 2026-07-29 23:09:01 +02:00
Nik Divjak 630f9e5324 fix(xdev): bound device summaries in UTF-8 bytes and flag untrusted metadata
Catalog summaries of mounted xd:// devices are inlined verbatim into the
system prompt. External devices (MCP servers, plugins) supply that text, and
it was bounded only by character count: a summary of multi-byte script passed
roughly three times the intended budget, and control characters survived into
the prompt where they can forge structure.

Summaries now go through a single sanitize-and-bound step that strips C0/C1
control characters and bounds the result in UTF-8 bytes via the central
truncateHeadBytes helper, so a cut lands on a code point boundary and never
renders a partial code point. The built-in/external distinction is derived
once per entry, and that same boolean both selects the description cap and is
exposed as `dynamic`, so the cap and the flag cannot disagree. The prompt uses
the flag to state that dynamic summaries are untrusted metadata, and the mount
notice says the same for newly appeared devices.

(cherry picked from commit 5989da6235d820bc687779a791e655e6f1b2df0f)
2026-07-29 23:09:00 +02:00
can1357 f62526f111 fix(coding-agent): preserve VCS cache refresh semantics
(cherry picked from commit 3f3e475109deb7b9e7690720827876fc982b5b8d)
2026-07-29 23:08:59 +02:00
can1357 1d41b269f7 Merge PR #6997: perf(coding-agent): keep reftable branch resolution off the render path (@metaphorics) 2026-07-29 23:08:59 +02:00
robomp-bot 65707c7f4c fix(coding-agent): close VCS cache lifecycle gaps
(cherry picked from commit b88851334b07eb1da6743b51b542ea5d3222ccca)
2026-07-29 23:08:58 +02:00
robomp-bot c5b0348150 fix(coding-agent): harden async reftable resolution
(cherry picked from commit e451f1d6f3537d4b58dfe479a6daf8919d169397)
2026-07-29 23:08:58 +02:00
robomp-bot d966b3f8a0 perf(coding-agent): keep reftable branch resolution off the render path
(cherry picked from commit 5724c30ff66e2036ed03a2ce3514a9237a72a657)
2026-07-29 23:08:58 +02:00
can1357 650a8f0faf fix(collab): detach reconciled loader on idle
(cherry picked from commit d675de815644a5b02358fa90d83e5cd5c78141d2)
2026-07-29 23:08:57 +02:00
can1357 872a931795 Merge PR #6996: fix(collab): start the guest loader when the host reports streaming (@metaphorics) 2026-07-29 23:08:57 +02:00