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
@@ -11,7 +11,7 @@ import { Expression } from './expression.ts';
11
11
  * leg the plan could not map onto a `ProbeRequest` would declare work nothing
12
12
  * runs.
13
13
  */
14
- export declare const WitnessInputs: z.ZodObject<{
14
+ export declare const ApiWitnessInputs: z.ZodObject<{
15
15
  path: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
16
16
  query: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
17
17
  header: z.ZodRecord<z.ZodString, z.ZodString>;
@@ -22,6 +22,72 @@ export declare const WitnessInputs: z.ZodObject<{
22
22
  kind: z.ZodLiteral<"absent">;
23
23
  }, z.core.$strict>], "kind">;
24
24
  }, z.core.$strict>;
25
+ export type ApiWitnessInputs = z.infer<typeof ApiWitnessInputs>;
26
+ /**
27
+ * The same, for a leg supplied to a command-kind operation. `stdin` is a
28
+ * tagged value rather than a key map for exactly the reason `body` is: one leg
29
+ * supplies a value and has to tell an absent standard input from one carrying
30
+ * JSON null, which a key map cannot express. The request shape's `stdin` stays
31
+ * a key map, because a declaration says which keys an operation accepts.
32
+ * `suppliedKeys` is the code that bridges the two spellings and it
33
+ * special-cases `stdin` alongside `body`.
34
+ *
35
+ * AD-18 applies to `environment` the way it applies to `header`, so an
36
+ * environment value carries no credential.
37
+ */
38
+ export declare const CommandWitnessInputs: z.ZodObject<{
39
+ argument: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
40
+ option: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
41
+ environment: z.ZodRecord<z.ZodString, z.ZodString>;
42
+ stdin: z.ZodDiscriminatedUnion<[z.ZodObject<{
43
+ kind: z.ZodLiteral<"json">;
44
+ value: z.ZodType<import("./primitives.ts").JsonValue, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonValue, unknown>>;
45
+ }, z.core.$strict>, z.ZodObject<{
46
+ kind: z.ZodLiteral<"text">;
47
+ value: z.ZodString;
48
+ }, z.core.$strict>, z.ZodObject<{
49
+ kind: z.ZodLiteral<"absent">;
50
+ }, z.core.$strict>], "kind">;
51
+ }, z.core.$strict>;
52
+ export type CommandWitnessInputs = z.infer<typeof CommandWitnessInputs>;
53
+ /**
54
+ * Either spelling. A plain union rather than a discriminated one for the same
55
+ * reason `InputBinding` is: the leg names an operation and the kind of the
56
+ * interface declaring it lives in another subtree, so no discriminator is
57
+ * available to the schema and the agreement is a compile-time check.
58
+ *
59
+ * Only the sensitivity leg takes the union. `ManifestationWitness` and
60
+ * `FixtureReset` keep the transport spelling, which keeps the probe artifact
61
+ * byte-identical and keeps this shape's widening inside the eval contract's own
62
+ * version bump. That is truthful rather than merely convenient: both of those
63
+ * legs are issued through the environment-probe port, whose `ProbeRequest`
64
+ * carries a method, a path template, and the four transport channels, and
65
+ * pre-flight rejects a non-api interface for exactly that reason.
66
+ */
67
+ export declare const WitnessInputs: z.ZodUnion<readonly [z.ZodObject<{
68
+ path: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
69
+ query: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
70
+ header: z.ZodRecord<z.ZodString, z.ZodString>;
71
+ body: z.ZodDiscriminatedUnion<[z.ZodObject<{
72
+ kind: z.ZodLiteral<"json">;
73
+ value: z.ZodType<import("./primitives.ts").JsonValue, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonValue, unknown>>;
74
+ }, z.core.$strict>, z.ZodObject<{
75
+ kind: z.ZodLiteral<"absent">;
76
+ }, z.core.$strict>], "kind">;
77
+ }, z.core.$strict>, z.ZodObject<{
78
+ argument: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
79
+ option: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
80
+ environment: z.ZodRecord<z.ZodString, z.ZodString>;
81
+ stdin: z.ZodDiscriminatedUnion<[z.ZodObject<{
82
+ kind: z.ZodLiteral<"json">;
83
+ value: z.ZodType<import("./primitives.ts").JsonValue, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonValue, unknown>>;
84
+ }, z.core.$strict>, z.ZodObject<{
85
+ kind: z.ZodLiteral<"text">;
86
+ value: z.ZodString;
87
+ }, z.core.$strict>, z.ZodObject<{
88
+ kind: z.ZodLiteral<"absent">;
89
+ }, z.core.$strict>], "kind">;
90
+ }, z.core.$strict>]>;
25
91
  export type WitnessInputs = z.infer<typeof WitnessInputs>;
26
92
  /**
27
93
  * Half a witness pair. `legId` roots the relation's pointers, which address this
@@ -30,7 +96,7 @@ export type WitnessInputs = z.infer<typeof WitnessInputs>;
30
96
  */
31
97
  export declare const SensitivityWitnessLeg: z.ZodObject<{
32
98
  legId: z.ZodString;
33
- inputs: z.ZodObject<{
99
+ inputs: z.ZodUnion<readonly [z.ZodObject<{
34
100
  path: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
35
101
  query: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
36
102
  header: z.ZodRecord<z.ZodString, z.ZodString>;
@@ -40,14 +106,33 @@ export declare const SensitivityWitnessLeg: z.ZodObject<{
40
106
  }, z.core.$strict>, z.ZodObject<{
41
107
  kind: z.ZodLiteral<"absent">;
42
108
  }, z.core.$strict>], "kind">;
43
- }, z.core.$strict>;
109
+ }, z.core.$strict>, z.ZodObject<{
110
+ argument: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
111
+ option: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
112
+ environment: z.ZodRecord<z.ZodString, z.ZodString>;
113
+ stdin: z.ZodDiscriminatedUnion<[z.ZodObject<{
114
+ kind: z.ZodLiteral<"json">;
115
+ value: z.ZodType<import("./primitives.ts").JsonValue, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonValue, unknown>>;
116
+ }, z.core.$strict>, z.ZodObject<{
117
+ kind: z.ZodLiteral<"text">;
118
+ value: z.ZodString;
119
+ }, z.core.$strict>, z.ZodObject<{
120
+ kind: z.ZodLiteral<"absent">;
121
+ }, z.core.$strict>], "kind">;
122
+ }, z.core.$strict>]>;
44
123
  }, z.core.$strict>;
45
124
  export type SensitivityWitnessLeg = z.infer<typeof SensitivityWitnessLeg>;
46
- export declare const WITNESS_CHANNELS: readonly ['path', 'query', 'body'];
125
+ export declare const API_WITNESS_CHANNELS: readonly ['path', 'query', 'body'];
126
+ export declare const COMMAND_WITNESS_CHANNELS: readonly ['argument', 'option', 'environment', 'stdin'];
127
+ export declare const WITNESS_CHANNELS: readonly ["path", "query", "body", "argument", "option", "environment", "stdin"];
47
128
  export declare const WitnessChannel: z.ZodEnum<{
129
+ argument: "argument";
48
130
  body: "body";
131
+ environment: "environment";
132
+ option: "option";
49
133
  path: "path";
50
134
  query: "query";
135
+ stdin: "stdin";
51
136
  }>;
52
137
  export type WitnessChannel = z.infer<typeof WitnessChannel>;
53
138
  /**
@@ -67,13 +152,17 @@ export type WitnessChannel = z.infer<typeof WitnessChannel>;
67
152
  export declare const SensitivityWitness: z.ZodObject<{
68
153
  witnessId: z.ZodString;
69
154
  channel: z.ZodEnum<{
155
+ argument: "argument";
70
156
  body: "body";
157
+ environment: "environment";
158
+ option: "option";
71
159
  path: "path";
72
160
  query: "query";
161
+ stdin: "stdin";
73
162
  }>;
74
163
  legs: z.ZodArray<z.ZodObject<{
75
164
  legId: z.ZodString;
76
- inputs: z.ZodObject<{
165
+ inputs: z.ZodUnion<readonly [z.ZodObject<{
77
166
  path: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
78
167
  query: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
79
168
  header: z.ZodRecord<z.ZodString, z.ZodString>;
@@ -83,7 +172,20 @@ export declare const SensitivityWitness: z.ZodObject<{
83
172
  }, z.core.$strict>, z.ZodObject<{
84
173
  kind: z.ZodLiteral<"absent">;
85
174
  }, z.core.$strict>], "kind">;
86
- }, z.core.$strict>;
175
+ }, z.core.$strict>, z.ZodObject<{
176
+ argument: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
177
+ option: z.ZodType<import("./primitives.ts").JsonObject, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonObject, unknown>>;
178
+ environment: z.ZodRecord<z.ZodString, z.ZodString>;
179
+ stdin: z.ZodDiscriminatedUnion<[z.ZodObject<{
180
+ kind: z.ZodLiteral<"json">;
181
+ value: z.ZodType<import("./primitives.ts").JsonValue, unknown, z.core.$ZodTypeInternals<import("./primitives.ts").JsonValue, unknown>>;
182
+ }, z.core.$strict>, z.ZodObject<{
183
+ kind: z.ZodLiteral<"text">;
184
+ value: z.ZodString;
185
+ }, z.core.$strict>, z.ZodObject<{
186
+ kind: z.ZodLiteral<"absent">;
187
+ }, z.core.$strict>], "kind">;
188
+ }, z.core.$strict>]>;
87
189
  }, z.core.$strict>>;
88
190
  relation: z.ZodType<Expression, unknown, z.core.$ZodTypeInternals<Expression, unknown>>;
89
191
  }, z.core.$strict>;
@@ -2,7 +2,7 @@
2
2
  import { z } from 'zod';
3
3
  import { Expression } from './expression.js';
4
4
  import { Identifier, JsonObjectValue, KeyName } from './primitives.js';
5
- import { ProbeRequestBody } from './probe-body.js';
5
+ import { ProbeRequestBody, ProbeRequestStdin } from './probe-body.js';
6
6
  /**
7
7
  * The four transport channels one probe leg supplies, as values. `RequestShape`
8
8
  * declares what an operation accepts; this declares what one leg sends. AD-18
@@ -13,7 +13,7 @@ import { ProbeRequestBody } from './probe-body.js';
13
13
  * leg the plan could not map onto a `ProbeRequest` would declare work nothing
14
14
  * runs.
15
15
  */
16
- export const WitnessInputs = z
16
+ export const ApiWitnessInputs = z
17
17
  .strictObject({
18
18
  path: JsonObjectValue,
19
19
  query: JsonObjectValue,
@@ -24,6 +24,46 @@ export const WitnessInputs = z
24
24
  id: 'WitnessInputs',
25
25
  description: "One probe leg's supplied inputs, keyed by AD-19 transport channel, in the spelling the environment-probe port accepts. Shared by both witness kinds and by the fixture reset, so the export carries it once.",
26
26
  });
27
+ /**
28
+ * The same, for a leg supplied to a command-kind operation. `stdin` is a
29
+ * tagged value rather than a key map for exactly the reason `body` is: one leg
30
+ * supplies a value and has to tell an absent standard input from one carrying
31
+ * JSON null, which a key map cannot express. The request shape's `stdin` stays
32
+ * a key map, because a declaration says which keys an operation accepts.
33
+ * `suppliedKeys` is the code that bridges the two spellings and it
34
+ * special-cases `stdin` alongside `body`.
35
+ *
36
+ * AD-18 applies to `environment` the way it applies to `header`, so an
37
+ * environment value carries no credential.
38
+ */
39
+ // Bare, with no `.meta({ id })`, and the reason is a published-schema one
40
+ // rather than a size one. A `$ref`'d definition's own errors reach ajv with a
41
+ // schema path relative to that definition, so two definitions under one
42
+ // `anyOf` report `#/required` and `#/additionalProperties` at the same
43
+ // instance path and nothing tells them apart. AD-13's mutation sweep needs one
44
+ // keyword deletion to be attributable to one occurrence, and the branch is
45
+ // attributable only while it is spelled in place.
46
+ export const CommandWitnessInputs = z.strictObject({
47
+ argument: JsonObjectValue,
48
+ option: JsonObjectValue,
49
+ environment: z.record(KeyName, z.string()),
50
+ stdin: ProbeRequestStdin,
51
+ });
52
+ /**
53
+ * Either spelling. A plain union rather than a discriminated one for the same
54
+ * reason `InputBinding` is: the leg names an operation and the kind of the
55
+ * interface declaring it lives in another subtree, so no discriminator is
56
+ * available to the schema and the agreement is a compile-time check.
57
+ *
58
+ * Only the sensitivity leg takes the union. `ManifestationWitness` and
59
+ * `FixtureReset` keep the transport spelling, which keeps the probe artifact
60
+ * byte-identical and keeps this shape's widening inside the eval contract's own
61
+ * version bump. That is truthful rather than merely convenient: both of those
62
+ * legs are issued through the environment-probe port, whose `ProbeRequest`
63
+ * carries a method, a path template, and the four transport channels, and
64
+ * pre-flight rejects a non-api interface for exactly that reason.
65
+ */
66
+ export const WitnessInputs = z.union([ApiWitnessInputs, CommandWitnessInputs]);
27
67
  /**
28
68
  * Half a witness pair. `legId` roots the relation's pointers, which address this
29
69
  * leg's response as `/interactions/{legId}/response-body/...`, so it shares one
@@ -36,7 +76,23 @@ export const SensitivityWitnessLeg = z.strictObject({
36
76
  // AD-10 selects the differential channel by the operation's state-change
37
77
  // marker: `path` or `query` where the marker is false, `body` where it is true.
38
78
  // `header` is absent on purpose; no AD names a header differential.
39
- export const WITNESS_CHANNELS = ['path', 'query', 'body'];
79
+ export const API_WITNESS_CHANNELS = ['path', 'query', 'body'];
80
+ // A command operation's differential channel. All four are admitted rather
81
+ // than two: AD-10's marker rule selects `path` or `query` against `body`
82
+ // because an HTTP read carries its identifier in the URL and a write carries
83
+ // it in the body, and a command carries its inputs the same way whether or not
84
+ // it changes state, so the marker decides nothing here. Which channel a given
85
+ // command witness may use is the contract author's choice.
86
+ export const COMMAND_WITNESS_CHANNELS = [
87
+ 'argument',
88
+ 'option',
89
+ 'environment',
90
+ 'stdin',
91
+ ];
92
+ export const WITNESS_CHANNELS = [
93
+ ...API_WITNESS_CHANNELS,
94
+ ...COMMAND_WITNESS_CHANNELS,
95
+ ];
40
96
  export const WitnessChannel = z.enum(WITNESS_CHANNELS);
41
97
  /**
42
98
  * AD-10's typed sensitivity witness: a pair of inputs and the AD-4 relation
@@ -70,7 +126,7 @@ export const ManifestationWitness = z.strictObject({
70
126
  legId: Identifier,
71
127
  interfaceId: Identifier,
72
128
  operationId: Identifier,
73
- inputs: WitnessInputs,
129
+ inputs: ApiWitnessInputs,
74
130
  relation: Expression,
75
131
  });
76
132
  /**
@@ -82,5 +138,5 @@ export const FixtureReset = z.strictObject({
82
138
  legId: Identifier,
83
139
  interfaceId: Identifier,
84
140
  operationId: Identifier,
85
- inputs: WitnessInputs,
141
+ inputs: ApiWitnessInputs,
86
142
  });
@@ -0,0 +1,31 @@
1
+ import type { InteractionStep } from '../schemas/plan.ts';
2
+ export type BindingOrder = {
3
+ /** Ascending tiers; within each, steps in declaration order. Every declared id appears exactly once. */
4
+ readonly tiers: readonly (readonly string[])[];
5
+ /**
6
+ * Ids Kahn's algorithm left unplaced, in declaration order: the members of an
7
+ * ordering cycle and every step downstream of one, since a step whose
8
+ * dependency never gets a tier never gets one either.
9
+ */
10
+ readonly cyclic: readonly string[];
11
+ };
12
+ /**
13
+ * Cyclic steps come back as data instead of an exception, matching
14
+ * `selectObservations`'s own policy of reporting ambiguity rather than deciding
15
+ * it. A compiled contract whose step ids are unique never reaches that list:
16
+ * `binding-cycle` rejects every cycle carrying a capture edge and
17
+ * `nested-temporal-clause` every cycle made of `after` edges alone, so the
18
+ * union graph is acyclic by the time any record is scored.
19
+ *
20
+ * The uniqueness clause is load-bearing. `checkNestedTemporalClause` resolves
21
+ * `after` through a plan index built with `duplicateIds: 'unresolved'`, which
22
+ * deletes a duplicated id and reads any clause naming it as dangling, while
23
+ * this function and `checkBindingCycle` both test against the raw declared-id
24
+ * set, where it is present. So a plan declaring one id twice can carry an
25
+ * `after` cycle those two disagree about, and its steps land here. Nothing
26
+ * downstream sees it: `seal` builds its own index with the default throwing
27
+ * option and rejects a duplicate id outright. Changing how
28
+ * `checkNestedTemporalClause` reads a duplicate is deliberate shipped
29
+ * behaviour and belongs to whoever owns that check.
30
+ */
31
+ export declare function bindingOrder(interactionPlan: readonly InteractionStep[]): BindingOrder;
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The order a plan's steps must be resolved in when one step's selection
3
+ * depends on another's. Kahn tiers over the union of the capture edges and
4
+ * AD-39's `after` edges, the same graph `checkBindingCycle` builds: every step
5
+ * in tier n depends only on steps in tiers below n, so a caller walking the
6
+ * tiers in order always has what it needs resolved by the time it reads it.
7
+ *
8
+ * The `after` edge is in the graph because `selectWithBindings` resolves a
9
+ * temporal anchor through the same binding filter as everything else, so a step
10
+ * can read an anchor whose own capture sites must already be written. Tiering
11
+ * captures alone made the answer depend on declaration order within a tier: two
12
+ * same-tier steps swapped flipped a verdict between `none` and one match.
13
+ *
14
+ * `{ literal }`, `{ matcher }`, and `{ principal }` bindings declare no
15
+ * dependency, so a step carrying only those and no clause is tier zero. So is a
16
+ * step whose captured pointer or `after` clause names an id the plan does not
17
+ * declare: a dangling capture is `unreachable-check-evidence`'s at compile time,
18
+ * AD-39 makes a dangling `after` permissive, and nothing here should invent an
19
+ * ordering for either.
20
+ *
21
+ * Within a tier the order is the order the steps are declared in
22
+ * `interactionPlan`, which is what "sequence order within a tier" can mean at
23
+ * compile time, where no observation `sequence` exists yet. ADR-006 bans
24
+ * reading order off array position in a run record, where the array is an
25
+ * ingest artifact nobody authored; a contract's `interactionPlan` is the
26
+ * author's own declaration, and permuting it yields a different contract with a
27
+ * different digest, so there is no permutation invariance to preserve.
28
+ */
29
+ import { capturedBindings } from '../compile/bindings.js';
30
+ /**
31
+ * Cyclic steps come back as data instead of an exception, matching
32
+ * `selectObservations`'s own policy of reporting ambiguity rather than deciding
33
+ * it. A compiled contract whose step ids are unique never reaches that list:
34
+ * `binding-cycle` rejects every cycle carrying a capture edge and
35
+ * `nested-temporal-clause` every cycle made of `after` edges alone, so the
36
+ * union graph is acyclic by the time any record is scored.
37
+ *
38
+ * The uniqueness clause is load-bearing. `checkNestedTemporalClause` resolves
39
+ * `after` through a plan index built with `duplicateIds: 'unresolved'`, which
40
+ * deletes a duplicated id and reads any clause naming it as dangling, while
41
+ * this function and `checkBindingCycle` both test against the raw declared-id
42
+ * set, where it is present. So a plan declaring one id twice can carry an
43
+ * `after` cycle those two disagree about, and its steps land here. Nothing
44
+ * downstream sees it: `seal` builds its own index with the default throwing
45
+ * option and rejects a duplicate id outright. Changing how
46
+ * `checkNestedTemporalClause` reads a duplicate is deliberate shipped
47
+ * behaviour and belongs to whoever owns that check.
48
+ */
49
+ export function bindingOrder(interactionPlan) {
50
+ // A duplicated id collapses to one node: the plan declares one name, and
51
+ // which of two same-named steps a capture meant is undecidable here.
52
+ const declared = [];
53
+ const dependencies = new Map();
54
+ for (const step of interactionPlan) {
55
+ if (dependencies.has(step.stepId))
56
+ continue;
57
+ declared.push(step.stepId);
58
+ dependencies.set(step.stepId, new Set());
59
+ }
60
+ for (const step of interactionPlan) {
61
+ const own = dependencies.get(step.stepId);
62
+ if (own === undefined)
63
+ continue;
64
+ for (const capture of capturedBindings(step)) {
65
+ const { stepId } = capture.target;
66
+ // A self-reference is a cycle of one, so it stays in the graph and lands
67
+ // in `cyclic` rather than being filtered into tier zero.
68
+ if (dependencies.has(stepId))
69
+ own.add(stepId);
70
+ }
71
+ if (step.after !== null && dependencies.has(step.after)) {
72
+ own.add(step.after);
73
+ }
74
+ }
75
+ const tiers = [];
76
+ const placed = new Set();
77
+ while (placed.size < declared.length) {
78
+ const tier = declared.filter((stepId) => !placed.has(stepId) &&
79
+ [...(dependencies.get(stepId) ?? [])].every((id) => placed.has(id)));
80
+ // Every remaining step depends on another remaining step, which is a cycle.
81
+ if (tier.length === 0)
82
+ break;
83
+ tiers.push(tier);
84
+ for (const stepId of tier)
85
+ placed.add(stepId);
86
+ }
87
+ return { tiers, cyclic: declared.filter((stepId) => !placed.has(stepId)) };
88
+ }
@@ -0,0 +1,93 @@
1
+ import { type ResolvedValue } from '../evaluate/resolved-value.ts';
2
+ import type { InteractionStep } from '../schemas/plan.ts';
3
+ import type { InputChannelName } from '../schemas/pointer.ts';
4
+ import type { JsonValue } from '../schemas/primitives.ts';
5
+ import type { Observation } from '../schemas/sealed-run-record.ts';
6
+ import { type PlanIndex } from '../seal/plan-index.ts';
7
+ import { type StepSelection } from './selection.ts';
8
+ /**
9
+ * One captured pointer's resolution. `ResolvedValue` alone cannot carry this:
10
+ * it is `JsonValue | ABSENT` with nowhere to put the observation the value came
11
+ * from, its `sequence`, or the referenced step's named ambiguity. `sequence` is
12
+ * what gives "earlier" a runtime meaning, since a capture graph that is acyclic
13
+ * still says nothing about which observation came first.
14
+ */
15
+ export type CapturedResolution = {
16
+ readonly status: 'resolved';
17
+ readonly value: ResolvedValue;
18
+ readonly observationId: Observation['observationId'];
19
+ readonly sequence: number;
20
+ } | {
21
+ readonly status: 'absent';
22
+ } | {
23
+ readonly status: 'ambiguous';
24
+ readonly matchedObservationIds: readonly Observation['observationId'][];
25
+ };
26
+ /**
27
+ * The key one captured binding occupies in the resolution map. Keyed by
28
+ * binding site rather than by pointer: one step can carry several captured
29
+ * bindings, and two of them may name the same pointer in different channels.
30
+ * JSON-encoded rather than delimiter-joined, since a parameter key is arbitrary
31
+ * caller-supplied text and could contain any separator.
32
+ */
33
+ export declare function bindingSiteKey(stepId: string, transportChannel: InputChannelName, key: string): string;
34
+ /**
35
+ * Resolves one captured pointer against the record.
36
+ *
37
+ * The referenced step is selected through `selectWithBindings`, so its own
38
+ * selection predicate applies before a value is read off it. Selecting it with
39
+ * `selectObservations` alone would match on `operationId` and leave a step that
40
+ * only its own bindings separate reporting the named ambiguity, which would
41
+ * make a capture from either half of a literal-bound collision pair resolve
42
+ * nothing at all. `resolved` carries the referenced step's own captured values,
43
+ * already filled by the tier below it, which is what makes the tiering
44
+ * load-bearing.
45
+ *
46
+ * The three dispositions already settled hold unchanged over the filtered
47
+ * result: one match binds, several under a declared `any` binds the lowest
48
+ * `sequence`, and several under `exactly-one`/`at-most-one` is the named
49
+ * ambiguity, returned as data with no value resolved.
50
+ *
51
+ * A pointer whose step the plan does not declare, or whose referenced step
52
+ * matched nothing, resolves `absent`.
53
+ *
54
+ * `resolved` as a status means an observation was selected, which is a
55
+ * different fact from the pointer finding a value in it: a tail that walks off
56
+ * the observed body comes back `resolved` carrying `ABSENT`, with the source
57
+ * observation and its `sequence` intact. That is why `CapturedResolution.value`
58
+ * is `ResolvedValue`. AD-26 makes absent an observation rather than an error,
59
+ * and `deepEquals` is false against it, so the referencing step still selects
60
+ * `none`; keeping the source observation means the ordering floor stays
61
+ * computable either way.
62
+ */
63
+ export declare function resolveCapturedValue(pointer: string, index: PlanIndex, observations: readonly Observation[], resolved: ReadonlyMap<string, CapturedResolution>): CapturedResolution;
64
+ /**
65
+ * Every captured binding in the plan, resolved in `bindingOrder`'s tiers and
66
+ * keyed by binding site. Walking the tiers in order is what lets a step's
67
+ * captured values be resolved against a referenced step whose own captures are
68
+ * already in the map. Steps `bindingOrder` reports cyclic are left out, so
69
+ * their bindings resolve as unlisted and filter every candidate away.
70
+ */
71
+ export declare function resolveCapturedBindings(interactionPlan: readonly InteractionStep[], index: PlanIndex, observations: readonly Observation[]): ReadonlyMap<string, CapturedResolution>;
72
+ export declare function deepEquals(a: ResolvedValue, b: ResolvedValue): boolean;
73
+ export declare function jsonTypeOf(value: JsonValue): string;
74
+ /**
75
+ * `selectObservations`, then the step's own selection predicate as a filter
76
+ * over the matches, then the cardinality verdict over what survived.
77
+ *
78
+ * The order is temporal clause, then capture ordering, then the binding
79
+ * filters. Ordering is enforced at score time as well as at compile time: the
80
+ * persistence read-back this exists for is exactly a claim about order, and a
81
+ * record whose `GET` sits at `sequence` 2 and whose `POST` sits at `sequence` 9
82
+ * would otherwise satisfy the binding and pass an oracle proving the opposite.
83
+ *
84
+ * `resolved` is the map `resolveCapturedBindings` fills from `bindingOrder`'s
85
+ * tiers, keyed by binding site. An unlisted or unresolved site filters every
86
+ * candidate out, so a caller that skipped a tier gets `none` rather than a
87
+ * silently wrong match.
88
+ *
89
+ * A filter over zero bindings and no clause separates nothing, so two steps
90
+ * sharing an operation and declaring neither both still return `several`: the
91
+ * declared structure does not distinguish them.
92
+ */
93
+ export declare function selectWithBindings(step: InteractionStep, observations: readonly Observation[], index: PlanIndex, resolved: ReadonlyMap<string, CapturedResolution>): StepSelection;