cluster: measured acceleration — parallel probing + disk ETag + composite lookup (#57 #58 #59)#61
Merged
Merged
Conversation
…der (#57) Per-probe decomposition (#57 diagnosis) confirmed the cold-resolve cost is a SUM of sequential legs (individual fastapi probes 84-96 ms). probeLlms → probeLlmsAll: all of ONE host's candidates fire under withTaskGroup; hits are collected and selected by candidate INDEX — never completion order — so the outcome is deterministic and identical to the old first-hit-wins loop while wall-clock drops to ~the slowest probe. The llms-full "upgrade" is satisfied from the same collected results (the sibling is in the candidate set), never re-probed. Hosts stay sequential with the early break: concurrency is bounded to one origin's candidate set (≤6 requests) — the documented, test-pinned politeness trade. Measured (fresh-process, release build, directional): resolve fastapi 1055-1159 ms → ~600 ms (registry leg alone is 369 ms — pypi's payload — so the probe leg now costs ~230 ms ≈ the slowest single probe). TDD: 3 new EngineTests (preference determinism, all-candidates fired pin, sibling absorbed no-reprobe) + a concurrency-safe recording fake; RED confirmed before implementation.
The 304-revalidation warm win was per-process (docstring: "empty on restart"). ETagCacheStore gains an opt-in persistURL: small entries (body <= 1 MB — sized to include registry JSONs like pypi's ~450 KB fastapi payload, measured during acceptance when a 256 KB cap silently excluded the highest-value entry; multi-MB llms-full dumps stay memory-only) are written through atomically with 0600 permissions and loaded lazily on first access. Corrupt/unreadable/wrong-version files start empty — never crash; loaded entries pass the normal LRU/byte bounds. Semantics unchanged: ALWAYS revalidate (the persisted body is only served after the origin answers 304); only validated 200s enter the store. Default stays nil (in-memory) — the MCP shell wires the user Caches dir path. Boundary: a LOCAL cache on the user's machine — inside the anti-positioning line (forbidden = shared/central content cache, not local persistence). Measured (fresh process, disk-warm vs cold): latest_version fastapi 391->155 ms, react 321->73 ms — the revalidation share recovered across restarts, as scoped by the #56 profile (connection-setup share is unrecoverable by any cache). TDD: +3 ETagCacheTests (restart roundtrip via 304, corruption tolerance + recovery, oversized-not-persisted + nil-URL zero side effects); RED confirmed.
Docs/config questions cost the look-up skill TWO sequential main-loop turns (resolve_source → fetch_docs), and #56 measured the per-turn cost as the dominant term while refuting the subagent alternative at ~7-30x spawn loss. The cheapest worker is the MCP server itself: - Engine: resolveSourcesFetchingTop(req) — resolve + fetch the top result in one call, exact parity with the two-step (same HTTP client, SSRF guard included); a fetch failure degrades gracefully (sources intact, content nil). - Shell: fetch_top boolean (+ max_bytes cap) on resolve_source; the content passes the SAME sanitize/truncate pipeline as fetch_docs — never a second, laxer path. encodeSourcesWithTop rides top_content{url,title,content} with the ranked list; a top-fetch miss emits an explicit note pointing at the fetch_docs fallback (never silent). - Skill: docs/config routing row → one call, with the descend-the-list fallback documented; README tools row updated. Measured (fresh process, react npm): two-call 440+940=1380 ms tool-side + 2 agent turns → one-call 552 ms + 1 turn; the saved TURN is the point (the per-turn model cost dominates — asserted in the #56 profile, stated as such). TDD: +2 EngineTests (composite content present; empty resolve → nil, no fetch) + ResolveSourceEncodingTests (boundary: content rides / miss degrades to note).
Both verify lenses PASSED; this closes their three advisories: - Write amplification: the disk file is rewritten only when the mutation can change the persisted subset (body <= persist cap) — a burst of over-cap bodies now costs zero disk I/O. Accepted trade documented: an eviction triggered by an over-cap body can leave evicted entries on disk until the next persistable write (harmless — bounds re-applied on load, freshness still 304-gated). - Permissions window: temp file is CREATED 0600 and rename(2)'d into place — permissions travel with the inode; no more write-then-chmod 0644 gap. rename also replaces (never writes through) a pre-planted symlink at the final path. Roundtrip test now asserts 0600. - Comment honesty: the "served only after 304" line read as a tamper barrier; it is a FRESHNESS guarantee — the actual security bound is the local-write precondition (user-level write access already implies full compromise). Stated plainly in the docstring.
This was referenced Jul 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #57
Refs #58
Refs #59
Summary
The three measured children of #56, implemented as a cluster (shared
DiscoveryEngine.swift+ count docs). Every claim below is measured against the #56 profile's corrected baseline (directional; reproduce viaevals/look-up/profile_mcp.py).probeLlmsAll: one host's llms.txt candidates fire concurrently underwithTaskGroup; selection by candidate index (never completion order — deterministic, result identical to sequential); the llms-full "upgrade" absorbed from collected results; hosts stay sequential (politeness bounded to ≤6 requests/origin, test-pinned)resolve_source fastapicold 1055–1159 → 562–738 ms (registry leg alone is 369 ms)0600to the user Caches dir; lazy load; corrupt file → start empty; all LRU/byte bounds preserved; always-revalidate semantics unchanged; local-only (inside the anti-positioning boundary)latest_version: fastapi 391→155 ms, react 321→73 msresolve_source{fetch_top:true}: ranked list + top result's content in ONE call (same sanitize/truncate pipeline asfetch_docs); miss → explicit note + intact list; skill routing table updatedTests
TDD throughout (RED confirmed per issue): 225 total (153 Swift + 72 Python) — +9 Swift (3 parallel-probe incl. the all-candidates politeness pin, 3 persistence incl. corruption self-heal, 3 composite incl. graceful-miss boundary). Counts synced via
sync-test-counts.sh.Checklist
Refsper issue)/idd-close #57 #58 #59🤖 /idd-all batch · cluster-PR (shared files) · Do NOT add Closes/Fixes/Resolves.