Lacunari

How it works

Five steps, no model

Every stage below is set-based SQL over data you already hold. There is no inference, no embedding, and no network call. That is a capability claim as much as a privacy one: the results are reproducible, and they do not change because a vendor shipped a new checkpoint.

01Ingest code · PDFs · scans keyed by content hash 02Extract symbols · EXIF · dates typed facets 03Map subjects · edges timelines 04 Derive absences the part nothing else does 05Work it claim · lock · lease humans and agents Steps 1–4 are set-based SQL. No model, no API key, no network call.
The whole pipeline. Everything up to the queue is derived from data you already hold, which is why the results are reproducible and do not change when a vendor ships a new checkpoint.

1 · Ingest

Point it at a directory, a repository, or a pile of scans. Documents are keyed by SHA-256 of their content, which is the decision the rest of the system falls out of: the same file arriving from three people is one document with three contributions. Nobody's attribution is lost, and independent copies become corroboration rather than clutter.

$ lac doc add scans/*.pdf --source alice --subject "Operation Market Garden" $ lac doc index . --source my-repo # a repo is a corpus that compiles

2 · Extract

Pull typed facets out of whatever the file actually is: EXIF and GPS from photographs, producer strings and page counts from PDFs, symbols and imports from source, keys from JSON. Extractors are pluggable programs with a contract — a text corpus and a codebase go down different paths, and the system knows which it is looking at.

3 · Map

Build the graph: subjects, the documents that mention them, co-occurrence edges, and timelines. An edge asserts only that two names appeared in the same document. Similar names are proposed for merging and never merged silently — an archive that quietly decides two spellings are one person has destroyed evidence.

4 · Derive the absences

The step nothing else does. Holes in otherwise-covered spans, claims resting on one source, entities connected to nothing, material held but never read. Each becomes a suggestion with a stable identity — which is what lets it be withdrawn automatically when someone closes it.

$ lac web gaps $ lac web suggest --dispatch # every hole becomes a claimable task

5 · Work it

The roadmap and the execution engine were always the same database. Start workers and they drain the board: each takes the top thing it is capable of, records what it cost, and asks again.

$ lac work & lac work & lac work &

They do not collide, for structural reasons rather than hopeful ones: a claim is one atomic UPDATE, and it locks the files that task declared. A worker that dies loses its lease and its files unlock. Work needing judgement escalates to a person on a backoff.

Nothing here runs a model. Lacunari coordinates agents; it does not execute them. You bring Claude, a local Llama, GPT, or a shell script — executors/ is the seam. That is why there is no vendor in the coordination path and no sandbox to live inside.