CORTEX phase 2: browse the corpus, attach real copies, and file work back

↗ view on GitHub · emileriksenkeev · 2026-08-05 · cc7b9f0a

Phase 1 gave the chat loop five read tools. This is the rest of the loop -
the picker, the pass-through, and the publish button (v7 §5.S2/S3/S4).

S2 - a Cortex tab in the document picker. Search (ranked) and Browse (the
complete filtered set) are kept visibly separate because Cortex only reports
superseded/canonical on search results, and showing a version flag the corpus
never gave would be inventing reassurance. "Attach" MATERIALIZES: Syd resolves
every read through document_versions.storage_path, so a pointer row is
invisible to the assistant that is meant to read it. The backend pulls the
bytes and runs the ingestEntities pipeline as library calls - not over HTTP,
which is capped at 50 uploads/hour and would stop a counterparty set halfway.
The copy is a per-matter working copy by design; edits must not leak back.

Staleness: the plan said compare `norm_hash`, but a live /api/fetch returns no
hash, no status, and no normalize/enrich timestamps. So cortexFingerprint()
takes the best signal actually present and records which one it used -
preferring a real hash the moment Cortex returns one, and otherwise using the
blob path inside the presigned URL, which is content-addressed (putBlob keys
on sha256) and therefore changes exactly when the bytes do. A document whose
fingerprint cannot be established reports "could not check", never "current".

S3 - uploads pass through to the corpus in the background, skipping documents
that came FROM Cortex (no boomerangs). /api/ingest does not exist yet (404,
the write path is still being built), so everything degrades to "queued, not
lost": pending in metadata, retried by a sweep that only ever touches rows
this integration stamped - publishing Syd's back catalogue is Emil's decision,
not a side effect of a restart.

S4 - "File to Cortex" on the row menu. Explicit, per artifact, never
automatic (§8.4). Idempotent, so a double click comes back deduped.

Also fixes a phase-1 bug found against live Cortex: the bridge sent
fields/files as the number 1, and Cortex reads those flags as
`v === true || v === "1" || v === "true"` - so every request for extracted
contract fields and file links has been silently ignored.

Provenance lands in documents.metadata, the jsonb column reserved and unread
since schema.sql:110. No migration: document_versions.source already allows
'user_upload' for the refresh path.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Repository emileriksenkeev/sydOS
Author emileriksenkeev <emil@keev.co>
Authored
Parents 7f93f540
Stats 14 files changed , +1970 , -58
Part of Cortex - company-wide document corpus integration

Capture this commit into my fork

Download a Markdown prompt that tells Claude how to port this exact commit into your working tree. Run it via claude -p < capture-commit-cc7b9f0a.md from inside the repo you want the change in.

⬇ Download capture-commit-cc7b9f0a.md