Skip to content

fix(cursor): bound capability reads and buffered tool budgets - #5533

Closed
luvs01 wants to merge 2 commits into
devfrom
stack/cursor-capability-budget
Closed

luvs01 wants to merge 2 commits into
devfrom
stack/cursor-capability-budget

Conversation

@luvs01

@luvs01 luvs01 commented Sep 22, 2026

Copy link
Copy Markdown
Collaborator

Summary

Combine #5233 and the buffered-tool budget correction in 799ebc5d5d6a8c75eeb99f358db5c64906117584 into one Cursor capability and tool-budget change on dev 482a3e0b6bd59b99276b163b0ceb3f1645c76035.

  • Read installed Cursor capabilities through a bounded regular-file handle. Reuse the metadata cache while refreshing the installed product version on cache hits; preserve the platform-specific symlink and special-file protections.
  • Reserve the translator's per-call and per-turn budget before retaining completed textual fallback arguments. Release that reservation when a real frame wins and transfer it when the fallback is emitted.
  • Preserve both original fix(cursor): bound installed bundle reads #5233 commits, including its review-driven cache-version correction, and the buffered-tool contribution's author/provenance. Update the corresponding structure contracts.

This aggregate is independent of maintainer-owned #5507: it does not carry its quarantine/replay changes, alter its branch, or add a dependent chain. No GUI change.

Verification

  • Exact head 799ebc5d5d6a8c75eeb99f358db5c64906117584: direct Bun focused run passed 141 tests / 648 assertions / 0 failures, covering cursor-effort-table, cursor-protobuf-events, cursor-effort-rows, cursor-effort-suffix, cursor-discovery, and the file-size ratchet.
  • bun run typecheck, bun run structure:check, and git diff --check 482a3e0b6bd59b99276b163b0ceb3f1645c76035 HEAD passed.
  • fix(cursor): bound installed bundle reads #5233's two original changed files match its final source head exactly. The buffered-tool contribution and carried aggregate commits match by stable Git patch ID.
  • This Windows run does not establish execution coverage for POSIX symlink/FIFO branches. Full suite, exact-head cross-platform CI, and independent review remain pending; the PR stays draft. No limits, baselines, skips, or source timeout values were changed.

Checklist

  • Scope stays focused and avoids unrelated cleanup.
  • Docs or release notes were updated when needed.
  • Security-sensitive changes were reviewed for secrets, auth, and unsafe defaults.

luvs01 and others added 2 commits September 22, 2026 20:11
Carries #5233 at 9b3a5db, including the outdated review finding fixed by its version-refresh follow-up. Sources: 6d2fdc4 and 9b3a5db.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
(cherry picked from commit 1ec4729ffb4265ee36b9665973879149fc1e55cb)
(cherry picked from commit 755d50b)
(cherry picked from commit 2a53a5772edcf14d798a213ef25b2705bcf9fe2c)
@coderabbitai

coderabbitai Bot commented Sep 22, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

Copy link
Copy Markdown
Contributor

Deterministic PR hygiene checks passed.

@github-actions github-actions Bot added the bug Something isn't working label Sep 22, 2026
@lidge-jun

Copy link
Copy Markdown
Owner

리뷰 · 우선순위 54 / 80

이 PR은 Cursor 쪽에서 서로 다른 두 가지를 한 번에 고칩니다. 하나는 설치된 agent 번들(cursor-effort-table)을 읽을 때, 심볼릭 링크·특수 파일에 속지 않도록 같은 파일 핸들로 열고(O_NOFOLLOW/O_NONBLOCK + fstat), 크기 한도를 지키며, 캐시가 맞아도 설치 버전(install.version)만 새로 붙이는 쪽입니다. 다른 하나는 텍스트로 보이는 가짜 툴콜을 잠시 모아 둘 때, 나중에 버릴 수도 있는데도 인자 바이트를 translator 예산에 바로 잡아 두고, 진짜 프레임이 이기면 예약을 풀고, 턴이 끝날 때 가짜만 남으면 그 예약을 그대로 써서 내보내는 쪽입니다. base는 dev이고, 닫힌 #5233과 포크 쪽 예산 수정을 한데 모은 draft입니다. GUI는 건드리지 않았고, 작성자 말대로 #5507의 quarantine/replay와는 별 줄이라고 적혀 있습니다.

라인 - src/integrations/cursor-effort-table.ts readCursorBundle: Windows에서는 symlink/FIFO 거절이 실제로 되는지 이 PR·테스트가 증명하지 않습니다(win32면 테스트가 바로 return). POSIX만 믿고 머지할지, Windows에서도 “실패하면 null → 정적 테이블”로 충분한지 확인이 필요합니다.
라인 - src/adapters/cursor/protobuf-events.ts finalizeTurnEvents: 버퍼에 넣어 둔 callId로 예산을 이미 잡은 뒤, flush 때 recordToolCall이 같은 id로 openCall을 다시 하고 open.args = call.args로 예산을 우회한 다음 commitToolCall합니다. 지금 TranslatorBudget.openCall은 중복 id에 안전하고, args가 같아서 이중 청구는 피하지만, 이후 commitToolCall이 args를 바꾸거나 예산을 다시 셈하면 깨지기 쉬운 형태입니다.
라인 - 한 PR에 “번들 읽기 경계”와 “텍스트 툴콜 예산”이 같이 들어 있습니다. 되돌리기·충돌 해소·리뷰 책임이 한 덩어리로 커집니다. #5233은 이미 닫혔으니 중복 머지 위험은 낮지만, 비슷한 반쪽 PR이 남아 있으면 같이 닫는 편이 낫습니다.
라인 - 작성 시점 CI에 test shard·structure 등 실패/취소가 보입니다. 본문 검증(포커스 141 테스트)과 별개로, draft를 ready로 올리기 전에 head에서의 전체 게이트를 다시 보는 편이 안전합니다. preview deploy 이야기는 생략합니다.

메인테이너의 판단이 필요한 지점

한 덩어리로 dev에 넣을지, 번들 IO와 예산 회계를 커밋/PR 단위로 나눌지. Windows에서 symlink 추종을 “정적 폴백으로 충분”하다고 볼지. #5507과 같은 주(protobuf-events 근처)라 머지 순서를 어떻게 잡을지. types.ts/config.ts 분할 이슈는 이 변경에 해당 없음.

너의 추천

의도는 분명하고 테스트도 핵심(캐시+버전 갱신, symlink/FIFO 거절, 예산 선점·실프레임 승리 시 해제)을 짚습니다. draft 유지를 전제로, Windows 약속만 한 줄로 확정하고, flush 경로에 “예산 바이트가 commit 후에도 한 번만 잡혔다”는 회귀 테스트를 보강한 뒤 머지 후보로 두는 쪽을 추천합니다. #5507과 겹치는 충돌이 나면 이 PR의 예산/버퍼 쪽이 더 좁으니 그쪽을 기준으로 rebase하는 편이 낫습니다. 무효·중복 반쪽 PR이 열려 있으면 닫으세요.

이 댓글은 grok-bot이 작성했습니다

@lidge-jun

Copy link
Copy Markdown
Owner

Carried into #5619 as a cherry-pick of this PR's net change at 799ebc5, with your authorship kept on the commit. Closing in favor of #5619. Thank you!

@lidge-jun lidge-jun closed this Sep 23, 2026
lidge-jun added a commit that referenced this pull request Sep 23, 2026
… fixes (#5619)

* fix(cursor): bound capability reads and buffered tool budgets (#5533)

Carries #5533 (and the closed #5233 it consolidates) onto current dev.

Co-authored-by: Epinephrine <luvs01@hanmail.net>

* fix(moonshot): bound normalized tool-schema expansion (#5547)

Carries #5547, which consolidates #5464 and the request-wide inline budget, onto current dev.

Co-authored-by: yeongjunyoo <47925973+yeongjunyoo@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Epinephrine <luvs01@hanmail.net>

* fix(moonshot): restore rejected inline budgets and charge nested growth once

A rejected sibling-reference expansion now restores the byte, node and expansion allowances it consumed, and outer growth no longer re-charges nested copies, so later independent expansions in the same request keep their allowance. Documents the provider-driven object type inference as a deliberate tradeoff and rewrites ADR-0355 in English.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* feat(reasoning): consolidate replay, opt-in tag parsing, and summary policy (#5566)

Carries #5566, which consolidates #5449, #5205 and #5491, onto current dev. The provider guide keeps the current bridge replay paragraph and adds the inline-tag and summary paragraphs.

Co-authored-by: Joonsuh Park <trckstr4422@gmail.com>
Co-authored-by: Daniel Sjöstrand <16033062+Danielsjostrand1979@users.noreply.github.com>
Co-authored-by: alexph-dev <alexph-dev@users.noreply.github.com>
Co-authored-by: Yum-wu <1172989563@qq.com>

* fix: bound Fernet slot runs, Kiro error-body read, and skill-path line slice (#5310)

Carries #5310 onto current dev. The follow-up commit makes the Fernet run cap fail closed and moves the Kiro regression out of the capped stream suite.

* docs(reasoning): reconcile inline-tag whitespace contract

Interleaved inline-tag parsing preserves answer whitespace; only Kiro single-block mode drops the whitespace after its leading block.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(responses): fail closed on Fernet run overflow and keep the Kiro suite under its cap

A slot with more than 64 structurally valid Fernet runs is now treated as unreadable or omitted as a whole, so no unexamined tail reaches the provider as text. The bounded Kiro fallback error-body regression moves byte for byte into a registered sibling file, and the Kiro, Responses and inbound contracts document the new bounds.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(reasoning): scan inline think tags with a moving cursor

The parser copied, rescanned and reserved the whole remaining response after every block, so one upstream chunk carrying many short blocks cost quadratic work. It now scans each chunk from an offset and charges the translator budget only for retained carry: undecided leading input or a trailing tag fragment.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(reasoning): keep undecided leading whitespace incremental

Before the format was decided, every content delta rebuilt, trimmed and re-reserved the whole leading prefix, so a stream of one-character whitespace deltas cost quadratic work. Leading whitespace is now kept in segments whose bytes are reserved once and joined only when the format is decided or the stream flushes.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(meta-muse): consolidate login admission and bounded response handling (#5591)

Carries #5591, which consolidates the closed #5234 and #5432, onto current dev. The provider contract keeps the inline-tag paragraph and adds the Meta Muse admission paragraph.

Co-authored-by: Epinephrine <luvs01@hanmail.net>

* fix(claude-desktop): keep applied state consistent across profile edits (#5590)

Carries #5590, which consolidates the closed #5337, onto current dev.

Co-authored-by: Epinephrine <luvs01@hanmail.net>
Co-authored-by: luvs01 <luvs01@users.noreply.github.com>

* fix(claude-desktop): commit applied markers only over the observed baseline

Both Desktop writers, provider-change auto-apply and client sync, now capture the desired profile and its applied marker before the Desktop write and commit the new marker only if profile presence, content, fingerprint and timestamp are unchanged. A concurrent edit, deletion or newer marker keeps its state and the write reports a skipped marker. The provider-change path no longer saves a whole stale config snapshot.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(claude-desktop): commit profile edits against the persisted marker

The Desktop profile PUT built its response from an earlier snapshot and saved that whole snapshot, so a marker committed by another writer during the awaited state build could be replaced by an older one. The edit now commits in one persisted-config mutation that keeps the latest marker for unchanged content and answers 409 when the profile itself changed meanwhile. The Meta Muse overflow test now asserts that the bounded-body limit, not a generic failure, produced the error.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(claude-desktop): report an unreadable config separately from an edit conflict

A missing or invalid config now answers 500 with its reason; only a concurrent profile change or exhausted rebase answers 409.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* feat(desktop): consolidate consent-based runtime takeover and ownership contracts (#5564)

Carries #5564, which consolidates #5459 and #5457, onto current dev. The review screenshot stays in the pull request description rather than the tree.

Co-authored-by: jun <bitkyc08@gmail.com>
Co-authored-by: sanggyulee <andy53295774@gmail.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>

* fix(desktop): bind takeover stop to the approved runtime and fail closed

Desktop takeover re-resolves ownership immediately before stopping and passes the approved PID, endpoint, config home, CLI version and compatibility token to an opt-in guarded stop. The guard is checked under the ownership mutation lease before any manager or signal stop; the approved PID and endpoint must settle and the service manager must then be proven inactive, otherwise the stop answers approval-changed or manager-still-active and the desktop neither waits for silence nor claims. Unreadable or unparseable stop output is terminal as well. A second unreadable service-state read now blocks takeover, Windows managing-CLI discovery follows PATHEXT with file-only candidates and refuses command-interpreter metacharacters, the claim refusal test uses real sandbox state, and the runtime and desktop contracts record that the claim token is a consistency check rather than consent proof. Plain ocx stop is unchanged.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(desktop): keep plain stop entry points and format the takeover changes

Desktop exit keeps its plain runtime_stop::run entry while takeover uses run_approved, AttachPlan::Ask no longer carries an unread field, the Rust changes follow rustfmt, the plain CLI stop path keeps its literal outcome return, the stop source oracles follow the reader and outcome union that now include the two guarded refusals, and the runtime contract fits its 600-line budget.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(desktop): run takeover seam tests without tokio macros and harden manager and shim checks

The two async takeover seam tests now run on the shell runtime already used by the crate instead of tokio test macros, which this crate does not enable. Windows command-shim probes refuse command-interpreter metacharacters in every recorded argument as well as the executable, and the guarded stop re-inspects the service manager identity immediately before the manager command, answering approval-changed without stopping if it moved.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(responses): keep effort-based reasoning visible after routing

Final-route normalization recomputed hideThinkingSummary without the validated active-effort condition, so routed Chat and Kiro requests with an active effort and an omitted summary still hid raw reasoning. It now uses the same predicate as the parser; explicit "none" and requests without an active effort stay hidden.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(service): match the running CLI case-insensitively only on Windows

On case-sensitive filesystems a PATH executable that differs only in case is a different file, so it must get its own version probe instead of reporting the running CLI version.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(meta-muse): require the dashboard session for manual login codes

The manual-code continuation now applies the same dashboard-session admission as the login start, so a management token cannot advance a pending Meta Muse login.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(reasoning): reserve the joined leading-whitespace copy

Joining retained leading whitespace allocated a second copy outside the translator budget; the join is now reserved first and released once the segments are cleared.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(service): skip CLI probes for an absent runtime and treat failed systemd units as stopped

Resolve no longer spawns managing-CLI version probes when no runtime is live, since takeover is only offered for a live runtime. A systemd unit reported failed with no main PID is stopped, so a guarded stop that leaves it failed succeeds and a leftover failed unit does not block takeover.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

* fix(service): keep failed systemd units fail-closed and assess takeover only for a live runtime in tests

systemd can report failed before an automatic restart, so failed with no main PID is again treated as unknown rather than stopped. The resolve contract tests that assert ownership and takeover fields now use a live runtime, matching the skip of managing-CLI probes when no runtime is live.

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>

---------

Co-authored-by: luvs01 <27862058+luvs01@users.noreply.github.com>
Co-authored-by: Epinephrine <luvs01@hanmail.net>
Co-authored-by: yeongjunyoo <47925973+yeongjunyoo@users.noreply.github.com>
Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
Co-authored-by: Joonsuh Park <trckstr4422@gmail.com>
Co-authored-by: Daniel Sjöstrand <16033062+Danielsjostrand1979@users.noreply.github.com>
Co-authored-by: alexph-dev <alexph-dev@users.noreply.github.com>
Co-authored-by: Yum-wu <1172989563@qq.com>
Co-authored-by: luvs01 <luvs01@users.noreply.github.com>
Co-authored-by: sanggyulee <andy53295774@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants