Build log · Part 0 of 6

Everything that held was a mechanism

What carried weight in an AI-operated knowledge graph, what was scenery, and why the parts that needed the models were the parts thrown away

Between April and July 2026, one person operated a knowledge graph of roughly 1,750 robotics companies using LLM agents, spent $997.48 on model calls across 85,613 invocations, then deleted about a third of what the money had bought and froze the remainder into a static site. The six documents left behind are an unusually candid build manual: every mechanism named, every failure priced. The obvious reading is that this is a story about cheap model labor and agent orchestration. The documents’ own telemetry supports the opposite reading, and that is the claim worth arguing: the durable engineering in this system was deterministic, the models were interchangeable metered labor fenced inside it, and every recorded failure occurred where a rule existed as prose or an instrument measured an act instead of an effect. The fourteen-agent harness, the Codex dispatch machinery, the session briefings — the parts that look most like innovation — were scaffolding for one operator’s attention, not the reason the corpus is trustworthy. Someone could disagree; the harness is what made solo operation feasible at all. But when the system was disassembled, the layers that required the models were the ones thrown away, and the part still standing is the part no model is needed to serve.

What carried weight: storage decisions, not pipeline features

The heaviest decision in the build is stated as a tenet — provenance, not verification — but its force is in the schema. A field value is stored as an observation with an origin and a timestamp. companies.provenance carries a versioned method identifier (jina_site_and_source_identity_v1) and a backlog_ref pointing at the work item that produced the verification, so the chain is traversable back into the operation’s own records. deals keeps both value text and value_num numeric, with value_confidence recording how far to trust the parse — capture-raw applied to a scalar. Entity resolution captures the source string unmodified and resolves downstream. The listen stage’s metadata object moved provenance coverage from 0 of 10,687 RSS rows to 11,740 of 11,740 captured rows after 2026-06-01, because it was added at capture rather than reconstructed at publish.

The same discipline extends to human intervention. The corrections module appends a structured entry — field, from, to, reason, session — on every manual write, against a declared correctable field set that raises on anything else, with the caller owning the transaction so the same code runs as dry run or applied change. The worked example is the Bayraktar Akıncı merge: the row that survived carried the better identifiers, the facts that survived came from the row that was deleted, and the record preserves the direction of the merge and the direction of the fact separately. This is the pattern a replicator should lift entire: manual fixes are provenance events, not silent updates.

The payoff arrived at teardown. The warfare layer, the editorial layer, and the commercial model were deleted, and “the remaining rows required no migration, because none of them asserted a current value.” A static SQLite file can stand behind its claims with no live system behind it precisely because no row ever claimed to be the truth.

What carried weight: ordering and fencing

The economics of the $997 are an ordering result. Triage ran 8,584 calls for $106.71 at $0.0124 per call and rejected 62.1% of 74,368 items upstream of an extractor costing roughly four times more per item, and it was tuned toward rejection on an explicit asymmetry: a false reject is recoverable on a later pass, a false accept is enrichment spend on noise. Entity resolution runs deterministic-first — a thirteen-line normalizer with 21 end-anchored suffix forms, deliberately shallow and order-dependent — then an alias table where 2,958 of 2,972 rows are LLM-sourced and roughly a thousand absorb vague source language (“russian uav”, “missile systems”) onto taxonomy class nodes so the graph’s specific nodes stay specific. The model runs only on misses, discards anything below a 0.72 confidence floor, and answers inside closed vocabularies: “a model answer that is not already a member of the vocabulary is not a new vocabulary entry.” The grooming passes are more restrictive still. One copied existing junction edges into a denormalized column and moved linked people from 848 to 4,545 of 4,766 at zero model cost. Another is gated to a hand-curated allowlist of two company slugs, because a read-only audit found 2 of 13 generic token matches genuine. Every edge records the literal method string that produced it.

The measured effect: June ran 10.7% more calls than May at 39% of the cost, with no reduction in corpus output. The reduction came from call composition and call avoidance. The transferable pattern is not “use a cheaper model” — it is that the model is the last resort inside a deterministic fence, and the fence is where the engineering lives.

What carried weight: the schema as a product decision

The migration from the legacy drone schema to directory was mostly deletion. companies went from 58 columns to 33; deployment_sites from 62 to 21, shedding 26 targeting columns; five classifier columns became facet edges. Facets replaced tenancy: a site is a row plus saved filters, membership resolved by a doubly-nested NOT EXISTS — AND across dimensions, OR within — and indexable and hierarchical are flags on data, so the set of generated pages is bounded by a query, not a hard-coded list. The delete rules encode an epistemology: CASCADE where a child row is meaningless without its parent, SET NULL where the link is an assertion about an entity in its own right. Keys were preserved rather than remapped, and the one bigint table got deterministic md5('directory-dsite:' || legacy_id)::uuid identifiers so re-runs reproduce them. Unmapped vocabulary was skipped and reported as a coverage gap, never silently auto-created. This layer plus the provenance model is the whole durable asset; 46,985 facet edges serve a person browsing by sector and a model filtering by capability from one copy of every fact.

The negative evidence, which matters more

The failures form a single pattern, and the documents state it themselves: the instruments measured the act rather than the effect. The freshness monitor fired daily, correctly, for six consecutive days across three of four cuts. The remediation worker beside it emitted outcome='ok' on all 242 of its runs, including the 200 on which it attempted nothing, because its signal recorded that the handler returned, not that the metric moved. Nothing escalated off the board; the breach outlived the system that measured it. A retrospective script reported metered spend of $0.18 against an actual $997.48 because it joined through the wrong table, and the number sat in a generated report for eleven days. A documentation coverage gate ran hourly for weeks without the --strict flag, exiting zero while code documentation fell from 100% to 76%. A four-day credential outage — 2,185 rejected calls, two entire days on which every stage executed and wrote nothing — reads in the spend series as two cheap days, because a rejected call costs $0.00. The traces recorded every failure faithfully; what did not exist was anything that read them. Even the model-identifier typo (claude-haiku-4.5 versus claude-haiku-4-5) silently split cost-by-model reporting in two, because identifiers were configuration strings, not validated values. And 100% of the $19.70 booked to error status was json_parse_failed: truncation at the output ceiling, clustered at 6,796 to 7,150 characters, against which a re-prompt for “valid JSON only” could do nothing — the retry loop, in the documents’ own verdict, “did not address the failure that actually occurred.”

Against this stands the contrast set, which is the essay’s real evidence. The inbound email quarantine holds because the boundary is a tool grant — Read, Grep, Glob, maxTurns: 4 — and the definition says so: “widening the list widens the blast radius of any instruction the body text happens to contain; no prompt wording changes that.” The destructive-operation guard holds because guardrail.sh is a deterministic deny path evaluated regardless of permission mode, while the 190-entry permission allowlist accreted into uselessness one prompt at a time. Drift detection is the one measurement with no exposure to silent skipping, because state_drifts is a stored generated column computed by the storage engine on write — it cannot report success while doing nothing — and the two corrections it needed both surfaced as implausible counts (drift 88 → 0 after the grain fix). The graph_writer cutover failed a smoke test on every table and produced a rule narrower than the design question: the smoke test runs as the role, before cutover. The tenet ledger makes the mapping explicit. Fifteen of 28 tenets are never cited anywhere; the cited ones have mechanisms attached. “The engine self-heals” had none, and it is the one that did not hold: production sat undeployed for roughly two weeks and the publish pipeline was down for five days, both found by a person looking.

The cost reading the headline number obscures

Total model-error cost was $20.74 — two percent of spend. The expensive failures were scope and blindness. 30.7% of model spend and 43.2% of completed backlog rows went into layers later deleted, two measures taken independently. The largest single line item, business_events at $262.15, was one agent on one model for 27 days, never run again. The reconstruction estimate’s own binding finding is that tiering would have saved roughly $449 of the April–May excess, but the scoping decision — deleting the warfare and editorial layers at teardown rather than building them at all — was “the only one of the four large enough to change the total on its own.” The backlog shows the same shape: median time to done was 0.18 days, median time to deferral 18.87 days, with no middle population, and one session deferred 46% of every abandoned row. The system had no instrument for any of this, because stage yield “has no column anywhere in the trace log”: attack_event_enrich consumed 34.8% of every call in the project to build a layer with no downstream consumer, its cost recorded exactly, its value unrepresentable. The depth profile carries the quietest version of the same joke: evidence_depth averaged 44.8, among the lowest axes, and it is the axis the product was sold on, while analysis_depth sat at 92.2 because a report had been generated for nearly every company.

What transfers

The replicable core is short. Store observations, not facts, with provenance born at collection and manual corrections recorded as provenance. Reject early and cheap, upstream of expensive acceptance, tuned toward rejection. Fence the model behind deterministic passes, alias tables, closed vocabularies, and confidence floors, and stamp every edge with the method that produced it. Make stages idempotent — claim-on-fetch, stamp-on-attempt — so that “re-run it” is a valid response to most failures; three of the four mechanisms here were retrofits, each priced by the incident that prompted it. Enforce rules as capabilities — grants, generated columns, deny hooks — and treat any rule that exists only as a prompt or a checklist as already decaying. Wire instruments to effects and put a reader on the other end, or accept that the board will show a green worker beside a red metric with no edge between them.

The rest is scenery. Fourteen agent definitions where several were authored before a queue existed for them; one packaged skill that never ran because the installer had no loop for it; a dispatch system whose honest speedup over the whole period is 1.86×; the drone taxonomy, the 2026 model identifiers, the vendor list — none of it is why the corpus is trustworthy. The terminal state is the proof. Model spend reached zero at 19:31 UTC on 2026-07-24, and what remains is 1,754 companies in a 25.9 MB SQLite file behind 1,923 static pages, every assertion still carrying its chain from click to source URL. The system was taken apart layer by layer, and the layers that needed the models running were the ones discarded. The disciplines are what is still standing.


Written by Kimi K3 from the six-part technical manual linked below, with no thesis supplied. One of four essays produced from the same brief — the others by GPT-5.4, Grok 4.5 and Claude Opus 4.8 — as a test of what independent readers would find load-bearing in the specs. All four converged on the same claim. Across 185 cited figures the four essays contained no fabrications. The comparison is in reports/bakeoff/.

The manual: Part 1 — the data model