Give change.detect deadline-aware phase budgets and return partial results, not tool errors
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 25/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- go
- Lĩnh vực
- api, backend, performance, testing
Hướng nghiên cứu
Read internal/mcp/tools_analysis.go and internal/analysis/diffmap.go first, then trace the shared helpers in internal/mcp/analysis_diff.go and the deadline rules in internal/mcp/tool_deadline.go. Implement phase budgets while preserving fast parent cancellation and partial results, then run the named detect budget, lowering, enrichment, and cancellation tests. Done means partial work returns before the reserved deadline and the stated load and regression targets pass.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Why
Under load, change.detect (detect_changes) can still run past its MCP tool deadline (60 s by default). When that happens the agent gets an abandoned call or a raw context deadline exceeded error, not an answer. A report on macOS arm64 saw 59 s abandonments on a 3-file compare. Each phase has a fixed budget that ignores the request deadline. Added together they come to about 36 s before memberships and serialization even start:
- freshness wait: up to 3 s
- git diff plus symbol lowering: one shared 30 s cap
- impact walk: 3 s
- community/process memberships: limited only by the request context
With store contention the total can go past the deadline. Worse, finished work gets thrown away. If the deadline fires after enrichment has completed, the impact result is dropped and a tool error comes back. Clients then retry right away, and each retry adds another full computation on the daemon.
Target for this release: 0 abandonments in 200 detect calls under contention, and detect p95 ≤ 15 s.
Current state
Checked on main (015b3410). None of this work has been merged.
internal/mcp/edit_serialization.go:defaultMutationReindexWait = 3 * time.Secondis the freshness wait thathandleDetectChangesgoes through (awaitMutationFreshnessForRepos).internal/analysis/diffmap.go,MapGitDiffContext: puts both phases under onecontext.WithTimeout(ctx, 30*time.Second)(line ~99) and passes that same ctx tojoinHunksToSymbolsContext(line ~113). A slow lowering therefore uses up the git budget. It comes back as a barectx.Err()from the per-hunk and per-node checks (~223/234/250), not as "git diff failed".internal/mcp/tools_analysis.go,handleDetectChanges: anyMapGitDiffContexterror becomesmcp.NewToolResultError(~384-387), and so does anyanalyzeDiffImpacterror (~436-439). For a non-ready graph the handler setsreader = niland returns file changes withcomplete: falseandrisk: "UNKNOWN". That path already works and must keep working.internal/mcp/analysis_diff.go:diffImpactContextcaps the walk at a fixed 3 s.analyzeDiffImpactreturns an error whenanalysisMembershipsForNodessees a cancel (~95-97), and it ends withreturn result, ctx.Err()(~120), which throws away a finished result.- The same diff and membership helpers are used by
review.diff_context(internal/mcp/tools_enhancements.go,handleDiffContext, ~3054/3070) andpr_context(internal/mcp/tools_pr_review_context.go, ~191/235). - The tool deadline comes from
internal/mcp/tool_deadline.go:DefaultToolCallTimeoutis 60 s, the override env isGORTEX_MCP_TOOL_TIMEOUT, andtransportDeadlineMarginis 1 s.AbandonedToolCalls()is a counter shared by the whole process. - There is no
detectBudgethelper, nolowering_truncatedfield and noenrichmentfield yet. bench/daemon-latencyhas nodetect_changeslanes, no dirty-tree fixture and no writer option yet. They are added by the detect validation and harness work, which is tracked separately.
This work builds on the structured detect envelope (complete / truncated / lower_bound on every response, plus per-phase timings_ms). That envelope is tracked separately and must land first.
What to do
- Split
MapGitDiffContextso git keeps its own capped context and lowering gets a separate budget. A git timeout or failure stays a tool error, because a failedgit diffis not an empty diff. - Add a
detectBudgethelper in a new file,internal/mcp/detect_budget.go:- It derives a soft deadline from
ctx.Deadline()minus a reserve for serialization (start at 2 s). - Each phase gets
min(fixed cap, share of remaining time). Starting shares: git ≤ 40 %, lowering ≤ 25 %, impact ≤ 25 %, memberships get the rest. - Tune the shares from the per-phase
timings_msthat the envelope work exposes, and record the final values in the PR.
- It derives a soft deadline from
- When a phase hits its soft budget, return what it has plus a reason:
- lowering:
changed_symbolsis a prefix,lowering_truncated: trueis set, and the files not yet joined are listed. - impact:
truncated: true, whichAnalyzeImpactContextalready produces. - memberships hit their budget or see a cancel: return a result with
enrichment: "unavailable", not an error. analyzeDiffImpactreturns the result withenrichment: "complete" | "partial" | "unavailable"instead ofctx.Err().
- lowering:
- Any partial result sets
complete: false. A partialchanged_symbolsis never paired withrisk: "NONE". - When the caller (parent context) cancels, as opposed to the soft budget running out, keep returning
ctx.Err()promptly. - Keep the
reader = nilpath for a non-ready graph ahead of all budget logic. - Use the same helper in
review.diff_contextandpr_context. - All new response keys are additive. Existing keys keep their shape.
Out of scope
- Count-only detect output (
detail: counts) and lowering hunks per file instead of per hunk. - Single-flight coalescing of identical concurrent detect calls. That is a separate issue and it depends on this one.
- Handling of failed or pending receipts: refusals, retry limits, reconcile.
- Changes to the global tool deadline or to the dispatch queue.
- Adding the
detect_changeslanes to the latency benchmark (covered by the detect validation and harness work).
Done when
- Reference load: a 4-worktree workspace with about 130k nodes per worktree (±20 %; per-worktree node and edge counts recorded on this issue), a dirty tree of 10 modified files / about 40 hunks / 1 deleted file, a background
analyze healthloop and 2 concurrentedit_filewriters. On this load,detect_changeswith full detail has 0 abandonments in 200 calls. - On the same load, detect p95 ≤ 15 s on Apple M-series 16 GB and on a GitHub ubuntu-24.04 4 vCPU runner, and p95 ≤ 25 s on GitHub windows-2022.
-
TestDetectPhaseBudgetTablehas a slow-reader case for each phase (freshness, git, lowering, impact, memberships). Every case returns beforedeadline − reservewithcomplete: falseand the right reason. -
TestDetectSlowLoweringReturnsPrefixgets a prefix withlowering_truncated: true, never a rawcontext deadline exceeded. -
TestDetectDeadlineAfterEnrichmentReturnsResultgets the result back, not an error. -
TestDetectParentCancelExitsFast: the handler exits within 100 ms of a parent cancel. - Over 50 forced-abandon runs on the reference load (ubuntu-24.04 4 vCPU), the handler goroutine exits ≤ 1 s after the deadline at p99, and never later than 10 s.
- A test proves a git failure is still a tool error and never shows up as "no changes".
- No test or fixture produces a partial
changed_symbolstogether withrisk: "NONE". -
review.diff_contextandpr_contextuse the same helper, with one test for each covering a budget hit. - No regression: on the gortex repo (~31k nodes, single worktree, no contention), full detect returns
complete: truewith no budget reason in 20 of 20 runs. Existing detect golden outputs are unchanged apart from the new additive keys (lowering_truncated,enrichment). -
go test -race ./internal/mcp/... ./internal/analysis/...passes.
How to verify
go test -race -run 'TestDetect(PhaseBudget|SlowLowering|DeadlineAfterEnrichment|ParentCancel)' ./internal/mcp/. The cancellation tests readAbandonedToolCalls(), so they must not uset.Parallel().- Run
bench/daemon-latencywith thedetect_changeslanes, the dirty-tree fixture and 2 writers against the reference workspace on each host. Report p50/p95/p99, the abandonment count and the per-phasetimings_ms, and paste the numbers here. - To force the deadline, lower
GORTEX_MCP_TOOL_TIMEOUT(read bytoolCallTimeoutFromEnv). Compare the goroutine count before and after the forced-abandon runs.
Dependencies
Blocked by (must land first):
- #1066 — Detect phase budgets build on the truthful detect envelope.
Merge after (same code region, keep this landing order): - #1068 — Edit-region landing order puts the remaining change-tool partials before detect phase budgets.
Blocks: - #1070 (needs this)
Related issues
- Addresses: #691 (close those when the targets below pass and the reporters confirm)
- Related: #692
- PRs: #857
Planning
- Milestone: v0.64.15
- Priority: latency (first priority)
- Estimate: ~4 engineer-days
- Ngôn ngữ chính
- Go
- Star
- 1.9k
- Fork
- 171
- Merge trung bình
- 17 giờ 55 phút
- Pull request đã merge (30 ngày)
- 181
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của zzet/gortex
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 1-2 ngày Mức phù hợp với người mới 30/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 3/5 Nửa ngày Mức phù hợp với người mới 55/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 18/100
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 18/100
Maintainer thường phản hồi trong vòng 1 ngày
Issue tương tự
-
date_time, url_encode, html_escape, to_unix_time, contains_all and contains_any panic when called without argumentsCó thể đã có người làm @antcybersec đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
projectdiscovery/dsl#372 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 68/100
JuliusBrussee/caveman#1449 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
clawsweeper:fix-shape-clear clawsweeper:needs-maintainer-review clawsweeper:needs-product-decision clawsweeper:no-new-fix-pr clawsweeper:source-repro impact:ux-friction issue-rating: 🦞 diamond lobster P2
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
openclaw/gogcli#1291 · 1 bình luận · 1 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
apache/arrow-swift#209 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
bug(instrumentation/kafka-go): producer hook writes trace headers into the caller's messagesCó thể đã có người làm @Aryanbhargava18 đã nhận hôm nay. Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
open-telemetry/opentelemetry-go-compile-instrumentation#1669 ·
Maintainer thường phản hồi trong vòng 2 ngày