Assessment

Evidence completeness

An assessment can only be as exact as the evidence underneath it. Completeness is how GlassBox says so out loud.

Three independent questions

Every receipt carries a completeness block answering three separate things. They are tracked separately because they fail separately.

Dependency resolution

Did every observed dependency resolve to a real DataHub URN? COMPLETE or INCOMPLETE, plus resolved and recorded counts.

Field-lineage coverage

Do we know which columns the decision read, or only which datasets?

Wildcard query

Did the run issue a SELECT *-shaped read, where the used columns cannot be enumerated from the query alone?

What each state permits

CoverageA field change can be judged as…
COMPLETE, no wildcardSTALE or UNAFFECTED — both verdicts are provable
INCOMPLETESTALE if a used field matched; otherwise UNKNOWN
Wildcard trueUNKNOWN for field-level changes — every column is potentially read

The asymmetry is deliberate. Proving a decision was affected needs only one matching dependency. Proving it was not affected needs to know the complete set of what it read.

Wildcard queries are not a bug

A SELECT * is a normal thing for an agent to write. GlassBox does not reject it — it records that column-level lineage is unavailable for that read, and downgrades the confidence of any later field-level verdict accordingly.

Resolution counts in the console

The console renders resolution as resolved / recorded. A receipt showing 1/1 with COMPLETE coverage supports an exact verdict either way. A receipt showing 3/5 cannot support UNAFFECTED, because two of the things it read are unknown.

Recording coverage explicitly

Coverage is asserted at registration, not inferred later. When importing or repairing state manually, it is supplied on the command line:

bash
uv run glassbox-invalidation-state register-receipt \
  .glassbox/invalidation.sqlite3 receipt.json \
  --field-coverage COMPLETE \
  --field-rule glassbox.sql-column-lineage.v1 \
  --wildcard-query false

--field-rule names the lineage rule that produced the claim. Recording which rule established coverage means a later change to that rule does not silently revalidate old receipts.

Live paths register automatically

register-receipt and postgres-register-receipt exist for historical imports and explicit repair. Live compiler paths register the receipt, its dependency index, and its publication obligation automatically, in one transaction.

Why this is surfaced in the product

The console shows coverage on every receipt, and the MCP tools return it with every influence projection. An operator looking at an UNKNOWN verdict needs to be able to tell the difference between "nothing changed" and "we could not tell" — those two are the same colour on almost every other tool.

Next

Deterministic invalidation covers the reason codes these states feed into.