eval-quality 0.2.0 → 0.5.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 +17 -12
- package/corpus/dev/README.md +3 -2
- 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/fragment-selection.json +1 -0
- 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/review-corpus.json +1 -0
- 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/adapters/command-line-adapter.d.ts +44 -0
- package/dist/adapters/command-line-adapter.js +284 -0
- package/dist/adapters/command-target-policy.d.ts +36 -0
- package/dist/adapters/command-target-policy.js +33 -0
- package/dist/adapters/index.d.ts +2 -0
- package/dist/adapters/index.js +1 -0
- package/dist/cli/render.d.ts +2 -5
- package/dist/cli/render.js +51 -1
- package/dist/core/compile/bindings.d.ts +26 -7
- package/dist/core/compile/bindings.js +49 -32
- package/dist/core/compile/compile.d.ts +12 -0
- package/dist/core/compile/compile.js +28 -1
- package/dist/core/compile/excluded-content.d.ts +11 -0
- package/dist/core/compile/excluded-content.js +42 -0
- package/dist/core/compile/expression-legality.d.ts +2 -2
- package/dist/core/compile/expression-legality.js +58 -12
- package/dist/core/compile/interface-inventory.d.ts +34 -1
- package/dist/core/compile/interface-inventory.js +88 -11
- package/dist/core/compile/reachability.d.ts +12 -2
- package/dist/core/compile/reachability.js +123 -36
- package/dist/core/compile/schema-version.d.ts +2 -0
- package/dist/core/compile/schema-version.js +25 -0
- package/dist/core/compile/sensitivity-witness.d.ts +31 -12
- package/dist/core/compile/sensitivity-witness.js +110 -23
- package/dist/core/compile/step-reference.d.ts +2 -0
- package/dist/core/compile/step-reference.js +49 -0
- package/dist/core/coverage/operations.d.ts +62 -0
- package/dist/core/coverage/operations.js +57 -0
- package/dist/core/coverage/relevance.d.ts +4 -2
- package/dist/core/coverage/relevance.js +22 -23
- package/dist/core/coverage/satisfaction.d.ts +2 -2
- package/dist/core/coverage/satisfaction.js +73 -48
- package/dist/core/declared-inputs.d.ts +83 -4
- package/dist/core/declared-inputs.js +105 -8
- package/dist/core/evaluate/evidence-resolution.d.ts +9 -12
- package/dist/core/evaluate/evidence-resolution.js +70 -10
- package/dist/core/evaluate/operators.d.ts +22 -0
- package/dist/core/evaluate/operators.js +17 -1
- package/dist/core/evaluate/resolution.d.ts +14 -3
- package/dist/core/evaluate/resolution.js +63 -3
- package/dist/core/excluded-content.d.ts +65 -0
- package/dist/core/excluded-content.js +113 -0
- package/dist/core/failure-codes.d.ts +2 -2
- package/dist/core/failure-codes.js +5 -2
- package/dist/core/ingest/conditions.d.ts +1 -1
- package/dist/core/ingest/ingest.js +8 -0
- package/dist/core/preflight/plan.d.ts +7 -5
- package/dist/core/preflight/plan.js +75 -32
- package/dist/core/preflight/projection.d.ts +6 -3
- package/dist/core/preflight/projection.js +22 -2
- package/dist/core/preflight/reduce.js +47 -7
- package/dist/core/preflight/witness-evidence.d.ts +5 -5
- package/dist/core/preflight/witness-evidence.js +63 -20
- package/dist/core/schemas/artifact.d.ts +683 -35
- package/dist/core/schemas/constraint-ledger.js +11 -0
- package/dist/core/schemas/defect-signature.d.ts +438 -16
- package/dist/core/schemas/defect-signature.js +58 -10
- package/dist/core/schemas/eval-contract.d.ts +517 -12
- package/dist/core/schemas/eval-contract.js +18 -2
- package/dist/core/schemas/evidence-artifact.d.ts +14 -4
- package/dist/core/schemas/evidence-artifact.js +1 -1
- package/dist/core/schemas/interface.d.ts +741 -13
- package/dist/core/schemas/interface.js +120 -7
- package/dist/core/schemas/isolation-manifest.js +16 -9
- package/dist/core/schemas/plan.d.ts +217 -3
- package/dist/core/schemas/plan.js +22 -1
- package/dist/core/schemas/pointer.d.ts +47 -1
- package/dist/core/schemas/pointer.js +89 -8
- package/dist/core/schemas/port-messages.d.ts +194 -10
- package/dist/core/schemas/port-messages.js +73 -6
- package/dist/core/schemas/probe-body.d.ts +18 -0
- package/dist/core/schemas/probe-body.js +13 -0
- package/dist/core/schemas/probe-policy.d.ts +36 -0
- package/dist/core/schemas/probe-policy.js +44 -0
- package/dist/core/schemas/probe.d.ts +122 -3
- package/dist/core/schemas/probe.js +1 -1
- package/dist/core/schemas/sealed-run-record.d.ts +131 -9
- package/dist/core/schemas/sealed-run-record.js +56 -11
- package/dist/core/schemas/sensitivity-witness.d.ts +108 -6
- package/dist/core/schemas/sensitivity-witness.js +61 -5
- package/dist/core/score/bindings.d.ts +2 -2
- package/dist/core/score/bindings.js +25 -13
- package/dist/core/score/qualification.d.ts +5 -5
- package/dist/core/score/qualification.js +67 -37
- package/dist/core/score/quotation.d.ts +1 -24
- package/dist/core/score/quotation.js +29 -4
- package/dist/core/score/score.js +28 -2
- package/dist/core/score/strength.d.ts +9 -0
- package/dist/core/score/strength.js +35 -1
- package/dist/core/score/witness.d.ts +21 -0
- package/dist/core/score/witness.js +9 -4
- package/dist/core/seal/derived-reference.d.ts +2 -9
- package/dist/core/seal/derived-reference.js +62 -23
- package/dist/core/seal/plan-index.d.ts +18 -3
- package/dist/core/seal/plan-index.js +44 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/ports/environment-probe-port.d.ts +60 -4
- package/dist/testing/conformance.d.ts +2 -1
- package/dist/testing/conformance.js +1 -0
- package/dist/testing/index.d.ts +3 -3
- package/dist/testing/index.js +1 -1
- package/dist/testing/probe-conformance.d.ts +56 -5
- package/dist/testing/probe-conformance.js +196 -5
- package/package.json +1 -1
- package/schemas/eval-contract.schema.json +1356 -464
- package/schemas/evidence-artifact.schema.json +59 -29
- package/schemas/isolation-manifest.schema.json +17 -10
- package/schemas/probe.schema.json +197 -71
- package/schemas/rubric.schema.json +1 -1
- package/schemas/sealed-run-record.schema.json +296 -39
|
@@ -43,12 +43,37 @@ import { serialize } from '../canonical/canonicalize.js';
|
|
|
43
43
|
* Should canonicalization fault on a caller's record, the fault propagates,
|
|
44
44
|
* which is what keeps this procedure from being circular with it.
|
|
45
45
|
*/
|
|
46
|
-
|
|
46
|
+
/**
|
|
47
|
+
* One tagged observed value as the text a quotation is compared against. A
|
|
48
|
+
* text body is its own value; a JSON body is its canonical serialisation, the
|
|
49
|
+
* same one `response-body` gets; an absent channel has no text.
|
|
50
|
+
*/
|
|
51
|
+
function observedText(body, artifactPath) {
|
|
52
|
+
if (body.kind === 'absent')
|
|
53
|
+
return null;
|
|
54
|
+
if (body.kind === 'text')
|
|
55
|
+
return body.value;
|
|
56
|
+
return serialize(body.value, artifactPath);
|
|
57
|
+
}
|
|
58
|
+
export function projectChannel(observation, channel, artifactPath, artifactId = null) {
|
|
47
59
|
switch (channel) {
|
|
48
60
|
case 'stdout':
|
|
49
|
-
return observation.stdout;
|
|
61
|
+
return observedText(observation.stdout, artifactPath);
|
|
50
62
|
case 'stderr':
|
|
51
|
-
return observation.stderr;
|
|
63
|
+
return observedText(observation.stderr, artifactPath);
|
|
64
|
+
case 'artifact': {
|
|
65
|
+
// One named file's own text. Serializing the whole map instead was
|
|
66
|
+
// wrong twice over: it escaped every newline and quotation mark, so
|
|
67
|
+
// a quotation from a file with more than one line could never match,
|
|
68
|
+
// and it searched every file at once, so a quotation from a file the
|
|
69
|
+
// finding did not cite matched anyway.
|
|
70
|
+
if (artifactId === null)
|
|
71
|
+
return null;
|
|
72
|
+
if (!Object.hasOwn(observation.artifacts, artifactId))
|
|
73
|
+
return null;
|
|
74
|
+
const written = observation.artifacts[artifactId];
|
|
75
|
+
return written === undefined ? null : observedText(written, artifactPath);
|
|
76
|
+
}
|
|
52
77
|
case 'response-status':
|
|
53
78
|
return observation.responseStatus === null
|
|
54
79
|
? null
|
|
@@ -73,7 +98,7 @@ export function projectChannel(observation, channel, artifactPath) {
|
|
|
73
98
|
* Whether one quotation appears in one observation's named channel, verbatim.
|
|
74
99
|
*/
|
|
75
100
|
function quotationWitnessed(quoted, observation, artifactPath) {
|
|
76
|
-
const projected = projectChannel(observation, quoted.channel, artifactPath);
|
|
101
|
+
const projected = projectChannel(observation, quoted.channel, artifactPath, quoted.artifactId);
|
|
77
102
|
// A null projection witnesses nothing, and `false` is the answer: an
|
|
78
103
|
// optional chain here would hand a caller `undefined` where the return type
|
|
79
104
|
// says boolean.
|
package/dist/core/score/score.js
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
*/
|
|
31
31
|
import { walkExpression } from '../compile/expression-legality.js';
|
|
32
32
|
import { evaluateCoverage } from '../coverage/coverage.js';
|
|
33
|
-
import { makePointerDenotesCollection, makeResolveOperand, } from '../evaluate/evidence-resolution.js';
|
|
33
|
+
import { makePointerDenotesCollection, makeResolveOperand, referenceSetKeysOf, } from '../evaluate/evidence-resolution.js';
|
|
34
34
|
import { resolveCheck } from '../evaluate/resolution.js';
|
|
35
35
|
import { SEVERITY_LEVELS, } from '../schemas/eval-contract.js';
|
|
36
36
|
import { buildPlanIndex } from '../seal/plan-index.js';
|
|
@@ -195,6 +195,29 @@ function trialSetDisagreementsOf(trials) {
|
|
|
195
195
|
});
|
|
196
196
|
return disagreements;
|
|
197
197
|
}
|
|
198
|
+
/**
|
|
199
|
+
* Cross-trial identifier reuse is NOT a collision, and this is where that was
|
|
200
|
+
* settled after being carried as an open question.
|
|
201
|
+
*
|
|
202
|
+
* `ingest` computes `duplicate-record-identifier` per sealed run record, since
|
|
203
|
+
* it sees one trial at a time, and nothing checks whether two DIFFERENT trials
|
|
204
|
+
* of one set reuse an observation, finding, or oracle-disposition identifier.
|
|
205
|
+
* That asymmetry looks like a gap beside `trial-set-field-disagreement`, which
|
|
206
|
+
* does compare `mode` and `evaluatorRecommendation` across trials.
|
|
207
|
+
*
|
|
208
|
+
* It is not one. A trial set is n independent evaluator runs of one contract,
|
|
209
|
+
* each producing its own record, and a harness that names its first observation
|
|
210
|
+
* `obs-1` names it that in every run. Reporting the second run for it would
|
|
211
|
+
* make a repeated run Invalid by construction, which is the opposite of what a
|
|
212
|
+
* trial set is for. The fields that ARE compared across trials are compared
|
|
213
|
+
* because they describe the SET rather than a run within it: two trials
|
|
214
|
+
* disagreeing about which mode they ran under cannot both be true of one set,
|
|
215
|
+
* while two trials both carrying `obs-1` are two true statements about two
|
|
216
|
+
* runs.
|
|
217
|
+
*
|
|
218
|
+
* The pooled basis this stage builds carries each entry with the trial it came
|
|
219
|
+
* from, so a repeated identifier is never resolved against the wrong row.
|
|
220
|
+
*/
|
|
198
221
|
/** Every `IngestCondition` of one `kind` across every trial, in trial order. */
|
|
199
222
|
function conditionsAcrossTrials(trials, kind) {
|
|
200
223
|
return trials.flatMap((trial) => trial.conditions.filter((condition) => condition.kind === kind));
|
|
@@ -246,6 +269,9 @@ export const score = (contract, trials, probe, preflightVerdict, policy, waiver,
|
|
|
246
269
|
id,
|
|
247
270
|
declaration.members,
|
|
248
271
|
]));
|
|
272
|
+
// The declared keys the members map above drops. `set-membership`'s set
|
|
273
|
+
// position reads the single declared key off each member.
|
|
274
|
+
const referenceSetKeys = referenceSetKeysOf(contract);
|
|
249
275
|
const judgeConduct = judgeConductOf(contract, trials);
|
|
250
276
|
const allOutcomes = [];
|
|
251
277
|
// The full `EvidenceArtifact.outcomes` shape, built alongside `allOutcomes`
|
|
@@ -317,7 +343,7 @@ export const score = (contract, trials, probe, preflightVerdict, policy, waiver,
|
|
|
317
343
|
entry.step.cardinality !== 'any');
|
|
318
344
|
const checkResolution = check === null
|
|
319
345
|
? null
|
|
320
|
-
: resolveCheck(check, resolveOperand, pointerDenotesCollection, policy.regexMatchStepBudget, `EvalContract.oracles[id=${oracle.id}].check`);
|
|
346
|
+
: resolveCheck(check, resolveOperand, pointerDenotesCollection, referenceSetKeys, policy.regexMatchStepBudget, `EvalContract.oracles[id=${oracle.id}].check`);
|
|
321
347
|
// Every disposition this trial records for this oracle, not just
|
|
322
348
|
// the first: `SealedRunRecord.oracleDispositions` carries no
|
|
323
349
|
// uniqueness constraint on `oracleId`, and ingest's
|
|
@@ -45,5 +45,14 @@ export declare function buildStrengthVector(admitted: readonly QualifiedProbe[],
|
|
|
45
45
|
* on it is not fit to decide a comparison either way. The severity-floor
|
|
46
46
|
* override runs only against the side the raw comparison favoured, and only
|
|
47
47
|
* ever downgrades that result to `incomparable`.
|
|
48
|
+
*
|
|
49
|
+
* That scope is AD-7's own and not an omission: its words are that a contract
|
|
50
|
+
* missing a behaviour at or above the floor "never dominates" one that caught
|
|
51
|
+
* it, which constrains dominance and says nothing about equivalence. Two
|
|
52
|
+
* vectors that are component-wise equal are `equivalent` whatever their
|
|
53
|
+
* severities, because neither is dominating anything for the override to
|
|
54
|
+
* withdraw. Widening it to `equivalent` would be a new rule rather than this
|
|
55
|
+
* one applied more thoroughly, and it is written down here so the asymmetry
|
|
56
|
+
* reads as a decision rather than a gap.
|
|
48
57
|
*/
|
|
49
58
|
export declare function compareDominance(a: ComparableResult, b: ComparableResult, severityFloor: Severity): DominanceRelationValue;
|
|
@@ -44,7 +44,18 @@ const classStrengthOf = (probesInClass, results) => {
|
|
|
44
44
|
return null;
|
|
45
45
|
let exercised = 0;
|
|
46
46
|
let caught = 0;
|
|
47
|
+
// Counted once per identifier, not once per entry. AD-7's rate is over
|
|
48
|
+
// unique qualified probe identifiers, and nothing in `src/` enforces that
|
|
49
|
+
// `admitted` carries each identifier once: no probe-corpus schema exists,
|
|
50
|
+
// so the uniqueness is inherited from upstream qualification rather than
|
|
51
|
+
// checked. A repeated identifier would otherwise count its trial-set
|
|
52
|
+
// result twice on both sides of the same ratio, which leaves the rate
|
|
53
|
+
// right and the raw counts wrong.
|
|
54
|
+
const counted = new Set();
|
|
47
55
|
for (const { probe } of probesInClass) {
|
|
56
|
+
if (counted.has(probe.probeId))
|
|
57
|
+
continue;
|
|
58
|
+
counted.add(probe.probeId);
|
|
48
59
|
const result = results.get(probe.probeId);
|
|
49
60
|
if (result === undefined || !result.exercised)
|
|
50
61
|
continue;
|
|
@@ -123,7 +134,21 @@ function componentComparison(a, b) {
|
|
|
123
134
|
return 'b-dominates-a';
|
|
124
135
|
return 'incomparable';
|
|
125
136
|
}
|
|
126
|
-
|
|
137
|
+
/**
|
|
138
|
+
* Both operands are looked up before they are compared, because `indexOf`
|
|
139
|
+
* answers `-1` for a value the ladder does not name and `-1 >= -1` reads as
|
|
140
|
+
* "at or above the floor" for two values that are on no ladder at all. A
|
|
141
|
+
* severity outside the closed set is not at or above anything, and a floor
|
|
142
|
+
* outside it bounds nothing, so either one absent is `false` rather than a
|
|
143
|
+
* comparison of two absences.
|
|
144
|
+
*/
|
|
145
|
+
const atOrAboveFloor = (severity, floor) => {
|
|
146
|
+
const rank = SEVERITY_LEVELS.indexOf(severity);
|
|
147
|
+
const bound = SEVERITY_LEVELS.indexOf(floor);
|
|
148
|
+
if (rank < 0 || bound < 0)
|
|
149
|
+
return false;
|
|
150
|
+
return rank >= bound;
|
|
151
|
+
};
|
|
127
152
|
/**
|
|
128
153
|
* Keyed by the first outcome carrying each `probeId`, not the last: two
|
|
129
154
|
* `Outcome` entries sharing one `probeId` is itself a defect somewhere
|
|
@@ -174,6 +199,15 @@ function favoredMissesWhatOtherCaught(favored, other, severityFloor) {
|
|
|
174
199
|
* on it is not fit to decide a comparison either way. The severity-floor
|
|
175
200
|
* override runs only against the side the raw comparison favoured, and only
|
|
176
201
|
* ever downgrades that result to `incomparable`.
|
|
202
|
+
*
|
|
203
|
+
* That scope is AD-7's own and not an omission: its words are that a contract
|
|
204
|
+
* missing a behaviour at or above the floor "never dominates" one that caught
|
|
205
|
+
* it, which constrains dominance and says nothing about equivalence. Two
|
|
206
|
+
* vectors that are component-wise equal are `equivalent` whatever their
|
|
207
|
+
* severities, because neither is dominating anything for the override to
|
|
208
|
+
* withdraw. Widening it to `equivalent` would be a new rule rather than this
|
|
209
|
+
* one applied more thoroughly, and it is written down here so the asymmetry
|
|
210
|
+
* reads as a decision rather than a gap.
|
|
177
211
|
*/
|
|
178
212
|
export function compareDominance(a, b, severityFloor) {
|
|
179
213
|
if (a.comparabilityKey !== b.comparabilityKey)
|
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AD-40's witness match: whether a finding cited against a probe actually
|
|
3
|
+
* witnessed the defect that probe seeded.
|
|
4
|
+
*
|
|
5
|
+
* This is the input that makes non-detection reachable. Without it, an oracle
|
|
6
|
+
* that correctly confirmed an untouched behaviour and one that failed to detect
|
|
7
|
+
* the seeded defect present identical inputs, so any table obeying AD-3 must
|
|
8
|
+
* give both the same answer and the catch rate is 1.00 by construction.
|
|
9
|
+
*
|
|
10
|
+
* Pure and total on its ordinary path, and no AD-6 outcome state is assigned
|
|
11
|
+
* here. The result is a fact about evidence; turning it into an outcome state
|
|
12
|
+
* is the decision procedure's.
|
|
13
|
+
*
|
|
14
|
+
* One deliberate non-totality: a `RuntimeFault` from the shipped evaluator
|
|
15
|
+
* propagates undecorated. A fault never becomes a verdict, and AD-28 makes it
|
|
16
|
+
* an invalidating condition under AD-21 rather than a behavioural result, so
|
|
17
|
+
* catching one here would convert AD-21's fault exit into a scored run. The
|
|
18
|
+
* qualification gate rejects every operand class that makes the evaluator's
|
|
19
|
+
* four plain-`Error` sites reachable, which leaves exactly two data-dependent
|
|
20
|
+
* `RuntimeFault`s: an exhausted regex budget and a non-canonicalizable value.
|
|
21
|
+
*/
|
|
1
22
|
import type { DefectSignature } from '../schemas/defect-signature.ts';
|
|
2
23
|
import type { PermittedInterface } from '../schemas/interface.ts';
|
|
3
24
|
import type { Probe } from '../schemas/probe.ts';
|
|
@@ -19,11 +19,12 @@
|
|
|
19
19
|
* four plain-`Error` sites reachable, which leaves exactly two data-dependent
|
|
20
20
|
* `RuntimeFault`s: an exhausted regex budget and a non-canonicalizable value.
|
|
21
21
|
*/
|
|
22
|
+
import { requestShapeOf } from '../declared-inputs.js';
|
|
22
23
|
import { makeResolveOperand } from '../evaluate/evidence-resolution.js';
|
|
23
24
|
import { resolveCheck } from '../evaluate/resolution.js';
|
|
24
25
|
import { makeWitnessPointerDenotesCollection } from '../preflight/witness-evidence.js';
|
|
25
26
|
import { OBSERVED_STEP_ID } from '../schemas/defect-signature.js';
|
|
26
|
-
import {
|
|
27
|
+
import { INPUT_CHANNELS } from '../schemas/pointer.js';
|
|
27
28
|
import { deepEquals, jsonTypeOf } from './bindings.js';
|
|
28
29
|
import { resolveHomeOperation } from './qualification.js';
|
|
29
30
|
/**
|
|
@@ -73,7 +74,7 @@ export const PROBE_WITNESS_RESULTS = [
|
|
|
73
74
|
* probe has no interaction plan to index.
|
|
74
75
|
*/
|
|
75
76
|
function selectorAdmits(binding, observation, operation) {
|
|
76
|
-
for (const channel of
|
|
77
|
+
for (const channel of INPUT_CHANNELS) {
|
|
77
78
|
const channelBinding = binding[channel];
|
|
78
79
|
if (channelBinding === null)
|
|
79
80
|
continue;
|
|
@@ -94,7 +95,7 @@ function selectorAdmits(binding, observation, operation) {
|
|
|
94
95
|
}
|
|
95
96
|
if (value.matcher === 'any')
|
|
96
97
|
continue;
|
|
97
|
-
const declared = operation
|
|
98
|
+
const declared = requestShapeOf(operation, channel)?.types[key];
|
|
98
99
|
if (declared === undefined || declared === null)
|
|
99
100
|
return false;
|
|
100
101
|
if (jsonTypeOf(actual) === declared)
|
|
@@ -119,7 +120,11 @@ const bySequence = (a, b) => a.sequence - b.sequence || (a.observationId < b.obs
|
|
|
119
120
|
* than an accident.
|
|
120
121
|
*/
|
|
121
122
|
function resolveCondition(signature, observation, operation, artifactPath) {
|
|
122
|
-
return resolveCheck(signature.condition.predicate, makeResolveOperand({ [OBSERVED_STEP_ID]: observation }, {}), makeWitnessPointerDenotesCollection(operation),
|
|
123
|
+
return resolveCheck(signature.condition.predicate, makeResolveOperand({ [OBSERVED_STEP_ID]: observation }, {}), makeWitnessPointerDenotesCollection(operation),
|
|
124
|
+
// No reference sets, matching the empty members map above: the
|
|
125
|
+
// qualification gate rejects a reference-set operand in a defect
|
|
126
|
+
// signature under `condition-reference-set-operand`.
|
|
127
|
+
{}, PROBE_REGEX_MATCH_STEP_BUDGET, artifactPath).resolution;
|
|
123
128
|
}
|
|
124
129
|
const defectFindingsFor = (findings, probeId) => findings.filter((finding) => finding.findingType === 'defect' && finding.probeId === probeId);
|
|
125
130
|
/**
|
|
@@ -1,11 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
* The derived-reference vocabulary (AD-16). Renders an evidence-target
|
|
3
|
-
* pointer, or a temporally-paired pair, as a description of the step's
|
|
4
|
-
* operation and selection predicate; the step's own identifier never appears.
|
|
5
|
-
* Resolves pointers through a `PlanIndex` into a phrase, kept apart from
|
|
6
|
-
* `plan-index.ts`'s resolving and `direction-prose.ts`'s relation templates.
|
|
7
|
-
*/
|
|
8
|
-
import type { Operation } from '../schemas/interface.ts';
|
|
1
|
+
import type { AnyOperation } from '../schemas/interface.ts';
|
|
9
2
|
import type { InteractionStep } from '../schemas/plan.ts';
|
|
10
3
|
import { type PlanIndex } from './plan-index.ts';
|
|
11
4
|
/**
|
|
@@ -21,7 +14,7 @@ import { type PlanIndex } from './plan-index.ts';
|
|
|
21
14
|
* duplicate `stepId` check if two siblings still collide after full
|
|
22
15
|
* escalation.
|
|
23
16
|
*/
|
|
24
|
-
export declare function renderStepReference(step: InteractionStep, operation:
|
|
17
|
+
export declare function renderStepReference(step: InteractionStep, operation: AnyOperation, siblings: readonly InteractionStep[], index: PlanIndex): string;
|
|
25
18
|
/**
|
|
26
19
|
* Renders every evidence target a direction declares as one canonically
|
|
27
20
|
* ordered, order-independent clause: byte-identical under any permutation of
|
|
@@ -1,8 +1,20 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* The derived-reference vocabulary (AD-16). Renders an evidence-target
|
|
3
|
+
* pointer, or a temporally-paired pair, as a description of the step's
|
|
4
|
+
* operation and selection predicate; the step's own identifier never appears.
|
|
5
|
+
* Resolves pointers through a `PlanIndex` into a phrase, kept apart from
|
|
6
|
+
* `plan-index.ts`'s resolving and `direction-prose.ts`'s relation templates.
|
|
7
|
+
*/
|
|
8
|
+
import { boundChannelsOf, isCommandOperation } from '../declared-inputs.js';
|
|
9
|
+
import { StructuralFailure } from '../failure-codes.js';
|
|
10
|
+
import { anyOperationOf, parseEvidenceTarget, resolveStep, } from './plan-index.js';
|
|
2
11
|
function resolveEvidenceTarget(pointer, index) {
|
|
3
12
|
const target = parseEvidenceTarget(pointer);
|
|
4
13
|
const step = resolveStep(index, target.stepId);
|
|
5
|
-
const operation =
|
|
14
|
+
const operation = anyOperationOf(index, step.operationId);
|
|
15
|
+
if (operation === undefined) {
|
|
16
|
+
throw new TypeError(`step names an operation the permitted interfaces do not declare: ${step.operationId}`);
|
|
17
|
+
}
|
|
6
18
|
return { target, step, operation };
|
|
7
19
|
}
|
|
8
20
|
// ---- joining ---------------------------------------------------------
|
|
@@ -21,30 +33,31 @@ function joinWithAnd(items) {
|
|
|
21
33
|
// ---- operation identity -----------------------------------------------
|
|
22
34
|
// Humanizing a kebab-case operationId is injective on distinct ids, and
|
|
23
35
|
// `buildPlanIndex` already rejects a duplicate `operationId` across
|
|
24
|
-
// interfaces, so two resolved operations never share this phrase.
|
|
25
|
-
//
|
|
26
|
-
// inventory from the brief
|
|
36
|
+
// interfaces, so two resolved operations never share this phrase. The
|
|
37
|
+
// transport identity is never printed here, whichever kind it is: AD-16
|
|
38
|
+
// withholds the operation inventory from the brief, so neither a method and a
|
|
39
|
+
// path template nor an executable and a subcommand path reach an evaluator.
|
|
40
|
+
//
|
|
41
|
+
// The noun follows the kind. Calling a command an endpoint told the evaluator
|
|
42
|
+
// something false about what it was reading, and the word is the only thing
|
|
43
|
+
// this phrase says beyond the operation's own name.
|
|
27
44
|
function operationReference(operation) {
|
|
28
|
-
|
|
45
|
+
const name = operation.operationId.split('-').join(' ');
|
|
46
|
+
return isCommandOperation(operation)
|
|
47
|
+
? `the ${name} command`
|
|
48
|
+
: `the ${name} endpoint`;
|
|
29
49
|
}
|
|
30
50
|
const ESCALATION_LEVELS = [
|
|
31
51
|
'generic',
|
|
32
52
|
'kind',
|
|
33
53
|
'literal',
|
|
34
54
|
];
|
|
35
|
-
|
|
36
|
-
'path',
|
|
37
|
-
'query',
|
|
38
|
-
'header',
|
|
39
|
-
'body',
|
|
40
|
-
];
|
|
41
|
-
// Sorted by transport channel in fixed order, then by key name, so this
|
|
55
|
+
// Sorted by input channel in `INPUT_CHANNELS` order, then by key name, so this
|
|
42
56
|
// never depends on a binding map's insertion order and the rendered prose
|
|
43
|
-
// stays permutation-invariant.
|
|
57
|
+
// stays permutation-invariant. `boundChannelsOf` supplies the channel order.
|
|
44
58
|
function bindingEntries(step) {
|
|
45
59
|
const entries = [];
|
|
46
|
-
for (const transportChannel of
|
|
47
|
-
const map = step.inputBinding[transportChannel];
|
|
60
|
+
for (const { channel: transportChannel, bound: map } of boundChannelsOf(step.inputBinding)) {
|
|
48
61
|
if (map === null)
|
|
49
62
|
continue;
|
|
50
63
|
for (const key of Object.keys(map).sort()) {
|
|
@@ -99,9 +112,10 @@ function formatLiteral(literal) {
|
|
|
99
112
|
// predecessor separates them by its own binding clause. Two predecessors that
|
|
100
113
|
// are themselves irreducible still tie, and the throw there is correct: the
|
|
101
114
|
// declared structure does not distinguish them, which is the same answer
|
|
102
|
-
// `irreducibleCollisionPair` already gets. That throw is a
|
|
103
|
-
//
|
|
104
|
-
//
|
|
115
|
+
// `irreducibleCollisionPair` already gets. That throw is a coded
|
|
116
|
+
// `StructuralFailure` under `irreducible-step-reference`, and it is
|
|
117
|
+
// hoisted to compile time by `checkStepReferenceReducibility`, which runs this
|
|
118
|
+
// same ladder and reports the same code before `seal` is ever called.
|
|
105
119
|
//
|
|
106
120
|
// It does NOT call `renderStepReference`, so none of that function's
|
|
107
121
|
// constraints apply: no direction-scoped sibling list is consulted, so AD-16's
|
|
@@ -191,7 +205,7 @@ function renderCaptureGroup(group, level, index, rendering, budget) {
|
|
|
191
205
|
const names = joinWithAnd(group.entries.map(entryName));
|
|
192
206
|
const locals = joinWithAnd(group.targets.map(localTargetPhrase));
|
|
193
207
|
const step = index.stepOf(group.stepId);
|
|
194
|
-
const operation = step === undefined ? undefined : index
|
|
208
|
+
const operation = step === undefined ? undefined : anyOperationOf(index, step.operationId);
|
|
195
209
|
if (step === undefined || operation === undefined) {
|
|
196
210
|
return unexpandedGroup(group);
|
|
197
211
|
}
|
|
@@ -222,7 +236,7 @@ function expandableCapture(entry, level, index, rendering, budget) {
|
|
|
222
236
|
const step = index.stepOf(target.stepId);
|
|
223
237
|
if (step === undefined)
|
|
224
238
|
return null;
|
|
225
|
-
return index
|
|
239
|
+
return anyOperationOf(index, step.operationId) === undefined ? null : target;
|
|
226
240
|
}
|
|
227
241
|
// Renders one entry on its own. Every captured entry that expands lands in a
|
|
228
242
|
// group instead, so the arm here is the level-independent fallback.
|
|
@@ -355,7 +369,13 @@ export function renderStepReference(step, operation, siblings, index) {
|
|
|
355
369
|
if (!starved)
|
|
356
370
|
break;
|
|
357
371
|
}
|
|
358
|
-
|
|
372
|
+
// Coded rather than a bare `TypeError`. A contract reaching here passed
|
|
373
|
+
// every compile check and then failed at seal time with a stack trace, and
|
|
374
|
+
// the defect is an ordinary authoring fault: two steps the declared
|
|
375
|
+
// structure does not tell apart. `checkStepReferenceReducibility` runs this
|
|
376
|
+
// same ladder at compile time so the fault is reported before seal, and
|
|
377
|
+
// this throw is what it catches.
|
|
378
|
+
throw new StructuralFailure('irreducible-step-reference', `EvalContract.interactionPlan[operationId=${operation.operationId}]`, `two or more steps invoking operation "${operation.operationId}" that one direction references render to the same derived reference even fully escalated; the declared structure does not distinguish them (AD-16, AD-3)`);
|
|
359
379
|
}
|
|
360
380
|
function siblingsByOperation(resolved) {
|
|
361
381
|
const map = new Map();
|
|
@@ -422,6 +442,20 @@ function localTargetPhrase(target) {
|
|
|
422
442
|
return field !== null
|
|
423
443
|
? `the ${field} field of its standard error`
|
|
424
444
|
: 'the standard error you obtained';
|
|
445
|
+
case 'artifact': {
|
|
446
|
+
if (target.artifactId === null) {
|
|
447
|
+
// Unreachable: `parseEvidenceTarget` sets this exactly when the
|
|
448
|
+
// channel is 'artifact'.
|
|
449
|
+
throw new TypeError('artifact evidence target names no artifact');
|
|
450
|
+
}
|
|
451
|
+
// The artifact is named for the same reason the transport channel
|
|
452
|
+
// is: two files can carry the same field name, and an evaluator
|
|
453
|
+
// reading "its findings field" twice cannot tell which file it
|
|
454
|
+
// means.
|
|
455
|
+
return field !== null
|
|
456
|
+
? `the ${field} field of the ${target.artifactId} it wrote`
|
|
457
|
+
: `the ${target.artifactId} it wrote`;
|
|
458
|
+
}
|
|
425
459
|
}
|
|
426
460
|
}
|
|
427
461
|
function fullTargetPhrase(resolved, siblingsOf, index) {
|
|
@@ -436,7 +470,12 @@ function fullTargetPhrase(resolved, siblingsOf, index) {
|
|
|
436
470
|
// 'b']`). Both would join to the same `".../a/b"` string, producing a false
|
|
437
471
|
// tie in `sentFirstOrder` below.
|
|
438
472
|
function channelSignature(target) {
|
|
439
|
-
return JSON.stringify([
|
|
473
|
+
return JSON.stringify([
|
|
474
|
+
target.channel,
|
|
475
|
+
target.transportChannel,
|
|
476
|
+
target.artifactId,
|
|
477
|
+
target.tail,
|
|
478
|
+
]);
|
|
440
479
|
}
|
|
441
480
|
// A total order over one pair, independent of argument order. The final
|
|
442
481
|
// reference-comparison rung fires only on a genuine tie, such as the same
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/** resolves a pointer to its step and operation; nothing about reachability. */
|
|
2
|
-
import type { Operation, PermittedInterface } from '../schemas/interface.ts';
|
|
2
|
+
import type { AnyOperation, CommandOperation, InterfaceKindName, Operation, PermittedInterface } from '../schemas/interface.ts';
|
|
3
3
|
import type { InteractionStep } from '../schemas/plan.ts';
|
|
4
|
-
import { type EvidenceChannelName, type
|
|
4
|
+
import { type EvidenceChannelName, type InputChannelName } from '../schemas/pointer.ts';
|
|
5
5
|
/**
|
|
6
6
|
* Exported so `core/evaluate/evidence-resolution.ts` decodes pointer tails
|
|
7
7
|
* with these same two functions, avoiding a second private copy (the drift
|
|
@@ -17,7 +17,8 @@ export declare const decodeTail: (tailSource: string) => readonly string[];
|
|
|
17
17
|
export type EvidenceTarget = {
|
|
18
18
|
stepId: string;
|
|
19
19
|
channel: EvidenceChannelName;
|
|
20
|
-
transportChannel:
|
|
20
|
+
transportChannel: InputChannelName | null;
|
|
21
|
+
artifactId: string | null;
|
|
21
22
|
tail: readonly string[];
|
|
22
23
|
};
|
|
23
24
|
/**
|
|
@@ -34,10 +35,18 @@ export declare function parseEvidenceTarget(pointer: string): EvidenceTarget;
|
|
|
34
35
|
* about reachability or channel typing; the general addressing-grammar
|
|
35
36
|
* resolver lives in `core/evaluate/evidence-resolution.ts` and reachability
|
|
36
37
|
* in `core/compile/reachability.ts`.
|
|
38
|
+
*
|
|
39
|
+
* `operationOf` stays narrow on purpose. It hands a resolved `Operation` to
|
|
40
|
+
* every downstream consumer, so widening its return type to the operation
|
|
41
|
+
* union would retype seventeen files at once. A command operation resolves to
|
|
42
|
+
* `undefined` from it and to a value from `commandOperationOf`, and each
|
|
43
|
+
* caller that has to branch reads the declaring kind first.
|
|
37
44
|
*/
|
|
38
45
|
export type PlanIndex = {
|
|
39
46
|
stepOf: (stepId: string) => InteractionStep | undefined;
|
|
40
47
|
operationOf: (operationId: string) => Operation | undefined;
|
|
48
|
+
commandOperationOf: (operationId: string) => CommandOperation | undefined;
|
|
49
|
+
interfaceKindOf: (operationId: string) => InterfaceKindName | undefined;
|
|
41
50
|
stepsUsing: (operationId: string) => readonly InteractionStep[];
|
|
42
51
|
};
|
|
43
52
|
export type PlanIndexOptions = {
|
|
@@ -59,5 +68,11 @@ export declare function buildPlanIndex(interactionPlan: readonly InteractionStep
|
|
|
59
68
|
* `RuntimeFault`.
|
|
60
69
|
*/
|
|
61
70
|
export declare function resolveStep(index: PlanIndex, stepId: string): InteractionStep;
|
|
71
|
+
/**
|
|
72
|
+
* The declared operation of whichever kind, for the callers that read only
|
|
73
|
+
* fields both shapes carry. Callers reading a kind-specific field ask
|
|
74
|
+
* `interfaceKindOf` first and then take the matching accessor.
|
|
75
|
+
*/
|
|
76
|
+
export declare const anyOperationOf: (index: PlanIndex, operationId: string) => AnyOperation | undefined;
|
|
62
77
|
/** Resolves an operation id through the index or throws. See `resolveStep`. */
|
|
63
78
|
export declare function resolveOperation(index: PlanIndex, operationId: string): Operation;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { operationsOf } from '../schemas/interface.js';
|
|
2
|
+
import { IDENTIFIER_ROOTED_CHANNEL, INPUT_CHANNELS, SCALAR_CHANNELS, TAIL_BEARING_CHANNELS, TRANSPORT_ROOTED_CHANNEL, } from '../schemas/pointer.js';
|
|
2
3
|
import { IDENTIFIER_CHARSET_SOURCE } from '../schemas/primitives.js';
|
|
3
4
|
// An RFC 6901 reference token, respelled here because pointer.ts keeps its
|
|
4
5
|
// own TOKEN/TAIL fragments private. IDENTIFIER_CHARSET_SOURCE and the channel
|
|
@@ -14,10 +15,10 @@ const alternation = (members) => members.join('|');
|
|
|
14
15
|
// Named capture groups replace positional indices, avoiding a fragile
|
|
15
16
|
// dependency on `IDENTIFIER_CHARSET_SOURCE` staying free of its own capturing
|
|
16
17
|
// groups.
|
|
17
|
-
const EVIDENCE_TARGET_PATTERN = new RegExp(`^/interactions/(?<stepId>${IDENTIFIER_CHARSET_SOURCE})/(?:(?<tailBearingChannel>${alternation(TAIL_BEARING_CHANNELS)})(?<tailBearingTail>${TAIL_SOURCE})|(?<scalarChannel>${alternation(SCALAR_CHANNELS)})|${TRANSPORT_ROOTED_CHANNEL}/(?<transportChannel>${alternation(
|
|
18
|
+
const EVIDENCE_TARGET_PATTERN = new RegExp(`^/interactions/(?<stepId>${IDENTIFIER_CHARSET_SOURCE})/(?:(?<tailBearingChannel>${alternation(TAIL_BEARING_CHANNELS)})(?<tailBearingTail>${TAIL_SOURCE})|(?<scalarChannel>${alternation(SCALAR_CHANNELS)})|${TRANSPORT_ROOTED_CHANNEL}/(?<transportChannel>${alternation(INPUT_CHANNELS)})(?<callInputsTail>${TAIL_SOURCE})|${IDENTIFIER_ROOTED_CHANNEL}/(?<artifactId>${IDENTIFIER_CHARSET_SOURCE})(?<artifactTail>${TAIL_SOURCE}))$`);
|
|
18
19
|
const isEvidenceChannel = (value) => TAIL_BEARING_CHANNELS.includes(value) ||
|
|
19
20
|
SCALAR_CHANNELS.includes(value);
|
|
20
|
-
const
|
|
21
|
+
const isInputChannel = (value) => INPUT_CHANNELS.includes(value);
|
|
21
22
|
/**
|
|
22
23
|
* Exported so `core/evaluate/evidence-resolution.ts` decodes pointer tails
|
|
23
24
|
* with these same two functions, avoiding a second private copy (the drift
|
|
@@ -47,6 +48,7 @@ export function parseEvidenceTarget(pointer) {
|
|
|
47
48
|
stepId,
|
|
48
49
|
channel: groups.scalarChannel,
|
|
49
50
|
transportChannel: null,
|
|
51
|
+
artifactId: null,
|
|
50
52
|
tail: [],
|
|
51
53
|
};
|
|
52
54
|
}
|
|
@@ -59,21 +61,32 @@ export function parseEvidenceTarget(pointer) {
|
|
|
59
61
|
stepId,
|
|
60
62
|
channel: groups.tailBearingChannel,
|
|
61
63
|
transportChannel: null,
|
|
64
|
+
artifactId: null,
|
|
62
65
|
tail: decodeTail(groups.tailBearingTail ?? ''),
|
|
63
66
|
};
|
|
64
67
|
}
|
|
65
68
|
if (groups.transportChannel !== undefined) {
|
|
66
|
-
if (!
|
|
67
|
-
// Unreachable:
|
|
69
|
+
if (!isInputChannel(groups.transportChannel)) {
|
|
70
|
+
// Unreachable: INPUT_CHANNELS is exactly what this group can match.
|
|
68
71
|
throw new TypeError(`call-inputs evidence target names no transport channel: ${pointer}`);
|
|
69
72
|
}
|
|
70
73
|
return {
|
|
71
74
|
stepId,
|
|
72
75
|
channel: 'call-inputs',
|
|
73
76
|
transportChannel: groups.transportChannel,
|
|
77
|
+
artifactId: null,
|
|
74
78
|
tail: decodeTail(groups.callInputsTail ?? ''),
|
|
75
79
|
};
|
|
76
80
|
}
|
|
81
|
+
if (groups.artifactId !== undefined) {
|
|
82
|
+
return {
|
|
83
|
+
stepId,
|
|
84
|
+
channel: IDENTIFIER_ROOTED_CHANNEL,
|
|
85
|
+
transportChannel: null,
|
|
86
|
+
artifactId: groups.artifactId,
|
|
87
|
+
tail: decodeTail(groups.artifactTail ?? ''),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
77
90
|
// Unreachable: the pattern's three branches are exhaustive once stepId matched.
|
|
78
91
|
throw new TypeError(`not an interaction-rooted evidence pointer of a recognized channel: ${pointer}`);
|
|
79
92
|
}
|
|
@@ -109,25 +122,42 @@ export function buildPlanIndex(interactionPlan, permittedInterfaces, options = {
|
|
|
109
122
|
}
|
|
110
123
|
}
|
|
111
124
|
const operations = new Map();
|
|
125
|
+
const commandOperations = new Map();
|
|
126
|
+
const kinds = new Map();
|
|
112
127
|
const duplicateOperationIds = new Set();
|
|
113
128
|
for (const iface of permittedInterfaces) {
|
|
114
|
-
for (const operation of iface
|
|
115
|
-
if (
|
|
129
|
+
for (const operation of operationsOf(iface)) {
|
|
130
|
+
if (kinds.has(operation.operationId) ||
|
|
116
131
|
duplicateOperationIds.has(operation.operationId)) {
|
|
117
132
|
if (duplicateIds === 'throw') {
|
|
118
133
|
throw new TypeError(`duplicate operation id across permitted interfaces: ${operation.operationId}`);
|
|
119
134
|
}
|
|
120
135
|
operations.delete(operation.operationId);
|
|
136
|
+
commandOperations.delete(operation.operationId);
|
|
137
|
+
kinds.delete(operation.operationId);
|
|
121
138
|
duplicateOperationIds.add(operation.operationId);
|
|
122
139
|
}
|
|
123
140
|
else {
|
|
124
|
-
|
|
141
|
+
kinds.set(operation.operationId, iface.kind);
|
|
142
|
+
// Sorted into the two maps by the interface's own kind rather
|
|
143
|
+
// than by probing the operation for a field: `web` and `mcp`
|
|
144
|
+
// carry the api operation shape and belong in the same map as
|
|
145
|
+
// `api`, since every consumer of a resolved operation reads
|
|
146
|
+
// the same declared fields off all three.
|
|
147
|
+
if (iface.kind === 'cli') {
|
|
148
|
+
commandOperations.set(operation.operationId, operation);
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
operations.set(operation.operationId, operation);
|
|
152
|
+
}
|
|
125
153
|
}
|
|
126
154
|
}
|
|
127
155
|
}
|
|
128
156
|
return {
|
|
129
157
|
stepOf: (stepId) => steps.get(stepId),
|
|
130
158
|
operationOf: (operationId) => operations.get(operationId),
|
|
159
|
+
commandOperationOf: (operationId) => commandOperations.get(operationId),
|
|
160
|
+
interfaceKindOf: (operationId) => kinds.get(operationId),
|
|
131
161
|
stepsUsing: (operationId) => stepsByOperation.get(operationId) ?? [],
|
|
132
162
|
};
|
|
133
163
|
}
|
|
@@ -145,6 +175,12 @@ export function resolveStep(index, stepId) {
|
|
|
145
175
|
}
|
|
146
176
|
return step;
|
|
147
177
|
}
|
|
178
|
+
/**
|
|
179
|
+
* The declared operation of whichever kind, for the callers that read only
|
|
180
|
+
* fields both shapes carry. Callers reading a kind-specific field ask
|
|
181
|
+
* `interfaceKindOf` first and then take the matching accessor.
|
|
182
|
+
*/
|
|
183
|
+
export const anyOperationOf = (index, operationId) => index.operationOf(operationId) ?? index.commandOperationOf(operationId);
|
|
148
184
|
/** Resolves an operation id through the index or throws. See `resolveStep`. */
|
|
149
185
|
export function resolveOperation(index, operationId) {
|
|
150
186
|
const operation = index.operationOf(operationId);
|
package/dist/index.d.ts
CHANGED
|
@@ -12,4 +12,4 @@ export type { ScoringPolicy } from './core/schemas/scoring-policy.ts';
|
|
|
12
12
|
export type { SealedEvaluatorBrief } from './core/schemas/sealed-evaluator-brief.ts';
|
|
13
13
|
export type { SealedRunRecord } from './core/schemas/sealed-run-record.ts';
|
|
14
14
|
export type { FixtureReset, ManifestationWitness, SensitivityWitness, SensitivityWitnessLeg, WitnessChannel, WitnessInputs, } from './core/schemas/sensitivity-witness.ts';
|
|
15
|
-
export declare const VERSION = "0.
|
|
15
|
+
export declare const VERSION = "0.5.0";
|
package/dist/index.js
CHANGED