Page 146: the number nobody was going to find
Two people paid below a legal minimum buried in a 147-page agreement, found and proved from the page, then fixed with a human signature.
A table on page 146 of the Meridian Care enterprise agreement decides what people get paid. Schedule J, minimum hourly rates by classification and level, 44 rows deep, on page 146 of 147, legally binding for three years. Nobody at Meridian has read it. Two employees are already below it: 20.00 and 17.50 an hour, against a floor of 21.34.

The number that runs a payroll sits in a document, not a database. This walkthrough shows the breach first, then how Strata built the check behind it.
Meridian Care is a fixture, seeded by scripts/strata_demo/seed_demo_kb.py into a real knowledge base (kb-21aa1f74da264ebc95d2a32ff34ae6af). The screenshots below are live captures of the product, but the company and the two employees are invented. The document shape is real; I come back to the 414-page agreement it was modelled on at the end.
What the cockpit shows first
The operations cockpit is where open exceptions land across every knowledge base; selecting the pay-floor alert gives this.

E1042, A. Nguyen, DDSO level 2, is on 20.00. E1088, M. Torres, DDSO level 2, is on 17.50. Both rows carry a compared against column showing 21.34. You don't have to trust a red badge: the reason sits in the next column.
That column is newer than the feature. At the July demo review a flagged rate didn't show the floor it broke, making the alert unverifiable on sight; the fix made link-mode dynamic thresholds emit the violated bound on every breach row, in the cockpit and the triggering-rows tables.
Three PDFs
Three files go into a knowledge base to start: the agreement, the payroll export and the HR register.

The agreement is 0.4 MB, the payroll export 9 KB, the HR register 6 KB. They're parsed into tables, which makes everything downstream a query rather than a summary. The Schedule J table comes out with its page and region recorded, and the audit at the end depends on that record.
The working model
From those three files, Strata mints object types and the links between them.

This is an ontology: a rate knows which role governs it, a role knows who holds it. AwardFloor is keyed on classification and level, the detail that used to break things. Real agreements key a pay scale on more than one column; the previous join parser returned nothing for an AND condition, so the related and impact endpoints degraded to "join condition not traversable". Segment 054 replaced it with a term parser that splits the composite into per-column equalities and builds the join as an AND of those, backed by 120 unit checks and 22 live checks. Anything outside that grammar, an OR, a literal, a subquery, still returns nothing and degrades rather than guessing: the grammar is an allowlist with no raw-SQL escape hatch.
The cards also carry data-quality rules: CompensationRate.employee_id is marked unique, and hourly_rate has a range of 0 to 200. Both produce their own alerts, and one is already open in the cockpit queue.
The limit is read from the agreement
The compliance question is "is anyone paid below the minimum that governs them", and the tempting build is to type 21.34 into a threshold box. Then page 146 changes and the check is quietly wrong, with nothing on screen to say so.

The stored config is four lines:
{ "kind": "dynamic_threshold",
"left": { "property": "hourly_rate" },
"operator": "<",
"right": { "link_type": "governed_by", "property": "min_hourly_rate" } }
There's no SQL in that config, and the user never writes any. The engine compiles it: validating every identifier against the active projection's property list, re-quoting it, and taking the operator from a fixed allowlist. The one-hop remote comparison compiles to a correlated EXISTS, so exactly one row survives per instance, keeping a join fan-out from inflating the counts or destabilising the fire-once fingerprint:
SELECT s.* FROM "ontology"."compensation_rate" s
WHERE TRY_CAST(s."hourly_rate" AS DOUBLE) IS NOT NULL
AND EXISTS (
SELECT 1 FROM "ontology"."award_floor" t
WHERE t."classification" = s."classification"
AND TRY_CAST(t."min_hourly_rate" AS DOUBLE) IS NOT NULL
AND TRY_CAST(s."hourly_rate" AS DOUBLE) < TRY_CAST(t."min_hourly_rate" AS DOUBLE))
Enabled monitors run on a five-minute tick; this one has a check interval of 3600 seconds, so in normal operation nobody presses anything. During the recording we pressed Evaluate now, the same code path with the wait removed.
The row that says we don't have the data
Every evaluated row gets one of three verdicts: breach, compliant, or no_data. A rate whose classification and level have no castable floor in Schedule J is recorded as no_data with the reason right_missing, and it never rounds down to "fine".

1 no-data · right_missing, sitting beside the two breaches rather than folded into them.This is the five seconds of the demo I care most about; it took a fixture change, not a code change. The three-way evaluation shipped in segment 056; the recording needed a seeded rate row whose classification isn't in the agreement at all, so a viewer sees the refusal happen rather than hearing me claim it. I'd rather read that verdict than a confident one: it tells me the comparison ran and came up short of evidence.
Who is affected, counted rather than estimated
The next question is how many people this touches. In the cockpit panel above, the answer is 1 JobClassification and 2 Employees, reached through applies_to, with the sample instances named on screen: DDSO · 2, E1042, E1088.
Those integers come from a declarative impact rule evaluated on the same data snapshot as the alert fingerprint, committed in the same DuckDB writer transaction as the fire-once claim and the alert insert. It counts COUNT(DISTINCT <instance-key tuple>) per hop, not distinct rows, so a two-column key can't multiply anybody. The acceptance gate for that segment asserts the integers byte-match an independent hand-run of the same DISTINCT-key SQL. Where a grounded count is unavailable, the panel suppresses the numeric tokens and prints "grounded impact unavailable": a missing count and a guessed count are different things.
The fifteen-second audit
Before anything changes, the cockpit will show you what would happen. Preview is a server-forced dry run.

"dry_run": true and the line "previewed", with no external bytes; underneath, the action is already parked awaiting approval, noting the requester cannot self-approve.Then you audit one of the two people by hand, from the product's own screens, starting on the record.

Follow governed_by to the floor that applies, and hover its source.

$20.00 on one page, $21.34 on the other, backed by a picture of the agreement. That's the audit: two clicks from the alert to the page, no step where you take the product's word for it. The provenance record behind the crop carries the document name, page: 146, a bbox_pdf rectangle, scope: "row" and, honestly, exact: false, since the answer is join-derived rather than lifted verbatim from one cell. Rows with a null bounding box fall back to opening the page.
One plan, one signature
The fix is a typed action, act_reissue_award_rate, and it does not run because the monitor asked. It parks.

system:monitor:mon_award_floor; the page header notes that approving resumes the reviewed manifest exactly, nothing re-planned.Two things make that inbox worth having. Requester identity is a signed origin claim, not anything in the request body, so a forged actor is rejected. The effect plan is frozen and hashed before the gate, so the bytes a human signs off are the bytes that execute, with no re-templating afterwards. A requester approving its own request gets a 409, trivially satisfied here since the requester is a monitor and the approver is a person.

The wording we use internally, "compensatable, not reversible", is deliberate. Compensation is derived at compile time from the frozen plan, checks the recorded after-image before acting, and refuses a stale or duplicate attempt. For the Xero case a draft invoice compensates by deletion, since Xero only permits voiding from authorised. When a dispatch crashes between send and acknowledgement, the reconciler writes outcome_unknown rather than picking a side. I'd rather ship a ledger that admits an uncertain outcome than one reporting a clean success it can't prove.
It keeps working as data arrives
Payroll posts its weekly export to a stream receiver rather than emailing a spreadsheet.

The receiver lands data quickly; what happens next matters more, since an export can arrive in a shape the model has never seen. Promotion routes through the matcher and the family sweep, so a novel shape parks instead of reshaping the live model.

That park raises its own cockpit alert, which is why the exception queue in the earlier screenshot carries a "schema drift: novel family" entry next to the pay-floor breach.
What has not shipped, and what was not measured
Demos flatter, so here are the honest edges.
Dispatching an action from inside the cockpit is planned, not shipped; the recording uses the shipped path: preview from the cockpit, run from the Object 360 dialog or the monitor-requested park. Feed history with a hardened receiver, and the PostgreSQL logical-replication CDC connector, are also planned. The compensation state machine is proven against a recorded stub connector; the live Xero draft-to-deleted proof is still open, so I won't claim it. Auto-promotion is proven in its own segment, but the receiver capture above has the toggle off, so that screenshot isn't evidence of it.
One measurement I'd like and don't have: how long the end-to-end run took in wall-clock terms, or how much of it was model time versus query time. The only cost signal I can read off the recording is the workspace credit counter, which moved from 466.5 to 461 across the session, covering everything I did on screen, not the pipeline alone.
Everything ran on one machine
All of this ran on one machine. The stream receiver posts to http://localhost:38003; the chatbot embed endpoint is http://localhost:33001. The agreement, the payroll export and the two employees' names never left it. For a care provider whose lawyers have opinions about where employment records live, that's why this conversation can happen at all.
Back to page 146

Meridian Care is invented; the document shape isn't. The walk-back below is the same feature running on the real corpus this fixture was modelled on: the Aruma DSEAV 2022-2025 enterprise agreement, 2.28 MB, 1,679 chunks, whose Schedule J is a table of 44 rows and 6 columns, and whose page number happens to be 146.

We also have the full narration timings for the 11 minute 17 second cut of this walkthrough, recorded live at 3840x2160 against the seeded knowledge base and paced at about 145 words per minute: strata_p146_demo_2026-07-13.srt. The subtitles are in the repository; the rendered master is not.
Page 146 used to be a wall of text. Now it's a check that runs every five minutes against live payroll, and the two names it flagged are sitting on an approval record with a page number attached.


