CortexDB 0.9.6 — blob extraction repaired under the unified WAL
Patch release. One important fix: multimodal blob extraction works
again on the unified-WAL write path — a regression present since
v0.9.0, surfaced by an external real-data report on 2026-08-05. Plus
cortexdb-connectors 0.2.16/0.2.17 with two batches of real-workspace
Slack fixes. No storage format changes, no migration; 0.9.x data
directories load as-is.
The fix (the headline)
Since v0.9.0, CORTEX_UNIFIED_WAL (the production default, and the
architecture going forward) routed single POST /v1/experience writes
through the indexer tail — which rebuilt each stored event without the
API-resolved physical BlobRef. A content.kind=blob_ref experience
(pdf/docx/image/audio uploaded via POST /v1/blobs) was therefore
written and embedded but stamped Complete as plain text: the
enrichment scanner's blob filter never matched and the configured
Tika/vision/Whisper content processors were never invoked. Only
text/plain (inlined at capture) passed through.
Now the indexer tail re-resolves the event's logical blob_id against
the same blob metadata store instance the API layer resolves with —
shared by construction — applying the same owner ACL (a blob owned by
another actor stays opaque; DISC-024 parity) and the same binary-only
gate. Wired into both tail apply paths (per-item and bulk) and the
legacy crash-reconcile path, with regression pins so it cannot silently
come back. Blob-backed experiences land as Pending, the scanner
dispatches them, and extraction runs — with enrichment on or off.
Also in this area:
- Loud startup warning when content processors are configured but
no LLM router is: that combination gets no extraction scanner (the
scanner requires the LLM-router constructor path), and previously
failed silently. Content-only jobs make zero LLM calls — configuring
CORTEX_LLM_URLdoes not add LLM spend for extraction. - The processor knobs —
CORTEX_DOCUMENT_PROVIDER,CORTEX_IMAGE_PROVIDER,CORTEX_AUDIO_PROVIDER,CORTEX_VIDEO_PROVIDER,CORTEX_SENSOR_PROVIDER,CORTEX_FFMPEG_PATH— are now registered with the boot-time config lint, so a typo'd provider is flagged instead of silently absent.
Connectors 0.2.16 / 0.2.17 (PyPI)
Two Slack bug-fix batches driven by a real-workspace hunt:
- 0.2.16: content-versioned message keys (edits land as new
versions instead of 409-poisoning every sync; display-name changes no
longer permanently fail re-sync), live
message_changedwebhook edits ingest, reactions get their own identity key (ending a 409→500→ redelivery storm), empty webhook signing secrets fail closed (Slack and GitHub), and a bounded stale-thread scan stops incremental sync from silently dropping replies to old threads. - 0.2.17: Unicode content gate (non-Latin messages ingest), 1 h
shared-cursor lookback for multi-channel in-flight loss, webhook
bodies capped at 5 MiB before auth (unauthenticated memory-DoS),
invalid UTF-8 → clean 400, Slack deliveries acked within the 3 s
deadline with background ingest + bounded retries, per-item
dead-letter budgets that name every abandoned item, per-channel
failure isolation, empty-window cursor hold, HTML unescaping, and
correct private-channel visibility labeling on both paths (real
member rosters via
conversations.members, fail-closed channel info, webhook privacy resolution viaSLACK_BOT_TOKEN).
Compatibility
/v1surface unchanged. No new required configuration.- Data directories from any 0.9.x release load without migration.
- Blob-backed events ingested while the regression was live were indexed as placeholders; re-ingesting them (same blob id, new write) runs extraction. No automatic backfill is attempted.