06-reference/concepts

test id grammar mac join key primitive

2026-05-14·concept·source: MG `/dq` deck (slides 11-15) + founder's MAC framework distillation
test-id-grammarmac-frameworkdbt-testingjoin-key-primitivedata-qualitydurable-primitive

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:

  1. 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-coverage reads run_results.json from dbt, joins to the plan's test_ids via meta.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.

  2. 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.json can immediately locate it in the matrix without translation.

  3. 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:

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:

  1. Establishes RDCO as the canonical source of the test_id pattern. Future variations cite us.
  2. Builds awareness for MAC commercial. Buyers adopting the grammar are pre-qualified leads — they already understand the matrix discipline.
  3. 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:

  1. test-id-grammar.md — canonical spec for the five-part grammar, 1 page
  2. matrix-spec.md — the 3×6 Scope × Basis matrix with cell examples, 1 page
  3. A dbt package providing meta schema validation: if test_id is present, validate that it matches the grammar, and that the scope/basis prefix matches the declared matrix cell
  4. Sample dbt project with ~10 tests instrumented with test_ids, showing the grammar in real use
  5. Reference implementations of run_results.json joining 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)

Caveats

Related