eval-quality 0.1.0 → 0.2.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.
- package/README.md +142 -67
- package/corpus/dev/README.md +17 -11
- package/corpus/dev/compile-seal-example/brief.json +1 -1
- package/corpus/dev/compile-seal-example/contract.json +1 -1
- package/corpus/dev/contracts/absent-collection-locations.json +1 -1
- package/corpus/dev/contracts/absent-sibling-groups.json +1 -1
- package/corpus/dev/contracts/absent-success-indicator.json +1 -1
- package/corpus/dev/contracts/empty-channel-roles.json +1 -1
- package/corpus/dev/contracts/empty-collection-locations.json +1 -1
- package/corpus/dev/contracts/empty-request-shapes.json +1 -1
- package/corpus/dev/contracts/empty-sibling-groups.json +1 -1
- package/corpus/dev/contracts/no-collection-quantifier.json +1 -1
- package/corpus/dev/contracts/no-operation-inventory.json +1 -1
- package/corpus/dev/contracts/no-read-back-relation.json +1 -1
- package/corpus/dev/contracts/no-state-change-marker.json +1 -1
- package/corpus/dev/contracts/no-type-violating-step.json +1 -1
- package/corpus/dev/contracts/per-key-split-oracles.json +1 -1
- package/corpus/dev/contracts/satisfied-declarations.json +1 -1
- package/corpus/dev/contracts/single-required-response-key.json +1 -1
- package/corpus/dev/contracts/split-indicator-oracle.json +1 -1
- package/corpus/dev/contracts/unaddressed-parameter-sibling.json +1 -1
- package/corpus/dev/contracts/unnamed-reference-set.json +1 -1
- package/corpus/dev/contracts/wrong-cardinality-form.json +1 -1
- package/corpus/dev/index.json +1 -1
- package/dist/application/index.d.ts +2 -0
- package/dist/application/index.js +1 -0
- package/dist/application/score.d.ts +48 -0
- package/dist/application/score.js +186 -0
- package/dist/cli/arguments.d.ts +7 -3
- package/dist/cli/arguments.js +73 -5
- package/dist/cli/exit-codes.d.ts +6 -2
- package/dist/cli/exit-codes.js +8 -9
- package/dist/cli/main.js +9 -0
- package/dist/cli/render.d.ts +1 -1
- package/dist/cli/render.js +6 -4
- package/dist/cli/run.d.ts +13 -3
- package/dist/cli/run.js +136 -16
- package/dist/core/canonical/canonicalize.d.ts +12 -0
- package/dist/core/canonical/canonicalize.js +18 -4
- package/dist/core/compile/bindings.d.ts +70 -0
- package/dist/core/compile/bindings.js +317 -0
- package/dist/core/compile/compile.d.ts +5 -0
- package/dist/core/compile/compile.js +9 -0
- package/dist/core/compile/expression-legality.d.ts +49 -0
- package/dist/core/compile/expression-legality.js +105 -31
- package/dist/core/compile/forbidden-inputs.d.ts +8 -1
- package/dist/core/compile/forbidden-inputs.js +16 -3
- package/dist/core/compile/interface-inventory.d.ts +23 -1
- package/dist/core/compile/interface-inventory.js +32 -3
- package/dist/core/compile/reachability.d.ts +18 -1
- package/dist/core/compile/reachability.js +46 -1
- package/dist/core/compile/sensitivity-witness.d.ts +1 -1
- package/dist/core/compile/sensitivity-witness.js +1 -1
- package/dist/core/emit/emit.d.ts +9 -0
- package/dist/core/emit/emit.js +214 -0
- package/dist/core/emit/private-artifact-digest.d.ts +11 -0
- package/dist/core/emit/private-artifact-digest.js +31 -0
- package/dist/core/evaluate/evidence-resolution.d.ts +11 -1
- package/dist/core/evaluate/evidence-resolution.js +4 -1
- package/dist/core/failure-codes.d.ts +2 -2
- package/dist/core/failure-codes.js +4 -2
- package/dist/core/ingest/conditions.d.ts +201 -0
- package/dist/core/ingest/conditions.js +48 -0
- package/dist/core/ingest/index.d.ts +13 -0
- package/dist/core/ingest/index.js +11 -0
- package/dist/core/ingest/ingest.d.ts +68 -0
- package/dist/core/ingest/ingest.js +310 -0
- package/dist/core/lineage/stage-table.d.ts +21 -4
- package/dist/core/lineage/stage-table.js +35 -3
- package/dist/core/preflight/witness-evidence.js +10 -0
- package/dist/core/schemas/artifact.d.ts +385 -14
- package/dist/core/schemas/constraint-ledger.js +40 -0
- package/dist/core/schemas/defect-signature.d.ts +273 -0
- package/dist/core/schemas/defect-signature.js +127 -0
- package/dist/core/schemas/eval-contract.d.ts +33 -0
- package/dist/core/schemas/eval-contract.js +14 -0
- package/dist/core/schemas/evidence-artifact.d.ts +99 -19
- package/dist/core/schemas/evidence-artifact.js +64 -8
- package/dist/core/schemas/plan.d.ts +112 -0
- package/dist/core/schemas/plan.js +67 -2
- package/dist/core/schemas/probe-qualification.d.ts +168 -0
- package/dist/core/schemas/probe-qualification.js +106 -0
- package/dist/core/schemas/probe.d.ts +312 -0
- package/dist/core/schemas/probe.js +6 -2
- package/dist/core/schemas/scoring-policy.d.ts +1 -0
- package/dist/core/schemas/scoring-policy.js +6 -1
- package/dist/core/schemas/sealed-evaluator-brief.d.ts +1 -0
- package/dist/core/schemas/sealed-evaluator-brief.js +4 -1
- package/dist/core/schemas/sealed-run-record.d.ts +30 -3
- package/dist/core/schemas/sealed-run-record.js +37 -5
- package/dist/core/score/binding-order.d.ts +31 -0
- package/dist/core/score/binding-order.js +88 -0
- package/dist/core/score/bindings.d.ts +93 -0
- package/dist/core/score/bindings.js +297 -0
- package/dist/core/score/ladder-table.d.ts +23 -0
- package/dist/core/score/ladder-table.js +109 -0
- package/dist/core/score/ladder.d.ts +229 -0
- package/dist/core/score/ladder.js +464 -0
- package/dist/core/score/mode-agreement.d.ts +30 -0
- package/dist/core/score/mode-agreement.js +16 -0
- package/dist/core/score/outcome-table.d.ts +17 -0
- package/dist/core/score/outcome-table.js +172 -0
- package/dist/core/score/outcome.d.ts +466 -0
- package/dist/core/score/outcome.js +562 -0
- package/dist/core/score/qualification.d.ts +83 -0
- package/dist/core/score/qualification.js +615 -0
- package/dist/core/score/quotation.d.ts +79 -0
- package/dist/core/score/quotation.js +201 -0
- package/dist/core/score/reduce-trials.d.ts +80 -0
- package/dist/core/score/reduce-trials.js +90 -0
- package/dist/core/score/score.d.ts +72 -0
- package/dist/core/score/score.js +581 -0
- package/dist/core/score/selection.d.ts +80 -0
- package/dist/core/score/selection.js +98 -0
- package/dist/core/score/strength.d.ts +49 -0
- package/dist/core/score/strength.js +193 -0
- package/dist/core/score/witness.d.ts +117 -0
- package/dist/core/score/witness.js +315 -0
- package/dist/core/seal/derived-reference.d.ts +1 -1
- package/dist/core/seal/derived-reference.js +236 -28
- package/dist/core/seal/seal.js +8 -3
- package/dist/core/stage-contracts.d.ts +62 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/testing/index.d.ts +2 -0
- package/dist/testing/index.js +1 -0
- package/package.json +12 -3
- package/schemas/eval-contract.schema.json +100 -2
- package/schemas/evidence-artifact.schema.json +96 -9
- package/schemas/probe.schema.json +508 -3
- package/schemas/scoring-policy.schema.json +8 -1
- package/schemas/sealed-evaluator-brief.schema.json +11 -1
- package/schemas/sealed-run-record.schema.json +19 -2
|
@@ -43,19 +43,22 @@ export type CheckResolutionValue = {
|
|
|
43
43
|
*/
|
|
44
44
|
export declare const CheckResolution: z.ZodType<CheckResolutionValue>;
|
|
45
45
|
/**
|
|
46
|
-
* AD-11's
|
|
47
|
-
*
|
|
48
|
-
*
|
|
46
|
+
* AD-11's identity inputs, transcribed so a reader can recompute the digest
|
|
47
|
+
* and see what was compared (AD-8's "by digest and opaque reference, never
|
|
48
|
+
* by content or path"). Named object rather than a concatenated tuple:
|
|
49
49
|
* revision 1 let two conforming scorers compute different versions from
|
|
50
50
|
* identical inputs if they hashed a different ordering. The scorer computes
|
|
51
|
-
* the scoring version over this shape.
|
|
51
|
+
* the scoring version over this shape. Six now, not five: `mode` is owed
|
|
52
|
+
* item 4's identity clause, superseding AD-11's original five-field
|
|
53
|
+
* sentence.
|
|
52
54
|
*/
|
|
53
|
-
export declare const SCORING_VERSION_INPUT_NAMES: readonly ['contractSchemaVersion', 'corpusDigest', 'fixtureDigest', 'evaluatorConfigurationDigest', 'scoringPolicyDigest'];
|
|
55
|
+
export declare const SCORING_VERSION_INPUT_NAMES: readonly ['contractSchemaVersion', 'corpusDigest', 'fixtureDigest', 'evaluatorConfigurationDigest', 'scoringPolicyDigest', 'mode'];
|
|
54
56
|
export declare const ScoringVersionInputName: z.ZodEnum<{
|
|
55
57
|
contractSchemaVersion: "contractSchemaVersion";
|
|
56
58
|
corpusDigest: "corpusDigest";
|
|
57
59
|
evaluatorConfigurationDigest: "evaluatorConfigurationDigest";
|
|
58
60
|
fixtureDigest: "fixtureDigest";
|
|
61
|
+
mode: "mode";
|
|
59
62
|
scoringPolicyDigest: "scoringPolicyDigest";
|
|
60
63
|
}>;
|
|
61
64
|
export declare const ScoringVersionInputs: z.ZodObject<{
|
|
@@ -64,11 +67,17 @@ export declare const ScoringVersionInputs: z.ZodObject<{
|
|
|
64
67
|
fixtureDigest: z.ZodString;
|
|
65
68
|
evaluatorConfigurationDigest: z.ZodString;
|
|
66
69
|
scoringPolicyDigest: z.ZodString;
|
|
70
|
+
mode: z.ZodEnum<{
|
|
71
|
+
"contract-scoring": "contract-scoring";
|
|
72
|
+
production: "production";
|
|
73
|
+
}>;
|
|
67
74
|
}, z.core.$strict>;
|
|
68
75
|
export declare const InvalidatedAttempt: z.ZodObject<{
|
|
69
76
|
attempt: z.ZodInt;
|
|
70
77
|
reason: z.ZodString;
|
|
71
78
|
}, z.core.$strict>;
|
|
79
|
+
/** exported so the trial-set reducer names this shape without importing Zod. */
|
|
80
|
+
export type InvalidatedAttempt = z.infer<typeof InvalidatedAttempt>;
|
|
72
81
|
/**
|
|
73
82
|
* AD-6: "Every artifact records its trial count, its invalidated attempts, and
|
|
74
83
|
* each attempt's reason, including on a PASS." None of the three is nullable,
|
|
@@ -83,6 +92,8 @@ export declare const Trials: z.ZodObject<{
|
|
|
83
92
|
reason: z.ZodString;
|
|
84
93
|
}, z.core.$strict>>;
|
|
85
94
|
}, z.core.$strict>;
|
|
95
|
+
/** exported so the ladder names this shape without importing Zod. */
|
|
96
|
+
export type Trials = z.infer<typeof Trials>;
|
|
86
97
|
export declare const Outcome: z.ZodObject<{
|
|
87
98
|
oracleId: z.ZodString;
|
|
88
99
|
probeId: z.ZodNullable<z.ZodString>;
|
|
@@ -119,6 +130,8 @@ export declare const Outcome: z.ZodObject<{
|
|
|
119
130
|
selectedObservationIds: z.ZodArray<z.ZodString>;
|
|
120
131
|
checkResolution: z.ZodNullable<z.ZodType<CheckResolutionValue, unknown, z.core.$ZodTypeInternals<CheckResolutionValue, unknown>>>;
|
|
121
132
|
}, z.core.$strict>;
|
|
133
|
+
/** exported so the dominance comparator names this shape without importing Zod. */
|
|
134
|
+
export type Outcome = z.infer<typeof Outcome>;
|
|
122
135
|
export declare const CoverageGap: z.ZodObject<{
|
|
123
136
|
rule: z.ZodString;
|
|
124
137
|
relevancePredicate: z.ZodString;
|
|
@@ -132,11 +145,49 @@ export declare const CoverageGap: z.ZodObject<{
|
|
|
132
145
|
}, z.core.$strict>;
|
|
133
146
|
/** the record as a type, so `core/coverage/` names it without importing Zod. */
|
|
134
147
|
export type CoverageGap = z.infer<typeof CoverageGap>;
|
|
148
|
+
/**
|
|
149
|
+
* Owed item 5's record for an ingested `defect` finding citing no oracle:
|
|
150
|
+
* AD-23 already retains the finding rather than discarding it, but nothing
|
|
151
|
+
* downstream consumed it until this `schemaVersion`. Mirrors `CoverageGap`'s
|
|
152
|
+
* shape and the `defect`-branch fields on `Finding` it is read from, but
|
|
153
|
+
* carries no relevance or satisfaction predicate: AD-31's coverage gap is a
|
|
154
|
+
* declaration AD-31 could not confirm was satisfied, while an uncited defect
|
|
155
|
+
* finding is a runtime observation an evaluator made outside every declared
|
|
156
|
+
* oracle, with no relevance predicate to name and no satisfaction predicate
|
|
157
|
+
* that failed. This is the version-3 bump: required, not optional, per owed
|
|
158
|
+
* item 5, so a producer that never emits it stops parsing rather than
|
|
159
|
+
* silently under-reporting the gap.
|
|
160
|
+
*/
|
|
161
|
+
export declare const UncitedFindingGap: z.ZodObject<{
|
|
162
|
+
findingId: z.ZodString;
|
|
163
|
+
observationIds: z.ZodArray<z.ZodString>;
|
|
164
|
+
quotedEvidence: z.ZodArray<z.ZodObject<{
|
|
165
|
+
quote: z.ZodString;
|
|
166
|
+
channel: z.ZodEnum<{
|
|
167
|
+
"call-inputs": "call-inputs";
|
|
168
|
+
"exit-code": "exit-code";
|
|
169
|
+
"response-body": "response-body";
|
|
170
|
+
"response-headers": "response-headers";
|
|
171
|
+
"response-status": "response-status";
|
|
172
|
+
stderr: "stderr";
|
|
173
|
+
stdout: "stdout";
|
|
174
|
+
}>;
|
|
175
|
+
}, z.core.$strict>>;
|
|
176
|
+
severity: z.ZodEnum<{
|
|
177
|
+
critical: "critical";
|
|
178
|
+
low: "low";
|
|
179
|
+
material: "material";
|
|
180
|
+
}>;
|
|
181
|
+
}, z.core.$strict>;
|
|
182
|
+
/** exported so `core/score/ladder.ts` names this shape without importing Zod. */
|
|
183
|
+
export type UncitedFindingGap = z.infer<typeof UncitedFindingGap>;
|
|
135
184
|
export declare const ClassStrength: z.ZodObject<{
|
|
136
185
|
caught: z.ZodInt;
|
|
137
186
|
exercised: z.ZodInt;
|
|
138
187
|
rate: z.ZodNullable<z.ZodNumber>;
|
|
139
188
|
}, z.core.$strict>;
|
|
189
|
+
/** exported so the rate-vector builder names this shape without importing Zod. */
|
|
190
|
+
export type ClassStrength = z.infer<typeof ClassStrength>;
|
|
140
191
|
/**
|
|
141
192
|
* A fixed three-key object instead of a map keyed by probe class. AD-7 is
|
|
142
193
|
* explicit that "canary probes and clean controls never enter the vector", so
|
|
@@ -159,6 +210,8 @@ export declare const StrengthVector: z.ZodObject<{
|
|
|
159
210
|
rate: z.ZodNullable<z.ZodNumber>;
|
|
160
211
|
}, z.core.$strict>>;
|
|
161
212
|
}, z.core.$strict>;
|
|
213
|
+
/** exported so the rate-vector builder names this shape without importing Zod. */
|
|
214
|
+
export type StrengthVector = z.infer<typeof StrengthVector>;
|
|
162
215
|
export declare const Strength: z.ZodObject<{
|
|
163
216
|
denominator: z.ZodString;
|
|
164
217
|
basis: z.ZodEnum<{
|
|
@@ -185,6 +238,8 @@ export declare const Strength: z.ZodObject<{
|
|
|
185
238
|
comparable: z.ZodBoolean;
|
|
186
239
|
note: z.ZodNullable<z.ZodString>;
|
|
187
240
|
}, z.core.$strict>;
|
|
241
|
+
/** exported so the dominance comparator names this shape without importing Zod. */
|
|
242
|
+
export type Strength = z.infer<typeof Strength>;
|
|
188
243
|
/**
|
|
189
244
|
* AD-12's three named checks, transcribed from the same sentence the field
|
|
190
245
|
* comes from: the package "validates a caller-presented lineage chain (length
|
|
@@ -221,13 +276,6 @@ export declare const EvidenceArtifact: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
221
276
|
revisionCount: z.ZodInt;
|
|
222
277
|
runId: z.ZodString;
|
|
223
278
|
scoringVersion: z.ZodString;
|
|
224
|
-
scoringVersionInputs: z.ZodObject<{
|
|
225
|
-
contractSchemaVersion: z.ZodInt;
|
|
226
|
-
corpusDigest: z.ZodString;
|
|
227
|
-
fixtureDigest: z.ZodString;
|
|
228
|
-
evaluatorConfigurationDigest: z.ZodString;
|
|
229
|
-
scoringPolicyDigest: z.ZodString;
|
|
230
|
-
}, z.core.$strict>;
|
|
231
279
|
comparabilityKey: z.ZodString;
|
|
232
280
|
excludedProbeIds: z.ZodArray<z.ZodString>;
|
|
233
281
|
exitCode: z.ZodInt;
|
|
@@ -237,6 +285,7 @@ export declare const EvidenceArtifact: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
237
285
|
corpusDigest: "corpusDigest";
|
|
238
286
|
evaluatorConfigurationDigest: "evaluatorConfigurationDigest";
|
|
239
287
|
fixtureDigest: "fixtureDigest";
|
|
288
|
+
mode: "mode";
|
|
240
289
|
scoringPolicyDigest: "scoringPolicyDigest";
|
|
241
290
|
}>>;
|
|
242
291
|
trials: z.ZodObject<{
|
|
@@ -331,6 +380,14 @@ export declare const EvidenceArtifact: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
331
380
|
noGap: z.ZodBoolean;
|
|
332
381
|
}, z.core.$strict>;
|
|
333
382
|
}, z.core.$strict>;
|
|
383
|
+
scoringVersionInputs: z.ZodObject<{
|
|
384
|
+
contractSchemaVersion: z.ZodInt;
|
|
385
|
+
corpusDigest: z.ZodString;
|
|
386
|
+
fixtureDigest: z.ZodString;
|
|
387
|
+
evaluatorConfigurationDigest: z.ZodString;
|
|
388
|
+
scoringPolicyDigest: z.ZodString;
|
|
389
|
+
mode: z.ZodLiteral<"production">;
|
|
390
|
+
}, z.core.$strict>;
|
|
334
391
|
mode: z.ZodLiteral<"production">;
|
|
335
392
|
productionVerdict: z.ZodEnum<{
|
|
336
393
|
CONCERNS: "CONCERNS";
|
|
@@ -344,13 +401,6 @@ export declare const EvidenceArtifact: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
344
401
|
revisionCount: z.ZodInt;
|
|
345
402
|
runId: z.ZodString;
|
|
346
403
|
scoringVersion: z.ZodString;
|
|
347
|
-
scoringVersionInputs: z.ZodObject<{
|
|
348
|
-
contractSchemaVersion: z.ZodInt;
|
|
349
|
-
corpusDigest: z.ZodString;
|
|
350
|
-
fixtureDigest: z.ZodString;
|
|
351
|
-
evaluatorConfigurationDigest: z.ZodString;
|
|
352
|
-
scoringPolicyDigest: z.ZodString;
|
|
353
|
-
}, z.core.$strict>;
|
|
354
404
|
comparabilityKey: z.ZodString;
|
|
355
405
|
excludedProbeIds: z.ZodArray<z.ZodString>;
|
|
356
406
|
exitCode: z.ZodInt;
|
|
@@ -360,6 +410,7 @@ export declare const EvidenceArtifact: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
360
410
|
corpusDigest: "corpusDigest";
|
|
361
411
|
evaluatorConfigurationDigest: "evaluatorConfigurationDigest";
|
|
362
412
|
fixtureDigest: "fixtureDigest";
|
|
413
|
+
mode: "mode";
|
|
363
414
|
scoringPolicyDigest: "scoringPolicyDigest";
|
|
364
415
|
}>>;
|
|
365
416
|
trials: z.ZodObject<{
|
|
@@ -454,6 +505,14 @@ export declare const EvidenceArtifact: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
454
505
|
noGap: z.ZodBoolean;
|
|
455
506
|
}, z.core.$strict>;
|
|
456
507
|
}, z.core.$strict>;
|
|
508
|
+
scoringVersionInputs: z.ZodObject<{
|
|
509
|
+
contractSchemaVersion: z.ZodInt;
|
|
510
|
+
corpusDigest: z.ZodString;
|
|
511
|
+
fixtureDigest: z.ZodString;
|
|
512
|
+
evaluatorConfigurationDigest: z.ZodString;
|
|
513
|
+
scoringPolicyDigest: z.ZodString;
|
|
514
|
+
mode: z.ZodLiteral<"contract-scoring">;
|
|
515
|
+
}, z.core.$strict>;
|
|
457
516
|
mode: z.ZodLiteral<"contract-scoring">;
|
|
458
517
|
contractVerdict: z.ZodEnum<{
|
|
459
518
|
CONCERNS: "CONCERNS";
|
|
@@ -461,6 +520,27 @@ export declare const EvidenceArtifact: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
461
520
|
PASS: "PASS";
|
|
462
521
|
WAIVED: "WAIVED";
|
|
463
522
|
}>;
|
|
523
|
+
uncitedFindingGaps: z.ZodArray<z.ZodObject<{
|
|
524
|
+
findingId: z.ZodString;
|
|
525
|
+
observationIds: z.ZodArray<z.ZodString>;
|
|
526
|
+
quotedEvidence: z.ZodArray<z.ZodObject<{
|
|
527
|
+
quote: z.ZodString;
|
|
528
|
+
channel: z.ZodEnum<{
|
|
529
|
+
"call-inputs": "call-inputs";
|
|
530
|
+
"exit-code": "exit-code";
|
|
531
|
+
"response-body": "response-body";
|
|
532
|
+
"response-headers": "response-headers";
|
|
533
|
+
"response-status": "response-status";
|
|
534
|
+
stderr: "stderr";
|
|
535
|
+
stdout: "stdout";
|
|
536
|
+
}>;
|
|
537
|
+
}, z.core.$strict>>;
|
|
538
|
+
severity: z.ZodEnum<{
|
|
539
|
+
critical: "critical";
|
|
540
|
+
low: "low";
|
|
541
|
+
material: "material";
|
|
542
|
+
}>;
|
|
543
|
+
}, z.core.$strict>>;
|
|
464
544
|
systemRecommendationRecorded: z.ZodEnum<{
|
|
465
545
|
CONCERNS: "CONCERNS";
|
|
466
546
|
FAIL: "FAIL";
|
|
@@ -3,7 +3,7 @@ import { z } from 'zod';
|
|
|
3
3
|
import { Severity } from './eval-contract.js';
|
|
4
4
|
import { lineageFields } from './lineage.js';
|
|
5
5
|
import { Digest, FindingId, Identifier, OracleId, ProbeId, } from './primitives.js';
|
|
6
|
-
import { OracleDispositionValue } from './sealed-run-record.js';
|
|
6
|
+
import { OracleDispositionValue, QuotedEvidence, RunMode, } from './sealed-run-record.js';
|
|
7
7
|
import { EvaluatorRecommendation, Verdict } from './verdict.js';
|
|
8
8
|
/**
|
|
9
9
|
* AD-6's closed twelve. Exported so a later reader can walk the list
|
|
@@ -52,12 +52,14 @@ export const CheckResolution = z
|
|
|
52
52
|
description: "One node of an oracle's `check` tree as it resolved. AD-4's resolution is three-valued rather than two, and the introduction vocabulary has exactly one member because AD-4 closes the introduction set at one: an empty collection. `null` where the resolution is not `insufficient-evidence`. A leaf carries an empty `children` array.",
|
|
53
53
|
});
|
|
54
54
|
/**
|
|
55
|
-
* AD-11's
|
|
56
|
-
*
|
|
57
|
-
*
|
|
55
|
+
* AD-11's identity inputs, transcribed so a reader can recompute the digest
|
|
56
|
+
* and see what was compared (AD-8's "by digest and opaque reference, never
|
|
57
|
+
* by content or path"). Named object rather than a concatenated tuple:
|
|
58
58
|
* revision 1 let two conforming scorers compute different versions from
|
|
59
59
|
* identical inputs if they hashed a different ordering. The scorer computes
|
|
60
|
-
* the scoring version over this shape.
|
|
60
|
+
* the scoring version over this shape. Six now, not five: `mode` is owed
|
|
61
|
+
* item 4's identity clause, superseding AD-11's original five-field
|
|
62
|
+
* sentence.
|
|
61
63
|
*/
|
|
62
64
|
export const SCORING_VERSION_INPUT_NAMES = [
|
|
63
65
|
'contractSchemaVersion',
|
|
@@ -65,14 +67,44 @@ export const SCORING_VERSION_INPUT_NAMES = [
|
|
|
65
67
|
'fixtureDigest',
|
|
66
68
|
'evaluatorConfigurationDigest',
|
|
67
69
|
'scoringPolicyDigest',
|
|
70
|
+
'mode',
|
|
68
71
|
];
|
|
69
72
|
export const ScoringVersionInputName = z.enum(SCORING_VERSION_INPUT_NAMES);
|
|
73
|
+
const SCORING_VERSION_MODE_DESCRIPTION = "Owed item 4's identity clause: mode enters AD-11's scoring version, superseding AD-11's five-field sentence. Read from the sealed run record, never re-derived, so two runs scored under one mode never collide with a version computed for the other. Required, not optional, which makes this the evidence artifact's `schemaVersion` 1 -> 2 BREAKING bump under AD-11, whose rule is that \"adding an optional field is a `schemaVersion` bump recorded in the field's own description; removing or retyping is breaking\". A version-1 artifact carries five scoring-version inputs where this one carries six, so it does not parse, and no version computed before the bump compares with one computed after it.";
|
|
70
74
|
export const ScoringVersionInputs = z.strictObject({
|
|
71
75
|
contractSchemaVersion: z.int().min(1),
|
|
72
76
|
corpusDigest: Digest,
|
|
73
77
|
fixtureDigest: Digest,
|
|
74
78
|
evaluatorConfigurationDigest: Digest,
|
|
75
79
|
scoringPolicyDigest: Digest,
|
|
80
|
+
mode: RunMode.describe(SCORING_VERSION_MODE_DESCRIPTION),
|
|
81
|
+
});
|
|
82
|
+
/**
|
|
83
|
+
* `scoringVersionInputs.mode` narrowed to the one value that agrees with
|
|
84
|
+
* `EvidenceArtifact`'s own branch discriminant (AD-11, AD-32), rather than a
|
|
85
|
+
* `.refine()` comparing the two fields. A refinement never exports, so the
|
|
86
|
+
* published document would keep admitting the disagreement, and the
|
|
87
|
+
* corpus-mutation generator synthesises witnesses for an untaken `oneOf`
|
|
88
|
+
* branch straight from that branch's own JSON Schema with no knowledge of a
|
|
89
|
+
* Zod-only cross-field rule -- verified: it produced two dozen genuine
|
|
90
|
+
* `zod=false published=true` disagreements this way. Narrowing the schema
|
|
91
|
+
* itself removes the gap at its source: a synthesised example for a
|
|
92
|
+
* `const`-typed field can only be that one value.
|
|
93
|
+
*
|
|
94
|
+
* Two named consts rather than one generic builder: a `<M extends
|
|
95
|
+
* RunModeValue>(mode: M)` helper builds each schema correctly, but TypeScript
|
|
96
|
+
* fails to preserve the per-call-site literal through `EvidenceArtifact`'s
|
|
97
|
+
* `z.discriminatedUnion` inference, so a fixture assigning the wrong branch's
|
|
98
|
+
* `mode` here compiles instead of erroring. Two concrete literals close that
|
|
99
|
+
* gap by construction; there is nothing generic left for the checker to lose.
|
|
100
|
+
*/
|
|
101
|
+
const productionScoringVersionInputs = ScoringVersionInputs.extend({
|
|
102
|
+
mode: z.literal('production').describe(SCORING_VERSION_MODE_DESCRIPTION),
|
|
103
|
+
});
|
|
104
|
+
const contractScoringVersionInputs = ScoringVersionInputs.extend({
|
|
105
|
+
mode: z
|
|
106
|
+
.literal('contract-scoring')
|
|
107
|
+
.describe(SCORING_VERSION_MODE_DESCRIPTION),
|
|
76
108
|
});
|
|
77
109
|
export const InvalidatedAttempt = z.strictObject({
|
|
78
110
|
attempt: z.int().min(1),
|
|
@@ -115,6 +147,25 @@ export const CoverageGap = z.strictObject({
|
|
|
115
147
|
satisfied: z.boolean(),
|
|
116
148
|
severity: Severity,
|
|
117
149
|
});
|
|
150
|
+
/**
|
|
151
|
+
* Owed item 5's record for an ingested `defect` finding citing no oracle:
|
|
152
|
+
* AD-23 already retains the finding rather than discarding it, but nothing
|
|
153
|
+
* downstream consumed it until this `schemaVersion`. Mirrors `CoverageGap`'s
|
|
154
|
+
* shape and the `defect`-branch fields on `Finding` it is read from, but
|
|
155
|
+
* carries no relevance or satisfaction predicate: AD-31's coverage gap is a
|
|
156
|
+
* declaration AD-31 could not confirm was satisfied, while an uncited defect
|
|
157
|
+
* finding is a runtime observation an evaluator made outside every declared
|
|
158
|
+
* oracle, with no relevance predicate to name and no satisfaction predicate
|
|
159
|
+
* that failed. This is the version-3 bump: required, not optional, per owed
|
|
160
|
+
* item 5, so a producer that never emits it stops parsing rather than
|
|
161
|
+
* silently under-reporting the gap.
|
|
162
|
+
*/
|
|
163
|
+
export const UncitedFindingGap = z.strictObject({
|
|
164
|
+
findingId: FindingId,
|
|
165
|
+
observationIds: z.array(Identifier).min(1),
|
|
166
|
+
quotedEvidence: z.array(QuotedEvidence).min(1),
|
|
167
|
+
severity: Severity,
|
|
168
|
+
});
|
|
118
169
|
export const ClassStrength = z.strictObject({
|
|
119
170
|
caught: z.int().min(0),
|
|
120
171
|
exercised: z.int().min(0),
|
|
@@ -178,7 +229,7 @@ export const Remediation = z.strictObject({
|
|
|
178
229
|
const evidenceCommonFields = {
|
|
179
230
|
...lineageFields,
|
|
180
231
|
runId: z.string().min(1),
|
|
181
|
-
scoringVersion: Digest.describe('AD-11: computed by the scorer over the
|
|
232
|
+
scoringVersion: Digest.describe('AD-11: computed by the scorer over the six named inputs below and never caller-supplied.'),
|
|
182
233
|
scoringVersionInputs: ScoringVersionInputs,
|
|
183
234
|
comparabilityKey: Digest.describe("AD-7's declared key: the scoring policy digest plus the corpus digest restricted to the probes both results cover. Deliberately weaker than the scoring version, so adding a probe narrows a comparison rather than voiding every prior result."),
|
|
184
235
|
excludedProbeIds: z
|
|
@@ -192,7 +243,7 @@ const evidenceCommonFields = {
|
|
|
192
243
|
.describe('Every condition that fired, in AD-21 terms. Free text by design: the rungs are prose in AD-21 and assigning them identifiers would be minting a vocabulary that AD has not. Each member is non-empty, on the same reasoning that `InvalidatedAttempt.reason` is: a condition that names itself with nothing has not been recorded. An empty array is legal and is what a PASS with no firing condition carries.'),
|
|
193
244
|
callerAttestedInputs: z
|
|
194
245
|
.array(ScoringVersionInputName)
|
|
195
|
-
.describe('Which of the
|
|
246
|
+
.describe('Which of the six scoring-version inputs were caller-attested rather than computed by this package. An enum over the six key names rather than free strings, because AD-32 requires the artifact to state *which* inputs were attested and an unconstrained string cannot be checked against anything. AD-11 names three of the six as caller-attested; the enum admits any subset so a stricter or looser integration stays representable.'),
|
|
196
247
|
trials: Trials,
|
|
197
248
|
outcomes: z.array(Outcome),
|
|
198
249
|
uncitedFindings: z
|
|
@@ -212,6 +263,7 @@ export const EvidenceArtifact = z
|
|
|
212
263
|
z
|
|
213
264
|
.strictObject({
|
|
214
265
|
...evidenceCommonFields,
|
|
266
|
+
scoringVersionInputs: productionScoringVersionInputs,
|
|
215
267
|
mode: z.literal('production'),
|
|
216
268
|
productionVerdict: Verdict,
|
|
217
269
|
})
|
|
@@ -219,8 +271,12 @@ export const EvidenceArtifact = z
|
|
|
219
271
|
z
|
|
220
272
|
.strictObject({
|
|
221
273
|
...evidenceCommonFields,
|
|
274
|
+
scoringVersionInputs: contractScoringVersionInputs,
|
|
222
275
|
mode: z.literal('contract-scoring'),
|
|
223
276
|
contractVerdict: Verdict,
|
|
277
|
+
uncitedFindingGaps: z
|
|
278
|
+
.array(UncitedFindingGap)
|
|
279
|
+
.describe("Owed item 5's rung record, contract-scoring only: one entry per uncited `defect` finding, per `core/score/outcome.ts`'s `uncitedDefectFindingGaps`. Required, not optional, which makes this the `schemaVersion` 2 -> 3 BREAKING bump under AD-11: an empty array is legal and is what a run with no uncited defect finding carries, but the key itself must be present. Never on the production branch, where the ladder signal alone is enough and this key would fail `strictObject`'s `unrecognized_keys` rule."),
|
|
224
280
|
systemRecommendationRecorded: EvaluatorRecommendation.describe("The evaluator's recommendation about the SYSTEM, recorded and never promoted. On a knowingly defective probe a system-directed FAIL is an input rather than a signal about the contract."),
|
|
225
281
|
systemRecommendationNote: z.string().nullable(),
|
|
226
282
|
})
|
|
@@ -228,5 +284,5 @@ export const EvidenceArtifact = z
|
|
|
228
284
|
])
|
|
229
285
|
.meta({
|
|
230
286
|
id: 'EvidenceArtifact',
|
|
231
|
-
description:
|
|
287
|
+
description: 'The scored output, owned by `emit` per AD-24, with no prior art; `score` produces the outcome and verdict values it serializes. The two modes are separate branches because AD-21 requires that the production verdict and the contract verdict never share a field. Mode is no longer first stated here: the Sealed Run Record now carries a required `mode`, where AD-21\'s "fixed before ingest" puts it, so this artifact restates a mode the sealed record already fixed and is never the source. Owed item 4 is closed as of this schemaVersion: `mode` is `ScoringVersionInputs`\'s sixth field, `core/score/ladder.ts` carries `ProductionAssessment`/`ContractAssessment` and their own total ladders, and `core/score/mode-agreement.ts` rejects a `production` record paired with a `contract-scoring` artifact in both directions as an AD-32 cross-artifact disagreement. That check is a hand-written function at the assembly boundary rather than a schema refinement, since no single schema sees both artifacts; `emit` is its one caller, immediately before returning the artifact it just built. Owed item 5 is closed as of this schemaVersion too: the contract-scoring branch carries a required `uncitedFindingGaps`, and both ladders in `core/score/ladder.ts` gain a shared `uncited-defect-finding` CONCERNS row over `AssessmentCommon.uncitedDefectFindings`, so an ingested defect finding citing no oracle now resolves at least CONCERNS instead of routing nowhere.',
|
|
232
288
|
});
|
|
@@ -7,7 +7,52 @@ import { JsonValue } from './primitives.ts';
|
|
|
7
7
|
* one implementation and the literal string to another, and flipped a witness
|
|
8
8
|
* match between `caught` and `missed` on one record; that form is
|
|
9
9
|
* unrepresentable here.
|
|
10
|
+
*
|
|
11
|
+
* Four members, one tag each. `{ literal }` writes the sent value down;
|
|
12
|
+
* `{ matcher: 'any' }` binds whatever was sent and `{ matcher: 'type-violating' }`
|
|
13
|
+
* binds a value whose JSON type differs from the operation's declared type for
|
|
14
|
+
* the key, which is how AD-31 rule 3's malformed-input behaviour is addressed.
|
|
15
|
+
*
|
|
16
|
+
* `{ captured }` addresses an earlier step's declared scalar output. Owed item
|
|
17
|
+
* 3: a `POST` returning a server-generated identifier followed by a `GET`
|
|
18
|
+
* proving persistence is unwritable with the first two, since a literal
|
|
19
|
+
* hard-codes a resource the evaluator never created and `any` matches
|
|
20
|
+
* unrelated reads. "Earlier" is earlier in the capture graph's own topological
|
|
21
|
+
* order, which `binding-cycle` makes exist. It is deliberately not AD-39's
|
|
22
|
+
* `after` clause: `nested-temporal-clause` already rejects every `after` cycle,
|
|
23
|
+
* so a capture forced to follow an `after` edge would leave `binding-cycle`
|
|
24
|
+
* unfireable. At score time the ordering is the record's `sequence`.
|
|
25
|
+
*
|
|
26
|
+
* `{ principal }` names a principal `testData.principals` declares. The two
|
|
27
|
+
* critical-severity cross-user behaviours (act as A, read as B, must be denied
|
|
28
|
+
* or absent) bind a step to an account that is neither a literal, since AD-19
|
|
29
|
+
* forbids credential values in declarations, nor an earlier step's output,
|
|
30
|
+
* since accounts are provisioned outside the observation stream. The name is
|
|
31
|
+
* an opaque label carrying no account identifier, credential, or subject data
|
|
32
|
+
* (AD-18). An undeclared name fires `undeclared-mandatory-input` in strict
|
|
33
|
+
* mode; a Zod refinement here would be a cross-subtree constraint the export
|
|
34
|
+
* cannot carry, and the published-schema differential sweep synthesises a
|
|
35
|
+
* union-branch witness that would expose the disagreement.
|
|
36
|
+
*
|
|
37
|
+
* A captured pointer resolves to a declared scalar with no transform applied,
|
|
38
|
+
* which keeps AD-4's ban on arithmetic, projection, and user-defined functions
|
|
39
|
+
* holding by construction: the grammar has no place to write one.
|
|
10
40
|
*/
|
|
41
|
+
/**
|
|
42
|
+
* The first two members, named individually so the probe-side selector under
|
|
43
|
+
* AD-40 admits exactly these two and nothing else. Bare `export const` with no
|
|
44
|
+
* `.meta({ id })`: an id would collapse the branches to `$ref`s and mint new
|
|
45
|
+
* `$defs`, so the export stays byte-identical.
|
|
46
|
+
*/
|
|
47
|
+
export declare const LiteralBindingValue: z.ZodObject<{
|
|
48
|
+
literal: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
|
|
49
|
+
}, z.core.$strict>;
|
|
50
|
+
export declare const MatcherBindingValue: z.ZodObject<{
|
|
51
|
+
matcher: z.ZodEnum<{
|
|
52
|
+
any: "any";
|
|
53
|
+
"type-violating": "type-violating";
|
|
54
|
+
}>;
|
|
55
|
+
}, z.core.$strict>;
|
|
11
56
|
export declare const BindingValue: z.ZodUnion<readonly [z.ZodObject<{
|
|
12
57
|
literal: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
|
|
13
58
|
}, z.core.$strict>, z.ZodObject<{
|
|
@@ -15,6 +60,10 @@ export declare const BindingValue: z.ZodUnion<readonly [z.ZodObject<{
|
|
|
15
60
|
any: "any";
|
|
16
61
|
"type-violating": "type-violating";
|
|
17
62
|
}>;
|
|
63
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
64
|
+
captured: z.ZodString;
|
|
65
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
66
|
+
principal: z.ZodString;
|
|
18
67
|
}, z.core.$strict>]>;
|
|
19
68
|
/** the constraint identifier the ledger carries for the check below. */
|
|
20
69
|
export declare const BINDING_CHANNEL_NON_EMPTY = "binding-channel-non-empty";
|
|
@@ -25,6 +74,10 @@ export declare const BindingChannel: z.ZodNullable<z.ZodRecord<z.ZodString, z.Zo
|
|
|
25
74
|
any: "any";
|
|
26
75
|
"type-violating": "type-violating";
|
|
27
76
|
}>;
|
|
77
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
78
|
+
captured: z.ZodString;
|
|
79
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
80
|
+
principal: z.ZodString;
|
|
28
81
|
}, z.core.$strict>]>>>;
|
|
29
82
|
/**
|
|
30
83
|
* A four-key strict object with each channel nullable, not a record over the
|
|
@@ -40,6 +93,10 @@ export declare const InputBinding: z.ZodObject<{
|
|
|
40
93
|
any: "any";
|
|
41
94
|
"type-violating": "type-violating";
|
|
42
95
|
}>;
|
|
96
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
97
|
+
captured: z.ZodString;
|
|
98
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
99
|
+
principal: z.ZodString;
|
|
43
100
|
}, z.core.$strict>]>>>;
|
|
44
101
|
query: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
45
102
|
literal: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
|
|
@@ -48,6 +105,10 @@ export declare const InputBinding: z.ZodObject<{
|
|
|
48
105
|
any: "any";
|
|
49
106
|
"type-violating": "type-violating";
|
|
50
107
|
}>;
|
|
108
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
109
|
+
captured: z.ZodString;
|
|
110
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
111
|
+
principal: z.ZodString;
|
|
51
112
|
}, z.core.$strict>]>>>;
|
|
52
113
|
header: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
53
114
|
literal: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
|
|
@@ -56,6 +117,10 @@ export declare const InputBinding: z.ZodObject<{
|
|
|
56
117
|
any: "any";
|
|
57
118
|
"type-violating": "type-violating";
|
|
58
119
|
}>;
|
|
120
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
121
|
+
captured: z.ZodString;
|
|
122
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
123
|
+
principal: z.ZodString;
|
|
59
124
|
}, z.core.$strict>]>>>;
|
|
60
125
|
body: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
61
126
|
literal: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
|
|
@@ -64,8 +129,34 @@ export declare const InputBinding: z.ZodObject<{
|
|
|
64
129
|
any: "any";
|
|
65
130
|
"type-violating": "type-violating";
|
|
66
131
|
}>;
|
|
132
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
133
|
+
captured: z.ZodString;
|
|
134
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
135
|
+
principal: z.ZodString;
|
|
67
136
|
}, z.core.$strict>]>>>;
|
|
68
137
|
}, z.core.$strict>;
|
|
138
|
+
/**
|
|
139
|
+
* AD-39's declared selector cardinality (owed item 2): what a step means when
|
|
140
|
+
* its selector matches more than one observation was not decided at the
|
|
141
|
+
* architecture layer, so a first-match scorer and a last-match scorer could
|
|
142
|
+
* bind different evidence. The contract now declares the rule per step.
|
|
143
|
+
* `several` under `exactly-one`/`at-most-one` is a named ambiguity condition;
|
|
144
|
+
* a reference function returns it as data. Routing that ambiguity to a
|
|
145
|
+
* verdict rung is later work. `any` is unrelated to
|
|
146
|
+
* `BindingValue`'s `{ matcher: 'any' }` above: same string, different field,
|
|
147
|
+
* no type-level collision. `ExpectedCardinality` (`interface.ts`) is a
|
|
148
|
+
* second, unrelated reuse of the word for AD-20's response-collection
|
|
149
|
+
* cardinality, and its `at-most` mode is a near-miss for `at-most-one` here;
|
|
150
|
+
* different type, different field, no collision, but easy to misread as the
|
|
151
|
+
* same declaration.
|
|
152
|
+
*/
|
|
153
|
+
export declare const SELECTOR_CARDINALITIES: readonly ['exactly-one', 'at-most-one', 'any'];
|
|
154
|
+
export type SelectorCardinalityValue = (typeof SELECTOR_CARDINALITIES)[number];
|
|
155
|
+
export declare const SelectorCardinality: z.ZodEnum<{
|
|
156
|
+
any: "any";
|
|
157
|
+
"at-most-one": "at-most-one";
|
|
158
|
+
"exactly-one": "exactly-one";
|
|
159
|
+
}>;
|
|
69
160
|
/**
|
|
70
161
|
* AD-39: a step is a selector over observations the evaluator produced, never
|
|
71
162
|
* an instruction. Its selection predicate is spelled as its two members, the
|
|
@@ -84,6 +175,10 @@ export declare const InteractionStep: z.ZodObject<{
|
|
|
84
175
|
any: "any";
|
|
85
176
|
"type-violating": "type-violating";
|
|
86
177
|
}>;
|
|
178
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
179
|
+
captured: z.ZodString;
|
|
180
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
181
|
+
principal: z.ZodString;
|
|
87
182
|
}, z.core.$strict>]>>>;
|
|
88
183
|
query: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
89
184
|
literal: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
|
|
@@ -92,6 +187,10 @@ export declare const InteractionStep: z.ZodObject<{
|
|
|
92
187
|
any: "any";
|
|
93
188
|
"type-violating": "type-violating";
|
|
94
189
|
}>;
|
|
190
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
191
|
+
captured: z.ZodString;
|
|
192
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
193
|
+
principal: z.ZodString;
|
|
95
194
|
}, z.core.$strict>]>>>;
|
|
96
195
|
header: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
97
196
|
literal: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
|
|
@@ -100,6 +199,10 @@ export declare const InteractionStep: z.ZodObject<{
|
|
|
100
199
|
any: "any";
|
|
101
200
|
"type-violating": "type-violating";
|
|
102
201
|
}>;
|
|
202
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
203
|
+
captured: z.ZodString;
|
|
204
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
205
|
+
principal: z.ZodString;
|
|
103
206
|
}, z.core.$strict>]>>>;
|
|
104
207
|
body: z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodObject<{
|
|
105
208
|
literal: z.ZodType<JsonValue, unknown, z.core.$ZodTypeInternals<JsonValue, unknown>>;
|
|
@@ -108,8 +211,17 @@ export declare const InteractionStep: z.ZodObject<{
|
|
|
108
211
|
any: "any";
|
|
109
212
|
"type-violating": "type-violating";
|
|
110
213
|
}>;
|
|
214
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
215
|
+
captured: z.ZodString;
|
|
216
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
217
|
+
principal: z.ZodString;
|
|
111
218
|
}, z.core.$strict>]>>>;
|
|
112
219
|
}, z.core.$strict>;
|
|
113
220
|
after: z.ZodNullable<z.ZodString>;
|
|
221
|
+
cardinality: z.ZodEnum<{
|
|
222
|
+
any: "any";
|
|
223
|
+
"at-most-one": "at-most-one";
|
|
224
|
+
"exactly-one": "exactly-one";
|
|
225
|
+
}>;
|
|
114
226
|
}, z.core.$strict>;
|
|
115
227
|
export type InteractionStep = z.infer<typeof InteractionStep>;
|
|
@@ -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
|
-
|
|
13
|
-
|
|
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';
|
|
@@ -43,6 +86,27 @@ export const InputBinding = z.strictObject({
|
|
|
43
86
|
header: BindingChannel,
|
|
44
87
|
body: BindingChannel,
|
|
45
88
|
});
|
|
89
|
+
/**
|
|
90
|
+
* AD-39's declared selector cardinality (owed item 2): what a step means when
|
|
91
|
+
* its selector matches more than one observation was not decided at the
|
|
92
|
+
* architecture layer, so a first-match scorer and a last-match scorer could
|
|
93
|
+
* bind different evidence. The contract now declares the rule per step.
|
|
94
|
+
* `several` under `exactly-one`/`at-most-one` is a named ambiguity condition;
|
|
95
|
+
* a reference function returns it as data. Routing that ambiguity to a
|
|
96
|
+
* verdict rung is later work. `any` is unrelated to
|
|
97
|
+
* `BindingValue`'s `{ matcher: 'any' }` above: same string, different field,
|
|
98
|
+
* no type-level collision. `ExpectedCardinality` (`interface.ts`) is a
|
|
99
|
+
* second, unrelated reuse of the word for AD-20's response-collection
|
|
100
|
+
* cardinality, and its `at-most` mode is a near-miss for `at-most-one` here;
|
|
101
|
+
* different type, different field, no collision, but easy to misread as the
|
|
102
|
+
* same declaration.
|
|
103
|
+
*/
|
|
104
|
+
export const SELECTOR_CARDINALITIES = [
|
|
105
|
+
'exactly-one',
|
|
106
|
+
'at-most-one',
|
|
107
|
+
'any',
|
|
108
|
+
];
|
|
109
|
+
export const SelectorCardinality = z.enum(SELECTOR_CARDINALITIES);
|
|
46
110
|
/**
|
|
47
111
|
* AD-39: a step is a selector over observations the evaluator produced, never
|
|
48
112
|
* an instruction. Its selection predicate is spelled as its two members, the
|
|
@@ -55,4 +119,5 @@ export const InteractionStep = z.strictObject({
|
|
|
55
119
|
operationId: Identifier,
|
|
56
120
|
inputBinding: InputBinding,
|
|
57
121
|
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."),
|
|
122
|
+
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
123
|
});
|