The Assay mark: a teal-cyan flask whose silhouette forms the letter A, with a gold ingot glowing at its base

Assays value, not just count

What did this product actually cost to build?

Everyone can tell you what you spent. Assay tells you what it was for — it records every unit of AI work as an attributed span, seals the conversation that drove it, and joins the two.

MIT substrate Local-first Append-only Unknown ≠ zero

Placing it

Four things Assay is not

Google Analytics for AI usage is the right shape — a ledger you own, analytics on top. It is the wrong tone. Assay is not a growth dashboard; it is a scale in a laboratory.

  • Not a cost-observability dashboard clone. A provider's billing page reports totals. Assay reports phases, attribution and provenance — and when it learns a past figure was wrong, it corrects it in the open rather than restating history.
  • Not a cloud SaaS that ships your prompts away. There is no hosted default and no telemetry back-channel. The sync verb sends an enumerated export whose raw-payload field does not exist in the type — not blanked, absent — and the receiving end rejects any record carrying one.
  • Not a wrapper or a proxy. Assay is not in the request path. It cannot slow a turn down and cannot break one. It reads what already happened.
  • Not a value oracle. Assay validates admissibility and provenance, never truth. A team that declares every session “feature work” will get a clean, well-versioned, useless aggregate — and Assay will report it faithfully.

The mechanism

Ore in. Metal out.

To assay is to test a material for its precious-metal content — to find out what ore is actually worth rather than weighing it. Six moves do that to token spend.

01

The ledger

Every unit of AI work is one immutable span: token counts broken out by phase, cost in integer micro-USD, and the chain from principal to session to task to tool call. A span is written once — the storage port exposes no update and no delete.

02

The seal

Conversation text reaches a store through one pipeline: scrub twelve secret classes, derive the honest features, truncate, seal with AES-256-GCM under a key you hold. It never lands in a metadata column and never in a sync batch.

03

The join

Said and spent, in one record. That join is what makes the second question answerable — not what a session cost, but what it was for, and what came of it.

04

The correction

A wrong figure is corrected, never rewritten. The remedy is an append-only row that every read resolves, carrying its own version and what it replaced, with the original still visible beside it.

05

The two readings

Where a question has two honest answers, Assay prints both and names which is which: inclusive, an upper bound that deliberately does not partition, and weighted, an estimate that does. It never picks one silently.

06

The one verb that reaches the network

It fetches public rate documents. It never opens the database, presents no credential, and transmits nothing. No other verb calls it, and it is never ambient.

The ledger is ours

We are the first customer

Assay's primary corpus is our own operation. Every figure below was measured read-only against that store, and every figure carries the date it was measured — because an undated number drifts.

253,417 spans

metered against one live store, 2026-05-14 to 2026-08-04

989,489 turns

sealed at rest with AES-256-GCM

$45,260.38

effective spend, correction-aware, as of 2026-08-03

45,255 spans

carry no price by design, and every total says so

Measured 2026-08-03 · these numbers do not update

Honesty — 01

A wrong figure is corrected, never rewritten

A price change never reaches back. When a figure is knowably wrong, the remedy is an append-only correction row that every read resolves — carrying its own version and what it replaced.

On our own store that is 86,235 correction rows, all stamped assay@6, recovering $5,575.91. Not one edited row.

Raw ledger$39,684.47
86,235 append-only corrections+$5,575.91
Effective, resolved at read$45,260.38

claude-opus-5 sat correctly unpriced for eight days holding $3,567.33 — because the ledger was honest and nothing read the bucket. The fix was a tripwire that reads it on a schedule.

Measured 2026-08-03 · every original figure still intact beside its correction

Honesty — 02

Unknown is not zero

$0.00 is a claim. “Unpriced” is a fact. If the pricer cannot vouch for a model, the span records its tokens and no cost — deliberately diverging from the upstream SDK, which falls back to $0. A false $0.00 under-reports spend; an absent cost is the truth.

253,417 spans on the live store2026-08-03
208,162 priced against a versioned table 45,255 carry no price — excluded from every total, and every total says so

A measured zero is never folded into an unknown

“This cost nothing” and “we cannot measure this” are different facts. In product attribution on the live store the two residual populations are $22.08 and $13,083.91. Merging them would have stated 30% of the ledger as a fact.

Measured zero$22.08
Genuinely unknown$13,083.91

593× the unknown population is 593 times the measured zero

Honesty — 03

Two readings. Both named.

Ask what a product cost to build and there are two honest answers. Assay prints both, labels which is which, and never picks one silently.

Reading A

Inclusive — an upper bound

The whole spend of every session that touched the product. These figures deliberately do not partition: a session that touched three products is counted whole in all three, so the column sums to more than the window total. That is the point — an upper bound that overstates is safer than an estimate that hides.

Reading B

Weighted — an estimate that partitions

Each session's spend times its share of that session's workspace references. This one does partition, and it reconciles: summed over 213 products it comes to $30,795.52 — exactly the covered population, to 123 µUSD of symmetric rounding.

A single number would have picked one and not told you. A breakdown a reader cannot tie back to the total is a breakdown nobody can trust.

Measured 2026-08-03 · 213 products · these numbers do not update

Sovereignty

Your spend. Your conversations. Your machine.

There is no hosted default and no telemetry back-channel. Conversation content is sealed under per-principal keys you hold, and the key never travels — the console does.

  • SQLite is the default store; Postgres is served through an injected executor, so the library carries no database dependency of its own.
  • Conversation text reaches a store through exactly one pipeline, sealed with AES-256-GCM under a per-principal key.
  • assay shred destroys one principal's key: their conversations become permanently unreadable while every row is retained.
  • A remote model scoring a span sees derived features only — token phases, ratios, tool name, timing, and for the raw payload a shape fingerprint: key count and depth, never a key name or a value.
  • Decryption is server-side, on the machine where the key already lives. The read-only console binds loopback, and a routable bind is refused unless you name it unsafe.
  • Exactly one verb reaches the network. It fetches public rate documents, presents no credential, and never opens the database.

The console

Where these numbers come from

The read-only console runs the same reports the CLI does — nothing is re-derived for the screen, so the console and the command line cannot disagree. A panel appears only if your store can answer it, and anything turned off is stated on the page.

The Assay console's spend panel: total spend, span count, unpriced spans called out in amber, token count with reasoning excluded, and a model mix breakdown.
Captured from assay dashboard over a deterministic synthetic corpus — assay seed for the spans, a synthetic transcript fixture for the conversations — never the live store. Its --snapshot mode stamps every static page with the capture instant in absolute UTC, the store, the version, the window and the filters, and ends in these numbers do not update.
The pricing-accuracy panel: unpriceable spans, correctable spans, overlay-priced spans, TTL-blind cache writes, and the pricing provenance split showing what the vendored table could price and what it could not.
Pricing accuracy — the same numbers assay pricing check reports. The screen and the cron cannot disagree.
The ROI panel, opening with an integrity block: analyzed spans, unpriced share excluded from every ratio, unattributed spend, and an attribution census naming how each outcome reached its spend.
ROI opens with the integrity block, not the ratio — because a ratio you cannot audit is arithmetic wearing the clothes of a measurement.

Pricing is positioning

The substrate is MIT. The value layer is the product.

Free, under MIT: the immutable log, the stores, the pricing table, the classifier, and the transcript capture. The money is the value layer — classification, valuation, waste, ROI, attribution, the ingest door, and the console.

The boundary is not a promise, it is a lint rule: the substrate may never import the value layer, and the build fails if it does. That makes an eventual open-source release a directory move rather than an untangling.

The repository is private today. The MIT grant on the substrate is standing, so publication would be a visibility flip rather than a relicensing — but it has not happened.

Assay your spend.

assay init writes a config file, an empty store, and a 0600 content key — then tells you to back the key up. Lose it and conversation content is unreadable; every derived number survives, because features are computed before the seal.