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
@@ -2,7 +2,7 @@
2
2
  import { z } from 'zod';
3
3
  import { HttpMethod, PathTemplate } from './interface.js';
4
4
  import { Identifier, JsonValue, KeyName, Rfc3339Utc } from './primitives.js';
5
- import { ProbeObservedBody, ProbeRequestBody } from './probe-body.js';
5
+ import { ProbeObservedBody, ProbeRequestBody, ProbeRequestStdin, } from './probe-body.js';
6
6
  export { ProbeObservedBody, ProbeRequestBody } from './probe-body.js';
7
7
  // AD-8: the corpus port resolves an opaque reference to bytes from a
8
8
  // caller-owned location. It does not check the digest: AD-8 puts digest
@@ -52,10 +52,20 @@ export const FileWriteResponse = z.strictObject({
52
52
  * authorization material is the adapter's, supplied by the same mapping that
53
53
  * authorizes the target.
54
54
  */
55
- export const ProbeRequest = z.strictObject({
55
+ const probeCorrelation = {
56
56
  probeId: Identifier.describe('An opaque correlation label minted by the pre-flight plan and echoed unchanged on the observation. Two witnesses of one operation, and the three observations a state-reset differential needs, are otherwise distinguishable only by array position, which NFR9 forbids any stage from reading.'),
57
57
  interfaceId: Identifier,
58
58
  operationId: Identifier,
59
+ };
60
+ /**
61
+ * A request to an interface that speaks HTTP. Tagged on `kind` so an adapter
62
+ * knows what it is being asked to do before it reads anything else, and so the
63
+ * two shapes cannot be confused for one another by a field that happens to be
64
+ * absent.
65
+ */
66
+ export const ApiProbeRequest = z.strictObject({
67
+ ...probeCorrelation,
68
+ kind: z.literal('api'),
59
69
  method: HttpMethod,
60
70
  pathTemplate: PathTemplate,
61
71
  channels: z.strictObject({
@@ -67,6 +77,38 @@ export const ProbeRequest = z.strictObject({
67
77
  body: ProbeRequestBody,
68
78
  }),
69
79
  });
80
+ /**
81
+ * A request to run a command.
82
+ *
83
+ * AD-35's rule is that a contract names a logical identifier and the caller
84
+ * maps it, and the analogue for a command is exactly the same shape: the
85
+ * `executable` is the logical name the contract declared, and the adapter maps
86
+ * it to something runnable from configuration outside the contract. No
87
+ * filesystem path, no interpreter, no shell string. The adapter builds the
88
+ * argument vector; it is never handed one to execute.
89
+ *
90
+ * `environment` is string-valued for the reason `header` is, and carries no
91
+ * credential for the reason AD-18 gives: authorization material is the
92
+ * adapter's, supplied by the same mapping that authorizes the target.
93
+ */
94
+ export const CommandProbeRequest = z.strictObject({
95
+ ...probeCorrelation,
96
+ kind: z.literal('cli'),
97
+ executable: Identifier.describe('A logical executable name, never a filesystem path, a URL, a host, or a port (AD-35). The adapter maps it to an authorized target through configuration outside the contract.'),
98
+ subcommandPath: z.array(Identifier),
99
+ channels: z.strictObject({
100
+ argument: z.record(KeyName, JsonValue),
101
+ option: z.record(KeyName, JsonValue),
102
+ environment: z
103
+ .record(KeyName, z.string())
104
+ .describe('String-valued because an environment variable is a string to the process; the other channels carry the declared JSON value.'),
105
+ stdin: ProbeRequestStdin,
106
+ }),
107
+ });
108
+ export const ProbeRequest = z.discriminatedUnion('kind', [
109
+ ApiProbeRequest,
110
+ CommandProbeRequest,
111
+ ]);
70
112
  /**
71
113
  * What the adapter observed. Deliberately response content only: no elapsed
72
114
  * time, no redirect count, no retry count. AD-35's caps are safety limits, so
@@ -78,13 +120,38 @@ export const ProbeRequest = z.strictObject({
78
120
  * policy denial, a cap, an abort, or a transport failure throws; a 500 is the
79
121
  * payload AD-10's seeded-fault check reads, never an error.
80
122
  */
81
- export const ProbeObservation = z.strictObject({
82
- probeId: Identifier,
83
- interfaceId: Identifier,
84
- operationId: Identifier,
123
+ export const ApiProbeObservation = z.strictObject({
124
+ ...probeCorrelation,
125
+ kind: z.literal('api'),
85
126
  status: z.int().min(100).max(599),
86
127
  headers: z
87
128
  .record(KeyName, z.string())
88
129
  .describe('Repeated headers are joined with ", " per RFC 9110 before they reach this shape. `set-cookie` is the one header that rule is wrong for, and it is dropped rather than mangled: nothing in AD-10 reads it, and a joined `set-cookie` is a value no consumer can split back.'),
89
130
  body: ProbeObservedBody,
90
131
  });
132
+ /**
133
+ * What the adapter observed of a command run: its two streams, its exit code,
134
+ * and the files it wrote.
135
+ *
136
+ * `exitCode` is signed, unlike an HTTP status, because a process terminated by
137
+ * a signal is conventionally reported as a negative code and this field records
138
+ * what happened rather than what is tidy. A non-zero exit is an observation
139
+ * exactly as a 500 is: only a policy denial, a cap, an abort, or a failure to
140
+ * start the process throws.
141
+ *
142
+ * `artifacts` is keyed by the identifier the operation declared, not by a
143
+ * filesystem path. Which path each identifier names is the adapter's mapping,
144
+ * the same disclosure boundary AD-35 draws around the executable itself.
145
+ */
146
+ export const CommandProbeObservation = z.strictObject({
147
+ ...probeCorrelation,
148
+ kind: z.literal('cli'),
149
+ exitCode: z.int(),
150
+ stdout: ProbeObservedBody,
151
+ stderr: ProbeObservedBody,
152
+ artifacts: z.record(Identifier, ProbeObservedBody),
153
+ });
154
+ export const ProbeObservation = z.discriminatedUnion('kind', [
155
+ ApiProbeObservation,
156
+ CommandProbeObservation,
157
+ ]);
@@ -21,5 +21,23 @@ export declare const ProbeObservedBody: z.ZodDiscriminatedUnion<[z.ZodObject<{
21
21
  }, z.core.$strict>, z.ZodObject<{
22
22
  kind: z.ZodLiteral<"absent">;
23
23
  }, z.core.$strict>], "kind">;
24
+ /**
25
+ * What one leg writes to a command's standard input. Three arms, like the
26
+ * observed body rather than the request body: standard input is a byte stream,
27
+ * so a command that reads a prompt receives text that was never JSON, and
28
+ * routing it through the `json` arm as a JSON string would make the leg claim
29
+ * a serialisation the command never sees. `absent` is the leg that writes
30
+ * nothing and closes the stream.
31
+ */
32
+ export declare const ProbeRequestStdin: z.ZodDiscriminatedUnion<[z.ZodObject<{
33
+ kind: z.ZodLiteral<"json">;
34
+ value: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
35
+ }, z.core.$strict>, z.ZodObject<{
36
+ kind: z.ZodLiteral<"text">;
37
+ value: z.ZodString;
38
+ }, z.core.$strict>, z.ZodObject<{
39
+ kind: z.ZodLiteral<"absent">;
40
+ }, z.core.$strict>], "kind">;
24
41
  export type ProbeRequestBody = z.infer<typeof ProbeRequestBody>;
25
42
  export type ProbeObservedBody = z.infer<typeof ProbeObservedBody>;
43
+ export type ProbeRequestStdin = z.infer<typeof ProbeRequestStdin>;
@@ -21,3 +21,16 @@ export const ProbeObservedBody = z.discriminatedUnion('kind', [
21
21
  z.strictObject({ kind: z.literal('text'), value: z.string() }),
22
22
  z.strictObject({ kind: z.literal('absent') }),
23
23
  ]);
24
+ /**
25
+ * What one leg writes to a command's standard input. Three arms, like the
26
+ * observed body rather than the request body: standard input is a byte stream,
27
+ * so a command that reads a prompt receives text that was never JSON, and
28
+ * routing it through the `json` arm as a JSON string would make the leg claim
29
+ * a serialisation the command never sees. `absent` is the leg that writes
30
+ * nothing and closes the stream.
31
+ */
32
+ export const ProbeRequestStdin = z.discriminatedUnion('kind', [
33
+ z.strictObject({ kind: z.literal('json'), value: JsonValue }),
34
+ z.strictObject({ kind: z.literal('text'), value: z.string() }),
35
+ z.strictObject({ kind: z.literal('absent') }),
36
+ ]);
@@ -0,0 +1,168 @@
1
+ /** AD-9's five qualification routes, one per way ground truth is earned. */
2
+ import { z } from 'zod';
3
+ /**
4
+ * AD-9 spells a route for each of the five ways a probe earns ground truth. The
5
+ * order is AD-9's own: historical fix boundary, controlled mutation,
6
+ * gameability demonstration, canary, clean control.
7
+ */
8
+ export declare const QUALIFICATION_ROUTES: readonly ['historical', 'controlled-mutation', 'gameability', 'canary', 'clean-control'];
9
+ export type QualificationRouteValue = (typeof QUALIFICATION_ROUTES)[number];
10
+ export declare const QualificationRoute: z.ZodEnum<{
11
+ canary: "canary";
12
+ "clean-control": "clean-control";
13
+ "controlled-mutation": "controlled-mutation";
14
+ gameability: "gameability";
15
+ historical: "historical";
16
+ }>;
17
+ /**
18
+ * AD-9's qualification record, as a tagged union on `route`.
19
+ *
20
+ * A union rather than one wide object with nullable fields: the five routes
21
+ * demand disjoint evidence, and a flat shape would make every route's evidence
22
+ * optional on every other route, which is the shape AD-9 was written against:
23
+ * "a mined fix commit being trusted when its own test already passed at the
24
+ * parent commit". Each branch names what its route must record and nothing
25
+ * else.
26
+ *
27
+ * Required on every probe, canaries included. AD-9 spells a route for all five
28
+ * kinds and closes with "an unqualified probe cannot enter a sealed set" with
29
+ * no exception, so exempting the canary would leave the route AD-9 writes for
30
+ * it with nothing to write it in. The exemption AD-9 does grant attaches to the
31
+ * defect signature, which is AD-40's field.
32
+ *
33
+ * Which route a probe may take is fixed by its class and its `expectedClean`
34
+ * flag, and that pairing is enforced by the corpus qualification gate rather
35
+ * than by a schema refinement: all combinations parse here, so an incompatible
36
+ * pairing stays a reason code carrying an artifact path rather than an
37
+ * anonymous parse failure.
38
+ *
39
+ * Inlined rather than given a `.meta({ id })`. Two `$defs` sharing an internal
40
+ * path are indistinguishable from a schema path alone, and every branch here
41
+ * carries an `ArtifactReference`, so a `$defs` entry would share def-relative
42
+ * suffixes with `Expression` and `ArtifactReference` and make the published
43
+ * keyword walk's stated no-collision premise false.
44
+ */
45
+ export declare const ProbeQualification: z.ZodDiscriminatedUnion<[z.ZodObject<{
46
+ route: z.ZodLiteral<"historical">;
47
+ failBeforeEvidence: z.ZodDiscriminatedUnion<[z.ZodObject<{
48
+ storage: z.ZodLiteral<"public">;
49
+ path: z.ZodString;
50
+ privateRef: z.ZodNull;
51
+ digest: z.ZodString;
52
+ }, z.core.$strict>, z.ZodObject<{
53
+ storage: z.ZodLiteral<"private">;
54
+ path: z.ZodNull;
55
+ privateRef: z.ZodString;
56
+ digest: z.ZodString;
57
+ }, z.core.$strict>], "storage">;
58
+ passAfterEvidence: z.ZodDiscriminatedUnion<[z.ZodObject<{
59
+ storage: z.ZodLiteral<"public">;
60
+ path: z.ZodString;
61
+ privateRef: z.ZodNull;
62
+ digest: z.ZodString;
63
+ }, z.core.$strict>, z.ZodObject<{
64
+ storage: z.ZodLiteral<"private">;
65
+ path: z.ZodNull;
66
+ privateRef: z.ZodString;
67
+ digest: z.ZodString;
68
+ }, z.core.$strict>], "storage">;
69
+ fixCommitDigest: z.ZodString;
70
+ oracleStableAcrossRevisions: z.ZodBoolean;
71
+ }, z.core.$strict>, z.ZodObject<{
72
+ route: z.ZodLiteral<"controlled-mutation">;
73
+ mutationSource: z.ZodString;
74
+ mutationOperator: z.ZodString;
75
+ targetArtifact: z.ZodDiscriminatedUnion<[z.ZodObject<{
76
+ storage: z.ZodLiteral<"public">;
77
+ path: z.ZodString;
78
+ privateRef: z.ZodNull;
79
+ digest: z.ZodString;
80
+ }, z.core.$strict>, z.ZodObject<{
81
+ storage: z.ZodLiteral<"private">;
82
+ path: z.ZodNull;
83
+ privateRef: z.ZodString;
84
+ digest: z.ZodString;
85
+ }, z.core.$strict>], "storage">;
86
+ expectedObservableFailure: z.ZodString;
87
+ baselinePassEvidence: z.ZodDiscriminatedUnion<[z.ZodObject<{
88
+ storage: z.ZodLiteral<"public">;
89
+ path: z.ZodString;
90
+ privateRef: z.ZodNull;
91
+ digest: z.ZodString;
92
+ }, z.core.$strict>, z.ZodObject<{
93
+ storage: z.ZodLiteral<"private">;
94
+ path: z.ZodNull;
95
+ privateRef: z.ZodString;
96
+ digest: z.ZodString;
97
+ }, z.core.$strict>], "storage">;
98
+ mutatedFailEvidence: z.ZodDiscriminatedUnion<[z.ZodObject<{
99
+ storage: z.ZodLiteral<"public">;
100
+ path: z.ZodString;
101
+ privateRef: z.ZodNull;
102
+ digest: z.ZodString;
103
+ }, z.core.$strict>, z.ZodObject<{
104
+ storage: z.ZodLiteral<"private">;
105
+ path: z.ZodNull;
106
+ privateRef: z.ZodString;
107
+ digest: z.ZodString;
108
+ }, z.core.$strict>], "storage">;
109
+ rollbackVerified: z.ZodBoolean;
110
+ }, z.core.$strict>, z.ZodObject<{
111
+ route: z.ZodLiteral<"gameability">;
112
+ degenerateResponse: z.ZodString;
113
+ naiveOracleSatisfiedEvidence: z.ZodDiscriminatedUnion<[z.ZodObject<{
114
+ storage: z.ZodLiteral<"public">;
115
+ path: z.ZodString;
116
+ privateRef: z.ZodNull;
117
+ digest: z.ZodString;
118
+ }, z.core.$strict>, z.ZodObject<{
119
+ storage: z.ZodLiteral<"private">;
120
+ path: z.ZodNull;
121
+ privateRef: z.ZodString;
122
+ digest: z.ZodString;
123
+ }, z.core.$strict>], "storage">;
124
+ disciplinedOracleRejectedEvidence: z.ZodDiscriminatedUnion<[z.ZodObject<{
125
+ storage: z.ZodLiteral<"public">;
126
+ path: z.ZodString;
127
+ privateRef: z.ZodNull;
128
+ digest: z.ZodString;
129
+ }, z.core.$strict>, z.ZodObject<{
130
+ storage: z.ZodLiteral<"private">;
131
+ path: z.ZodNull;
132
+ privateRef: z.ZodString;
133
+ digest: z.ZodString;
134
+ }, z.core.$strict>], "storage">;
135
+ }, z.core.$strict>, z.ZodObject<{
136
+ route: z.ZodLiteral<"canary">;
137
+ indicts: z.ZodEnum<{
138
+ corpus: "corpus";
139
+ fixture: "fixture";
140
+ }>;
141
+ nonDetectionEvidence: z.ZodDiscriminatedUnion<[z.ZodObject<{
142
+ storage: z.ZodLiteral<"public">;
143
+ path: z.ZodString;
144
+ privateRef: z.ZodNull;
145
+ digest: z.ZodString;
146
+ }, z.core.$strict>, z.ZodObject<{
147
+ storage: z.ZodLiteral<"private">;
148
+ path: z.ZodNull;
149
+ privateRef: z.ZodString;
150
+ digest: z.ZodString;
151
+ }, z.core.$strict>], "storage">;
152
+ }, z.core.$strict>, z.ZodObject<{
153
+ route: z.ZodLiteral<"clean-control">;
154
+ baselinePassEvidence: z.ZodDiscriminatedUnion<[z.ZodObject<{
155
+ storage: z.ZodLiteral<"public">;
156
+ path: z.ZodString;
157
+ privateRef: z.ZodNull;
158
+ digest: z.ZodString;
159
+ }, z.core.$strict>, z.ZodObject<{
160
+ storage: z.ZodLiteral<"private">;
161
+ path: z.ZodNull;
162
+ privateRef: z.ZodString;
163
+ digest: z.ZodString;
164
+ }, z.core.$strict>], "storage">;
165
+ revisionCommitDigest: z.ZodString;
166
+ noKnownDefectStatement: z.ZodString;
167
+ }, z.core.$strict>], "route">;
168
+ export type ProbeQualification = z.infer<typeof ProbeQualification>;
@@ -0,0 +1,106 @@
1
+ /** AD-9's five qualification routes, one per way ground truth is earned. */
2
+ import { z } from 'zod';
3
+ import { ArtifactReference } from './artifact-reference.js';
4
+ import { Digest } from './primitives.js';
5
+ /**
6
+ * AD-9 spells a route for each of the five ways a probe earns ground truth. The
7
+ * order is AD-9's own: historical fix boundary, controlled mutation,
8
+ * gameability demonstration, canary, clean control.
9
+ */
10
+ export const QUALIFICATION_ROUTES = [
11
+ 'historical',
12
+ 'controlled-mutation',
13
+ 'gameability',
14
+ 'canary',
15
+ 'clean-control',
16
+ ];
17
+ export const QualificationRoute = z.enum(QUALIFICATION_ROUTES);
18
+ /**
19
+ * AD-9's qualification record, as a tagged union on `route`.
20
+ *
21
+ * A union rather than one wide object with nullable fields: the five routes
22
+ * demand disjoint evidence, and a flat shape would make every route's evidence
23
+ * optional on every other route, which is the shape AD-9 was written against:
24
+ * "a mined fix commit being trusted when its own test already passed at the
25
+ * parent commit". Each branch names what its route must record and nothing
26
+ * else.
27
+ *
28
+ * Required on every probe, canaries included. AD-9 spells a route for all five
29
+ * kinds and closes with "an unqualified probe cannot enter a sealed set" with
30
+ * no exception, so exempting the canary would leave the route AD-9 writes for
31
+ * it with nothing to write it in. The exemption AD-9 does grant attaches to the
32
+ * defect signature, which is AD-40's field.
33
+ *
34
+ * Which route a probe may take is fixed by its class and its `expectedClean`
35
+ * flag, and that pairing is enforced by the corpus qualification gate rather
36
+ * than by a schema refinement: all combinations parse here, so an incompatible
37
+ * pairing stays a reason code carrying an artifact path rather than an
38
+ * anonymous parse failure.
39
+ *
40
+ * Inlined rather than given a `.meta({ id })`. Two `$defs` sharing an internal
41
+ * path are indistinguishable from a schema path alone, and every branch here
42
+ * carries an `ArtifactReference`, so a `$defs` entry would share def-relative
43
+ * suffixes with `Expression` and `ArtifactReference` and make the published
44
+ * keyword walk's stated no-collision premise false.
45
+ */
46
+ export const ProbeQualification = z.discriminatedUnion('route', [
47
+ z
48
+ .strictObject({
49
+ route: z.literal('historical'),
50
+ failBeforeEvidence: ArtifactReference.describe('The recorded failure at the parent revision. AD-9 exists because 2 of 18 mined fix commits had a test that already passed at the parent, so this is the half that cannot be assumed.'),
51
+ passAfterEvidence: ArtifactReference,
52
+ fixCommitDigest: Digest.describe('The causally isolated fix boundary AD-9 requires the two evidence records to straddle.'),
53
+ oracleStableAcrossRevisions: z
54
+ .boolean()
55
+ .describe("AD-9 requires the oracle to be stable across both revisions. `false` parses and fails the gate: a route that cannot record its own unmet precondition cannot be audited, and the schema is not where AD-9's admission decision is made."),
56
+ })
57
+ .describe('A historical probe: a defect mined from a real fix boundary, seeded by reverting it.'),
58
+ z
59
+ .strictObject({
60
+ route: z.literal('controlled-mutation'),
61
+ mutationSource: z
62
+ .string()
63
+ .min(1)
64
+ .describe("Where the mutation came from, in the corpus author's own terms. An opaque caller string, unrelated to `Defect.source`'s two-member enum, which records whether the defect is natural or introduced."),
65
+ mutationOperator: z.string().min(1),
66
+ targetArtifact: ArtifactReference,
67
+ expectedObservableFailure: z.string().min(1),
68
+ baselinePassEvidence: ArtifactReference,
69
+ mutatedFailEvidence: ArtifactReference,
70
+ rollbackVerified: z
71
+ .boolean()
72
+ .describe("AD-9's verified rollback or cleanup. `false` parses and fails the gate, for the same reason `oracleStableAcrossRevisions` does."),
73
+ })
74
+ .describe('A controlled mutation: a defect introduced by a named operator against a named artifact.'),
75
+ z
76
+ .strictObject({
77
+ route: z.literal('gameability'),
78
+ degenerateResponse: z
79
+ .string()
80
+ .min(1)
81
+ .describe('The compliant-looking degenerate response, described rather than embedded: AD-8 forbids sealed-case content from entering any artifact.'),
82
+ naiveOracleSatisfiedEvidence: ArtifactReference,
83
+ disciplinedOracleRejectedEvidence: ArtifactReference,
84
+ })
85
+ .describe('A gameability probe: the demonstration that a degenerate response satisfies a naive oracle and is rejected by a disciplined one.'),
86
+ z
87
+ .strictObject({
88
+ route: z.literal('canary'),
89
+ indicts: z
90
+ .enum(['corpus', 'fixture'])
91
+ .describe("AD-9's canary qualifies by demonstrating that non-detection indicts one of these two rather than the contract. Which one it indicts is the demonstration's own result and is recorded rather than left to the reader."),
92
+ nonDetectionEvidence: ArtifactReference,
93
+ })
94
+ .describe('A canary: a probe whose non-detection is evidence about the instrument, never about the contract.'),
95
+ z
96
+ .strictObject({
97
+ route: z.literal('clean-control'),
98
+ baselinePassEvidence: ArtifactReference,
99
+ revisionCommitDigest: Digest,
100
+ noKnownDefectStatement: z
101
+ .string()
102
+ .min(1)
103
+ .describe('AD-9 qualifies a clean control at "a revision with no known defect in the probed interface". No field can prove an absence, so the statement is recorded as an attestation under AD-32 and read as trust rather than as a computed fact.'),
104
+ })
105
+ .describe('A known-clean control: recorded baseline-pass evidence at a revision with no known defect in the probed interface.'),
106
+ ]);