fix(mcp): classify and pace backend search timeouts - #2176
Conversation
|
#2279 amends ADR-130 so the record covers the behaviour implemented here — the two-value One delta to reconcile before both land: the amendment requires The requirement is deliberately cheap to satisfy — a per-surface default floor published alongside the retry policy is sufficient, and deriving a sharper value from observed backend state is preferred but not required. The reason it is mandatory rather than optional is that the amendment answers the recorded load-amplification arithmetic partly by moving the pacing decision to the server; an absent field returns that decision to the client. Raising it here rather than adjusting the record, since the field is the load-bearing part of that argument. |
|
ADR-130 Amendment 2 has landed on The same amendment introduces a requirement this branch does not yet meet. At this head, json!({
"kind": "search_incomplete",
"message": "no-match was not established because selected backends failed",
"retryable": degradation.retryable,
"missing_backends": degradation.missing_backends,
"backend_errors": backend_errors_value(°radation.backend_errors),
})( Worth noting for whoever picks this up: merging If the coordinator has no per-call estimate to publish, the amendment is |
|
Re-reviewing the delta added since my last note. One new commit, and it holds up.
The doc claims the pace comes from the full pre-truncation failure set. That checks out: The field does reach the wire —
One gap, small and cheap to close: the wire assertions are all on the negative arm. A On the documented client policy — three attempts, exponential backoff with jitter, breaker |
|
CI is green across all 27 contexts at the current head. The shape is right, and two things that usually go wrong here are handled deliberately:
The typing claim also holds: The predicate does not cover the deadline family, and misses the case it exists for
RuntimeError::Storage(khive_storage::StorageError::Timeout { .. })
| RuntimeError::DeadlineExceeded { .. }
All three currently classify as
So the classification excludes a deadline that provably did no work while including one that There is already a maintained classifier for this, next door
It is not a drop-in substitute — its question is "may this succeed on retry", which is broader Smaller
|
ohdearquant
left a comment
There was a problem hiding this comment.
Automated review. Posted by this repository's automated pull-request review pipeline; this is not a human read and does not gate the merge by itself.
Verdict on head df57290: REQUEST-CHANGES, 2 blocking findings. Finding details are delivered to the review's recipients rather than posted here. Do not merge this head while blocking findings are outstanding; a pipeline comment on a newer head supersedes this one.
## Summary - add typed `arm_participation` evidence for the text and vector KG search arms with `ran`, `skipped`, and `error` status plus bounded final candidate counts - preserve the evidence on complete, partial, zero-match, degraded-empty, presentation, and frame-budget paths without changing filtering, fusion, or deterministic ranking - document exact-name presence checks and align degraded arm status with ADR-130 / #2176 bounded backend cause vocabulary - cover exact-name text hits, long keyword-dense zero hits, vector and both-source counting, partial results, degraded-empty failures, and diagnostic omission ## Verification - `cargo test --workspace` - `cargo test -p khive-mcp --lib` (449 passed) - `cargo test -p kkernel coordinator::tests` (63 passed) - `cargo check -p kkernel --all-targets` - `cargo clippy --workspace --all-targets -- -D warnings` - `cargo fmt --all -- --check` - `git diff --check` Closes #1935
Both sides kept: the typed backend failure this branch introduces, and main's vector-arm split (vector_selected, vector_error) and search-arm participation evidence.
The hydration-seam test reaches the config ledger through fan_out_search, so the census arm requires it to hold the same serial key as its peers.
Summary
timeoutversusbackend_errorcauses through the coordinator service boundary without parsing rendered messagessearch_incompleteretryable only when every failed backend leg timed out, using the full pre-truncation failure setretry_after_msVerification
cargo test -p khive-mcp(455 unit + 145 integration tests passed)cargo test -p khive-mcp --lib search_failure_classificationcargo test -p khive-mcp --lib search_retry_pacecargo check -p khive-mcp -p kkernel --all-targetscargo clippy -p khive-mcp -p kkernel --all-targets -- -D warningscargo fmt --all -- --checkgit diff --checkRegression coverage proves timeout-only pacing, mixed-failure suppression, structural classification, pre-truncation classification/pacing, and the 10-second ceiling.
Closes #2069
Closes #1990