eval-quality 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/README.md +142 -67
  2. package/corpus/dev/README.md +20 -13
  3. package/corpus/dev/compile-seal-example/brief.json +1 -1
  4. package/corpus/dev/compile-seal-example/contract.json +1 -1
  5. package/corpus/dev/contracts/absent-collection-locations.json +1 -1
  6. package/corpus/dev/contracts/absent-sibling-groups.json +1 -1
  7. package/corpus/dev/contracts/absent-success-indicator.json +1 -1
  8. package/corpus/dev/contracts/empty-channel-roles.json +1 -1
  9. package/corpus/dev/contracts/empty-collection-locations.json +1 -1
  10. package/corpus/dev/contracts/empty-request-shapes.json +1 -1
  11. package/corpus/dev/contracts/empty-sibling-groups.json +1 -1
  12. package/corpus/dev/contracts/fragment-selection.json +1 -0
  13. package/corpus/dev/contracts/no-collection-quantifier.json +1 -1
  14. package/corpus/dev/contracts/no-operation-inventory.json +1 -1
  15. package/corpus/dev/contracts/no-read-back-relation.json +1 -1
  16. package/corpus/dev/contracts/no-state-change-marker.json +1 -1
  17. package/corpus/dev/contracts/no-type-violating-step.json +1 -1
  18. package/corpus/dev/contracts/per-key-split-oracles.json +1 -1
  19. package/corpus/dev/contracts/review-corpus.json +1 -0
  20. package/corpus/dev/contracts/satisfied-declarations.json +1 -1
  21. package/corpus/dev/contracts/single-required-response-key.json +1 -1
  22. package/corpus/dev/contracts/split-indicator-oracle.json +1 -1
  23. package/corpus/dev/contracts/unaddressed-parameter-sibling.json +1 -1
  24. package/corpus/dev/contracts/unnamed-reference-set.json +1 -1
  25. package/corpus/dev/contracts/wrong-cardinality-form.json +1 -1
  26. package/corpus/dev/index.json +1 -1
  27. package/dist/application/index.d.ts +2 -0
  28. package/dist/application/index.js +1 -0
  29. package/dist/application/score.d.ts +48 -0
  30. package/dist/application/score.js +186 -0
  31. package/dist/cli/arguments.d.ts +7 -3
  32. package/dist/cli/arguments.js +73 -5
  33. package/dist/cli/exit-codes.d.ts +6 -2
  34. package/dist/cli/exit-codes.js +8 -9
  35. package/dist/cli/main.js +9 -0
  36. package/dist/cli/render.d.ts +3 -6
  37. package/dist/cli/render.js +57 -5
  38. package/dist/cli/run.d.ts +13 -3
  39. package/dist/cli/run.js +136 -16
  40. package/dist/core/canonical/canonicalize.d.ts +12 -0
  41. package/dist/core/canonical/canonicalize.js +18 -4
  42. package/dist/core/compile/bindings.d.ts +89 -0
  43. package/dist/core/compile/bindings.js +334 -0
  44. package/dist/core/compile/compile.d.ts +17 -0
  45. package/dist/core/compile/compile.js +37 -1
  46. package/dist/core/compile/excluded-content.d.ts +11 -0
  47. package/dist/core/compile/excluded-content.js +42 -0
  48. package/dist/core/compile/expression-legality.d.ts +49 -0
  49. package/dist/core/compile/expression-legality.js +158 -38
  50. package/dist/core/compile/forbidden-inputs.d.ts +8 -1
  51. package/dist/core/compile/forbidden-inputs.js +16 -3
  52. package/dist/core/compile/interface-inventory.d.ts +57 -2
  53. package/dist/core/compile/interface-inventory.js +119 -13
  54. package/dist/core/compile/reachability.d.ts +28 -1
  55. package/dist/core/compile/reachability.js +167 -35
  56. package/dist/core/compile/schema-version.d.ts +2 -0
  57. package/dist/core/compile/schema-version.js +25 -0
  58. package/dist/core/compile/sensitivity-witness.d.ts +31 -12
  59. package/dist/core/compile/sensitivity-witness.js +110 -23
  60. package/dist/core/compile/step-reference.d.ts +2 -0
  61. package/dist/core/compile/step-reference.js +49 -0
  62. package/dist/core/coverage/operations.d.ts +62 -0
  63. package/dist/core/coverage/operations.js +57 -0
  64. package/dist/core/coverage/relevance.d.ts +4 -2
  65. package/dist/core/coverage/relevance.js +22 -23
  66. package/dist/core/coverage/satisfaction.d.ts +2 -2
  67. package/dist/core/coverage/satisfaction.js +73 -48
  68. package/dist/core/declared-inputs.d.ts +83 -4
  69. package/dist/core/declared-inputs.js +105 -8
  70. package/dist/core/emit/emit.d.ts +9 -0
  71. package/dist/core/emit/emit.js +214 -0
  72. package/dist/core/emit/private-artifact-digest.d.ts +11 -0
  73. package/dist/core/emit/private-artifact-digest.js +31 -0
  74. package/dist/core/evaluate/evidence-resolution.d.ts +10 -3
  75. package/dist/core/evaluate/evidence-resolution.js +74 -11
  76. package/dist/core/evaluate/operators.d.ts +22 -0
  77. package/dist/core/evaluate/operators.js +17 -1
  78. package/dist/core/evaluate/resolution.d.ts +14 -3
  79. package/dist/core/evaluate/resolution.js +63 -3
  80. package/dist/core/excluded-content.d.ts +65 -0
  81. package/dist/core/excluded-content.js +113 -0
  82. package/dist/core/failure-codes.d.ts +2 -2
  83. package/dist/core/failure-codes.js +7 -2
  84. package/dist/core/ingest/conditions.d.ts +201 -0
  85. package/dist/core/ingest/conditions.js +48 -0
  86. package/dist/core/ingest/index.d.ts +13 -0
  87. package/dist/core/ingest/index.js +11 -0
  88. package/dist/core/ingest/ingest.d.ts +68 -0
  89. package/dist/core/ingest/ingest.js +318 -0
  90. package/dist/core/lineage/stage-table.d.ts +21 -4
  91. package/dist/core/lineage/stage-table.js +35 -3
  92. package/dist/core/preflight/plan.d.ts +7 -5
  93. package/dist/core/preflight/plan.js +75 -32
  94. package/dist/core/preflight/projection.d.ts +6 -3
  95. package/dist/core/preflight/projection.js +22 -2
  96. package/dist/core/preflight/reduce.js +47 -7
  97. package/dist/core/preflight/witness-evidence.d.ts +5 -5
  98. package/dist/core/preflight/witness-evidence.js +73 -20
  99. package/dist/core/schemas/artifact.d.ts +1049 -30
  100. package/dist/core/schemas/constraint-ledger.js +51 -0
  101. package/dist/core/schemas/defect-signature.d.ts +695 -0
  102. package/dist/core/schemas/defect-signature.js +175 -0
  103. package/dist/core/schemas/eval-contract.d.ts +550 -12
  104. package/dist/core/schemas/eval-contract.js +32 -2
  105. package/dist/core/schemas/evidence-artifact.d.ts +109 -19
  106. package/dist/core/schemas/evidence-artifact.js +64 -8
  107. package/dist/core/schemas/interface.d.ts +741 -13
  108. package/dist/core/schemas/interface.js +120 -7
  109. package/dist/core/schemas/isolation-manifest.js +16 -9
  110. package/dist/core/schemas/plan.d.ts +329 -3
  111. package/dist/core/schemas/plan.js +89 -3
  112. package/dist/core/schemas/pointer.d.ts +47 -1
  113. package/dist/core/schemas/pointer.js +89 -8
  114. package/dist/core/schemas/port-messages.d.ts +194 -10
  115. package/dist/core/schemas/port-messages.js +73 -6
  116. package/dist/core/schemas/probe-body.d.ts +18 -0
  117. package/dist/core/schemas/probe-body.js +13 -0
  118. package/dist/core/schemas/probe-qualification.d.ts +168 -0
  119. package/dist/core/schemas/probe-qualification.js +106 -0
  120. package/dist/core/schemas/probe.d.ts +431 -0
  121. package/dist/core/schemas/probe.js +6 -2
  122. package/dist/core/schemas/scoring-policy.d.ts +1 -0
  123. package/dist/core/schemas/scoring-policy.js +6 -1
  124. package/dist/core/schemas/sealed-evaluator-brief.d.ts +1 -0
  125. package/dist/core/schemas/sealed-evaluator-brief.js +4 -1
  126. package/dist/core/schemas/sealed-run-record.d.ts +161 -12
  127. package/dist/core/schemas/sealed-run-record.js +92 -15
  128. package/dist/core/schemas/sensitivity-witness.d.ts +108 -6
  129. package/dist/core/schemas/sensitivity-witness.js +61 -5
  130. package/dist/core/score/binding-order.d.ts +31 -0
  131. package/dist/core/score/binding-order.js +88 -0
  132. package/dist/core/score/bindings.d.ts +93 -0
  133. package/dist/core/score/bindings.js +309 -0
  134. package/dist/core/score/ladder-table.d.ts +23 -0
  135. package/dist/core/score/ladder-table.js +109 -0
  136. package/dist/core/score/ladder.d.ts +229 -0
  137. package/dist/core/score/ladder.js +464 -0
  138. package/dist/core/score/mode-agreement.d.ts +30 -0
  139. package/dist/core/score/mode-agreement.js +16 -0
  140. package/dist/core/score/outcome-table.d.ts +17 -0
  141. package/dist/core/score/outcome-table.js +172 -0
  142. package/dist/core/score/outcome.d.ts +466 -0
  143. package/dist/core/score/outcome.js +562 -0
  144. package/dist/core/score/qualification.d.ts +83 -0
  145. package/dist/core/score/qualification.js +645 -0
  146. package/dist/core/score/quotation.d.ts +56 -0
  147. package/dist/core/score/quotation.js +226 -0
  148. package/dist/core/score/reduce-trials.d.ts +80 -0
  149. package/dist/core/score/reduce-trials.js +90 -0
  150. package/dist/core/score/score.d.ts +72 -0
  151. package/dist/core/score/score.js +607 -0
  152. package/dist/core/score/selection.d.ts +80 -0
  153. package/dist/core/score/selection.js +98 -0
  154. package/dist/core/score/strength.d.ts +58 -0
  155. package/dist/core/score/strength.js +227 -0
  156. package/dist/core/score/witness.d.ts +138 -0
  157. package/dist/core/score/witness.js +320 -0
  158. package/dist/core/seal/derived-reference.d.ts +2 -9
  159. package/dist/core/seal/derived-reference.js +293 -46
  160. package/dist/core/seal/plan-index.d.ts +18 -3
  161. package/dist/core/seal/plan-index.js +44 -8
  162. package/dist/core/seal/seal.js +8 -3
  163. package/dist/core/stage-contracts.d.ts +62 -2
  164. package/dist/index.d.ts +1 -1
  165. package/dist/index.js +1 -1
  166. package/dist/ports/environment-probe-port.d.ts +60 -4
  167. package/dist/testing/index.d.ts +2 -0
  168. package/dist/testing/index.js +1 -0
  169. package/dist/testing/probe-conformance.d.ts +29 -0
  170. package/dist/testing/probe-conformance.js +34 -5
  171. package/package.json +12 -3
  172. package/schemas/eval-contract.schema.json +1787 -797
  173. package/schemas/evidence-artifact.schema.json +126 -9
  174. package/schemas/isolation-manifest.schema.json +17 -10
  175. package/schemas/probe.schema.json +636 -5
  176. package/schemas/rubric.schema.json +1 -1
  177. package/schemas/scoring-policy.schema.json +8 -1
  178. package/schemas/sealed-evaluator-brief.schema.json +11 -1
  179. package/schemas/sealed-run-record.schema.json +314 -40
package/README.md CHANGED
@@ -1,18 +1,28 @@
1
1
  # `eval-quality`
2
2
 
3
- ### `eval-quality` does three things
3
+ **[Documentation](https://bmad-code-org.github.io/bmad-eval-quality/)** ·
4
+ [Getting started](https://bmad-code-org.github.io/bmad-eval-quality/tutorials/getting-started/) ·
5
+ [CLI reference](https://bmad-code-org.github.io/bmad-eval-quality/reference/cli-commands/) ·
6
+ [npm](https://www.npmjs.com/package/eval-quality)
7
+
8
+ ```bash
9
+ npx eval-quality --help
10
+ ```
11
+
12
+ ### `eval-quality` does four things
4
13
 
5
14
  1. **Compile**: validate and normalize an eval contract into a machine-readable artifact.
6
15
  2. **Seal**: render the brief for the independent evaluator while hiding the planted bug and scoring answer.
7
16
  3. **Preflight**: verify baseline environment readiness and probe reachability before running an evaluator.
17
+ 4. **Score**: compare the evaluator's completed findings against the hidden bug signature and mint a versioned evidence artifact.
8
18
 
9
- Scoring is the next milestone: comparing the evaluator’s completed findings with the hidden bug signature to determine whether the bug was actually caught.
19
+ It executes nothing. No agent, no judge, and no system under test runs inside it; your harness runs the evaluation and hands over a sealed run record.
10
20
 
11
- ### What is the eval spec?
21
+ ### What is the evaluation contract?
12
22
 
13
23
  It is the test.
14
24
 
15
- More precisely, it is the evaluator’s instructions for how to expose a failure and what evidence counts as finding it.
25
+ More precisely, it is the evaluator’s instructions for how to expose a failure and what evidence counts as finding it. The long name is Behavioral Evaluation Contract; the docs shorten it to eval contract or evaluation contract.
16
26
 
17
27
  It defines:
18
28
 
@@ -42,25 +52,35 @@ A strong eval checks the response **and** persistence, so it catches the bug.
42
52
 
43
53
  Write the eval. Hide the bug. See if the eval catches it.
44
54
 
45
- ## Key Concepts
55
+ ## The core flow, in eight nouns
56
+
57
+ Every run of an evaluation walks the same order:
46
58
 
47
- Understanding `eval-quality` requires three core artifacts:
59
+ ```text
60
+ evaluation contract → probe → observation → preflight → evidence → oracle → rubric → score / verdict
61
+ ```
48
62
 
49
- | Concept | What it is | Example |
63
+ | Noun | What it is | Example |
50
64
  | --- | --- | --- |
51
- | **Contract** (`eval-contract.json`) | The test specification defining expected behaviors, oracles (checks), permitted tools, and evidence rules. | "Verify API rejects invalid JWT and creates zero database records." |
52
- | **Probe** (`probe.json`) | A diagnostic request sent to the environment to test baseline state, reachability, or fault injection. | A request sending an expired token to `/api/v1/resource`. |
53
- | **Observation** (`observation.json`) | The empirical response evidence recorded when a probe is executed against the environment. | `{ responseStatus: 401, responseBody: { error: "token_expired" } }` |
65
+ | **Evaluation contract** | What we want to measure: the behaviors, the checks, the interfaces a probe may touch, and the bounds a run stays inside. | "A PATCH that reports success has persisted the change." |
66
+ | **Probe** | How to poke the system to produce evidence: a test case, a call, a step. In scoring, a probe also names the defect it seeded. | "Update note n-1, then read it back." |
67
+ | **Observation** | What actually happened when the system was poked: the recorded status, headers, and body of one call. | `PATCH` returned 200 with the new title; the later `GET` returned the old one. |
68
+ | **Preflight** | Whether the environment and the observations are fit for meaningful measurement. | Both operations reachable, the fixture reset, the clean control clean. |
69
+ | **Evidence** | The recorded output, trajectory, and artifacts from the evaluation run: what the evaluator saw and what it claimed. | A finding citing the two observations above. |
70
+ | **Oracle** | The assertion: the relation that has to hold over the evidence. | The title sent equals the title read back. |
71
+ | **Rubric** | The grading guide for judgment-heavy quality, with anchored criteria a judge scores against. The judge runs outside the package and its scores arrive in the sealed run record. | Present only when a contract declares one. |
72
+ | **Score / verdict** | The combined result: did the evaluation catch the planted defect? `PASS`, `WAIVED`, `CONCERNS`, or `FAIL`, or Invalid when the run produced no verdict. | `FAIL`, exit code 2. |
54
73
 
55
- ### How They Fit Together
74
+ The word evidence is used twice on purpose. The evidence in the flow is what the evaluator produced, and it reaches `score` inside a sealed run record. The evidence artifact is what `score` mints at the end: the outcomes, the verdict, the strength vector, and the exit code.
56
75
 
57
- ```text
58
- ┌────────────────────────┐ ┌────────────────────────┐ ┌────────────────────────┐
59
- │ Eval Contract │ │ Probe │ │ Observation │
60
- │ (The Specification) │ ───► (Diagnostic Request) │ ───► │ (Empirical Result) │
61
- │ "What should happen" │ │ "Send malformed JWT" │ │ "Got 401, 0 records"
62
- └────────────────────────┘ └────────────────────────┘ └────────────────────────┘
63
- ```
76
+ The four commands sit on that flow like this:
77
+
78
+ | Command | Reads | Writes |
79
+ | --- | --- | --- |
80
+ | `compile` | an authored contract | `eval-contract.json`, checked against the schema and the discipline rules |
81
+ | `seal` | a contract | `sealed-evaluator-brief.json`, the contract minus everything that would give the answer away |
82
+ | `preflight` | a contract, a probe list, observations | `preflight-verdict.json`, fit or unfit to measure |
83
+ | `score` | a sealed run record, the contract, a probe, the preflight verdict, a scoring policy, a caller-attested corpus digest, and the isolation manifest and evaluator configuration the record was produced under | `evidence-artifact.json`, and the verdict's own exit code |
64
84
 
65
85
  ## Elaboration
66
86
 
@@ -85,13 +105,7 @@ confirm the specific error, and confirm no record was created.
85
105
 
86
106
  A passing eval says little when the contract never asked for the probe that would expose the failure. Testing whether the eval can catch a failure you already know about is the first check worth running.
87
107
 
88
- ```text
89
- product spec
90
- → Behavioral Evaluation Contract
91
- → known defect or gameability probe
92
- → independent evaluator
93
- → per-oracle evidence and a gate decision
94
- ```
108
+ The loop that does that is a twin run. Keep the contract, the probes, the oracles, and the scoring policy fixed. Run the evaluator once against the clean system and once against the same system carrying one known defect. Score both runs. The contract is strong when the clean run passes and the mutated run degrades, and it has a blind spot when both stay green.
95
109
 
96
110
  ## What each part provides
97
111
 
@@ -101,8 +115,12 @@ product spec
101
115
  - the oracle vocabulary and authoring rules
102
116
  - the contract compiler
103
117
  - the environment pre-flight
104
- - Eval Contract strength scoring (next milestone)
105
- - versioned evidence output and PASS / WAIVED / CONCERNS / FAIL governance (next milestone)
118
+ - Eval Contract strength scoring: the AD-7 rate vector and dominance relation, implemented in
119
+ `src/core/score/strength.ts` and reached by the `score` command
120
+ - PASS / WAIVED / CONCERNS / FAIL governance: both verdict ladders, implemented and total in
121
+ `src/core/score/ladder.ts`, and the `score` command's own exit code
122
+ - versioned evidence output: `evidence-artifact.json`, implemented in `src/core/emit/emit.ts` and
123
+ minted by the `score` command
106
124
 
107
125
  The caller provides:
108
126
 
@@ -113,12 +131,15 @@ The caller provides:
113
131
  - a sealed run record returned for ingestion
114
132
 
115
133
  `eval-quality` executes nothing: it never spawns a process, calls a model, drives a system under test,
116
- or invokes a judge. Its pure stages are compile, seal, ingest, pre-flight, score, and emit; compile,
117
- seal, and pre-flight ship, and ingest, score, and emit are the next milestone. Pre-flight probes the
118
- fixture through the environment-probe port, so a contract that declares a fixture reset
134
+ or invokes a judge. Its six stages are compile, seal, ingest, pre-flight, score, and emit, all pure,
135
+ and every one is reachable through the CLI and the library alike. That list is the declared stage
136
+ order; on the clock, ingest follows the evaluator run, so it sits after pre-flight and just before
137
+ score. Compile, seal, and pre-flight each
138
+ have their own command and their own exported function. `ingest`, `score`, and `emit` are reached
139
+ through the one `score` command and the one exported `runScore` call that chains them, per AD-14's
140
+ rule that a command exposes no more than the library itself calls. Pre-flight probes the fixture through the environment-probe port, so a contract that declares a fixture reset
119
141
  needs the caller's probe policy to authorize that operation's method as well as the read methods
120
- every other pre-flight leg uses. Engine integration is a later adapter behind a port, not a v0
121
- dependency. See
142
+ every other pre-flight leg uses. Engine integration is a later adapter behind a port. See
122
143
  [ADR-004](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ADR-004-execution-boundary.md).
123
144
 
124
145
  ## Who it is for
@@ -145,27 +166,32 @@ Rubrics compile under the same discipline: an anchored scale, a bounded length,
145
166
 
146
167
  ## How Eval Contract strength scoring works
147
168
 
148
- Do not trust a contract because it looks thorough. Put a known defect behind it, run the evaluator, and check whether the contract's oracles caused the defect to be caught.
169
+ The `score` command and its `runScore` library call compute it; `npm run generate:worked-example`
170
+ runs the same functions over the committed worked chain, and
171
+ [the full walkthrough](https://bmad-code-org.github.io/bmad-eval-quality/how-to/author-behavioral-contracts/)
172
+ reads the result field by field. Do not trust a contract because it looks thorough. Put a known defect behind it, run the evaluator, and check whether the contract's oracles caused the defect to be caught.
149
173
 
150
174
  Two probe classes go behind a contract, and a strong contract rejects both:
151
175
 
152
176
  - **Defect probes**, where the behavior is simply wrong.
153
177
  - **Gameability probes**, where the behavior looks compliant while dodging the oracle's intent. A test that raises coverage while asserting nothing is the familiar version of this.
154
178
 
155
- Probes come from qualified historical defects or verified controlled mutations. The corpus separates a visible development set from an immutable sealed set for each scoring version.
179
+ Probes come from qualified historical defects or verified controlled mutations. The corpus separates a visible development set from an immutable sealed set for each scoring version. Only the development set exists today; the sealed set is part of the design and ships in no release yet.
156
180
 
157
181
  Every required oracle check resolves to exactly one state, and the state travels with the result, so
158
182
  "the check reported" is never sufficient on its own: `caught`, `confirmed`, `missed`,
159
183
  `passed-clean-control`, `false-positive`, `abstained`, `bypassed`, `unreached`, `oracle-error`,
160
184
  `judge-error`, `infrastructure-error`, or `not-applicable`.
161
185
 
162
- A required oracle that missed, abstained, errored, or is absent prevents PASS, and a high overall score never overrides it. An infrastructure error or a failed environment pre-flight is not a behavioral result at all; it invalidates the run and is re-executed rather than scored.
186
+ A required oracle that missed, abstained, errored, or is absent prevents PASS, and a high overall score never overrides it. An infrastructure error or a failed environment pre-flight is not a behavioral result at all; it invalidates the run, and the run is re-executed.
187
+
188
+ Repeated runs of one probe are trials, and they reduce to one result per probe before any rate is computed. The `score` stage takes a trial set; the `score` command and `runScore` hand it one sealed run record per call, so a run scored from the published surface completes one trial, and against a policy declaring a minimum of three, as the worked example's does, its strength vector is reported and marked non-comparable.
163
189
 
164
190
  ## Using it
165
191
 
166
- `eval-quality` is its own repository and package, not a plugin inside another framework.
192
+ `eval-quality` is its own repository and package, with no framework around it.
167
193
 
168
- The **library** is the primary surface. It exports the contract schema, the oracle vocabulary, the compiler, the pre-flight, and the evidence types. The published typed schema is what lets coding agents author contracts correctly by default, which is how the discipline scales beyond the people who went looking for the tool.
194
+ The **library** is the primary surface. It exports the artifact types, the compiler, the pre-flight, `runScore`, the canonical digest, the lineage validator, and the failure-code and verdict registries. The Zod schemas themselves are not exported; they are published as JSON Schema under `eval-quality/schemas/*`. The published typed schema is what lets coding agents author contracts correctly by default, which is how the discipline scales beyond the people who went looking for the tool.
169
195
 
170
196
  The **CLI** wraps the same library for callers that cannot import TypeScript: CI jobs, GitHub Actions, PR-review and unit-test bots, other frameworks' skills, and any agent permitted to run a shell command.
171
197
 
@@ -173,7 +199,8 @@ The **CLI** wraps the same library for callers that cannot import TypeScript: CI
173
199
 
174
200
  - **`compile`**: Typechecks an authored `eval-contract.json`. Verifies that all behaviors, oracles, rubrics, and sensitivity witnesses comply with structural and authoring rules.
175
201
  - **`seal`**: Generates a `sealed-evaluator-brief.json` by stripping secret defect signatures, planted answers, and author commentary. The brief carries only the directions and safety bounds the evaluator needs.
176
- - **`preflight`**: Reduces caller-supplied probe observations against the contract to verify environment baseline readiness and probe reachability. Halts early with exit code `3` if the environment is unready.
202
+ - **`preflight`**: Reduces caller-supplied probe observations against the contract to verify environment baseline readiness and probe reachability. All four of `--contract`, `--probes`, `--observations`, and `--run-id` are required. Halts early with exit code `3` if the environment is unready. `schemas/probe.schema.json` gives the shape of one probe in the list; each observation echoes a planned leg's id back as `probeId`, and the getting-started tutorial writes six by hand.
203
+ - **`score`**: Chains ingest, score, and emit over one sealed run record, minting `evidence-artifact.json` and exiting with the AD-21 verdict's own exit code. `schemas/sealed-run-record.schema.json` gives the record's shape, and the committed worked chain under `_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/spike-worked-example/` carries one, scored. `--record`, `--contract`, `--probe`, `--preflight-verdict`, `--policy`, and `--corpus-digest` are required; `--isolation-manifest` and `--evaluator-configuration` are each optional and their absence invalidates the run and the command still parses; `--private-manifest` is optional and, when given, each entry's declared digest is checked against its resolved bytes. `--corpus-root` names the directory a private reference resolves under, and is required only when `--private-manifest` or a private-storage isolation-manifest reference is actually present.
177
204
 
178
205
  ### Running the CLI
179
206
 
@@ -187,17 +214,25 @@ npx eval-quality seal --in contract.json --out ./eval-out
187
214
  npx eval-quality preflight --contract contract.json \
188
215
  --probes probes.json --observations observations.json \
189
216
  --run-id 2026-08-28-a --out ./eval-out
217
+
218
+ npx eval-quality score --record record.json --contract contract.json \
219
+ --probe probe.json --preflight-verdict preflight-verdict.json \
220
+ --policy policy.json --corpus-digest <digest> \
221
+ --out ./eval-out
190
222
  ```
191
223
 
192
224
  Every command is non-interactive: no prompt, no terminal check, and no behaviour that differs when
193
225
  stdin is a pipe. Each one is a single call into the library plus artifact serialization.
194
226
 
195
- **Input and output.** An input flag left out reads stdin, and `-` names stdin explicitly; at most one
196
- input may be `-`. Without `--out` the artifact goes to stdout, so a command composes with a pipe.
227
+ **Input and output.** `--in` is the only input that falls back to stdin: `compile` and `seal` read it
228
+ when `--in` is left out. `-` names stdin explicitly on any input, and at most one input may be `-` per
229
+ invocation. `compile` and `seal` each take one input; `preflight` takes three, all required; `score`
230
+ takes eight, three of them optional (`--isolation-manifest`, `--evaluator-configuration`, and
231
+ `--private-manifest`). Without `--out` the artifact goes to stdout, so a command composes with a pipe.
197
232
  An `--out` ending in `.json` is a file path; anything else is a directory, and the artifact is
198
- written to `<target>/<kind>.json` where `kind` is `eval-contract`, `sealed-evaluator-brief`, or
199
- `preflight-verdict`. Diagnostics and errors go to stderr, always, so stdout carries the artifact
200
- alone.
233
+ written to `<target>/<kind>.json` where `kind` is `eval-contract`, `sealed-evaluator-brief`,
234
+ `preflight-verdict`, or `evidence-artifact`. Diagnostics and errors go to stderr, always, so stdout
235
+ carries the artifact alone.
201
236
 
202
237
  **Exit codes.**
203
238
 
@@ -206,18 +241,21 @@ alone.
206
241
  | `0` | success, and every verdict other than FAIL or a promoted CONCERNS |
207
242
  | `1` | CONCERNS promoted by `--strict` |
208
243
  | `2` | FAIL |
209
- | `3` | invalid: a pre-flight verdict that did not pass |
244
+ | `3` | invalid: a failed pre-flight, or any other AD-21 invalidating condition |
210
245
  | `4` | structural failure |
211
246
  | `5` | runtime fault |
212
247
  | `64` | usage error |
213
248
 
214
- Codes 1 and 2 report a scored verdict. Scoring ships in a later release, so no command here reaches
215
- either yet, and `--strict` changes no code this binary produces. The flag and the two codes are part
216
- of the published contract, so they are documented now and wired now.
249
+ `--strict` never promotes a CONCERNS whose firing conditions are all evidence conditions: those
250
+ conditions report that the measurement fell short of the policy. Codes 1 and 2 report a verdict
251
+ `score`'s ladder resolved, read directly off `LadderResolution.exitCode`; every other invalidating
252
+ condition behind code 3 is reachable through `score` too, alongside the failed pre-flight `preflight`
253
+ itself reports.
217
254
 
218
255
  `--strict` is the gate-promotion flag and is accepted on every command. `--strict-inputs` and
219
256
  `--no-strict-inputs` are a different switch: they set the compiler's input strictness, which is on
220
- by default.
257
+ by default, and `preflight` and `score` each reject both with exit `64` because neither has a compile
258
+ step.
221
259
 
222
260
  **The published JSON Schema.** A consumer that does not read TypeScript validates against the
223
261
  twelve generated documents, published at the `eval-quality/schemas/*` subpath:
@@ -229,6 +267,17 @@ import spec from 'eval-quality/schemas/eval-contract.schema.json' with { type: '
229
267
  The import attribute is required: ESM on Node 22 and 24 both throw `ERR_IMPORT_ATTRIBUTE_MISSING`
230
268
  without it. The development corpus ships the same way, at `eval-quality/corpus/dev/`, so an adopter
231
269
  can read real compiled contracts and one compiled-and-sealed pair without cloning this repository.
270
+ `eval-quality/adapters` is one of the five published subpaths, holding the three reference adapters
271
+ the conformance suite runs against.
272
+
273
+ Eleven of the twelve published schemas carry a `schemaVersion`. `artifact-reference` is exempt: it
274
+ is embedded inside other artifacts, so it has no version to break.
275
+
276
+ `schemaVersion` is declared as any integer at or above 1, so a document at an unexpected version
277
+ parses. The bumps in the next release each add a required field, which is why an older document
278
+ fails; the version itself is compared in exactly one place, `validateLineageChain`, over
279
+ lineage-chain members, and nowhere on the command path. The package is pre-1.0, so pin exactly.
280
+ `CHANGELOG.md` records what each release breaks.
232
281
 
233
282
  ## Relationship with BMad and TEA
234
283
 
@@ -241,7 +290,7 @@ graph LR
241
290
 
242
291
  TEA is the reference authoring client. It reads BMad planning artifacts, notices eval-relevant work, drafts a contract, and calls this package. It is not co-installed, and `eval-quality` holds no knowledge of TEA, BMad, or any planning-artifact format.
243
292
 
244
- Any human, bot, CI job, skill, or other framework can author a contract and use `eval-quality` directly. The discipline still applies, because the compiler judges the artifact rather than trusting whoever produced it.
293
+ Any human, bot, CI job, skill, or other framework can author a contract and use `eval-quality` directly. The discipline still applies, because the compiler judges the artifact, whoever produced it.
245
294
 
246
295
  Evaluator runs remain isolated to prevent builder-context leakage and preserve traceability. Stronger contract oracles produced the measured detection improvement.
247
296
 
@@ -249,7 +298,9 @@ Evaluator runs remain isolated to prevent builder-context leakage and preserve t
249
298
  1. Author an `eval-contract.json` declaring required knowledge step files (e.g. `playwright-utils-mandate.md`).
250
299
  2. Run `eval-quality compile --in contract.json` to validate contract structure and discipline rules.
251
300
  3. Run `eval-quality seal --in contract.json --out ./run` to generate `sealed-evaluator-brief.json`.
252
- 4. Pass `sealed-evaluator-brief.json` to `bmad-tea` to execute the task without seeing answer keys.
301
+ 4. Probe the harness's environment and run `eval-quality preflight` over the observations; a verdict that does not pass is exit `3`, and the run stops there.
302
+ 5. Pass `sealed-evaluator-brief.json` to `bmad-tea` to execute the task without seeing answer keys, once against the clean harness and once against a harness with one known step file removed.
303
+ 6. Seal each evaluator run into a `sealed-run-record.json` and run `eval-quality score` over it with the probe that names the removed file as the seeded defect. The clean run should pass; the mutated run should degrade, and the exit code says which.
253
304
 
254
305
  ## Evidence and limitations
255
306
 
@@ -261,13 +312,13 @@ Read the [product brief](_bmad-output/planning-artifacts/briefs/brief-eval-quali
261
312
 
262
313
  ## Architecture status
263
314
 
264
- The [architecture spine](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ARCHITECTURE-SPINE.md) is split by pipeline half: the compile-and-seal half is epic-ready, while the score half is not. Gate C closed at zero blocking authoring points and 14 of 14 declaration-only predicates. Gate D's generated-current-fields arm matched the hand-written positive control at 3 of 3 seeded-defect catches, so `seal` joins the stage-one order without adding an evidence-precondition field.
315
+ The [architecture spine](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ARCHITECTURE-SPINE.md) is split by pipeline half, and its own status line still reads that the compile-and-seal half is epic-ready while the score half is not. The code has moved past that line. Epic 7 delivered AD-21, AD-33, and AD-40 as pure functions with generated tables, and epic 8 shipped the `ingest`, `score`, and `emit` stages, the `score` command, and `runScore` over them, which closes every item the spine's *Owed to the reference implementation* section listed. The `score` stage consumes a trial set; the command and `runScore` hand it one record per call, so a run scored from the published surface completes one trial, and whenever the policy's declared minimum exceeds one its strength vector is reported and marked non-comparable. Gate C closed at zero blocking authoring points and 14 of 14 declaration-only predicates. Gate D's generated-current-fields arm matched the hand-written positive control at 3 of 3 seeded-defect catches, so `seal` joins the stage-one order without adding an evidence-precondition field.
265
316
 
266
- Contract strength scoring has been open since [ADR-007](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ADR-007-compile-score-split.md): three rounds of external review established that the catch rate was 1.00 by construction, because nothing matched a finding to the defect its probe seeded. That input now exists and the mapping that reads it is owed to a reference implementation.
317
+ Contract strength scoring has been open since [ADR-007](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ADR-007-compile-score-split.md): three rounds of external review established that the catch rate was 1.00 by construction, because nothing matched a finding to the defect its probe seeded. That input now exists, and so does the mapping that reads it: `src/core/score/witness.ts` is AD-40's witness match, delivered by epic 7. What is still owed is its validation against the block-2 replication, which the spine records as committed and not yet run.
267
318
 
268
319
  Contract compilation was declared ready in ADR-007 and a fourth review withdrew that claim in [ADR-008](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ADR-008-compile-half-owed-to-calibration.md). The named calibration is now complete. The absent local-only mut2 arm was reconstructed from its recorded base, reproduced its prior black-box behavior, and ran under a pre-registered three-arm, three-repetition design. All three arms composed filters and detected the seeded defect in every valid repetition. This closes the calibration gate narrowly; it does not generalize the historical 0.33-to-1.00 effect beyond one behavior and one controlled mutation.
269
320
 
270
- Both are documented as defects rather than dressed as decisions, because four rounds have shown that a confidently worded revision is the thing that goes wrong here.
321
+ Both are documented as defects, because four rounds have shown that a confidently worded revision is the thing that goes wrong here.
271
322
 
272
323
  The decision record, in order: [ADR-001](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-22/ADR-001-evaluator-isolation-boundary.md) on evaluator isolation, [ADR-002](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-22/ADR-002-contract-authoring-discipline.md) on why authoring discipline is the product, [ADR-003](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ADR-003-measurement-mechanics.md) on measurement mechanics, [ADR-004](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ADR-004-execution-boundary.md) on why this package executes nothing, [ADR-005](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ADR-005-review-round-corrections.md) and [ADR-006](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ADR-006-interaction-plan.md) on what review and hand-authoring corrected, [ADR-007](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ADR-007-compile-score-split.md) on the split, [ADR-008](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ADR-008-compile-half-owed-to-calibration.md) on why the other half stopped claiming to be finished too, and [ADR-009](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/ADR-009-adversarial-gate-corrections.md) on the seventeen places where two conforming implementations still disagreed. Review triage lives in [`reviews/`](_bmad-output/planning-artifacts/architecture/architecture-eval-quality-2026-07-29/reviews/).
273
324
 
@@ -279,28 +330,38 @@ Out of scope entirely: a new eval engine, a hosted service, a dashboard or GUI,
279
330
 
280
331
  ## Development
281
332
 
333
+ Node `>=22.20.0`, which `package.json` declares as the engine floor. `zod` is the only production
334
+ dependency.
335
+
282
336
  ```bash
283
337
  npm install
284
- npm run validate # typecheck, lint, docs, shareable, spine, vectors, schemas, registries, AD-31 table, layers, lineage, boundary, corpus, tests with coverage
338
+ npm run validate # build, typecheck, lint, docs, doc invocations, shareable, spine, vectors, schemas, both code registries, the AD-21, AD-31 and AD-33 tables, layers, lineage, boundary, corpus, worked chain, website deps, tests with coverage
285
339
  npm run build # emit to dist/
286
340
  npm run lint:fix # auto-fix with Biome
287
341
  npm run test:coverage # run the suite and fail below AD-30's 90 percent statement and branch floor on core/
288
342
  npm run generate:schemas # rebuild schemas/*.schema.json from the Zod source
289
343
  npm run check:schemas # fail if the committed schemas differ from the source by one byte
290
- npm run check:ad5-registry # fail if the failure-code list drifts from the AD-5 table
344
+ npm run check:ad5-registry # fail if the compile-time failure-code list drifts from the AD-5 table
345
+ npm run check:ad28-registry # fail if the runtime fault-code list drifts from the AD-28 table
291
346
  npm run check:lineage # fail if a module outside the stage table writes an artifact's lineage fields
292
347
  npm run check:boundary # fail if anything the tarball carries references the planning system that produced it
348
+ npm run generate:ad21-table # rebuild docs/ad21-verdict-decision.generated.md from the two verdict ladders
349
+ npm run check:ad21-table # fail if the committed AD-21 table differs from the builder by one byte
293
350
  npm run generate:ad31-table # rebuild docs/ad31-coverage-predicates.generated.md from the predicates
294
351
  npm run check:ad31-table # fail if the committed AD-31 table differs from the builder by one byte
352
+ npm run generate:ad33-table # rebuild docs/ad33-outcome-decision.generated.md from the decision procedure
353
+ npm run check:ad33-table # fail if the committed AD-33 table differs from the builder by one byte
295
354
  npm run generate:dev-corpus # rebuild corpus/dev/ from the contract fixtures through the shipped compile and seal
296
355
  npm run check:corpus # fail if the committed corpus differs from the builder by one byte
356
+ npm run generate:worked-example # rebuild the spike worked chain by running the compile, seal, score, and emit functions over it
357
+ npm run check:worked-example # fail if the committed worked chain differs from the builder by one byte
297
358
  npm run build:shareable # render the planning artifacts to self-contained HTML
298
359
  npm run test:conformance # run the published port conformance suite against every shipped adapter
299
360
  ```
300
361
 
301
362
  `schemas/` holds the twelve published JSON Schema documents, generated from the Zod definitions and
302
363
  committed. They are the contract for consumers who do not read TypeScript, so they are proven
303
- equivalent to the source rather than assumed to be: a byte-exact drift check, a rejection suite
364
+ equivalent to the source: a byte-exact drift check, a rejection suite
304
365
  asserting the validator keyword and instance path for every negative fixture, a differential check
305
366
  comparing Zod's verdict against a third-party validator's over a generated corpus, and a
306
367
  keyword-mutation sweep that deletes each published constraint and requires some fixture to notice.
@@ -311,15 +372,16 @@ is ES modules, which are always strict, so an attempt throws a `TypeError` there
311
372
  caller sees the write fail silently. A revision is minted as a new artifact carrying its parent's
312
373
  digest and a revision count one greater. `check:lineage` fails the build when a lineage field is
313
374
  written outside `src/core/schemas/`, `src/core/lineage/`, and the modules the AD-24 stage table
314
- names as that artifact's producer, which today are `src/core/seal/seal.ts` and
315
- `src/core/preflight/reduce.ts`.
375
+ names as that artifact's producer, which today are `src/core/seal/seal.ts`,
376
+ `src/core/preflight/reduce.ts`, and `src/core/emit/emit.ts`.
316
377
 
317
378
  The `eval-quality/conformance` subpath publishes the port boundary: the four port types, the message
318
- shapes they carry, and an executable conformance suite. An adapter is conforming when
379
+ shapes they carry, the AD-28 `RUNTIME_FAULT_CODES` registry and `RuntimeFaultCode` type a conforming
380
+ adapter throws against, and an executable conformance suite. An adapter is conforming when
319
381
  `runCorpusPortConformance`, `runClockPortConformance`, `runFileSystemPortConformance`, or
320
- `runEnvironmentProbePortConformance` returns a report whose `passed` is true, which is the definition
321
- rather than a paraphrase of one; each returns a report instead of asserting, so the suite carries no
322
- test framework and runs under whichever one you already use.
382
+ `runEnvironmentProbePortConformance` returns a report whose `passed` is true, which is the definition;
383
+ each returns a report, so the suite carries no test framework and runs under whichever one you
384
+ already use.
323
385
 
324
386
  ```ts
325
387
  import { runCorpusPortConformance, type CorpusPort } from 'eval-quality/conformance'
@@ -327,20 +389,33 @@ import { runCorpusPortConformance, type CorpusPort } from 'eval-quality/conforma
327
389
 
328
390
  The suite drives a subject through four scenarios and checks six assertions per port method: a
329
391
  mechanism failure is a typed fault, exactly one underlying call happens on success and on failure, an
330
- aborted signal rejects promptly, an in-band error value is thrown rather than returned, and a
392
+ aborted signal rejects promptly, an in-band error value is thrown as a fault, and a
331
393
  successful call returns a response the published schema accepts. The environment-probe port adds
332
394
  thirteen more from AD-35's default-deny target policy. `npm run test:conformance` runs the suite
333
395
  against the three adapters this package ships and against an in-repository probe subject that exists
334
396
  only as the suite's own subject.
335
397
 
398
+ `docs/ad21-verdict-decision.generated.md` holds AD-21's two published verdict ladders, production and
399
+ contract-scoring, emitted from the rule tables in `src/core/score/ladder.ts` together with the
400
+ fixtures that exercise them, and guarded by `npm run check:ad21-table`. Each row carries its
401
+ condition, its rung, the guard in prose, and whether `--strict` may promote it.
402
+
336
403
  `docs/ad31-coverage-predicates.generated.md` holds AD-31's published predicate table, emitted from
337
404
  the seven relevance predicates and their seven satisfaction twins run over a hand-authored contract
338
405
  corpus. It is generated by `npm run generate:ad31-table` and guarded by `npm run check:ad31-table`,
339
406
  a byte-exact drift check that fails when a predicate changes and the committed document does not, so
340
- the table is evidence the predicates produce rather than documentation kept beside them. Regenerate
341
- rather than hand-edit it.
342
-
343
- `build:shareable` renders this README, the product brief, the PRD, the architecture spine, all nine ADRs, and every document those pages link to (contributing, code of conduct, security, licence, and the four experiment records) to `_bmad-output/shareable/` as standalone styled HTML for sharing outside the repo. Rendering the linked documents is what lets a recipient without repository access follow the evidence, contribution, security, and licence links instead of hitting a 404; anything that has no page of its own, such as a directory, is marked in the export as needing repository access. Regenerate rather than hand-edit those files: `check:shareable` fails the build when the committed export is stale or carries a repository URL that is not the canonical one. Mermaid diagrams render as code blocks there, which is a known limitation.
407
+ the table is evidence the predicates produce. A hand edit fails the check; regenerate.
408
+
409
+ `docs/ad33-outcome-decision.generated.md` holds AD-33's published decision table: the ten
410
+ invalidating conditions, the twenty-row outcome ladder, the two waiver rules, the eight
411
+ corroboration rules, the named structural constraints with the infeasible input pairs derived from
412
+ them, and five censuses over the fixture set. It is generated by `npm run generate:ad33-table` and
413
+ guarded by `npm run check:ad33-table`, the same byte-exact drift check, and the builder refuses to
414
+ publish a census cell at zero, so a rule or a state losing its last fixture fails the build. AD-33
415
+ puts a cell-per-input-tuple table out of arithmetic reach, so what is published is the enumerated
416
+ output of the total function itself. A hand edit fails the check; regenerate.
417
+
418
+ `build:shareable` renders this README, the product brief, the PRD, the architecture spine, all nine ADRs, and every document those pages link to (contributing, code of conduct, security, licence, and the four experiment records) to `_bmad-output/shareable/` as standalone styled HTML for sharing outside the repo. Rendering the linked documents is what lets a recipient without repository access follow the evidence, contribution, security, and licence links; anything that has no page of its own, such as a directory, is marked in the export as needing repository access. A hand edit fails the check; regenerate: `check:shareable` fails the build when the committed export is stale or carries a repository URL that is not the canonical one. Mermaid diagrams render as code blocks there, which is a known limitation.
344
419
 
345
420
  ## Contributing
346
421
 
@@ -6,8 +6,9 @@ this package without cloning the repository. Everything here is generated by
6
6
 
7
7
  ## What is here
8
8
 
9
- - `contracts/<contractId>.json`: nineteen contracts, one per AD-20 discipline rule in each
10
- declaration state. Sixteen are published only after this package's own compile stage accepts
9
+ - `contracts/<contractId>.json`: twenty-one contracts. Nineteen are one per AD-20 discipline
10
+ rule in each declaration state, and two describe a system under test that runs behind a command
11
+ rather than over HTTP. Eighteen are published only after this package's own compile stage accepts
11
12
  them, so every one of those is a contract the compiler admits. Three fail compilation by design;
12
13
  those ship as authored input, and `index.json` records the failure code each one raises.
13
14
  - `compile-seal-example/contract.json` and `compile-seal-example/brief.json`: one contract and
@@ -23,14 +24,20 @@ contract's strength is a separate thing this package does not ship.
23
24
  ## What is absent, and why
24
25
 
25
26
  **The qualified-probe dimensions are absent.** AD-38 asks for at least one qualified probe per
26
- probe class and per `expectedClean` state. Qualifying a probe needs a trial reducer, which Owed
27
- item 1 records as not yet built, and a defect signature for the probe, which Owed item 7 records as
28
- missing for the only probe this repository names. Both dimensions arrive with the stage that adds
29
- them.
30
-
31
- **Three of the four artifacts in AD-38's end-to-end example are absent.** The example there is a
32
- sealed brief, a conforming sealed run record, an isolation manifest, and an evaluator
33
- configuration. The last three are produced by ingest, which does not exist yet, and Owed item 7
34
- forbids hand-filling downstream values: the chain must be regenerated from the reference reducer
35
- once that reducer exists. So this directory ships the compile-and-seal pair under a name that does
36
- not claim AD-38's term.
27
+ probe class and per `expectedClean` state. The probe schema now carries both halves qualification
28
+ needs: AD-9's per-route qualification record and AD-40's machine-readable defect signature, with a
29
+ corpus gate that admits a probe only when the two agree with its class. The trial reducer and the
30
+ score stage that reads it are both shipped, so an admitted probe can be scored end to end today;
31
+ what is still missing is this directory's own gate widening to require at least one such probe. The
32
+ dimension arrives with the change that adds that gate.
33
+
34
+ **Three of the four artifacts in AD-38's end-to-end example are absent here.** The example there is
35
+ a sealed brief, a conforming sealed run record, an isolation manifest, and an evaluator
36
+ configuration. The last three are inputs the shipped `ingest` stage consumes, authored for the
37
+ worked example in `scripts/worked-example-target.ts` and exercised there through
38
+ `ingest`/`score`/`emit`. Only the run record among them is committed, as
39
+ `spike-worked-example/sealed-run-record.json`; the isolation manifest and the evaluator
40
+ configuration exist only as the authored values that build passes to `ingest`, never serialized to
41
+ a file. This directory still ships only the compile-and-seal pair, scoped to what a corpus of
42
+ contracts needs,
43
+ under a name that does not claim AD-38's term.
@@ -1 +1 @@
1
- {"behaviors":[{"description":"A created thing is readable back in the list of things.","id":"B-001","observableSuccessCriterion":"A list call after a create returns one element per seeded thing, carrying the name the create call sent.","oracles":["O-001","O-002","O-003","O-004","O-005","O-006","O-007"],"requirementLinks":[{"id":"REQ-1","scheme":"local"}],"riskLinks":[{"id":"RISK-1","scheme":"local-risk"}],"severity":"critical"}],"budgets":{"maxCostUsd":"0.25","maxToolCalls":20,"maxWallClockMinutes":5},"contractDigest":"sha256:1f7c657db755e9550ee78c57bdb81ea9f9de9ca227dbeaf823939a0313cbd781","directions":[{"oracleId":"O-001","text":"Its items field from the list things endpoint (with the supplied query limit) is asserted to satisfy the declared \"covers-by-key\" condition. The declared polarity expects this relation to hold. One list call over the seeded set. A list omitting a seeded thing, or repeating one is treated as a defect."},{"oracleId":"O-002","text":"The create thing endpoint (with the supplied body name): its error field, its id field, and its ok field is asserted to satisfy every declared condition together. The declared polarity expects this relation to hold. The whole create response. A create reporting success with no identifier, or with a diagnostic beside it is treated as a defect."},{"oracleId":"O-003","text":"The list things endpoint (with the supplied query limit): its error field and its items field is asserted to satisfy every declared condition together. The declared polarity expects this relation to hold. The list response taken as a whole. A list carrying items alongside a diagnostic field is treated as a defect."},{"oracleId":"O-004","text":"Its error field from the create thing endpoint (with a malformed body name value) and its error field from the list things endpoint (with a malformed query limit value) is asserted to satisfy every declared condition together. The declared polarity expects this relation to hold. Both sibling operations, each given an input that violates its declared type. One sibling rejecting the malformed input while the other accepts it is treated as a defect."},{"oracleId":"O-005","text":"The body name value you sent to the create thing endpoint (with the supplied body name), compared with the query limit value you sent to the list things endpoint (with the supplied query limit) is asserted to satisfy every declared condition together. The declared polarity expects this relation to hold. The two sibling parameters, as sent. One parameter carried and the other dropped is treated as a defect."},{"oracleId":"O-006","text":"The body name value you sent to the create thing endpoint (with the supplied body name), compared with its items field from the list things endpoint (with the supplied query limit) is asserted to contain the declared member. The declared polarity expects this relation to hold. The list read after the create, against the name the create sent. A create reporting success whose thing never appears in a later list is treated as a defect."},{"oracleId":"O-007","text":"Every element reachable through its items field from the list things endpoint (with the supplied query limit) is asserted to meet the declared condition. The declared polarity expects this relation to hold. Every element of the returned list. A list whose first element carries an identifier and whose later elements do not is treated as a defect."}],"parentDigest":null,"permittedInterfaces":[{"kind":"api","logicalId":"thing-api"}],"probeStepBound":8,"revisionCount":0,"safetyLimits":["No request to any host other than the mapped thing-api target."],"schemaVersion":1,"scopedResources":[]}
1
+ {"behaviors":[{"description":"A created thing is readable back in the list of things.","id":"B-001","observableSuccessCriterion":"A list call after a create returns one element per seeded thing, carrying the name the create call sent.","oracles":["O-001","O-002","O-003","O-004","O-005","O-006","O-007"],"requirementLinks":[{"id":"REQ-1","scheme":"local"}],"riskLinks":[{"id":"RISK-1","scheme":"local-risk"}],"severity":"critical"}],"budgets":{"maxCostUsd":"0.25","maxToolCalls":20,"maxWallClockMinutes":5},"contractDigest":"sha256:7ca80def8afa456f9afa171dbdbe7be9c7c9c9b799cf7bedfa5f6a0db71cd0a9","directions":[{"oracleId":"O-001","text":"Its items field from the list things endpoint (with the supplied query limit) is asserted to satisfy the declared \"covers-by-key\" condition. The declared polarity expects this relation to hold. One list call over the seeded set. A list omitting a seeded thing, or repeating one is treated as a defect."},{"oracleId":"O-002","text":"The create thing endpoint (with the supplied body name): its error field, its id field, and its ok field is asserted to satisfy every declared condition together. The declared polarity expects this relation to hold. The whole create response. A create reporting success with no identifier, or with a diagnostic beside it is treated as a defect."},{"oracleId":"O-003","text":"The list things endpoint (with the supplied query limit): its error field and its items field is asserted to satisfy every declared condition together. The declared polarity expects this relation to hold. The list response taken as a whole. A list carrying items alongside a diagnostic field is treated as a defect."},{"oracleId":"O-004","text":"Its error field from the create thing endpoint (with a malformed body name value) and its error field from the list things endpoint (with a malformed query limit value) is asserted to satisfy every declared condition together. The declared polarity expects this relation to hold. Both sibling operations, each given an input that violates its declared type. One sibling rejecting the malformed input while the other accepts it is treated as a defect."},{"oracleId":"O-005","text":"The body name value you sent to the create thing endpoint (with the supplied body name), compared with the query limit value you sent to the list things endpoint (with the supplied query limit) is asserted to satisfy every declared condition together. The declared polarity expects this relation to hold. The two sibling parameters, as sent. One parameter carried and the other dropped is treated as a defect."},{"oracleId":"O-006","text":"The body name value you sent to the create thing endpoint (with the supplied body name), compared with its items field from the list things endpoint (with the supplied query limit) is asserted to contain the declared member. The declared polarity expects this relation to hold. The list read after the create, against the name the create sent. A create reporting success whose thing never appears in a later list is treated as a defect."},{"oracleId":"O-007","text":"Every element reachable through its items field from the list things endpoint (with the supplied query limit) is asserted to meet the declared condition. The declared polarity expects this relation to hold. Every element of the returned list. A list whose first element carries an identifier and whose later elements do not is treated as a defect."}],"parentDigest":null,"permittedInterfaces":[{"kind":"api","logicalId":"thing-api"}],"principals":[],"probeStepBound":8,"revisionCount":0,"safetyLimits":["No request to any host other than the mapped thing-api target."],"schemaVersion":2,"scopedResources":[]}
@@ -1 +1 @@
1
- {"behaviors":[{"description":"A created thing is readable back in the list of things.","id":"B-001","observableSuccessCriterion":"A list call after a create returns one element per seeded thing, carrying the name the create call sent.","oracles":["O-001","O-002","O-003","O-004","O-005","O-006","O-007"],"requirementLinks":[{"id":"REQ-1","scheme":"local"}],"riskLinks":[{"id":"RISK-1","scheme":"local-risk"}],"severity":"critical"}],"budgets":{"maxCostUsd":"0.25","maxToolCalls":20,"maxWallClockMinutes":5},"contractId":"satisfied-declarations","fixtureReset":null,"forbiddenInputs":["original-spec","source-code","repository","builder-transcript","implementation-logs","comparator-results","human-labels"],"interactionPlan":[{"after":null,"inputBinding":{"body":{"name":{"matcher":"any"}},"header":null,"path":null,"query":null},"operationId":"create-thing","stepId":"create"},{"after":"create","inputBinding":{"body":null,"header":null,"path":null,"query":{"limit":{"literal":10}}},"operationId":"list-things","stepId":"list"},{"after":null,"inputBinding":{"body":{"name":{"matcher":"type-violating"}},"header":null,"path":null,"query":null},"operationId":"create-thing","stepId":"malformed-create"},{"after":null,"inputBinding":{"body":null,"header":null,"path":null,"query":{"limit":{"matcher":"type-violating"}}},"operationId":"list-things","stepId":"malformed-list"}],"oracles":[{"check":{"actualKey":"id","expectedKey":"id","op":"covers-by-key","operands":[{"referenceSet":"expected-things"},{"pointer":"/interactions/list/response-body/items"}]},"commentary":"Reconciles the whole list against the declared set.","direction":{"evidenceTargets":["/interactions/list/response-body/items"],"negativeDomain":"A list omitting a seeded thing, or repeating one.","polarity":"expects-hold","relation":"covers-by-key","scope":"One list call over the seeded set."},"id":"O-001","polarity":"expects-hold"},{"check":{"op":"all","operands":[{"op":"existence","operands":[{"pointer":"/interactions/create/response-body/ok"}]},{"op":"existence","operands":[{"pointer":"/interactions/create/response-body/id"}]},{"op":"absence","operands":[{"pointer":"/interactions/create/response-body/error"}]}]},"commentary":null,"direction":{"evidenceTargets":["/interactions/create/response-body/ok","/interactions/create/response-body/id","/interactions/create/response-body/error"],"negativeDomain":"A create reporting success with no identifier, or with a diagnostic beside it.","polarity":"expects-hold","relation":"all","scope":"The whole create response."},"id":"O-002","polarity":"expects-hold"},{"check":{"op":"all","operands":[{"op":"existence","operands":[{"pointer":"/interactions/list/response-body/items"}]},{"op":"absence","operands":[{"pointer":"/interactions/list/response-body/error"}]}]},"commentary":null,"direction":{"evidenceTargets":["/interactions/list/response-body/items","/interactions/list/response-body/error"],"negativeDomain":"A list carrying items alongside a diagnostic field.","polarity":"expects-hold","relation":"all","scope":"The list response taken as a whole."},"id":"O-003","polarity":"expects-hold"},{"check":{"op":"all","operands":[{"op":"existence","operands":[{"pointer":"/interactions/malformed-create/response-body/error"}]},{"op":"existence","operands":[{"pointer":"/interactions/malformed-list/response-body/error"}]}]},"commentary":null,"direction":{"evidenceTargets":["/interactions/malformed-create/response-body/error","/interactions/malformed-list/response-body/error"],"negativeDomain":"One sibling rejecting the malformed input while the other accepts it.","polarity":"expects-hold","relation":"all","scope":"Both sibling operations, each given an input that violates its declared type."},"id":"O-004","polarity":"expects-hold"},{"check":{"op":"all","operands":[{"op":"existence","operands":[{"pointer":"/interactions/create/call-inputs/body/name"}]},{"op":"existence","operands":[{"pointer":"/interactions/list/call-inputs/query/limit"}]}]},"commentary":null,"direction":{"evidenceTargets":["/interactions/create/call-inputs/body/name","/interactions/list/call-inputs/query/limit"],"negativeDomain":"One parameter carried and the other dropped.","polarity":"expects-hold","relation":"all","scope":"The two sibling parameters, as sent."},"id":"O-005","polarity":"expects-hold"},{"check":{"op":"containment","operands":[{"pointer":"/interactions/list/response-body/items"},{"pointer":"/interactions/create/call-inputs/body/name"}]},"commentary":null,"direction":{"evidenceTargets":["/interactions/list/response-body/items","/interactions/create/call-inputs/body/name"],"negativeDomain":"A create reporting success whose thing never appears in a later list.","polarity":"expects-hold","relation":"containment","scope":"The list read after the create, against the name the create sent."},"id":"O-006","polarity":"expects-hold"},{"check":{"collection":{"pointer":"/interactions/list/response-body/items"},"op":"for-all","predicate":{"op":"existence","operands":[{"pointer":"@/id"}]}},"commentary":null,"direction":{"evidenceTargets":["/interactions/list/response-body/items"],"negativeDomain":"A list whose first element carries an identifier and whose later elements do not.","polarity":"expects-hold","relation":"for-all","scope":"Every element of the returned list."},"id":"O-007","polarity":"expects-hold"}],"parentDigest":null,"permittedInterfaces":[{"kind":"api","logicalId":"thing-api","operations":[{"method":"POST","operationId":"create-thing","pathTemplate":"/things","requestShape":{"body":{"permittedKeys":["name"],"requiredKeys":["name"],"types":{"name":"string"}},"header":{"permittedKeys":[],"requiredKeys":[],"types":{}},"path":{"permittedKeys":[],"requiredKeys":[],"types":{}},"query":{"permittedKeys":[],"requiredKeys":[],"types":{}}},"responseDescriptor":{"channelRoles":{"/error":"diagnostic","/id":"payload","/ok":"success-indicator"},"collectionLocations":[],"permittedKeys":["id","ok","error"],"requiredKeys":["id","ok"],"successIndicator":"/ok","types":{"error":"string","id":"string","ok":"boolean"}},"sensitivityWitness":{"channel":"body","legs":[{"inputs":{"body":{"kind":"json","value":{"name":"alpha"}},"header":{},"path":{},"query":{}},"legId":"create-witness-a"},{"inputs":{"body":{"kind":"json","value":{"name":"beta"}},"header":{},"path":{},"query":{}},"legId":"create-witness-b"}],"relation":{"op":"not","operands":[{"op":"deep-equality","operands":[{"pointer":"/interactions/create-witness-a/response-body"},{"pointer":"/interactions/create-witness-b/response-body"}]}]},"witnessId":"create-thing-sensitivity"},"stateChangeMarker":true,"volatilePointers":["/id"]},{"method":"GET","operationId":"list-things","pathTemplate":"/things","requestShape":{"body":{"permittedKeys":[],"requiredKeys":[],"types":{}},"header":{"permittedKeys":[],"requiredKeys":[],"types":{}},"path":{"permittedKeys":[],"requiredKeys":[],"types":{}},"query":{"permittedKeys":["limit"],"requiredKeys":[],"types":{"limit":"number"}}},"responseDescriptor":{"channelRoles":{"/error":"diagnostic","/items":"collection"},"collectionLocations":[{"expectedCardinality":{"count":3,"mode":"exact"},"pointer":"/items","referenceSet":"expected-things"}],"permittedKeys":["items","error"],"requiredKeys":["items"],"successIndicator":"/items","types":{"error":"string","items":"array"}},"sensitivityWitness":{"channel":"query","legs":[{"inputs":{"body":{"kind":"absent"},"header":{},"path":{},"query":{"limit":1}},"legId":"list-witness-a"},{"inputs":{"body":{"kind":"absent"},"header":{},"path":{},"query":{"limit":2}},"legId":"list-witness-b"}],"relation":{"op":"not","operands":[{"op":"deep-equality","operands":[{"pointer":"/interactions/list-witness-a/response-body"},{"pointer":"/interactions/list-witness-b/response-body"}]}]},"witnessId":"list-things-sensitivity"},"stateChangeMarker":false,"volatilePointers":[]}]}],"probeStepBound":8,"referenceSets":{"expected-things":{"commentary":null,"keys":["id"],"members":[{"id":"t-1"},{"id":"t-2"},{"id":"t-3"}]}},"requiredEvidence":["Request and response pair for every call, in order."],"revisionCount":0,"rubrics":[{"criteria":[{"evidence":"/interactions/list/response-body/items","id":"RC-001","text":"Does the returned list carry every expected identifier?"}],"failureModePenalties":[{"description":"An expected thing is missing.","name":"omission"}],"id":"R-001","maxLength":400,"scaleLevels":[{"anchor":"Every expected thing is present.","level":1}]}],"safetyLimits":["No request to any host other than the mapped thing-api target."],"schemaVersion":1,"scopedResources":null,"siblingGroups":{"operations":[["create-thing","list-things"]],"parameters":[["limit","name"]]},"sourceSpecDigest":null,"testData":{"cleanup":"Delete every thing created during the run.","setup":"Seed exactly three things with identifiers t-1, t-2, t-3."},"waivers":[{"approval":"gate-c-reviewer","condition":null,"expiresAt":"2027-01-01T00:00:00Z","id":"W-001","rationale":"The upstream seed is unavailable in the sandbox environment.","rule":"omission-and-completeness"}]}
1
+ {"behaviors":[{"description":"A created thing is readable back in the list of things.","id":"B-001","observableSuccessCriterion":"A list call after a create returns one element per seeded thing, carrying the name the create call sent.","oracles":["O-001","O-002","O-003","O-004","O-005","O-006","O-007"],"requirementLinks":[{"id":"REQ-1","scheme":"local"}],"riskLinks":[{"id":"RISK-1","scheme":"local-risk"}],"severity":"critical"}],"budgets":{"maxCostUsd":"0.25","maxToolCalls":20,"maxWallClockMinutes":5},"contractId":"satisfied-declarations","fixtureReset":null,"forbiddenInputs":["original-spec","source-code","repository","builder-transcript","implementation-logs","comparator-results","human-labels"],"interactionPlan":[{"after":null,"cardinality":"exactly-one","inputBinding":{"body":{"name":{"matcher":"any"}},"header":null,"path":null,"query":null},"operationId":"create-thing","stepId":"create"},{"after":"create","cardinality":"exactly-one","inputBinding":{"body":null,"header":null,"path":null,"query":{"limit":{"literal":10}}},"operationId":"list-things","stepId":"list"},{"after":null,"cardinality":"exactly-one","inputBinding":{"body":{"name":{"matcher":"type-violating"}},"header":null,"path":null,"query":null},"operationId":"create-thing","stepId":"malformed-create"},{"after":null,"cardinality":"exactly-one","inputBinding":{"body":null,"header":null,"path":null,"query":{"limit":{"matcher":"type-violating"}}},"operationId":"list-things","stepId":"malformed-list"}],"oracles":[{"check":{"actualKey":"id","expectedKey":"id","op":"covers-by-key","operands":[{"referenceSet":"expected-things"},{"pointer":"/interactions/list/response-body/items"}]},"commentary":"Reconciles the whole list against the declared set.","direction":{"evidenceTargets":["/interactions/list/response-body/items"],"negativeDomain":"A list omitting a seeded thing, or repeating one.","polarity":"expects-hold","relation":"covers-by-key","scope":"One list call over the seeded set."},"id":"O-001","polarity":"expects-hold"},{"check":{"op":"all","operands":[{"op":"existence","operands":[{"pointer":"/interactions/create/response-body/ok"}]},{"op":"existence","operands":[{"pointer":"/interactions/create/response-body/id"}]},{"op":"absence","operands":[{"pointer":"/interactions/create/response-body/error"}]}]},"commentary":null,"direction":{"evidenceTargets":["/interactions/create/response-body/ok","/interactions/create/response-body/id","/interactions/create/response-body/error"],"negativeDomain":"A create reporting success with no identifier, or with a diagnostic beside it.","polarity":"expects-hold","relation":"all","scope":"The whole create response."},"id":"O-002","polarity":"expects-hold"},{"check":{"op":"all","operands":[{"op":"existence","operands":[{"pointer":"/interactions/list/response-body/items"}]},{"op":"absence","operands":[{"pointer":"/interactions/list/response-body/error"}]}]},"commentary":null,"direction":{"evidenceTargets":["/interactions/list/response-body/items","/interactions/list/response-body/error"],"negativeDomain":"A list carrying items alongside a diagnostic field.","polarity":"expects-hold","relation":"all","scope":"The list response taken as a whole."},"id":"O-003","polarity":"expects-hold"},{"check":{"op":"all","operands":[{"op":"existence","operands":[{"pointer":"/interactions/malformed-create/response-body/error"}]},{"op":"existence","operands":[{"pointer":"/interactions/malformed-list/response-body/error"}]}]},"commentary":null,"direction":{"evidenceTargets":["/interactions/malformed-create/response-body/error","/interactions/malformed-list/response-body/error"],"negativeDomain":"One sibling rejecting the malformed input while the other accepts it.","polarity":"expects-hold","relation":"all","scope":"Both sibling operations, each given an input that violates its declared type."},"id":"O-004","polarity":"expects-hold"},{"check":{"op":"all","operands":[{"op":"existence","operands":[{"pointer":"/interactions/create/call-inputs/body/name"}]},{"op":"existence","operands":[{"pointer":"/interactions/list/call-inputs/query/limit"}]}]},"commentary":null,"direction":{"evidenceTargets":["/interactions/create/call-inputs/body/name","/interactions/list/call-inputs/query/limit"],"negativeDomain":"One parameter carried and the other dropped.","polarity":"expects-hold","relation":"all","scope":"The two sibling parameters, as sent."},"id":"O-005","polarity":"expects-hold"},{"check":{"op":"containment","operands":[{"pointer":"/interactions/list/response-body/items"},{"pointer":"/interactions/create/call-inputs/body/name"}]},"commentary":null,"direction":{"evidenceTargets":["/interactions/list/response-body/items","/interactions/create/call-inputs/body/name"],"negativeDomain":"A create reporting success whose thing never appears in a later list.","polarity":"expects-hold","relation":"containment","scope":"The list read after the create, against the name the create sent."},"id":"O-006","polarity":"expects-hold"},{"check":{"collection":{"pointer":"/interactions/list/response-body/items"},"op":"for-all","predicate":{"op":"existence","operands":[{"pointer":"@/id"}]}},"commentary":null,"direction":{"evidenceTargets":["/interactions/list/response-body/items"],"negativeDomain":"A list whose first element carries an identifier and whose later elements do not.","polarity":"expects-hold","relation":"for-all","scope":"Every element of the returned list."},"id":"O-007","polarity":"expects-hold"}],"parentDigest":null,"permittedInterfaces":[{"kind":"api","logicalId":"thing-api","operations":[{"method":"POST","operationId":"create-thing","pathTemplate":"/things","requestShape":{"body":{"permittedKeys":["name"],"requiredKeys":["name"],"types":{"name":"string"}},"header":{"permittedKeys":[],"requiredKeys":[],"types":{}},"path":{"permittedKeys":[],"requiredKeys":[],"types":{}},"query":{"permittedKeys":[],"requiredKeys":[],"types":{}}},"responseDescriptor":{"channelRoles":{"/error":"diagnostic","/id":"payload","/ok":"success-indicator"},"collectionLocations":[],"permittedKeys":["id","ok","error"],"requiredKeys":["id","ok"],"successIndicator":"/ok","types":{"error":"string","id":"string","ok":"boolean"}},"sensitivityWitness":{"channel":"body","legs":[{"inputs":{"body":{"kind":"json","value":{"name":"alpha"}},"header":{},"path":{},"query":{}},"legId":"create-witness-a"},{"inputs":{"body":{"kind":"json","value":{"name":"beta"}},"header":{},"path":{},"query":{}},"legId":"create-witness-b"}],"relation":{"op":"not","operands":[{"op":"deep-equality","operands":[{"pointer":"/interactions/create-witness-a/response-body"},{"pointer":"/interactions/create-witness-b/response-body"}]}]},"witnessId":"create-thing-sensitivity"},"stateChangeMarker":true,"volatilePointers":["/id"]},{"method":"GET","operationId":"list-things","pathTemplate":"/things","requestShape":{"body":{"permittedKeys":[],"requiredKeys":[],"types":{}},"header":{"permittedKeys":[],"requiredKeys":[],"types":{}},"path":{"permittedKeys":[],"requiredKeys":[],"types":{}},"query":{"permittedKeys":["limit"],"requiredKeys":[],"types":{"limit":"number"}}},"responseDescriptor":{"channelRoles":{"/error":"diagnostic","/items":"collection"},"collectionLocations":[{"expectedCardinality":{"count":3,"mode":"exact"},"pointer":"/items","referenceSet":"expected-things"}],"permittedKeys":["items","error"],"requiredKeys":["items"],"successIndicator":"/items","types":{"error":"string","items":"array"}},"sensitivityWitness":{"channel":"query","legs":[{"inputs":{"body":{"kind":"absent"},"header":{},"path":{},"query":{"limit":1}},"legId":"list-witness-a"},{"inputs":{"body":{"kind":"absent"},"header":{},"path":{},"query":{"limit":2}},"legId":"list-witness-b"}],"relation":{"op":"not","operands":[{"op":"deep-equality","operands":[{"pointer":"/interactions/list-witness-a/response-body"},{"pointer":"/interactions/list-witness-b/response-body"}]}]},"witnessId":"list-things-sensitivity"},"stateChangeMarker":false,"volatilePointers":[]}]}],"probeStepBound":8,"referenceSets":{"expected-things":{"commentary":null,"keys":["id"],"members":[{"id":"t-1"},{"id":"t-2"},{"id":"t-3"}]}},"requiredEvidence":["Request and response pair for every call, in order."],"revisionCount":0,"rubrics":[{"criteria":[{"evidence":"/interactions/list/response-body/items","id":"RC-001","text":"Does the returned list carry every expected identifier?"}],"failureModePenalties":[{"description":"An expected thing is missing.","name":"omission"}],"id":"R-001","maxLength":400,"scaleLevels":[{"anchor":"Every expected thing is present.","level":1}]}],"safetyLimits":["No request to any host other than the mapped thing-api target."],"schemaVersion":4,"scopedResources":null,"siblingGroups":{"operations":[["create-thing","list-things"]],"parameters":[["limit","name"]]},"sourceSpecDigest":null,"testData":{"cleanup":"Delete every thing created during the run.","principals":null,"resources":null,"setup":"Seed exactly three things with identifiers t-1, t-2, t-3."},"waivers":[{"approval":"gate-c-reviewer","condition":null,"expiresAt":"2027-01-01T00:00:00Z","id":"W-001","rationale":"The upstream seed is unavailable in the sandbox environment.","rule":"omission-and-completeness"}]}