The test_id grammar — MAC's join-key primitive
Why this is in the vault
The test_id is the load-bearing technical primitive that makes the entire MAC / /dq loop work. It's small, elegant, dbt-native, vendor-agnostic, and reusable in any data-quality testing context — including ones beyond MAC. Filing as a standalone concept article because it's the sort of durable primitive that should outlive any specific product version; if MAC's commercial shape changes, the grammar remains.
The grammar
{model}:{scope}:{identifier}:{basis}[:descriptor]
Five-part identifier, four required + one optional. Example:
gold_txn_pipeline:R6:absolute:expansion_implies_flag
gold_txn_pipeline:A2:relative-source:silver_to_gold_row_count
gold_txn_pipeline:C1:human:arr_signoff_2026_q2
The five parts
| Part | What it is | Example values |
|---|---|---|
| model | The dbt model under test | gold_txn_pipeline, silver_orders, dim_customer |
| scope | One of three test scope levels with a cell-position prefix | C1 (Column scope, row 1), R6 (Row scope, row 6), A2 (Aggregate scope, row 2) |
| identifier | A hyphenated key naming what's being checked | not-null, unique-pk, arr-formula, silver-to-gold-count |
| basis | One of six test bases | absolute, relative-source, relative-production, relative-recon, temporal, human |
| descriptor (optional) | A specific qualifier when the identifier alone is ambiguous | expansion_implies_flag, arr_signoff_2026_q2, pii_completeness_eu |
Why this grammar is the join-key primitive
The test_id is what lets MAC's loop close end-to-end. Without it, the framework would be a methodology that requires a human to track which test corresponds to which matrix cell. With it, the matrix becomes a queryable artifact.
Three loop closures the test_id enables:
Plan ↔ Coverage join. The timeless test plan (one markdown file per model) and the timestamped coverage report (one markdown file per nightly run) share test_ids as the join key.
/dq-coveragereadsrun_results.jsonfrom dbt, joins to the plan's test_ids viameta.test_id, and produces a coverage report showing which planned tests passed/warned/failed/were skipped this run. The plan never changes; the coverage diffs every night.Matrix ↔ Implementation join. The 3×6 matrix cell (e.g., R6 = Row scope, basis 6 = Human) is encoded in the test_id's scope segment. A human looking at the plan can see "all tests in row R6" by filtering. A human looking at a failing test in
run_results.jsoncan immediately locate it in the matrix without translation.Triage ↔ Ticket join. When
/dq-triage <test_id>fires, the test_id becomes the foreign key to a Discovery Ticket (Jira PRO, Linear, GitHub Issue, or markdown). The ticket carries the test_id in its body so failures from multiple runs roll up to a single ticket. The umbrella-detection pattern ("10 tests, 3 root causes") works because triage can group test_ids by shared identifier or shared scope.
Why the dbt meta block is the right home for it
dbt's schema.yml supports a meta block on every test:
- name: not_null
config:
where: "row_id is not null"
meta:
test_id: "gold_txn_pipeline:C1:not-null:row_id"
matrix_cell: "C1"
basis: "absolute"
state: "go"
The meta block survives across dbt runs, appears in run_results.json, and is queryable via dbt list --select state:modified patterns. No external tool is required to plumb test_ids through the dbt run — they're first-class metadata.
Why this primitive is durable across MAC versions
If MAC's product shape changes (different pricing, different positioning, different commercial bundle), the grammar holds:
- The grammar is dbt-native. Any dbt project can adopt it without buying anything. That's the "MAC alpha for you even if you never become a MAC customer" surface.
- The grammar is tool-agnostic. It doesn't depend on a specific ticket system, dashboard, or CI tool. The MAC dashboard reads test_ids; so could any other dashboard.
- The grammar is matrix-agnostic. If a future MAC version revises the 3×6 matrix (e.g., adding a 7th basis, collapsing Recon into Rel:Production), only the scope/basis part of the grammar shifts. The five-part structure remains.
- The grammar is human-readable. A developer reading
gold_txn_pipeline:R6:absolute:expansion_implies_flagunderstands what's being tested without consulting documentation. That's the test for any naming convention worth keeping.
Why this matters for the open-source vs commercial-product tension
The 4-tier model concept filed earlier today ([[concepts/2026-05-14-four-tier-buy-build-stack-soloproneur-tam-filter]]) names a tension: tier-3 BUILD work is alpha for you but rarely spawns commercial products at VC scale. MAC is a tier-2 BUY (narrow agentic workflow) at soloproneur TAM scale.
The test_id grammar is the part of MAC that wants to be open-source. It's the durable primitive that anyone using dbt should adopt regardless of whether they buy MAC. Releasing the grammar as an open spec (e.g., as a dbt-pkg or a published markdown doc) does three things:
- Establishes RDCO as the canonical source of the test_id pattern. Future variations cite us.
- Builds awareness for MAC commercial. Buyers adopting the grammar are pre-qualified leads — they already understand the matrix discipline.
- Doesn't cannibalize MAC. The grammar is the join key, not the product. MAC commercial sells the interactive interview (
/dq-plan), the matrix gap audit (/dq-audit), the test instrumentation (/dq-instrument), the coverage diff reports, the triage workflow, and the sample project + onboarding. The grammar alone gets you nothing without those skills.
This is the same pattern as Anthropic's MCP — released the protocol as open spec, kept the model and the products proprietary. The protocol becomes the load-bearing primitive everyone adopts; the products that use it well still win.
Suggested first OSS release shape
A minimal package or repo with:
test-id-grammar.md— canonical spec for the five-part grammar, 1 pagematrix-spec.md— the 3×6 Scope × Basis matrix with cell examples, 1 page- A dbt package providing
metaschema validation: iftest_idis present, validate that it matches the grammar, and that the scope/basis prefix matches the declared matrix cell - Sample dbt project with ~10 tests instrumented with test_ids, showing the grammar in real use
- Reference implementations of
run_results.jsonjoining for coverage reporting (Python, SQL, dbt macro)
The OSS release is intentionally NOT MAC. It's the grammar + matrix spec + a few helpers. MAC commercial owns the agentic workflow that adopts the grammar and runs the loop.
What's NOT in this grammar (deliberate exclusions)
- Severity (dbt's
error/warn) — already handled by dbt config, not part of the test_id. - State (Stop / Go / Pause / Monitor) — orthogonal to the test_id; lives in
metaseparately asmeta.statebecause it changes over time while the test_id is immutable. - Owner — out of scope for the grammar; lives in Discovery Tickets or
meta.ownerif needed. - Expiration (for human-basis sign-offs) — handled by
meta.expires_after, not encoded in test_id.
Caveats
- The grammar is dbt-centric in its current form. Generalizing to non-dbt data quality (Great Expectations, Soda, Monte Carlo, Elementary) would require translating the
metablock to those tools' equivalent metadata surfaces. Possible but unproven. - The 3×6 matrix is RDCO's specific framework choice. Other testing frameworks may use different scope/basis decompositions. The grammar can accommodate them (different scope/basis values) but the canonical spec ships with the 3×6 default.
- Test_ids should be stable across renames. If
gold_txn_pipelinebecomesgold_transactions_pipeline, every test_id changes — that's a real migration cost that MAC's tooling should handle (rename helper) but the grammar itself doesn't solve.
Related
- [[01-projects/mac/2026-05-14-mac-pricing-intent]] — MAC pricing decision; the test_id grammar is the underlying technical primitive
- [[01-projects/mac/2026-05-14-mac-prelaunch-readiness-checklist]] — pre-launch readiness; test_id grammar is on the "don't touch — it's right" list
- [[concepts/2026-05-14-four-tier-buy-build-stack-soloproneur-tam-filter]] — open-spec primitive on the BUY-commodity tier; commercial product on the BUY-narrow-workflow tier
- [[concepts/2026-05-13-fde-asymmetric-edge-rdco-positioning]] — the asymmetric edge thesis; canonicalizing a primitive is one of the cheaper plays inside the productization-gap thesis
- [[06-reference/source-pdfs/2026-05-14-mg-dq-tdd-for-analytics-deck-progress-engagement.pdf]] — source deck (slides 11-15 cover the grammar)
- [[concepts/2026-05-13-amble-is-software-losing-its-head-defensibility-migration]] — Amble's "data exhaust" pattern; test_ids are the data exhaust that MAC's loop generates