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
@@ -1,5 +1,6 @@
1
1
  /** the interaction plan: steps as selectors over observations. */
2
2
  import { z } from 'zod';
3
+ import { InteractionPointer } from './pointer.js';
3
4
  import { Identifier, JsonValue, KeyName } from './primitives.js';
4
5
  /**
5
6
  * AD-39: input-binding values are tagged and never share a value space. The
@@ -7,10 +8,52 @@ import { Identifier, JsonValue, KeyName } from './primitives.js';
7
8
  * one implementation and the literal string to another, and flipped a witness
8
9
  * match between `caught` and `missed` on one record; that form is
9
10
  * unrepresentable here.
11
+ *
12
+ * Four members, one tag each. `{ literal }` writes the sent value down;
13
+ * `{ matcher: 'any' }` binds whatever was sent and `{ matcher: 'type-violating' }`
14
+ * binds a value whose JSON type differs from the operation's declared type for
15
+ * the key, which is how AD-31 rule 3's malformed-input behaviour is addressed.
16
+ *
17
+ * `{ captured }` addresses an earlier step's declared scalar output. Owed item
18
+ * 3: a `POST` returning a server-generated identifier followed by a `GET`
19
+ * proving persistence is unwritable with the first two, since a literal
20
+ * hard-codes a resource the evaluator never created and `any` matches
21
+ * unrelated reads. "Earlier" is earlier in the capture graph's own topological
22
+ * order, which `binding-cycle` makes exist. It is deliberately not AD-39's
23
+ * `after` clause: `nested-temporal-clause` already rejects every `after` cycle,
24
+ * so a capture forced to follow an `after` edge would leave `binding-cycle`
25
+ * unfireable. At score time the ordering is the record's `sequence`.
26
+ *
27
+ * `{ principal }` names a principal `testData.principals` declares. The two
28
+ * critical-severity cross-user behaviours (act as A, read as B, must be denied
29
+ * or absent) bind a step to an account that is neither a literal, since AD-19
30
+ * forbids credential values in declarations, nor an earlier step's output,
31
+ * since accounts are provisioned outside the observation stream. The name is
32
+ * an opaque label carrying no account identifier, credential, or subject data
33
+ * (AD-18). An undeclared name fires `undeclared-mandatory-input` in strict
34
+ * mode; a Zod refinement here would be a cross-subtree constraint the export
35
+ * cannot carry, and the published-schema differential sweep synthesises a
36
+ * union-branch witness that would expose the disagreement.
37
+ *
38
+ * A captured pointer resolves to a declared scalar with no transform applied,
39
+ * which keeps AD-4's ban on arithmetic, projection, and user-defined functions
40
+ * holding by construction: the grammar has no place to write one.
10
41
  */
42
+ /**
43
+ * The first two members, named individually so the probe-side selector under
44
+ * AD-40 admits exactly these two and nothing else. Bare `export const` with no
45
+ * `.meta({ id })`: an id would collapse the branches to `$ref`s and mint new
46
+ * `$defs`, so the export stays byte-identical.
47
+ */
48
+ export const LiteralBindingValue = z.strictObject({ literal: JsonValue });
49
+ export const MatcherBindingValue = z.strictObject({
50
+ matcher: z.enum(['any', 'type-violating']),
51
+ });
11
52
  export const BindingValue = z.union([
12
- z.strictObject({ literal: JsonValue }),
13
- z.strictObject({ matcher: z.enum(['any', 'type-violating']) }),
53
+ LiteralBindingValue,
54
+ MatcherBindingValue,
55
+ z.strictObject({ captured: InteractionPointer }),
56
+ z.strictObject({ principal: Identifier }),
14
57
  ]);
15
58
  /** the constraint identifier the ledger carries for the check below. */
16
59
  export const BINDING_CHANNEL_NON_EMPTY = 'binding-channel-non-empty';
@@ -37,12 +80,54 @@ export const BindingChannel = BindingChannelMap.nullable().meta({
37
80
  * requires every member at parse time and fails five of the Gate C fixture's
38
81
  * six steps, all of which bind a subset of the channels.
39
82
  */
40
- export const InputBinding = z.strictObject({
83
+ export const ApiInputBinding = z.strictObject({
41
84
  path: BindingChannel,
42
85
  query: BindingChannel,
43
86
  header: BindingChannel,
44
87
  body: BindingChannel,
45
88
  });
89
+ /** The same shape over the four channels a command-kind operation accepts. */
90
+ export const CommandInputBinding = z.strictObject({
91
+ argument: BindingChannel,
92
+ option: BindingChannel,
93
+ environment: BindingChannel,
94
+ stdin: BindingChannel,
95
+ });
96
+ /**
97
+ * A plain union rather than a discriminated one, and the agreement between a
98
+ * step's bound channels and its operation's kind is a compile-time check
99
+ * rather than a schema refinement.
100
+ *
101
+ * A step names an `operationId` and nothing else; the kind of the interface
102
+ * declaring that operation lives in a different subtree of the same document.
103
+ * That is the cross-subtree constraint the `{ principal }` comment above
104
+ * already records as unrepresentable in the export. Adding a `kind` field to
105
+ * the step itself was the other option and duplicates a fact the operation
106
+ * already carries, which makes a disagreeing step a second inconsistency to
107
+ * check rather than one fewer.
108
+ */
109
+ export const InputBinding = z.union([ApiInputBinding, CommandInputBinding]);
110
+ /**
111
+ * AD-39's declared selector cardinality (owed item 2): what a step means when
112
+ * its selector matches more than one observation was not decided at the
113
+ * architecture layer, so a first-match scorer and a last-match scorer could
114
+ * bind different evidence. The contract now declares the rule per step.
115
+ * `several` under `exactly-one`/`at-most-one` is a named ambiguity condition;
116
+ * a reference function returns it as data. Routing that ambiguity to a
117
+ * verdict rung is later work. `any` is unrelated to
118
+ * `BindingValue`'s `{ matcher: 'any' }` above: same string, different field,
119
+ * no type-level collision. `ExpectedCardinality` (`interface.ts`) is a
120
+ * second, unrelated reuse of the word for AD-20's response-collection
121
+ * cardinality, and its `at-most` mode is a near-miss for `at-most-one` here;
122
+ * different type, different field, no collision, but easy to misread as the
123
+ * same declaration.
124
+ */
125
+ export const SELECTOR_CARDINALITIES = [
126
+ 'exactly-one',
127
+ 'at-most-one',
128
+ 'any',
129
+ ];
130
+ export const SelectorCardinality = z.enum(SELECTOR_CARDINALITIES);
46
131
  /**
47
132
  * AD-39: a step is a selector over observations the evaluator produced, never
48
133
  * an instruction. Its selection predicate is spelled as its two members, the
@@ -55,4 +140,5 @@ export const InteractionStep = z.strictObject({
55
140
  operationId: Identifier,
56
141
  inputBinding: InputBinding,
57
142
  after: Identifier.nullable().describe("The temporal clause: the identifier of an earlier step, or `null`. That the named step carries no clause of its own is AD-39's one-level bound, which fires `nested-temporal-clause` at compile time and is deliberately not enforced here, so the code keeps a shape to fire on."),
143
+ cardinality: SelectorCardinality.describe("AD-39's declared selector cardinality (owed item 2): `exactly-one` or `at-most-one` when the step expects a single matching observation, `any` when several are legitimate. Several matches under `exactly-one`/`at-most-one` is the named ambiguity condition; a reference selection function returns it as data. Required rather than optional, which makes this a BREAKING `schemaVersion` bump under AD-11: adding an optional field is additive, and this field is not optional."),
58
144
  });
@@ -7,9 +7,10 @@ import { z } from 'zod';
7
7
  * are exported here because the Sealed Run Record's quoted evidence needs to
8
8
  * name a channel by one shared spelling.
9
9
  */
10
- export declare const EVIDENCE_CHANNELS: readonly ['response-body', 'response-headers', 'response-status', 'call-inputs', 'stdout', 'stderr', 'exit-code'];
10
+ export declare const EVIDENCE_CHANNELS: readonly ['response-body', 'response-headers', 'response-status', 'call-inputs', 'stdout', 'stderr', 'exit-code', 'artifact'];
11
11
  export type EvidenceChannelName = (typeof EVIDENCE_CHANNELS)[number];
12
12
  export declare const EvidenceChannel: z.ZodEnum<{
13
+ artifact: "artifact";
13
14
  "call-inputs": "call-inputs";
14
15
  "exit-code": "exit-code";
15
16
  "response-body": "response-body";
@@ -31,9 +32,54 @@ export declare const TransportChannel: z.ZodEnum<{
31
32
  path: "path";
32
33
  query: "query";
33
34
  }>;
35
+ /**
36
+ * The four channels a command-kind operation accepts input on. They sit beside
37
+ * the transport channels because this module owns channel vocabulary, and the
38
+ * request shape that declares them has to name them without forward-declaring
39
+ * a tuple it does not own.
40
+ *
41
+ * `stdin` is the command analogue of `body` and inherits its asymmetry: a
42
+ * request shape declares it as a key map, while one witness leg supplies it as
43
+ * a tagged body value.
44
+ */
45
+ export declare const COMMAND_CHANNELS: readonly ['argument', 'option', 'environment', 'stdin'];
46
+ export type CommandChannelName = (typeof COMMAND_CHANNELS)[number];
47
+ /**
48
+ * Every channel `call-inputs` may take as its next segment, both kinds
49
+ * together. A pointer is parsed with no contract in hand, so the grammar
50
+ * admits all eight and the question of which four a given operation may use is
51
+ * answered by reachability, which has the operation.
52
+ */
53
+ export declare const INPUT_CHANNELS: readonly ["path", "query", "header", "body", "argument", "option", "environment", "stdin"];
54
+ export type InputChannelName = (typeof INPUT_CHANNELS)[number];
34
55
  export declare const TAIL_BEARING_CHANNELS: readonly ["response-body", "response-headers", "stdout", "stderr"];
35
56
  export declare const SCALAR_CHANNELS: readonly ["response-status", "exit-code"];
36
57
  export declare const TRANSPORT_ROOTED_CHANNEL: "call-inputs";
58
+ export declare const IDENTIFIER_ROOTED_CHANNEL: "artifact";
59
+ /**
60
+ * The response-side channels each kind produces, and neither produces the
61
+ * other's. Declared here rather than rebuilt from a description, so a channel
62
+ * added to the vocabulary has to be assigned to a side and a test can assert
63
+ * the two partition the response side exactly.
64
+ *
65
+ * `call-inputs` belongs to neither: it carries what was sent rather than what
66
+ * came back, and both kinds have it.
67
+ */
68
+ export declare const API_RESPONSE_CHANNELS: readonly ["response-body", "response-headers", "response-status"];
69
+ export declare const COMMAND_RESPONSE_CHANNELS: readonly ["stdout", "stderr", "exit-code", "artifact"];
70
+ /**
71
+ * Every channel but the identifier-rooted one, in the vocabulary's own order.
72
+ *
73
+ * Spelled out and typed against the enum rather than filtered from it: a filter
74
+ * widens to `EvidenceChannelName[]` and `z.enum` needs a tuple, and the whole
75
+ * point of the list is that adding a ninth channel has to be a decision about
76
+ * which side of this line it falls on rather than something a filter absorbs.
77
+ * `tests/schemas/pointer.test.ts` asserts it partitions the vocabulary with
78
+ * `IDENTIFIER_ROOTED_CHANNEL` exactly.
79
+ */
80
+ export declare const NON_IDENTIFIER_ROOTED_CHANNELS: readonly ["response-body", "response-headers", "response-status", "call-inputs", "stdout", "stderr", "exit-code"];
81
+ /** Every channel that carries what came back, whichever kind produced it. */
82
+ export declare const RESPONSE_SIDE_CHANNELS: readonly ["response-body", "response-headers", "response-status", "stdout", "stderr", "exit-code", "artifact"];
37
83
  export declare const INTERACTION_POINTER_PATTERN: RegExp;
38
84
  export declare const BOUND_ELEMENT_POINTER_PATTERN: RegExp;
39
85
  export declare const DESCRIPTOR_POINTER_PATTERN: RegExp;
@@ -16,10 +16,11 @@ export const EVIDENCE_CHANNELS = [
16
16
  'stdout',
17
17
  'stderr',
18
18
  'exit-code',
19
+ 'artifact',
19
20
  ];
20
21
  export const EvidenceChannel = z.enum(EVIDENCE_CHANNELS).meta({
21
22
  id: 'EvidenceChannel',
22
- description: "AD-26's closed evidence channel vocabulary. The same seven the interaction-rooted pointer addresses; a channel outside this set is a syntax error rather than an unreachable-evidence finding.",
23
+ description: "AD-26's closed evidence channel vocabulary. The same eight the interaction-rooted pointer addresses; a channel outside this set is a syntax error rather than an unreachable-evidence finding.",
23
24
  });
24
25
  /**
25
26
  * AD-19's four transport channels. `call-inputs` alone has no declared
@@ -31,11 +32,37 @@ export const TransportChannel = z.enum(TRANSPORT_CHANNELS).meta({
31
32
  id: 'TransportChannel',
32
33
  description: "AD-19's four transport channels. They are the segment `call-inputs` takes before its tail, and the four keys an observation's recorded call inputs are keyed by.",
33
34
  });
34
- // The three-way partition (tail-bearing, scalar, transport-rooted) is spelled
35
- // out and typed against the enum rather than rebuilt from it, so a typo fails
36
- // the typecheck; a test asserts it stays disjoint and exhaustive. A status or
37
- // exit code is scalar, so a pointer into one is a syntax error rather than an
38
- // unreachable-evidence finding.
35
+ /**
36
+ * The four channels a command-kind operation accepts input on. They sit beside
37
+ * the transport channels because this module owns channel vocabulary, and the
38
+ * request shape that declares them has to name them without forward-declaring
39
+ * a tuple it does not own.
40
+ *
41
+ * `stdin` is the command analogue of `body` and inherits its asymmetry: a
42
+ * request shape declares it as a key map, while one witness leg supplies it as
43
+ * a tagged body value.
44
+ */
45
+ export const COMMAND_CHANNELS = [
46
+ 'argument',
47
+ 'option',
48
+ 'environment',
49
+ 'stdin',
50
+ ];
51
+ /**
52
+ * Every channel `call-inputs` may take as its next segment, both kinds
53
+ * together. A pointer is parsed with no contract in hand, so the grammar
54
+ * admits all eight and the question of which four a given operation may use is
55
+ * answered by reachability, which has the operation.
56
+ */
57
+ export const INPUT_CHANNELS = [
58
+ ...TRANSPORT_CHANNELS,
59
+ ...COMMAND_CHANNELS,
60
+ ];
61
+ // The four-way partition (tail-bearing, scalar, transport-rooted,
62
+ // identifier-rooted) is spelled out and typed against the enum rather than
63
+ // rebuilt from it, so a typo fails the typecheck; a test asserts it stays
64
+ // disjoint and exhaustive. A status or exit code is scalar, so a pointer into
65
+ // one is a syntax error rather than an unreachable-evidence finding.
39
66
  export const TAIL_BEARING_CHANNELS = [
40
67
  'response-body',
41
68
  'response-headers',
@@ -47,13 +74,67 @@ export const SCALAR_CHANNELS = [
47
74
  'exit-code',
48
75
  ];
49
76
  export const TRANSPORT_ROOTED_CHANNEL = 'call-inputs';
77
+ // A fourth class rather than a fourth rule. AD-26's repair for `call-inputs`
78
+ // is that "a channel that names one of several things needs a declared segment
79
+ // to resolve against", and a written file is the same situation: an operation
80
+ // may write several, so the pointer names which one before its tail. The only
81
+ // difference from `call-inputs` is that the segment is an open identifier
82
+ // rather than a closed enum, because the artifact names are the contract
83
+ // author's own. What the segment resolves against is the operation's declared
84
+ // `artifacts` list, and a name absent from it is `unresolved-artifact-reference`
85
+ // rather than evidence that resolves absent.
86
+ export const IDENTIFIER_ROOTED_CHANNEL = 'artifact';
87
+ /**
88
+ * The response-side channels each kind produces, and neither produces the
89
+ * other's. Declared here rather than rebuilt from a description, so a channel
90
+ * added to the vocabulary has to be assigned to a side and a test can assert
91
+ * the two partition the response side exactly.
92
+ *
93
+ * `call-inputs` belongs to neither: it carries what was sent rather than what
94
+ * came back, and both kinds have it.
95
+ */
96
+ export const API_RESPONSE_CHANNELS = [
97
+ 'response-body',
98
+ 'response-headers',
99
+ 'response-status',
100
+ ];
101
+ export const COMMAND_RESPONSE_CHANNELS = [
102
+ 'stdout',
103
+ 'stderr',
104
+ 'exit-code',
105
+ 'artifact',
106
+ ];
107
+ /**
108
+ * Every channel but the identifier-rooted one, in the vocabulary's own order.
109
+ *
110
+ * Spelled out and typed against the enum rather than filtered from it: a filter
111
+ * widens to `EvidenceChannelName[]` and `z.enum` needs a tuple, and the whole
112
+ * point of the list is that adding a ninth channel has to be a decision about
113
+ * which side of this line it falls on rather than something a filter absorbs.
114
+ * `tests/schemas/pointer.test.ts` asserts it partitions the vocabulary with
115
+ * `IDENTIFIER_ROOTED_CHANNEL` exactly.
116
+ */
117
+ export const NON_IDENTIFIER_ROOTED_CHANNELS = [
118
+ 'response-body',
119
+ 'response-headers',
120
+ 'response-status',
121
+ 'call-inputs',
122
+ 'stdout',
123
+ 'stderr',
124
+ 'exit-code',
125
+ ];
126
+ /** Every channel that carries what came back, whichever kind produced it. */
127
+ export const RESPONSE_SIDE_CHANNELS = [
128
+ ...API_RESPONSE_CHANNELS,
129
+ ...COMMAND_RESPONSE_CHANNELS,
130
+ ];
50
131
  // An RFC 6901 reference token: any character but "/" and "~", plus the two
51
132
  // escapes. A token may be empty, which is RFC 6901's spelling for a key that is
52
133
  // the empty string.
53
134
  const TOKEN = '(?:[^/~]|~[01])*';
54
135
  const TAIL = `(?:/${TOKEN})*`;
55
136
  const alternation = (members) => members.join('|');
56
- export const INTERACTION_POINTER_PATTERN = new RegExp(`^/interactions/${IDENTIFIER_CHARSET_SOURCE}/(?:(?:${alternation(TAIL_BEARING_CHANNELS)})${TAIL}|(?:${alternation(SCALAR_CHANNELS)})|${TRANSPORT_ROOTED_CHANNEL}/(?:${alternation(TRANSPORT_CHANNELS)})${TAIL})$`);
137
+ export const INTERACTION_POINTER_PATTERN = new RegExp(`^/interactions/${IDENTIFIER_CHARSET_SOURCE}/(?:(?:${alternation(TAIL_BEARING_CHANNELS)})${TAIL}|(?:${alternation(SCALAR_CHANNELS)})|${TRANSPORT_ROOTED_CHANNEL}/(?:${alternation(INPUT_CHANNELS)})${TAIL}|${IDENTIFIER_ROOTED_CHANNEL}/${IDENTIFIER_CHARSET_SOURCE}${TAIL})$`);
57
138
  export const BOUND_ELEMENT_POINTER_PATTERN = new RegExp(`^@(?:/${TOKEN})+$`);
58
139
  export const DESCRIPTOR_POINTER_PATTERN = new RegExp(`^(?:/${TOKEN})*$`);
59
140
  /**
@@ -63,7 +144,7 @@ export const DESCRIPTOR_POINTER_PATTERN = new RegExp(`^(?:/${TOKEN})*$`);
63
144
  export const InteractionPointer = z
64
145
  .string()
65
146
  .regex(INTERACTION_POINTER_PATTERN)
66
- .describe('AD-26 interaction-rooted pointer: "/interactions/{stepId}/" followed by one channel of the closed vocabulary. `call-inputs` takes one of the four transport channels as its next segment; `response-status` and `exit-code` take no tail. Syntax only: whether the step exists and whether the evidence is reachable are compile-time checks, not schema checks.');
147
+ .describe('AD-26 interaction-rooted pointer: "/interactions/{stepId}/" followed by one channel of the closed vocabulary. `call-inputs` takes one input channel as its next segment, one of the four transport channels or one of the four command channels; `artifact` takes the identifier of a file the operation declares it writes; `response-status` and `exit-code` take no tail. Syntax only: whether the step exists and whether the evidence is reachable are compile-time checks, not schema checks.');
67
148
  /**
68
149
  * Spelling 2, bound-element relative. Consumer: a `{ pointer }` operand inside
69
150
  * a quantifier predicate. Never an evidence target, because AD-3 computes
@@ -29,19 +29,16 @@ export declare const FileWriteResponse: z.ZodObject<{
29
29
  byteLength: z.ZodInt;
30
30
  }, z.core.$strict>;
31
31
  /**
32
- * AD-35: the request names a logical interface identifier and never a URL,
33
- * host, or port. Mapping the identifier to an authorized target is the
34
- * adapter's, from configuration outside the contract.
35
- *
36
- * No credential appears here. AD-18 forbids a credential value in a
37
- * declaration, and the values that reach this shape come from a declaration;
38
- * authorization material is the adapter's, supplied by the same mapping that
39
- * authorizes the target.
32
+ * A request to an interface that speaks HTTP. Tagged on `kind` so an adapter
33
+ * knows what it is being asked to do before it reads anything else, and so the
34
+ * two shapes cannot be confused for one another by a field that happens to be
35
+ * absent.
40
36
  */
41
- export declare const ProbeRequest: z.ZodObject<{
37
+ export declare const ApiProbeRequest: z.ZodObject<{
42
38
  probeId: z.ZodString;
43
39
  interfaceId: z.ZodString;
44
40
  operationId: z.ZodString;
41
+ kind: z.ZodLiteral<"api">;
45
42
  method: z.ZodEnum<{
46
43
  DELETE: "DELETE";
47
44
  GET: "GET";
@@ -64,6 +61,90 @@ export declare const ProbeRequest: z.ZodObject<{
64
61
  }, z.core.$strict>], "kind">;
65
62
  }, z.core.$strict>;
66
63
  }, z.core.$strict>;
64
+ /**
65
+ * A request to run a command.
66
+ *
67
+ * AD-35's rule is that a contract names a logical identifier and the caller
68
+ * maps it, and the analogue for a command is exactly the same shape: the
69
+ * `executable` is the logical name the contract declared, and the adapter maps
70
+ * it to something runnable from configuration outside the contract. No
71
+ * filesystem path, no interpreter, no shell string. The adapter builds the
72
+ * argument vector; it is never handed one to execute.
73
+ *
74
+ * `environment` is string-valued for the reason `header` is, and carries no
75
+ * credential for the reason AD-18 gives: authorization material is the
76
+ * adapter's, supplied by the same mapping that authorizes the target.
77
+ */
78
+ export declare const CommandProbeRequest: z.ZodObject<{
79
+ probeId: z.ZodString;
80
+ interfaceId: z.ZodString;
81
+ operationId: z.ZodString;
82
+ kind: z.ZodLiteral<"cli">;
83
+ executable: z.ZodString;
84
+ subcommandPath: z.ZodArray<z.ZodString>;
85
+ channels: z.ZodObject<{
86
+ argument: z.ZodRecord<z.ZodString, z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>;
87
+ option: z.ZodRecord<z.ZodString, z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>;
88
+ environment: z.ZodRecord<z.ZodString, z.ZodString>;
89
+ stdin: z.ZodDiscriminatedUnion<[z.ZodObject<{
90
+ kind: z.ZodLiteral<"json">;
91
+ value: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
92
+ }, z.core.$strict>, z.ZodObject<{
93
+ kind: z.ZodLiteral<"text">;
94
+ value: z.ZodString;
95
+ }, z.core.$strict>, z.ZodObject<{
96
+ kind: z.ZodLiteral<"absent">;
97
+ }, z.core.$strict>], "kind">;
98
+ }, z.core.$strict>;
99
+ }, z.core.$strict>;
100
+ export declare const ProbeRequest: z.ZodDiscriminatedUnion<[z.ZodObject<{
101
+ probeId: z.ZodString;
102
+ interfaceId: z.ZodString;
103
+ operationId: z.ZodString;
104
+ kind: z.ZodLiteral<"api">;
105
+ method: z.ZodEnum<{
106
+ DELETE: "DELETE";
107
+ GET: "GET";
108
+ HEAD: "HEAD";
109
+ OPTIONS: "OPTIONS";
110
+ PATCH: "PATCH";
111
+ POST: "POST";
112
+ PUT: "PUT";
113
+ }>;
114
+ pathTemplate: z.ZodString;
115
+ channels: z.ZodObject<{
116
+ path: z.ZodRecord<z.ZodString, z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>;
117
+ query: z.ZodRecord<z.ZodString, z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>;
118
+ header: z.ZodRecord<z.ZodString, z.ZodString>;
119
+ body: z.ZodDiscriminatedUnion<[z.ZodObject<{
120
+ kind: z.ZodLiteral<"json">;
121
+ value: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
122
+ }, z.core.$strict>, z.ZodObject<{
123
+ kind: z.ZodLiteral<"absent">;
124
+ }, z.core.$strict>], "kind">;
125
+ }, z.core.$strict>;
126
+ }, z.core.$strict>, z.ZodObject<{
127
+ probeId: z.ZodString;
128
+ interfaceId: z.ZodString;
129
+ operationId: z.ZodString;
130
+ kind: z.ZodLiteral<"cli">;
131
+ executable: z.ZodString;
132
+ subcommandPath: z.ZodArray<z.ZodString>;
133
+ channels: z.ZodObject<{
134
+ argument: z.ZodRecord<z.ZodString, z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>;
135
+ option: z.ZodRecord<z.ZodString, z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>>;
136
+ environment: z.ZodRecord<z.ZodString, z.ZodString>;
137
+ stdin: z.ZodDiscriminatedUnion<[z.ZodObject<{
138
+ kind: z.ZodLiteral<"json">;
139
+ value: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
140
+ }, z.core.$strict>, z.ZodObject<{
141
+ kind: z.ZodLiteral<"text">;
142
+ value: z.ZodString;
143
+ }, z.core.$strict>, z.ZodObject<{
144
+ kind: z.ZodLiteral<"absent">;
145
+ }, z.core.$strict>], "kind">;
146
+ }, z.core.$strict>;
147
+ }, z.core.$strict>], "kind">;
67
148
  /**
68
149
  * What the adapter observed. Deliberately response content only: no elapsed
69
150
  * time, no redirect count, no retry count. AD-35's caps are safety limits, so
@@ -75,10 +156,11 @@ export declare const ProbeRequest: z.ZodObject<{
75
156
  * policy denial, a cap, an abort, or a transport failure throws; a 500 is the
76
157
  * payload AD-10's seeded-fault check reads, never an error.
77
158
  */
78
- export declare const ProbeObservation: z.ZodObject<{
159
+ export declare const ApiProbeObservation: z.ZodObject<{
79
160
  probeId: z.ZodString;
80
161
  interfaceId: z.ZodString;
81
162
  operationId: z.ZodString;
163
+ kind: z.ZodLiteral<"api">;
82
164
  status: z.ZodInt;
83
165
  headers: z.ZodRecord<z.ZodString, z.ZodString>;
84
166
  body: z.ZodDiscriminatedUnion<[z.ZodObject<{
@@ -91,6 +173,104 @@ export declare const ProbeObservation: z.ZodObject<{
91
173
  kind: z.ZodLiteral<"absent">;
92
174
  }, z.core.$strict>], "kind">;
93
175
  }, z.core.$strict>;
176
+ /**
177
+ * What the adapter observed of a command run: its two streams, its exit code,
178
+ * and the files it wrote.
179
+ *
180
+ * `exitCode` is signed, unlike an HTTP status, because a process terminated by
181
+ * a signal is conventionally reported as a negative code and this field records
182
+ * what happened rather than what is tidy. A non-zero exit is an observation
183
+ * exactly as a 500 is: only a policy denial, a cap, an abort, or a failure to
184
+ * start the process throws.
185
+ *
186
+ * `artifacts` is keyed by the identifier the operation declared, not by a
187
+ * filesystem path. Which path each identifier names is the adapter's mapping,
188
+ * the same disclosure boundary AD-35 draws around the executable itself.
189
+ */
190
+ export declare const CommandProbeObservation: z.ZodObject<{
191
+ probeId: z.ZodString;
192
+ interfaceId: z.ZodString;
193
+ operationId: z.ZodString;
194
+ kind: z.ZodLiteral<"cli">;
195
+ exitCode: z.ZodInt;
196
+ stdout: z.ZodDiscriminatedUnion<[z.ZodObject<{
197
+ kind: z.ZodLiteral<"json">;
198
+ value: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
199
+ }, z.core.$strict>, z.ZodObject<{
200
+ kind: z.ZodLiteral<"text">;
201
+ value: z.ZodString;
202
+ }, z.core.$strict>, z.ZodObject<{
203
+ kind: z.ZodLiteral<"absent">;
204
+ }, z.core.$strict>], "kind">;
205
+ stderr: z.ZodDiscriminatedUnion<[z.ZodObject<{
206
+ kind: z.ZodLiteral<"json">;
207
+ value: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
208
+ }, z.core.$strict>, z.ZodObject<{
209
+ kind: z.ZodLiteral<"text">;
210
+ value: z.ZodString;
211
+ }, z.core.$strict>, z.ZodObject<{
212
+ kind: z.ZodLiteral<"absent">;
213
+ }, z.core.$strict>], "kind">;
214
+ artifacts: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
215
+ kind: z.ZodLiteral<"json">;
216
+ value: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
217
+ }, z.core.$strict>, z.ZodObject<{
218
+ kind: z.ZodLiteral<"text">;
219
+ value: z.ZodString;
220
+ }, z.core.$strict>, z.ZodObject<{
221
+ kind: z.ZodLiteral<"absent">;
222
+ }, z.core.$strict>], "kind">>;
223
+ }, z.core.$strict>;
224
+ export declare const ProbeObservation: z.ZodDiscriminatedUnion<[z.ZodObject<{
225
+ probeId: z.ZodString;
226
+ interfaceId: z.ZodString;
227
+ operationId: z.ZodString;
228
+ kind: z.ZodLiteral<"api">;
229
+ status: z.ZodInt;
230
+ headers: z.ZodRecord<z.ZodString, z.ZodString>;
231
+ body: z.ZodDiscriminatedUnion<[z.ZodObject<{
232
+ kind: z.ZodLiteral<"json">;
233
+ value: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
234
+ }, z.core.$strict>, z.ZodObject<{
235
+ kind: z.ZodLiteral<"text">;
236
+ value: z.ZodString;
237
+ }, z.core.$strict>, z.ZodObject<{
238
+ kind: z.ZodLiteral<"absent">;
239
+ }, z.core.$strict>], "kind">;
240
+ }, z.core.$strict>, z.ZodObject<{
241
+ probeId: z.ZodString;
242
+ interfaceId: z.ZodString;
243
+ operationId: z.ZodString;
244
+ kind: z.ZodLiteral<"cli">;
245
+ exitCode: z.ZodInt;
246
+ stdout: z.ZodDiscriminatedUnion<[z.ZodObject<{
247
+ kind: z.ZodLiteral<"json">;
248
+ value: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
249
+ }, z.core.$strict>, z.ZodObject<{
250
+ kind: z.ZodLiteral<"text">;
251
+ value: z.ZodString;
252
+ }, z.core.$strict>, z.ZodObject<{
253
+ kind: z.ZodLiteral<"absent">;
254
+ }, z.core.$strict>], "kind">;
255
+ stderr: z.ZodDiscriminatedUnion<[z.ZodObject<{
256
+ kind: z.ZodLiteral<"json">;
257
+ value: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
258
+ }, z.core.$strict>, z.ZodObject<{
259
+ kind: z.ZodLiteral<"text">;
260
+ value: z.ZodString;
261
+ }, z.core.$strict>, z.ZodObject<{
262
+ kind: z.ZodLiteral<"absent">;
263
+ }, z.core.$strict>], "kind">;
264
+ artifacts: z.ZodRecord<z.ZodString, z.ZodDiscriminatedUnion<[z.ZodObject<{
265
+ kind: z.ZodLiteral<"json">;
266
+ value: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
267
+ }, z.core.$strict>, z.ZodObject<{
268
+ kind: z.ZodLiteral<"text">;
269
+ value: z.ZodString;
270
+ }, z.core.$strict>, z.ZodObject<{
271
+ kind: z.ZodLiteral<"absent">;
272
+ }, z.core.$strict>], "kind">>;
273
+ }, z.core.$strict>], "kind">;
94
274
  export type CorpusResolveRequest = z.infer<typeof CorpusResolveRequest>;
95
275
  export type CorpusResolveResponse = z.infer<typeof CorpusResolveResponse>;
96
276
  export type ClockReadRequest = z.infer<typeof ClockReadRequest>;
@@ -99,5 +279,9 @@ export type FileReadRequest = z.infer<typeof FileReadRequest>;
99
279
  export type FileReadResponse = z.infer<typeof FileReadResponse>;
100
280
  export type FileWriteRequest = z.infer<typeof FileWriteRequest>;
101
281
  export type FileWriteResponse = z.infer<typeof FileWriteResponse>;
282
+ export type ApiProbeRequest = z.infer<typeof ApiProbeRequest>;
283
+ export type CommandProbeRequest = z.infer<typeof CommandProbeRequest>;
102
284
  export type ProbeRequest = z.infer<typeof ProbeRequest>;
285
+ export type ApiProbeObservation = z.infer<typeof ApiProbeObservation>;
286
+ export type CommandProbeObservation = z.infer<typeof CommandProbeObservation>;
103
287
  export type ProbeObservation = z.infer<typeof ProbeObservation>;