@tangle-network/agent-eval 0.205.2 → 0.207.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 (67) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/dist/adapters/http.d.ts +1 -1
  3. package/dist/analyst/index.d.ts +1 -1
  4. package/dist/analyst/index.js +1 -1
  5. package/dist/{benchmark-command-DuDTN5ID.js → benchmark-command-DtP94cOB.js} +2 -2
  6. package/dist/{benchmark-command-DuDTN5ID.js.map → benchmark-command-DtP94cOB.js.map} +1 -1
  7. package/dist/benchmarks/index.d.ts +2 -2
  8. package/dist/campaign/index.d.ts +3 -3
  9. package/dist/campaign/index.js +2 -2
  10. package/dist/cli.js +3 -2
  11. package/dist/cli.js.map +1 -1
  12. package/dist/contract/index.d.ts +4 -4
  13. package/dist/{define-agent-eval-CKB6wyML.d.ts → define-agent-eval-B2YV-RDE.d.ts} +3 -3
  14. package/dist/{define-agent-eval-CKB6wyML.d.ts.map → define-agent-eval-B2YV-RDE.d.ts.map} +1 -1
  15. package/dist/{index-BRdZ0oJo.d.ts → index-CojsA_EE.d.ts} +2 -2
  16. package/dist/{index-BRdZ0oJo.d.ts.map → index-CojsA_EE.d.ts.map} +1 -1
  17. package/dist/{index-R8Xhod8e.d.ts → index-DVDiJIhi.d.ts} +3 -3
  18. package/dist/{index-R8Xhod8e.d.ts.map → index-DVDiJIhi.d.ts.map} +1 -1
  19. package/dist/index.d.ts +2 -2
  20. package/dist/meta-eval/index.d.ts +69 -0
  21. package/dist/meta-eval/index.d.ts.map +1 -1
  22. package/dist/meta-eval/index.js +135 -1
  23. package/dist/meta-eval/index.js.map +1 -1
  24. package/dist/openapi.json +1 -1
  25. package/dist/rl.d.ts +12 -12
  26. package/dist/rl.d.ts.map +1 -1
  27. package/dist/rl.js +17 -17
  28. package/dist/rl.js.map +1 -1
  29. package/dist/search/index.d.ts +8 -2
  30. package/dist/search/index.d.ts.map +1 -1
  31. package/dist/search/index.js +1 -1
  32. package/dist/{search-kernel-DNpsHb8P.d.ts → search-kernel-CZ8KJQRw.d.ts} +6 -3
  33. package/dist/{search-kernel-DNpsHb8P.d.ts.map → search-kernel-CZ8KJQRw.d.ts.map} +1 -1
  34. package/dist/systemone-protocol-DKoi1NdK.d.ts +132 -0
  35. package/dist/systemone-protocol-DKoi1NdK.d.ts.map +1 -0
  36. package/dist/systemone-protocol.d.ts +2 -0
  37. package/dist/systemone-protocol.js +214 -0
  38. package/dist/systemone-protocol.js.map +1 -0
  39. package/dist/{jev-review-Cw06AKuF.d.ts → systemone-review-DGTKkLMG.d.ts} +16 -16
  40. package/dist/systemone-review-DGTKkLMG.d.ts.map +1 -0
  41. package/dist/{jev-review-DZEjDzlF.js → systemone-review-DTClwgmE.js} +11 -11
  42. package/dist/systemone-review-DTClwgmE.js.map +1 -0
  43. package/dist/systemone.d.ts +60 -0
  44. package/dist/systemone.d.ts.map +1 -0
  45. package/dist/{jev.js → systemone.js} +16 -16
  46. package/dist/systemone.js.map +1 -0
  47. package/dist/{tree-By7LtLUu.js → tree-CN8mlzUO.js} +11 -3
  48. package/dist/{tree-By7LtLUu.js.map → tree-CN8mlzUO.js.map} +1 -1
  49. package/docs/changes/jev-evidence-review.md +1 -1
  50. package/docs/changes/systemone-provider-neutral.md +36 -0
  51. package/docs/public-api.md +96 -70
  52. package/docs/search-ledger.md +9 -3
  53. package/docs/{jev-behavior-review.md → systemone-behavior-review.md} +17 -17
  54. package/docs/{jev-integrations.md → systemone-integrations.md} +4 -4
  55. package/docs/{jev-replay.md → systemone-replay.md} +6 -6
  56. package/docs/{jev.md → systemone.md} +96 -33
  57. package/package.json +9 -9
  58. package/dist/jev-protocol-BQLxwbqD.d.ts +0 -99
  59. package/dist/jev-protocol-BQLxwbqD.d.ts.map +0 -1
  60. package/dist/jev-protocol.d.ts +0 -2
  61. package/dist/jev-protocol.js +0 -114
  62. package/dist/jev-protocol.js.map +0 -1
  63. package/dist/jev-review-Cw06AKuF.d.ts.map +0 -1
  64. package/dist/jev-review-DZEjDzlF.js.map +0 -1
  65. package/dist/jev.d.ts +0 -60
  66. package/dist/jev.d.ts.map +0 -1
  67. package/dist/jev.js.map +0 -1
@@ -4,17 +4,17 @@ Use native evaluations to assess bounded hypotheses about recorded behavior. Do
4
4
  classifier whether an agent is "malicious" or a whole run is "safe". Observable policy breaches,
5
5
  model-supported hypotheses, missing evidence and unusual behavior are different results.
6
6
 
7
- The optional `/jev` helpers are ordinary functions:
7
+ The optional `/systemone` helpers are ordinary functions:
8
8
 
9
- - `prepareJevReview`: validate and freeze caller-defined native questions, evidence references,
9
+ - `prepareSystemOneReview`: validate and freeze caller-defined native questions, evidence references,
10
10
  coverage and decision thresholds before spending. The digest binds the definition, input and
11
11
  authored question/option order. Optional undefined object fields are absent on the wire.
12
- - `assessJevReview`: validate native answers and interpret designated alternative masses as
12
+ - `assessSystemOneReview`: validate native answers and interpret designated alternative masses as
13
13
  `supported`, `refuted` or `unresolved`. Re-scoring makes no network call.
14
- - `jevReviewFindings`: map that report into the existing `AnalystFinding` contract. It keeps
14
+ - `systemOneReviewFindings`: map that report into the existing `AnalystFinding` contract. It keeps
15
15
  unresolved checks visible and labels supported claims as model-supported hypotheses.
16
16
 
17
- These helpers do not constrain `jevEvaluator`, `jevJudge`, `jevAnalyst`, or the provider-independent
17
+ These helpers do not constrain `systemOneEvaluator`, `systemOneJudge`, `systemOneAnalyst`, or the provider-independent
18
18
  `createEvaluator`/`asJudge`/`asAnalyst` APIs. Use an ordinary custom mapper for different policies.
19
19
  No model, taxonomy, severity, operating threshold, global safety score or storage backend is chosen
20
20
  by the generic implementation.
@@ -26,16 +26,16 @@ Supply the native request on each invocation. This example's `question`, `eviden
26
26
 
27
27
  ```ts
28
28
  import {
29
- prepareJevReview, assessJevReview, jevEvaluator,
30
- } from '@tangle-network/agent-eval/jev'
29
+ prepareSystemOneReview, assessSystemOneReview, systemOneEvaluator,
30
+ } from '@tangle-network/agent-eval/systemone'
31
31
 
32
- const evaluate = jevEvaluator({
32
+ const evaluate = systemOneEvaluator({
33
33
  evaluate: nativeTransport, // One Router /v1/systemone attempt; preserve signal/idempotency key.
34
34
  receipt: readRouterReceipt,
35
35
  maximumCharge: enforcedMaximumCharge,
36
36
  })
37
37
 
38
- const review = prepareJevReview({
38
+ const review = prepareSystemOneReview({
39
39
  version: policy.version,
40
40
  request: {
41
41
  model: selectedModel,
@@ -59,7 +59,7 @@ const review = prepareJevReview({
59
59
  })
60
60
  const result = await evaluate(review.request, executionContext)
61
61
  await persistAuthorizedObservation({ review, result })
62
- const report = assessJevReview(review, result.value)
62
+ const report = assessSystemOneReview(review, result.value)
63
63
  ```
64
64
 
65
65
  The example assumes a native Choice question with `supported`, `refuted` and `insufficient`
@@ -71,8 +71,8 @@ not a requirement imposed on other evaluators.
71
71
 
72
72
  ## Optional behavior recipe
73
73
 
74
- `examples/jev-behavior-review.ts` provides replaceable question definitions and
75
- `behaviorReviewAnalyst`, which composes the existing `jevAnalyst`. Copy/adapt the recipe in an
74
+ `examples/systemone-behavior-review.ts` provides replaceable question definitions and
75
+ `behaviorReviewAnalyst`, which composes the existing `systemOneAnalyst`. Copy/adapt the recipe in an
76
76
  application; it is not a default policy installed by importing the package. Select only relevant
77
77
  checks and provide thresholds, severity, exact policy and evidence for every selected check.
78
78
 
@@ -126,7 +126,7 @@ probability with its frozen binary threshold rule; it must not silently drop the
126
126
  `/rl` already has `detectRewardHacking` for reward divergence, distribution shift, reward
127
127
  disagreement and judge drift. Those diagnostic scores are not probabilities. Keep the raw,
128
128
  ungated proxy and independently measured task outcome so a previous rejection does not hide the
129
- disagreement. Do not substitute the Jev monitor as the only independent outcome.
129
+ disagreement. Do not substitute the System One monitor as the only independent outcome.
130
130
 
131
131
  The analyst system already has deterministic control-integrity and behavioral/efficiency
132
132
  checks, plus deep trace analyst definitions such as intent divergence and knowledge poisoning.
@@ -134,7 +134,7 @@ Run exact checks for facts code can establish; use a bounded semantic review for
134
134
  escalate selected cases to the existing deeper analyst. None is replaced by this recipe.
135
135
 
136
136
  A prepared review can be a custom registry input or built from a filtered trace store. Existing
137
- `asAnalyst`/`jevAnalyst` forward the shared paid-call account, cancellation and deadline. The
137
+ `asAnalyst`/`systemOneAnalyst` forward the shared paid-call account, cancellation and deadline. The
138
138
  recipe verifies persisted definition identity before inference, records the native observation
139
139
  before mapping, and returns ordinary findings. Graphs consume these through their existing
140
140
  analyst-registry adapter. No new supervisor, scheduler, ledger, or trace database is introduced.
@@ -158,7 +158,7 @@ It decides `pass`, `hack` or `unknown` for one claim from signals the caller com
158
158
  - `farmingSignal`: one value of a parameter the scope declares, repeated across a lane's sweep of claims.
159
159
  - `graderReferenceSignal`: the claim page justifies itself by the checker or by the printed letter.
160
160
  - `refereeSignal`: a model reads the source and the claim's parameters, never the claimant's prose (`sourceScopeRefereeMessages`, `parseSourceScopeReferee`).
161
- - `jevSignal`: typed questions over the same brief (`claimIntegrityJevReview`). The caller supplies calibrated thresholds.
161
+ - `systemOneSignal`: typed questions over the same brief (`claimIntegritySystemOneReview`). The caller supplies calibrated thresholds.
162
162
  - `monitorSignal`: `askTraceQuestions` with `claimIntegrityTraceQuestions`, on escalation only.
163
163
  - `checkerReadSignal`: context for a reader; it never moves a verdict.
164
164
 
@@ -172,7 +172,7 @@ Keep verdicts, scopes and questions away from the agent that filed the claim: an
172
172
  ## Security and validation boundaries
173
173
 
174
174
  TypeSafe's Jev 1.13 documentation explicitly warns that adversarial state content can move the
175
- answer. Delimiters and explicit criteria are useful instructions, not a proof of injection
175
+ answer; treat every System One model the same way. Delimiters and explicit criteria are useful instructions, not a proof of injection
176
176
  resistance. These monitors are advisory evidence, not the sole authorization/safety barrier.
177
177
  Trusted policy and references must come from outside the evaluated agent; tenant scope, redaction,
178
178
  credential handling and controls remain with existing application/security owners.
@@ -192,7 +192,7 @@ attacks, not only the worker under a fixed monitor.
192
192
 
193
193
  The new tests exercise pure mapping, canonical identity, metadata isolation and real
194
194
  Eval/AnalystRegistry accounting composition with an injected model boundary. They do not prove
195
- that Jev detects these behaviors correctly or is robust against adversarial prompts. No live
195
+ that a System One model detects these behaviors correctly or is robust against adversarial prompts. No live
196
196
  provider, product UI rollout, runtime hook installation or production enforcement is added here.
197
197
 
198
198
  Sources reviewed: https://docs.typesafe.ai/confidence and
@@ -1,7 +1,7 @@
1
1
  # Ten useful integrations, one evaluator
2
2
 
3
- Jev evaluates bounded questions. Applications supply state, questions and the policy interpreting
4
- answers. jevEvaluator handles the native model; createEvaluator supports other classifiers.
3
+ A System One model evaluates bounded questions. Applications supply state, questions and the policy interpreting
4
+ answers. systemOneEvaluator handles the native model; createEvaluator supports other classifiers.
5
5
  asJudge and asAnalyst adapt the same operation to existing consumers.
6
6
 
7
7
  | Use | Outcome | Existing execution path |
@@ -10,12 +10,12 @@ asJudge and asAnalyst adapt the same operation to existing consumers.
10
10
  | Recommendation triage | Prioritize evidence-linked Intelligence recommendations | Product triage selects existing engine findings and preserves their identities. |
11
11
  | Trace diagnosis | Narrow likely failures before deeper investigation | AnalystRegistry, scoped evidence, and the existing deep analyst. |
12
12
  | Behavioral review | Flag observable policy concerns, not hidden intent | Optional behavior-review recipe plus deterministic reward/control checks. |
13
- | Rubric judging | Compare product or agent outputs | jevJudge/asJudge with caller mappings and independent final assessment. |
13
+ | Rubric judging | Compare product or agent outputs | systemOneJudge/asJudge with caller mappings and independent final assessment. |
14
14
  | Context selection | Select useful retrieved evidence | Native assessments, then deterministic packing with mandatory context protected. |
15
15
  | Skill selection | Select from authorized capabilities | Caller alternatives, including no-selection; existing runtime executes actions. |
16
16
  | Next verification | Choose a test, retrieval or review that resolves uncertainty | Existing graph checkpoints and awaited boundaries, not new permissions. |
17
17
  | Candidate selection | Choose among generated plans or artifacts | Existing matrix/graph, exact checks first, semantic assessment second. |
18
- | Configuration experiments | Compare questions, context, models and thresholds | examples/jev-decision-benchmark.ts using runAgentMatrix and cost receipts. |
18
+ | Configuration experiments | Compare questions, context, models and thresholds | examples/systemone-decision-benchmark.ts using runAgentMatrix and cost receipts. |
19
19
 
20
20
  These are compositions, not ten new frameworks. Product triage and the benchmark recipe are concrete
21
21
  adoption work; other rows reuse existing APIs or identify application policies to configure. An API
@@ -1,4 +1,4 @@
1
- # Inspect recorded Jev evidence without new inference
1
+ # Inspect recorded System One evidence without new inference
2
2
 
3
3
  The historical decoder from #897 is already the protocol owner. This example
4
4
  uses that implementation; it adds no parser, SDK, ledger, database or replay
@@ -7,7 +7,7 @@ policy.
7
7
  From a repository checkout with dependencies installed:
8
8
 
9
9
  ```sh
10
- pnpm exec tsx examples/jev-replay.ts request.json response.json
10
+ pnpm exec tsx examples/systemone-replay.ts request.json response.json
11
11
  ```
12
12
 
13
13
  Supply the original native request and response as separate JSON files. The
@@ -18,8 +18,8 @@ metadata such as generation IDs and decimal receipt strings. Neither input file
18
18
  is rewritten. This is offline inspection, not replay of a paid provider request.
19
19
 
20
20
  Historical null state and null score levels remain readable through
21
- `parseJevRecordedRequest`. They are still invalid for new paid calls through
22
- `parseJevRequest`. Do not cast a historical request to the live type, or change
21
+ `parseSystemOneRecordedRequest`. They are still invalid for new paid calls through
22
+ `parseSystemOneRequest`. Do not cast a historical request to the live type, or change
23
23
  its stored rubric just to satisfy today's admission schema.
24
24
 
25
25
  A mismatch, unreadable file or malformed record returns exit code 1 with a
@@ -30,9 +30,9 @@ terminal or output destination and retain its existing access controls.
30
30
  The same helper is importable from the example:
31
31
 
32
32
  ```ts
33
- import { inspectJevFiles } from './examples/jev-replay'
33
+ import { inspectSystemOneFiles } from './examples/systemone-replay'
34
34
 
35
- const observation = await inspectJevFiles('request.json', 'response.json')
35
+ const observation = await inspectSystemOneFiles('request.json', 'response.json')
36
36
  // Apply an application-owned deterministic mapping to the retained answers.
37
37
  ```
38
38
 
@@ -1,35 +1,50 @@
1
- # Typed evaluations: products, judges, and analysts
1
+ # System One evaluations: products, judges, and analysts
2
+
3
+ System One is a typed decision protocol: a request carries `state` and named questions (noul
4
+ yes/no, choice, or score rubric), and the answer is a probability for every allowed option.
5
+ TypeSafe published it with Jev; Cloudflare Workers AI (Clef, Clef-flash) and Perplexity's
6
+ Decisions API (pplx-decider) serve models on the same wire format. This package owns what a
7
+ valid result means. It names no endpoint, credential or model. Tangle Router owns the provider
8
+ routes behind `POST /v1/systemone`, with their prices, limits and served-model checks, so a
9
+ consumer changes models by changing one id.
2
10
 
3
11
  Configure a transport once. Supply your own model, state, and questions on every
4
12
  call. Interpret the answers in ordinary code; no campaign or agent is required.
5
13
 
6
14
  ```ts
7
- import { TypeSafeClient, noul, choice } from '@typesafe-ai/sdk'
8
- import { jevEvaluator } from '@tangle-network/agent-eval/jev'
9
-
10
- const client = new TypeSafeClient({
11
- baseURL: routerOrigin, // Origin without /v1; omit to use TypeSafe directly.
12
- apiKey: scopedRouterKey,
13
- retry: { maxRetries: 0 },
14
- })
15
- const evaluate = jevEvaluator({
16
- evaluate: (request, { signal, idempotencyKey }) => client.systemOne(request, {
17
- signal,
18
- retry: { maxRetries: 0 },
19
- headers: { 'Idempotency-Key': idempotencyKey },
20
- }),
15
+ import { systemOneEvaluator } from '@tangle-network/agent-eval/systemone'
16
+
17
+ const evaluate = systemOneEvaluator({
18
+ evaluate: async (request, { signal, idempotencyKey }) => {
19
+ const response = await fetch(`${routerOrigin}/v1/systemone`, {
20
+ method: 'POST',
21
+ signal,
22
+ headers: {
23
+ Authorization: `Bearer ${scopedRouterKey}`,
24
+ 'Content-Type': 'application/json',
25
+ 'Idempotency-Key': idempotencyKey,
26
+ },
27
+ body: JSON.stringify(request),
28
+ })
29
+ if (!response.ok) throw new Error(`System One request failed: ${response.status}`)
30
+ return response.json()
31
+ },
21
32
  pricing: reviewedTokenPricing, // An estimate, not a provider-observed charge.
22
33
  })
23
34
 
24
35
  const result = await evaluate({
25
- model: selectedModel,
36
+ model: selectedModel, // a native_evaluation id from Router's /v1/models
26
37
  state: { requirements, evidence },
27
38
  questions: {
28
- supported: noul('Does the evidence support the claim?'),
29
- next: choice({ task: 'Choose the next step using the evidence' }, {
30
- inspect: { when: 'Evidence is missing or contradictory' },
31
- finish: { when: 'The requirements are satisfied' },
32
- }),
39
+ supported: { type: 'noul', instructions: 'Does the evidence support the claim?' },
40
+ next: {
41
+ type: 'choice',
42
+ instructions: 'Choose the next step using the evidence',
43
+ criteria: {
44
+ inspect: 'Evidence is missing or contradictory',
45
+ finish: 'The requirements are satisfied',
46
+ },
47
+ },
33
48
  },
34
49
  }, { signal, costLedger })
35
50
 
@@ -38,21 +53,68 @@ result.value.answers.next.probabilities.inspect // number
38
53
  result.receipt // Existing CostLedger receipt, separate from native answers.
39
54
  ```
40
55
 
41
- The named configuration and evidence values belong to the application. Plain JSON
42
- questions work too; SDK builders are optional. Structured criteria, null instructions and choice or noul
56
+ The named configuration and evidence values belong to the application. TypeSafe's SDK
57
+ builders produce the same JSON and are optional. Structured criteria, null instructions and choice or noul
43
58
  descriptions, and omitted optional fields are supported. `state` and each score
44
- level must be text or JSON; TypeSafe rejects null there, so the parser does too. Static TypeScript questions preserve
59
+ level must be text or JSON; TypeSafe rejects null there, so the parser does too. Providers
60
+ add their own limits: Clef requires non-null `instructions`, 1–64 questions with ids matching
61
+ `^[A-Za-z0-9_.-]{1,100}$`, and 2–255 choice options. Static TypeScript questions preserve
45
62
  exact answer names and choice-label unions. Runtime JSON must be validated; its
46
63
  labels cannot become compile-time literals automatically.
47
64
 
48
- ## Any classifier, not just Jev
65
+ ## Providers, rounding and confidence
66
+
67
+ The wire format is the same for every provider; how each reports its numbers is not. A
68
+ provider's raw result goes through `normalizeSystemOneResult(raw, request, profile)` and then
69
+ the strict `parseSystemOneResult`. The route owner supplies the profile.
70
+
71
+ | Recorded 2026-10-04 | Rounding | `confidence` as returned | Profile |
72
+ | --- | --- | --- | --- |
73
+ | TypeSafe `jev-1.13.0` | 2 decimals. Probabilities sum to 1; the score is not always their expectation (8.79 against 8.86). | `systemOneConfidence` (153 of 153 recorded answers within rounding) | `{ decimals: 2, confidence: 'canonical' }` |
74
+ | Cloudflare `clef`, `clef-flash` | 4 decimals, each probability rounded on its own. Wrapped in Workers AI's `{ result, success, errors, messages }`. | (Σp² − 1/n)/(1 − 1/n) | `{ decimals: 4, confidence: 'provider-defined' }` |
75
+
76
+ The recordings are `tests/fixtures/systemone/providers-2026-10-04.json`, checked by
77
+ `tests/systemone-providers.test.ts`. Without normalization, the strict parser refuses both
78
+ recorded TypeSafe score answers and both recorded Clef score answers.
79
+
80
+ - An answer that already passes the strict checks keeps its probabilities and score.
81
+ - An answer that fails them only within the declared rounding is repaired. A distribution whose
82
+ sum is more than 1e-4 from 1 is divided by its sum. A score becomes the expectation of the
83
+ distribution.
84
+ - Error beyond the rounding throws `SystemOneResponseError`; it is a provider defect. The
85
+ bounds are n half-units for the sum and half a unit plus one unit per level index for the score.
86
+ - With `confidence: 'provider-defined'`, the provider's value moves to `provider_confidence` and
87
+ `confidence` becomes `systemOneConfidence(probabilities)`, so every route reports the same
88
+ function of its probabilities: TypeSafe's published formulas
89
+ (https://docs.typesafe.ai/confidence).
90
+ - Noul answers never change. `noul` is the probability of yes for every provider.
91
+
92
+ Probabilities are not made equivalent across models. A Clef 0.8 and a Jev 0.8 are different
93
+ statements, so a threshold belongs to one model: change `{ model, threshold }` together and audit
94
+ the pair with `auditProbabilityPolicy` against independent outcomes.
95
+
96
+ Score each question type with its proper scoring rule from `/meta-eval`, on `probabilities` and
97
+ `noul`, never on `confidence`:
98
+
99
+ | Question | Rule |
100
+ | --- | --- |
101
+ | `noul` | `brierScore` (binary) |
102
+ | `choice` | `multiclassBrierScore` (sum form, range 0 to 2) |
103
+ | `score` | `rankedProbabilityScore` (levels in order, range 0 to 1) |
104
+
105
+ Top-label ECE comes from `calibrationFromPairs` on (top probability, top answer correct) pairs, with
106
+ `range: { lo: 0, hi: 1 }` and `binning: 'equal-frequency'` for equal-mass bins.
107
+ When items share a source (one task, one pull request), interval estimates resample whole sources:
108
+ `clusterBootstrapMean` takes per-item values or per-item paired differences with their cluster id.
109
+
110
+ ## Any classifier, not only System One
49
111
 
50
112
  `createEvaluator`, `asJudge`, and `asAnalyst` are provider-independent exports from
51
- `@tangle-network/agent-eval/evaluation` (also re-exported from `/jev`).
113
+ `@tangle-network/agent-eval/evaluation` (also re-exported from `/systemone`).
52
114
  `createEvaluator({ execute, receipt })` meters a typed asynchronous function.
53
- It does not require a Jev response, probability output, prompt, or provider SDK.
115
+ It does not require a System One response, probability output, prompt, or provider SDK.
54
116
 
55
- `jevEvaluator` adds native protocol validation and optional `acceptModel(requested,
117
+ `systemOneEvaluator` adds native protocol validation and optional `acceptModel(requested,
56
118
  served)` policy. It preserves the reported model instead of guessing alias rules.
57
119
  Router independently enforces its supported model and pricing policy.
58
120
 
@@ -69,13 +131,13 @@ and analyst context. `map(value, input, analystContext)` creates evidence-backed
69
131
  findings. Use the existing `makeFinding` factory and real event/span/artifact references.
70
132
  An empty finding list is valid; an inference failure is not a clean review.
71
133
 
72
- The optional `jevJudge` and `jevAnalyst` conveniences accept static questions or a
134
+ The optional `systemOneJudge` and `systemOneAnalyst` conveniences accept static questions or a
73
135
  question-producing function. State renderers may be async. Judge renderers receive
74
136
  the evaluation context; analyst renderers and finding mappers receive the effective
75
137
  cancellation/deadline signal. Rendering must honor that signal during external work.
76
138
  Both conveniences accept a `record` callback for the complete observation.
77
139
 
78
- For a numeric rubric, `jevJudge` defaults to `normalizedJevScore`: equally spaced
140
+ For a numeric rubric, `systemOneJudge` defaults to `normalizedSystemOneScore`: equally spaced
79
141
  score expectations on [0,1], noul values unchanged, and an optional weighted mean.
80
142
  It emits no canned notes. Supply `map` for choice utilities, different scales, or
81
143
  critical-failure policies. Dynamic questions and custom mappings require explicit
@@ -98,7 +160,7 @@ none is supplied, an explicit `budgetUsd` creates an account for that invocation
98
160
  Otherwise the evaluator keeps its configured ledger, including its cumulative cap
99
161
  across direct calls, judges, and analysts. An absent analyst budget never creates a
100
162
  fresh unlimited account that overrides the configured one. This precedence is the
101
- same for Jev and other classifiers. A per-analysis budget replaces the default
163
+ same for System One and other classifiers. A per-analysis budget replaces the default
102
164
  account; it is not an additional child limit. Pass the shared run ledger explicitly
103
165
  when the whole run must conserve one authority. Only trusted host code should choose
104
166
  or replace that authority.
@@ -132,10 +194,11 @@ confidence as demonstrated calibration or a classification as proof of root caus
132
194
 
133
195
  ## Checks
134
196
 
135
- Run `pnpm exec vitest run tests/jev*.test.ts tests/evaluation-authority.test.ts`,
197
+ Run `pnpm exec vitest run tests/systemone*.test.ts tests/evaluation-authority.test.ts`,
136
198
  `pnpm typecheck`, `pnpm build`, and `pnpm verify:package`. These are contract and
137
199
  execution checks, not live-provider quality or deployment evidence. The product-integrity
138
200
  rubric lives in `examples/`, not the generic implementation, and is not a default policy.
139
201
 
140
202
  Protocol: https://docs.typesafe.ai/api
141
- SDK: https://github.com/typesafe-ai/typesafe-sdk-js
203
+ Clef: https://developers.cloudflare.com/workers-ai/models/clef/
204
+ SDK (optional builders): https://github.com/typesafe-ai/typesafe-sdk-js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tangle-network/agent-eval",
3
- "version": "0.205.2",
3
+ "version": "0.207.0",
4
4
  "description": "Evaluate and improve AI agents from runs, traces, judges, and feedback. Compare candidates, cluster failures, measure lift, and gate releases.",
5
5
  "homepage": "https://github.com/tangle-network/agent-eval#readme",
6
6
  "repository": {
@@ -19,10 +19,10 @@
19
19
  "import": "./dist/index.js",
20
20
  "default": "./dist/index.js"
21
21
  },
22
- "./jev": {
23
- "types": "./dist/jev.d.ts",
24
- "import": "./dist/jev.js",
25
- "default": "./dist/jev.js"
22
+ "./systemone": {
23
+ "types": "./dist/systemone.d.ts",
24
+ "import": "./dist/systemone.js",
25
+ "default": "./dist/systemone.js"
26
26
  },
27
27
  "./profile-cell": {
28
28
  "types": "./dist/profile-cell.d.ts",
@@ -177,10 +177,10 @@
177
177
  "import": "./dist/evaluation.js",
178
178
  "default": "./dist/evaluation.js"
179
179
  },
180
- "./jev/protocol": {
181
- "types": "./dist/jev-protocol.d.ts",
182
- "import": "./dist/jev-protocol.js",
183
- "default": "./dist/jev-protocol.js"
180
+ "./systemone/protocol": {
181
+ "types": "./dist/systemone-protocol.d.ts",
182
+ "import": "./dist/systemone-protocol.js",
183
+ "default": "./dist/systemone-protocol.js"
184
184
  }
185
185
  },
186
186
  "bin": {
@@ -1,99 +0,0 @@
1
- //#region src/jev-protocol.d.ts
2
- /**
3
- * Structural equivalents of TypeSafe's published request schema
4
- * (https://api.typesafe.ai/openapi.json); callers can use its builders unchanged.
5
- */
6
- type JevJson = string | number | boolean | null | JevJson[] | {
7
- [key: string]: JevJson;
8
- };
9
- /** What TypeSafe accepts as `state` and as a score level: text or JSON, never null. */
10
- type JevState = string | {
11
- [key: string]: JevJson;
12
- } | JevJson[];
13
- /** Instructions and choice or noul descriptions, which TypeSafe also accepts as null. */
14
- type JevDescription = JevState | null;
15
- type JevScoreCriteria = readonly [JevState, JevState, ...JevState[]];
16
- type JevQuestion = {
17
- type: 'noul';
18
- instructions?: JevDescription;
19
- criteria?: {
20
- true?: JevDescription;
21
- false?: JevDescription;
22
- } | null;
23
- } | {
24
- type: 'score';
25
- instructions?: JevDescription;
26
- criteria: JevScoreCriteria;
27
- } | {
28
- type: 'choice';
29
- instructions?: JevDescription;
30
- criteria: Record<string, JevDescription>;
31
- };
32
- type JevQuestions = Record<string, JevQuestion>;
33
- interface JevRequest<Q extends JevQuestions = JevQuestions> {
34
- model: string;
35
- state: JevState;
36
- questions: Q;
37
- }
38
- /** Historical Tangle observations accepted null state and score levels. Not a live request. */
39
- type JevRecordedQuestion = Exclude<JevQuestion, {
40
- type: 'score';
41
- }> | {
42
- type: 'score';
43
- instructions?: JevDescription;
44
- criteria: readonly [JevDescription, JevDescription, ...JevDescription[]];
45
- };
46
- type JevRecordedQuestions = Record<string, JevRecordedQuestion>;
47
- interface JevRecordedRequest<Q extends JevRecordedQuestions = JevRecordedQuestions> {
48
- model: string;
49
- state: JevDescription;
50
- questions: Q;
51
- }
52
- type ScoreKeys<T extends readonly JevDescription[]> = number extends T['length'] ? number : Extract<keyof T, `${number}`>;
53
- type JevAnswerFor<Q extends JevRecordedQuestion> = Q extends {
54
- type: 'noul';
55
- } ? {
56
- readonly type: 'noul';
57
- readonly noul: number;
58
- } : Q extends {
59
- type: 'score';
60
- criteria: infer C extends readonly JevDescription[];
61
- } ? {
62
- readonly type: 'score';
63
- readonly score: number;
64
- readonly confidence: number;
65
- readonly legend: { readonly [K in ScoreKeys<C>]: C[K]; };
66
- readonly probabilities: { readonly [K in ScoreKeys<C>]: number; };
67
- } : Q extends {
68
- type: 'choice';
69
- criteria: infer C;
70
- } ? {
71
- readonly type: 'choice';
72
- readonly choice: keyof C & string;
73
- readonly confidence: number;
74
- readonly probabilities: { readonly [K in keyof C]: number; };
75
- } : never;
76
- type JevAnswer = JevAnswerFor<JevQuestion>;
77
- interface JevResult<Q extends JevRecordedQuestions = JevQuestions> {
78
- readonly model: string;
79
- readonly answers: { readonly [K in keyof Q]: JevAnswerFor<Q[K]>; };
80
- readonly usage: {
81
- readonly input_tokens: number;
82
- readonly output_tokens: number;
83
- };
84
- }
85
- declare class JevResponseError extends Error {
86
- constructor(message: string);
87
- }
88
- /** Validate named questions without a state, as a judge does before it has input. */
89
- declare function parseJevQuestions(raw: unknown): JevQuestions;
90
- declare function parseJevRequest(raw: unknown): JevRequest;
91
- /** Read immutable historical evidence without rewriting it or authorizing new inference.
92
- * Live transports must still call parseJevRequest, even for re-execution of an old request. */
93
- declare function parseJevRecordedRequest(raw: unknown): JevRecordedRequest;
94
- declare function jevUsage(raw: unknown): JevResult['usage'];
95
- /** Validate native evidence, not model alias policy or the caller's scoring rules. */
96
- declare function parseJevResult<Q extends JevRecordedQuestions>(raw: unknown, request: JevRecordedRequest<Q>): JevResult<Q>;
97
- //#endregion
98
- export { parseJevRecordedRequest as _, JevQuestion as a, JevRecordedQuestions as c, JevResponseError as d, JevResult as f, parseJevQuestions as g, jevUsage as h, JevJson as i, JevRecordedRequest as l, JevState as m, JevAnswerFor as n, JevQuestions as o, JevScoreCriteria as p, JevDescription as r, JevRecordedQuestion as s, JevAnswer as t, JevRequest as u, parseJevRequest as v, parseJevResult as y };
99
- //# sourceMappingURL=jev-protocol-BQLxwbqD.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"jev-protocol-BQLxwbqD.d.ts","names":[],"sources":["../src/jev-protocol.ts"],"mappings":";;;;;KAOY,6CAA6C;GAAe,cAAc;;;KAE1E;GAAuB,cAAc;IAAY;;KAEjD,iBAAiB;KACjB,6BAA6B,UAAU,aAAa;KACpD;EAEN;EACA,eAAe;EACf;IAAa,OAAO;IAAgB,QAAQ;;;EAE5C;EAAe,eAAe;EAAgB,UAAU;;EACxD;EAAgB,eAAe;EAAgB,UAAU,eAAe;;KAClE,eAAe,eAAe;UACzB,WAAW,UAAU,eAAe;EACnD;EACA,OAAO;EACP,WAAW;;;KAID,sBACR,QAAQ;EAAe;;EAErB;EACA,eAAe;EACf,oBAAoB,gBAAgB,mBAAmB;;KAEjD,uBAAuB,eAAe;UACjC,mBAAmB,UAAU,uBAAuB;EACnE;EACA,OAAO;EACP,WAAW;;KAGR,UAAU,mBAAmB,mCAAmC,uBAEjE,cAAc;KACN,aAAa,UAAU,uBAAuB;EAAY;;WACvD;WAAuB;IAClC;EAAY;EAAe,gBAAgB,mBAAmB;;WAEjD;WACA;WACA;WACA,oBAAoB,KAAK,UAAU,KAAK,EAAE;WAC1C,2BAA2B,KAAK,UAAU;IAErD;EAAY;EAAgB,gBAAgB;;WAE/B;WACA,cAAc;WACd;WACA,2BAA2B,WAAW;;KAG7C,YAAY,aAAa;UACpB,UAAU,UAAU,uBAAuB;WACjD;WACA,qBAAqB,WAAW,IAAI,aAAa,EAAE;WACnD;aAAkB;aAA+B;;;cAG/C,yBAAyB;EACpC,YAAY;;;iBA6BE,kBAAkB,eAAe;iBAyCjC,gBAAgB,eAAe;;;iBAM/B,wBAAwB,eAAe;iBAevC,SAAS,eAAe;;iBA2BxB,eAAe,UAAU,sBACvC,cACA,SAAS,mBAAmB,KAC3B,UAAU"}
@@ -1,2 +0,0 @@
1
- import { _ as parseJevRecordedRequest, a as JevQuestion, c as JevRecordedQuestions, d as JevResponseError, f as JevResult, g as parseJevQuestions, h as jevUsage, i as JevJson, l as JevRecordedRequest, m as JevState, n as JevAnswerFor, o as JevQuestions, p as JevScoreCriteria, r as JevDescription, s as JevRecordedQuestion, t as JevAnswer, u as JevRequest, v as parseJevRequest, y as parseJevResult } from "./jev-protocol-BQLxwbqD.js";
2
- export { JevAnswer, JevAnswerFor, JevDescription, JevJson, JevQuestion, JevQuestions, JevRecordedQuestion, JevRecordedQuestions, JevRecordedRequest, JevRequest, JevResponseError, JevResult, JevScoreCriteria, JevState, jevUsage, parseJevQuestions, parseJevRecordedRequest, parseJevRequest, parseJevResult };
@@ -1,114 +0,0 @@
1
- import { r as canonicalString } from "./canonical-BsZVgBhW.js";
2
- import { isDeepStrictEqual } from "node:util";
3
- //#region src/jev-protocol.ts
4
- var JevResponseError = class extends Error {
5
- constructor(message) {
6
- super(`Jev: ${message}`);
7
- this.name = "JevResponseError";
8
- }
9
- };
10
- function object(value) {
11
- if (value === null || typeof value !== "object" || Array.isArray(value)) throw new JevResponseError("Expected an object");
12
- return value;
13
- }
14
- function textOrJson(value, name) {
15
- if (typeof value === "string") return;
16
- if (value === null || typeof value !== "object") throw new TypeError(`${name} must be text or a JSON object/array`);
17
- canonicalString(value);
18
- }
19
- function optionalTextOrJson(value, name) {
20
- if (value !== null) textOrJson(value, name);
21
- }
22
- /** Validate named questions without a state, as a judge does before it has input. */
23
- function parseJevQuestions(raw) {
24
- return readQuestions(raw, false);
25
- }
26
- function readQuestions(raw, recorded) {
27
- const questions = object(raw);
28
- if (!Object.keys(questions).length) throw new TypeError("At least one question is required");
29
- for (const [name, rawQuestion] of Object.entries(questions)) {
30
- const question = object(rawQuestion);
31
- if (question.instructions !== void 0) optionalTextOrJson(question.instructions, `${name} instructions`);
32
- if (question.type === "noul") {
33
- if (question.criteria != null) {
34
- const criteria = object(question.criteria);
35
- if (Object.keys(criteria).some((key) => key !== "true" && key !== "false")) throw new TypeError("Noul criteria must describe true and/or false");
36
- for (const value of Object.values(criteria)) if (value !== void 0) optionalTextOrJson(value, `${name} criteria`);
37
- }
38
- } else if (question.type === "score") {
39
- if (!Array.isArray(question.criteria) || question.criteria.length < 2) throw new TypeError("Score criteria require at least two ordered entries");
40
- for (const value of question.criteria) {
41
- if (recorded && value === null) continue;
42
- textOrJson(value, `${name} score level`);
43
- }
44
- } else if (question.type === "choice") {
45
- const criteria = object(question.criteria);
46
- if (!Object.keys(criteria).length) throw new TypeError("Choice criteria cannot be empty");
47
- for (const value of Object.values(criteria)) optionalTextOrJson(value, `${name} choice`);
48
- } else throw new TypeError("Unsupported native question type");
49
- }
50
- return raw;
51
- }
52
- function parseJevRequest(raw) {
53
- return readRequest(raw, false);
54
- }
55
- /** Read immutable historical evidence without rewriting it or authorizing new inference.
56
- * Live transports must still call parseJevRequest, even for re-execution of an old request. */
57
- function parseJevRecordedRequest(raw) {
58
- canonicalString(raw);
59
- return readRequest(raw, true);
60
- }
61
- function readRequest(raw, recorded) {
62
- const request = object(raw);
63
- if (typeof request.model !== "string" || !request.model.trim()) throw new TypeError("Evaluation requires a model");
64
- if (!recorded || request.state !== null) textOrJson(request.state, "Evaluation state");
65
- readQuestions(request.questions, recorded);
66
- return raw;
67
- }
68
- function jevUsage(raw) {
69
- const usage = object(object(raw).usage);
70
- for (const key of ["input_tokens", "output_tokens"]) if (!Number.isSafeInteger(usage[key]) || Number(usage[key]) < 0) throw new JevResponseError("Missing or invalid usage");
71
- return usage;
72
- }
73
- function probability(value) {
74
- if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1) throw new JevResponseError("Invalid probability");
75
- return value;
76
- }
77
- function exactKeys(value, names) {
78
- if (Object.keys(value).length !== names.length || names.some((key) => !Object.hasOwn(value, key))) throw new JevResponseError("Response keys differ from the request");
79
- }
80
- /** Validate native evidence, not model alias policy or the caller's scoring rules. */
81
- function parseJevResult(raw, request) {
82
- canonicalString(raw);
83
- const response = object(raw);
84
- if (typeof response.model !== "string" || !response.model.trim()) throw new JevResponseError("Missing served model");
85
- const answers = object(response.answers);
86
- exactKeys(answers, Object.keys(request.questions));
87
- for (const [name, question] of Object.entries(request.questions)) {
88
- const answer = object(answers[name]);
89
- if (answer.type !== question.type) throw new JevResponseError("Wrong answer type");
90
- if (question.type === "noul") {
91
- probability(answer.noul);
92
- continue;
93
- }
94
- probability(answer.confidence);
95
- const levels = question.type === "score" ? question.criteria.map((_, index) => String(index)) : Object.keys(question.criteria);
96
- const probabilities = object(answer.probabilities);
97
- exactKeys(probabilities, levels);
98
- const sum = levels.reduce((total, level) => total + probability(probabilities[level]), 0);
99
- if (Math.abs(sum - 1) > 1e-4) throw new JevResponseError("Invalid probability distribution");
100
- if (question.type === "score") {
101
- const legend = object(answer.legend);
102
- exactKeys(legend, levels);
103
- if (levels.some((level) => !isDeepStrictEqual(legend[level], question.criteria[Number(level)]))) throw new JevResponseError("Provider changed the rubric");
104
- const expected = levels.reduce((total, level) => total + Number(level) * Number(probabilities[level]), 0);
105
- if (typeof answer.score !== "number" || !Number.isFinite(answer.score) || Math.abs(answer.score - expected) > 1e-4) throw new JevResponseError("Score differs from its distribution");
106
- } else if (typeof answer.choice !== "string" || !Object.hasOwn(probabilities, answer.choice) || levels.some((level) => Number(probabilities[level]) > Number(probabilities[String(answer.choice)]) + 1e-4)) throw new JevResponseError("Choice is not a highest-probability option");
107
- }
108
- jevUsage(raw);
109
- return raw;
110
- }
111
- //#endregion
112
- export { JevResponseError, jevUsage, parseJevQuestions, parseJevRecordedRequest, parseJevRequest, parseJevResult };
113
-
114
- //# sourceMappingURL=jev-protocol.js.map