docs: P2 — bounded in-sift queue; digest + chunk-embedding caches pulled forward

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-22 23:47:09 -07:00
co-authored by Claude Opus 5.5
parent cb0cb83fb9
commit 9f8d9f4f13
+31 -4
View File
@@ -13,8 +13,12 @@ requests** — the deriver stalled for ~20 min until llama-server was restarted.
never add to that failure mode: never add to that failure mode:
- **Bounded in-flight to Dixie**: at most `dixie.max_inflight` (default **2**) digest/embed - **Bounded in-flight to Dixie**: at most `dixie.max_inflight` (default **2**) digest/embed
calls from sift at once; a request that can't get a permit within 5 s **falls back to calls from sift at once. Waiting requests sit in a **bounded FIFO queue inside sift**
`clean`** (with a warning) instead of queueing on Dixie. (`dixie.queue_depth` default **8**, `dixie.queue_wait` default **20 s**); a request that
can't get a permit within the wait, or arrives to a full queue, **falls back to `clean`**
(with a warning). Sift's queue is visible and cancellable; Dixie's own queue never is —
never let requests queue *on Dixie*. (20 s wait + ~15 s digest fits Hermes's 60 s
`web_extract` budget.)
- **Streaming requests** (`stream: true`) for chat completions, and cancel the context on - **Streaming requests** (`stream: true`) for chat completions, and cancel the context on
timeout, so closing the connection actually stops generation (verify this with a test timeout, so closing the connection actually stops generation (verify this with a test
against a real llama-server: start a long digest, cancel at 2 s, confirm the slot frees — against a real llama-server: start a long digest, cancel at 2 s, confirm the slot frees —
@@ -69,6 +73,28 @@ Out: `search` (P3), cache (P4), knowledge graph.
6. Fallbacks (always 200 with `warnings`): permit timeout, Dixie error, 45 s timeout, 6. Fallbacks (always 200 with `warnings`): permit timeout, Dixie error, 45 s timeout,
empty output → `clean` truncated to the output cap, `digest.fallback: "<reason>"`. empty output → `clean` truncated to the output cap, `digest.fallback: "<reason>"`.
## 2a. Caches (pulled forward from P4, Kyle 2026-09-22)
Content-addressed, SQLite in `/var/lib/sift/cache.db` (`modernc.org/sqlite`), so there is no
staleness problem: a changed page has a different hash.
1. **Digest cache** — key `sha256(content_hash | normalised_question | model | prompt_version)`
→ digest text + `chunks_used`. Normalise the question: trim, collapse whitespace,
lowercase. Hit → no Dixie call at all (`digest.cached: true`). Bump `prompt_version` whenever
the prompt or chunking changes.
2. **Chunk-embedding cache** — key `(content_hash, chunk_index, embed_model)` → vector
(float32 blob). A second question on the same long page skips re-embedding. Also cache
the question embedding by normalised question (short TTL not needed; it's content-addressed).
Rules: **Honcho context is never cached** (per-workspace, changes constantly) — fetch it
fresh and attach to a cached digest; nothing in the cache is workspace-specific. Size-bound
the DB (default 500 MB, LRU eviction by last-hit time; evict in a background tick). Cache
failures are warnings, never errors. `/metrics`: hit/miss per cache, evictions, DB size.
The URL → cleaned-content **fetch cache stays in P4** (it needs TTL/staleness rules).
Tests: hit/miss on identical vs changed content; normalisation; prompt_version bump
invalidates; context not stored; eviction under size cap; corrupt DB → warn and bypass.
## 3. Context (`internal/context`, Honcho retrieval only) ## 3. Context (`internal/context`, Honcho retrieval only)
- `POST {honcho}/v3/workspaces/{ws}/search` `{"query": q, "limit": 5}`; response is a JSON - `POST {honcho}/v3/workspaces/{ws}/search` `{"query": q, "limit": 5}`; response is a JSON
@@ -126,8 +152,9 @@ digest_ms fallback`. Never log page content, questions longer than 80 chars, or
- Fake Dixie (`httptest`, streaming SSE) for: prompt framing (document inside tags, system - Fake Dixie (`httptest`, streaming SSE) for: prompt framing (document inside tags, system
prompt present), `enable_thinking:false` + `max_tokens` sent, fallback on timeout / error / prompt present), `enable_thinking:false` + `max_tokens` sent, fallback on timeout / error /
empty, permit cap (3 concurrent requests with `max_inflight=2` → one falls back), context empty, permit cap + queue (with `max_inflight=2, queue_depth=1`: 2 run, 1 waits, the 4th
cancel propagates (fake server observes the disconnect). falls back immediately; a waiter past `queue_wait` falls back), context cancel propagates
(fake server observes the disconnect).
- Chunk selection: document order restored, token budget respected, no-question path. - Chunk selection: document order restored, token budget respected, no-question path.
- Context: allowlist, `guardian-star` refused even if configured, 3 s timeout → warning. - Context: allowlist, `guardian-star` refused even if configured, 3 s timeout → warning.
- Recover: Wayback JSON parsing (available/unavailable), `id_` rewrite, fake-success fixtures - Recover: Wayback JSON parsing (available/unavailable), `id_` rewrite, fake-success fixtures