10 Machine evidence providers
Quarto-Needs treats external tools as evidence providers, not as semantic authorities. Providers report execution facts; the Python core decides whether those facts agree with the engineering graph.
10.1 Provider pipeline
The provider-neutral flow is:
external tool result
│
▼
provider adapter
│
▼
evidence-checks-v1 deterministic payload
│
├── semantic validation against requirements/test-cases/evidence
│
▼
evidence-envelope-v1 attestation
│
▼
CI / review / Quarto projection
Provider adapters never mutate authored .qmd files. They normalize existing machine results into versioned artifacts under .quarto-needs/evidence/.
10.2 Generic check contract
schemas/evidence-checks-v1.schema.json defines the common payload used by non-pytest providers. Each check records:
- stable
id; - normalized
outcome:passed,failed, orskipped; - linked requirement IDs;
- linked modeled test-case IDs;
- linked modeled evidence IDs;
- optional provider-specific
details.
The payload itself has no timestamp. Determinism belongs here; run identity and freshness belong in the attestation envelope.
10.3 Initial adapters
The initial provider layer includes:
| Provider | Input | Normalized semantics |
|---|---|---|
| JUnit | JUnit XML | testcase outcome and optional Quarto-Needs properties |
| coverage.py | coverage JSON | explicit total-coverage threshold |
| Quarto render | process result | render target + exit-code verdict |
| JSON Schema | precomputed validation results | schema-validation verdicts |
| lint | process result | tool identity + exit-code verdict |
| type-check | process result | tool identity + exit-code verdict |
10.3.1 JUnit properties
JUnit testcases can carry model bindings as properties:
<properties>
<property name="quarto-needs.requirement" value="FUN-001;NFR-004"/>
<property name="quarto-needs.test-case" value="TC-006"/>
<property name="quarto-needs.evidence" value="EVD-006"/>
</properties>The adapter normalizes comma- or semicolon-separated IDs and preserves deterministic ordering.
10.3.2 Coverage policy
Coverage does not become evidence merely because a percentage exists. The adapter requires an explicit threshold supplied by the caller. The payload records both the observed coverage and the threshold used to derive the verdict.
10.3.3 Process providers
Quarto render, lint, and type-check adapters normalize an already executed process result. They do not shell out themselves. This keeps execution policy outside the semantic adapter and avoids arbitrary command execution inside configuration.
10.3.4 JSON Schema
The JSON Schema adapter normalizes validation results that have already been computed. It deliberately does not resolve or execute arbitrary schemas and remote references itself.
10.4 Generic semantic validation
validate_check_evidence() compares generic provider payloads with the canonical graph. By default, every machine check must bind to at least one modeled evidence object.
The validator checks:
- the machine outcome is passing;
- requirement IDs exist;
- modeled test-case IDs exist;
- claimed requirements are connected to claimed test-cases through the verification semantic family;
- modeled evidence IDs exist;
- a modeled evidence object’s declared
provider, when present, matches the machine provider; - modeled evidence objects are connected to the claimed test-cases through the evidence semantic family.
Generic validation uses EVD3xx diagnostics. This is separate from pytest-specific EVD1xx diagnostics and provider-neutral attestation/freshness EVD2xx diagnostics.
| Code | Meaning |
|---|---|
EVD301 |
the payload has no valid checks array, or contains a non-object check |
EVD302 |
a machine check outcome is not passed
|
EVD303 |
a machine check is not bound to a modeled evidence object |
EVD304 |
a machine check references an unknown test-case |
EVD305 |
a machine check references an unknown requirement |
EVD306 |
a claimed requirement is not verification-linked to a test-case the check claims |
EVD307 |
a machine check references an unknown evidence object |
EVD308 |
modeled evidence declares a different provider than the machine evidence |
EVD309 |
modeled evidence does not evidence a test-case the check claims |
EVD306 and EVD309 are the generic counterpart of the reciprocal gate described in Executable evidence: a provider may claim a requirement only when the model independently links that requirement to the claimed test-case, and only when the modeled evidence object is itself connected to it.
10.5 Trust boundary
A provider result is never sufficient by itself. Positive engineering evidence requires all applicable layers to agree:
provider result
AND model traceability
AND modeled evidence binding
AND attested graph/configuration state
AND freshness policy
That separation is intentional: a successful tool invocation cannot silently redefine which requirement it proves.