Thesis × build-map · verified against real code · 2026-07-05

Verticalize the Engine — the RAG we already have, pointed at one corpus, becomes a product

The retrieval + grounding + generation + citation engine inside ollwrite is corpus-agnostic. Point it at a vertical corpus, wrap it in a single-purpose front door, and you have a distinct product with zero new grounding code. CiteBible — the Session 1 spec below — is the cheapest possible proof. This doc maps it, line by line, onto code that already exists. Sibling reads: the product thesis it sits beside and the build-out & GTM plan.

The one line. The engine is done and proven. A vertical product is a thin front door + one no-auth endpoint over it — not a build. The only thing between CiteBible and a live URL is a Sam-console deploy of oll-memory, which today runs on localhost:5008.

  1. Verticalize = same engine, different corpus + one single-purpose front door. ollwrite already ships two workspaces on one engine — the switch is literally a workspace param.
  2. CiteBible Session 1 = one page, one input, one button, 3–5 cited WEB verses, one link to ollwrite. Nothing else.
  3. The grounding gate that makes it trustworthy already exists — a relevance floor that abstains without calling the model on a retrieval miss. No hallucinated citation can come back.
  4. The one real blocker is a deploy, not code: oll-memory is green but unmerged (PR #80), not on the public internet yet.

Part 1 · The thesis: verticalize the engine

One engine, corpus-agnostic. Swap the corpus, wrap a front door, ship a product — and touch zero grounding code.

The engine has four parts, and none of them know or care what the corpus is about:

1 · Retrieval

On-device Ollama nomic embeddings over pgvector. Dense cosine similarity against an ingested corpus.

2 · Grounding gate

A relevance floor on the raw cosine. Below it → abstain, don't generate. This is the whole trust promise.

3 · Generation

Groq via the oll-model gateway, fed a numbered, grounded prompt built only from retrieved chunks.

4 · Citation loop

Every claim carries its source chunk; the system prompt forbids inventing a citation not in the sources.

Proof it already verticalizes — and it's in code, not a slide

ollwrite ships two workspaces on ONE engine: "My Writing" (private notes) and "Bible study" (a public WEB scripture corpus). Same editor, same sidecar, same retrieval/grounding/generation path. The only thing that changes is which corpus is queried — and that switch is literally a workspace parameter:

// ollwrite/src/lib/workspace-store.ts:25
export type WorkspaceKey = 'writing' | 'bible';

// ollwrite/src/components/memory/workspace-switcher.tsx:22
const ORDER: WorkspaceKey[] = ['writing', 'bible'];

That is the verticalization, already built. "Add a vertical" = add a corpus + a label to that union, not a new engine.

Generalizing it

Any public-domain or owned corpus → a vertical. The vertical candidates below are drawn from the existing platform-extension research — they are candidates, not commitments:

CorpusCandidate productWhy it's a candidate
The Bible (WEB translation)CiteBibleFree, public-domain, emotionally load-bearing. The cheapest proof.
A company handbook / wiki"VaultChat" candidateOwned corpus, B2B willingness-to-pay — but a gated build.
Financial ledgers / filings"LedgerChat" candidateHigh WTP — but corpus + liability are the real cost, not the engine.

Why CiteBible is the cheapest proof: the WEB corpus is free and public-domain (no licensing, no liability), and the emotional pull — a person carrying something real — showcases the engine's actual magic: responding to a specific, messy sentence, which a static listicle or keyword search can never do.

Part 2 · CiteBible — Session 1, the one box

The spec, encoded verbatim in intent. A live reachable URL is the only finish line.

🎯 Goal

A live, reachable URL where a stranger types what they're carrying and gets grounded, cited scripture back. Nothing else ships.

✅ In scope — ONE page

  • One text input"What are you carrying right now?" Accepts a real situation, not a topic — e.g. "my mother is dying and I'm angry at God."
  • One button.
  • One results area — 3–5 verses, each with a reference (book, chapter, verse) + translation (WEB).
  • "If a verse can't be grounded, it doesn't show."
  • One line under the results: "Write from this →" linking to ollwrite — the only platform connection.
  • Deployed on a subdomain off the existing Coolify setup. A working URL is the finish line.

🚫 Out of scope — set it down

The pull to add these is the pattern to resist. Name each, then set it down:

  • Custom domain
  • Auth / accounts
  • Payment
  • Daily verses
  • Summaries
  • Mobile app
  • Multi-language
  • SEO pages
  • Church outreach

✔ Definition of done

Open the URL on a phone, type a real situation, read back accurate cited verses.

⚖ Non-negotiable

Grounding. Better 3 real verses than 5 with one hallucinated citation.

✨ The magic

Respond to the specific thing typed — never collapse to keyword-matching a topic.

Part 3 · How CiteBible maps onto real existing code

The "we already built this" map — a request → response flow, every step grounded in a verified file:line.

1
The bible public workspace already exists
A read-only WEB scripture corpus, collection bible, already ingested in oll-memory — isPublic:true, label "Bible study", paneLabel "Scripture (WEB)", framing "cited to book:chapter:verse", with 3 starter prompts incl. "What does the Bible say about grace?"
ollwrite/src/lib/workspace-store.ts:9-10, :48-66
2
Client call — chatMemory(message)
Posts to /api/memory/chat with body {message, styleDirective, workspace} and returns {answer, provider, model, citations: MemoryChunk[]}, where MemoryChunk = {document_id, index, text, score, page, metadata}.
ollwrite/src/lib/memory-client.ts:217-236 · type at :14
3
BFF handler — retrieve, ground, generate
Retrieve chunks from oll-memory (nomic) → build a numbered grounded prompt → generate with oll-model (privacy "any" = Groq) → return {answer, citations}.
ollwrite/src/app/api/memory/chat/route.ts + ../handler.ts (handleChat)
4
THE GROUNDING GATE — the whole quality promise, already built
A relevance floor of 0.50 on the RAW dense cosine (vector_score), NOT the rank-based RRF score. Measured live: clearly-relevant chunks score 0.67–0.85 (a synonym-only match still ~0.75); clearly-irrelevant 0.32–0.39. 0.50 sits in the gap, so a retrieval miss abstains instead of grounding on nonsense. On a miss it returns ABSTAIN_ANSWER without calling the model — the code's own words:
// ollwrite/src/app/api/memory/handler.ts:621-628
// We return this WITHOUT calling the model, so it is structurally
// impossible for a miss to come back as a plausible-looking,
// fabricated cited answer.
export const ABSTAIN_ANSWER = "…";
The system prompt also forbids inventing a citation not present in the sources.
ollwrite/src/app/api/memory/handler.ts:48-75 (floor rationale) · :621-628 (abstain)
5
Reference rendering — Book Chapter[:Verse]
The scripture reference is derived from the chapter document_id (e.g. romans-8Romans 8). The chat pane already states: "Answers are grounded in the WEB scripture corpus, cited to book:chapter:verse."
ollwrite/src/components/memory/sources-pane.tsx:107-110 · chat-pane.tsx:117
6
The underlying gateway — oll-model, LIVE
POST /api/text/complete (header X-Service-Token; body {messages, provider?, model?, max_tokens?}{text, provider, model, tokens_in, tokens_out, latency_ms}; providers groq / claude / ollama). Live at model.oll.am — health returns 200 (checked 2026-07-05).
services/oll-model/routes.py · dtos.py

What CiteBible actually needs to build

A thin front door: one public page + one no-auth server endpoint that reads the PUBLIC bible collection and returns {answer, citations}. The retrieval, grounding gate, generation, and citation rendering are all already written.

The one real code gap: today's /api/memory/chat BFF requires authresolveUserId returns 401 when there's no token (ollwrite/src/app/api/memory/chat/route.ts:33-34). A public, no-login box therefore needs one of:

  • a small additive PUBLIC variant pinned to the public bible collection (a public-demo endpoint), OR
  • a standalone thin service that calls oll-memory search (workspace=bible) + oll-model generate with the service token, carrying no user identity.

Either way: no new grounding code.

The one blocker to a live URL

The honest heart of this doc: the engine is proven locally, but there is nothing to front on the public internet yet.

oll-memory is green but unmerged — and not deployed

The engine is proven locally (today's screenshots), but oll-memory is PR #80 — green, unmerged, and NOT deployed. It runs on localhost:5008. There is no engine on the public internet to front. A public CiteBible URL is gated on deploying it:

#80
merge the green PR
memory.oll.am
Coolify app
oll_memory
Neon DB (pgvector)
nomic
self-hosted Ollama for embeddings
WEB corpus
ingest into the collection

That is a Sam-console act. Once oll-memory is live, the thin front door + subdomain is a <1hr build to a live URL — trivial precisely because the engine and its grounding are already done.

A second Sam-console tell: the prod service token differs

The production oll-model service token differs from the dev token — a live POST with the dev token returns 403 FORBIDDEN. That's another Sam-console secret to set, and it confirms the shape of the gap: this is credentials + console, not code.

Recommendation — propose-only

Two steps, in order:

  1. Sam deploys oll-memory (merge #80 → memory.oll.am + oll_memory Neon + self-hosted nomic + ingest the WEB corpus + set the prod service token).
  2. Then the public front door + subdomain ships to a live URL, fast — one page, one no-auth endpoint on the public bible collection.

Ship-vs-build, honestly

CiteBible is a genuine thin front door over a DONE, proven engine — this is shipping, not a new build. The pull to resist is (a) rebuilding grounding — it exists and is the strongest part — or (b) adding domain / auth / payment — all explicitly out of scope for Session 1. The finish line is a working URL you can open on a phone; everything else is set down.

Engine (verified in code, 2026-07-05) ollwrite/src/lib/workspace-store.ts (:25, :9-10, :48-66) · workspace-switcher.tsx:22 · memory-client.ts:217-236 · app/api/memory/chat/route.ts (:33-34) · app/api/memory/handler.ts (:48-75, :621-628) · components/memory/sources-pane.tsx:107-110 · chat-pane.tsx:117
Gateway (verified) services/oll-model/routes.py · dtos.py · model.oll.am health = 200
Blocker oll-memory PR #80 (green, unmerged, localhost:5008) → deploy = Sam-console act

Sits beside the product thesis and the build-out & GTM plan; the corpus-per-vertical strategy is in the platform research. Thesis × build-map · propose-only · 2026-07-05 · every code claim above was read from source before it was written down.