Ramine Darabiha · AI-native product builder

Darabiha

Live · started August 2026

Give a family archivist a document. Review the people, relationships and stories it finds.

An agentic private family archive with multilingual evidence, deterministic reconciliation and audited proposals. Connected assistants suggest changes; family members decide. The public TreeTree sample uses invented records.

Try public sample · Latest product decision · View source

My scope: Product strategy, archive reconstruction, data modeling, privacy and access design, interaction design, full-stack engineering, AI workflows, infrastructure, migration, testing, and operations

With: Darabiha family (Contribute records, corrections, stories, and photographs to the archive)

Hand the archivist a scan, a photograph or a genealogy export, and review the people, relationships and stories it finds. Darabiha helps a family turn scattered, multilingual records into a history it can explore and correct. The archive stays private, and the family remains the authority on what belongs in it.

I designed and built the product with AI agents, including its archivist, graph model and privacy controls. The important technical choice is what happens before a change lands: deterministic reconciliation checks identity, conflicting evidence remains a disputed claim, and a remote assistant can submit a proposal without gaining permission to rewrite the tree. A model's confidence is not a substitute for the family's decision.

Try a public-safe agent session

TreeTree is the public template, with a synthetic sandbox you can try. In a WebMCP-capable browser, an agent operates the same canvas you see through structured tools. In the recorded session here, I used those tools to read the starting family, add an invented Iris Rowan, and link Maya Rowan as her parent. The ordinary Undo button reversed the relationship; a subsequent tool read confirmed that Iris's record remained.

The walkthrough shows actual captured states, not a simulated conversation. The live sample keeps invented records in the browser and exposes eight tools for reading, adding, linking, importing and undoing. It demonstrates human and agent control of one interface. It does not expose the private archive or stand in for its document-ingestion, claim-review or permissioned remote-MCP workflow.

A family history, not just a tree

Eight views open on the same records: Family, Tree, List, Timeline, Calendar, Map, Numbers, and Fill in. Fill in is where the archive asks instead of answering, holding the things the old records imply but never state. The interface runs in three languages, one of them right to left, and only the interface is translated: names, biographies, and stories stay in the language they were written in. A GEDCOM export is one click, so the data is never captive.

Darabiha is a private, non-commercial deployment: one family, one Cloudflare Worker, one database and one file bucket, with no tenancy shared with anyone else. A relative can ask the archivist to add a grandmother and be asked the follow-up question that person is uniquely able to answer. The design treats incomplete evidence as a reason to ask, not an invitation to invent.

Three decisions, and what settled each

A contradiction becomes a claim, not an overwrite

Person facts began as columns on a row. Two sources disagreeing about a birth year meant the second write won and the first source vanished, leaving no trace that there had ever been a disagreement. The project's own readiness ledger recorded that state without softening it: provenance missing at claim level, confidence not persisted per claim, and competing claims unable to coexist without overwriting the person row.

The answer was not a confidence number on the row. Facts moved into an evidence_claims table keyed by subject, subject id, and predicate, where each row carries the value, a status, a confidence, the source type, the attachment it came from, a source label, a locator inside that source, an excerpt, and who wrote it. Writing a value now demotes any conflicting preferred claim on the same predicate to disputed instead of deleting it, and inserts nothing at all when an identical preferred claim already exists, so reading the same document a second time changes nothing.

What settled it was making the disagreement actionable rather than merely visible. Adjudication promotes a disputed claim to preferred, which demotes its rivals and writes the value back onto the record, or rejects it outright; both paths write an audit row naming the actor, the subject, and the predicate. Two commits carry the pair, cbe7491 and 1a76309. The migrations are additive at runtime, so records written before the change stay readable and say plainly that no claim-level source was recorded for them.

Reconciliation runs before the model, not through it

The same person arrives twice, spelled differently. A strict matcher produces duplicate ancestors; a loose one silently merges two cousins who share a name. Leaving that judgment inside the model makes the outcome unauditable and different on every run, which is the wrong property for a record a family expects to rely on for decades.

So the rule is 104 lines of ordinary code that run over every proposal before anything is written. Names are normalized first: compatibility decomposition, diacritics stripped, script variants folded so a name written with the Arabic forms of yeh and kaf matches the same name written with the Persian ones, and Arabic-Indic digits folded to ASCII so a year is the same year whichever numerals wrote it. Four fields decide identity: birth date, death date, birth city, birth country. A field can only contradict when both records state it, so silence never blocks a merge. Exactly one compatible match turns an addition into an update that fills gaps and overwrites nothing already stated. No match is a new person. More than one plausible match, or a genuine conflict, becomes a question carrying the candidate records and one line of evidence for each. Compatible evidence enriches; contradiction asks.

What settled it is that every ambiguity class is pinned by a test: alef maksura must not be conflated with yeh, the yeh and kaf variants must match, identity years written in Arabic-Indic numerals must match, an empty canonical name must never become a deduplication key, duplicates arriving inside a single import batch must collapse into one, and facts an incoming record is simply silent about must survive. The tool surface enforces the same rule from the other side: the archivist has thirteen tools, every one declared strict, merging is reserved for an unambiguous duplicate, and deleting a person is documented as not the way to handle one.

A connected agent may propose, never write

The archive is itself an MCP server, so the family can reach it from whichever assistant they already use. The obvious implementation is to put the create, update, and delete operations that already exist behind the same authorization. That was rejected. Raw mutation is never exposed over MCP, because an outside agent has none of the context a family editor has and no way to be asked.

A connection approved for reading gets twelve read-only tools. A connection approved to propose gets four additive ones, a correction tool, and a way to list what it has filed. Those handlers are pure builders: they turn arguments into a validated change proposal and file it in a queue, and the scope check runs before the handler rather than after it. Nothing they file touches the tree. An editor applies it through the same audited path a person's own edit takes, with the agent and the approving member recorded as the claim's source. A correction from an assistant does not even become a proposal; it becomes a question in the Fill in tab, and the record stands until a person answers.

What settled it is that the boundary is a release gate rather than a claim. One script walks the whole flow against the deployed site: discovery, dynamic client registration, consent with PKCE, rejection of a replayed authorization code, the read tools against the live archive, refresh rotation, revocation of an entire token family when a consumed refresh token is replayed, a propose-scope filing, an editor apply correctly refused for a member holding read-only access, and revocation from settings. The recorded production run passed twenty-five of twenty-five steps, and the one test proposal it filed was rejected afterward rather than left sitting in a family's tree. This is separate evidence from the public browser sandbox above.

What an outsider can check

The TreeTree repository publishes the generic archive under an MIT license, with invented fixtures instead of private family records. The claim table, reconciliation rule, tool schemas and import path are available to inspect. GEDCOM 5.5.1 and 7 files, including ones nested inside a ZIP, are parsed deterministically before any model sees them, so an import is reproducible and runs without an API key; tests cover the supported round-trip subset. The public template and the private deployment are separate artifacts, so a successful sandbox interaction is not presented as a fresh run of the private archive's release gate.

Failure is recorded as carefully as success. When the archive once went unreadable, the first diagnosis was wrong twice: an error detector matched the top-level message while the platform wrapped the real one, and a hand-seeded fallback object was validated by eye when the byte that mattered was an invisible trailing newline. The instrumentation eventually proved that the daily database read quota was account-wide and this archive had never been the consumer, having read about 380 thousand rows against a five million allowance while an unrelated project on the same account read 48 million from three unindexed sweeps. The fix is a circuit breaker that opens on the first recognized quota response and serves reads from private snapshots until the provider's own reset, deliberately keeping the visibility and role snapshots so an outage can never weaken the password or member gate. It was settled when the site served members from snapshots and returned 401 to anonymous callers with the database still exhausted.

Limits, and what is not true yet

One Worker is one family. There is no multi-tenancy and none is planned; the isolation is the point, which also means a new archive is a deployment rather than a sign-up, and production carries no create-a-family flow inside it.

Merges and person, relationship, and story changes store their inverse and can be undone; deleting an uploaded file cannot be, and stays that way until file retention exists. GEDCOM round-trips the supported subset of people, links, dates, places, notes, events, and residences, while rich source and media extensions remain a documented gap. The archivist depends on a hosted model, with two providers behind one seam and neither of them self-hosted; without a key the archive still reads and the AI features answer 503. Public redaction of likely living people is a rule rather than a judgment: no recorded death plus a birth within 120 years leaves a public reader the birth year and nothing else. Public AI requests are capped at 30 per address per hour and password attempts at 10 per 15 minutes, with only a hash of the address stored and never the address. The free platform tier fits an archive of several hundred people; a larger or busier one needs the paid plan.

The linked public sandbox has a deliberately narrower scope than the archive. The browser-agent workflow was verified on September 8, 2026; no hosted-model document analysis or private-record access is demonstrated by that session.

The product can show where a fact came from and who preferred it over the alternative. It cannot make a wrong document right. That work stays with the family, which is the intended division of labour.

My contribution

I designed and built the product end to end: archive reconstruction, product model, graph schema, privacy and access system, visual and interaction design, full-stack implementation, the archivist itself, data migration, testing, Cloudflare infrastructure, and ongoing operation. The archivist acts only through typed proposals that carry their source, become disputed claims when they conflict with the record, and are applied as audited, reviewable changes. Family members remain the authority for their own history and contribute the records, corrections, stories, and photographs the product preserves. Product judgment, privacy decisions, source acceptance, verification, and release remained mine.

Darabiha itself remains behind its password gate. Only TreeTree's invented sample records appear in the public demonstration; the real archive, records and family media remain private.