Canonical Facts & Calc Usage Guide
Purpose
The canonical facts system lets us store key numbers (valuations, revenue, headcounts) in YAML and reference them across wiki pages. When a number changes, we update one YAML file and every page that references it stays correct.
Two MDX components power this:
<KBF>— display a single KB fact inline (with hover tooltip showing metadata)<Calc>— compute a derived value from 2+ facts (e.g. revenue multiples, growth rates)
Quick Reference
{/* Simple fact display */}
<KBF entity="anthropic" property="valuation">$380B</KBF>
{/* Fact with auto-rendered value (no children needed) */}
<KBF entity="anthropic" property="valuation" />
{/* Fact with inline date — renders "300,000+ (as of 2025)" */}
<KBF entity="anthropic" property="business-customers" showDate />
{/* Computed value from two facts */}
<Calc expr="{anthropic.valuation} / {anthropic.revenue}" precision={0} suffix="x" />
{/* Growth percentage */}
{/* Revenue growth from $1B to $4B (early 2025 to mid-2025) — hardcoded because Calc can't reference specific asOf dates */}
300%
Which Numbers Should Be Facts?
Not every number in the wiki should be a fact. The key question is: will this number change when new data arrives?
Must be facts (Tier 1)
Numbers that change over time AND appear on 2+ pages.
| Example | Why |
|---|---|
| Anthropic's valuation | Updated every funding round, referenced on IPO, valuation, and company pages |
| OpenAI's revenue | Changes quarterly, appears on multiple comparison pages |
| Total AI safety funding | Updated annually, appears on funding and field overview pages |
These are the highest-ROI facts. Updating one YAML entry keeps N pages correct.
Should be facts (Tier 2)
Numbers that change over time but currently appear on only 1 page.
| Example | Why |
|---|---|
| "300,000+ business customers" | Will be 400,000+ within months |
| Prediction market probabilities | Change daily |
| Net cash burn rates | Updated quarterly |
Even on one page, wrapping these in <KBF> means the update workflow is "edit KB YAML" not "search through prose."
Should NOT be facts (Tier 3)
Fixed historical numbers that will never change.
| Example | Why |
|---|---|
| "Founded in 2021" | Historical fact, won't update |
| "Series A raised $124M in May 2021" | Fixed in time |
| "Hired Wilson Sonsini in December 2025" | One-time event |
Making these into facts adds overhead with no benefit.
Decision flowchart
- Will this number change when new data comes in? No → plain text
- Does it appear on 2+ pages? Yes → must be a fact (Tier 1)
- Appears on 1 page but will change? Yes → should be a fact (Tier 2)
When to Use <KBF> vs <Calc>
Use <KBF> for single fact display
Any time you're showing a stored number — a valuation, revenue figure, headcount, date — use <KBF>.
{/* With explicit display text */}
<KBF entity="anthropic" property="valuation">\$380 billion</KBF>
{/* Auto-display from the fact's value field */}
<KBF entity="anthropic" property="valuation" />
{/* With inline date for temporal claims */}
Over <KBF entity="anthropic" property="business-customers" showDate /> business customers
{/* Renders: "Over 300,000+ (as of 2025) business customers" */}
showDate is important for sentences where the recency of a number is part of the claim. When the fact gets updated (e.g. to 400,000+ / 2026-06), the prose automatically reads the new number and date without anyone needing to edit the surrounding text.
Use <Calc> for derived computations
When you need a value that's computed from 2+ facts — ratios, multiples, growth percentages — use <Calc>.
{/* Revenue multiple */}
<Calc expr="{anthropic.valuation} / {anthropic.revenue}" precision={0} suffix="x" />
{/* Growth rate */}
{/* Revenue growth from $1B to $4B (early 2025 to mid-2025) — hardcoded because Calc can't reference specific asOf dates */}
300%
{/* Comparison */}
<Calc expr="{openai.valuation} / {anthropic.valuation}" precision={1} suffix="x" />
The power: when either input fact updates, the derived number auto-updates too. A revenue multiple stays correct whether the valuation or revenue changes.
Do NOT use <Calc> for single values
If you're just displaying one fact with no computation, use <KBF>, not <Calc>. <Calc> is for math, <KBF> is for display.
{/* Wrong — no computation happening */}
<Calc expr="{anthropic.valuation}" format="currency" />
{/* Right — just display the fact */}
<KBF entity="anthropic" property="valuation" />
Use plain text for everything else
Historical numbers, qualitative descriptions, and one-off figures that won't change don't need either component.
KB Fact Structure
Facts live in packages/kb/data/things/<entity>.yaml under the facts: section. Each fact has a stable ID and human-readable property name:
thing:
id: anthropic
name: Anthropic
facts:
- id: f_mN3pQ7kX2r
property: valuation
value: 380e9 # Structured numeric (auto-formatted)
asOf: 2026-02 # When this was current
source: "https://..." # Attribution URL
notes: "Series G post-money" # Context shown in tooltip
Required fields:
id— stable unique identifier (auto-generated)property— human-readable property name (e.g.valuation,revenue,headcount)value— numeric (e.g.380e9,[20e9, 26e9]) or string
Optional fields:
asOf— temporal anchor (strongly recommended for any changing number)notes— shown in tooltipsource— attribution link
Custom YAML Tags
KB YAML files support two custom tags for type-safe data entry:
!ref — Entity References
Cross-references between entities. Ensures referential integrity at load time.
# Preferred format (stableId:slug — enables cross-validation)
value: !ref mK9pX3rQ7n:dario-amodei
# Bare stableId (deprecated, still works)
value: !ref mK9pX3rQ7n
!date — Explicit Date Typing
Forces a value to be treated as a date, even when YAML would otherwise parse it as a number or string. This is especially important for bare years like 2019, which YAML auto-parses as the integer 1919 (or similar numeric coercion).
# Without !date — YAML parses 2019 as an integer, not a date
founded: 2019 # ⚠️ Parsed as number 2019, not a date
# With !date — explicitly typed as a date
founded: !date 2019 # ✓ { type: "date", value: "2019" }
started: !date 2023-06 # ✓ { type: "date", value: "2023-06" }
born: !date 2023-06-15 # ✓ { type: "date", value: "2023-06-15" }
When to use !date:
- Bare years (e.g.
2019,2023) — always use!dateto prevent numeric parsing - Year-month (e.g.
2023-06) — use!datefor clarity, though the loader's date heuristic (DATE_RE) can usually detect these - Full ISO dates (e.g.
2023-06-15) — optional; the heuristic detects these reliably, but!datemakes intent explicit
When !date is not needed:
- Date strings in
asOfandvalidEndfields — these are always treated as dates by the loader regardless of format - Quoted date strings that match the
YYYY-MM-DDorYYYY-MMpattern — the loader's regex heuristic handles these
Adding New Facts
- Add the entry to the appropriate
packages/kb/data/things/<entity>.yamlfile - Run
pnpm buildto rebuild - Reference in MDX with
<KBF entity="entity" property="property" />
Updating Facts
When new data arrives:
- Edit the YAML file in
packages/kb/data/things/<entity>.yaml - Add a new entry with updated
valueandasOf(keep old entries for historical reference) - Run
pnpm buildto rebuild - Every
<KBF>and<Calc>referencing that property auto-updates
Keep old point-in-time facts as separate entries when pages reference them explicitly:
# current valuation (gets updated)
- id: f_mN3pQ7kX2r
property: valuation
value: 380e9
asOf: 2026-02
# historical snapshot (stays fixed, referenced by comparison sections)
c45b168f:
# previous valuation (kept for historical reference)
- id: f_prev_val
property: valuation
value: 350e9
asOf: 2025-11
Data Authority
KB YAML (packages/kb/data/things/*.yaml) is the authoritative source for structured facts on entities it covers. As of March 2026, 9+ entities have been migrated to KB: Anthropic, OpenAI, xAI, Meta AI, MIRI, SSI, Dustin Moskovitz, Elon Musk, and Sam Altman. Old data/facts/*.yaml files for these entities are deprecated — do not update them.
For entities not yet in KB, data/facts/*.yaml remains authoritative. See Data System Authority Rules for the full hierarchy.
Scaling Strategy
Current state: 9+ entity KB YAML files in packages/kb/data/things/, 60 properties across the KB schema, ~13 pages actively using <KBF> tags. Priority order for expansion:
Phase 1 — Migrate remaining organizations with old facts files
Google DeepMind, Center for AI Safety, Chan Zuckerberg Initiative, and other entities still using data/facts/*.yaml. Move their structured data into KB YAML.
Phase 2 — Field-level metrics Compute benchmarks, total AI safety funding, researcher headcounts. Numbers that get updated with each new report and appear across multiple pages.
Phase 3 — Cross-referenced numbers Any figure appearing on 3+ pages. Find these via grep and migrate to KB facts for consistency.
Don't try to fact-ify everything at once. Expand entity-by-entity as pages get created or updated.
Common Patterns
Valuation with context
valued at <KBF entity="anthropic" property="valuation" /> in its latest funding round
Temporal metric in prose
Over <KBF entity="anthropic" property="business-customers" showDate /> business customers
{/* → "Over 300,000+ (as of 2025) business customers" */}
Revenue multiple in a table
| Metric | Value |
|--------|-------|
| **Revenue Multiple** | <Calc expr="{anthropic.valuation} / {anthropic.revenue}" precision={0} suffix="x" /> |
Growth rate comparison
revenue grew 300% in seven months
Side-by-side company comparison
Anthropic trades at ≈<Calc expr="{anthropic.valuation} / {anthropic.revenue}" precision={0} suffix="x" /> revenue
vs OpenAI's ≈<Calc expr="{openai.valuation} / {openai.revenue}" precision={0} suffix="x" />