@tangle-network/agent-eval 0.205.2 → 0.206.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 (46) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/analyst/index.d.ts +1 -1
  3. package/dist/analyst/index.js +1 -1
  4. package/dist/{benchmark-command-DuDTN5ID.js → benchmark-command-DtP94cOB.js} +2 -2
  5. package/dist/{benchmark-command-DuDTN5ID.js.map → benchmark-command-DtP94cOB.js.map} +1 -1
  6. package/dist/cli.js +1 -1
  7. package/dist/meta-eval/index.d.ts +6 -0
  8. package/dist/meta-eval/index.d.ts.map +1 -1
  9. package/dist/meta-eval/index.js +15 -1
  10. package/dist/meta-eval/index.js.map +1 -1
  11. package/dist/openapi.json +1 -1
  12. package/dist/rl.d.ts +12 -12
  13. package/dist/rl.d.ts.map +1 -1
  14. package/dist/rl.js +17 -17
  15. package/dist/rl.js.map +1 -1
  16. package/dist/systemone-protocol-DKoi1NdK.d.ts +132 -0
  17. package/dist/systemone-protocol-DKoi1NdK.d.ts.map +1 -0
  18. package/dist/systemone-protocol.d.ts +2 -0
  19. package/dist/systemone-protocol.js +214 -0
  20. package/dist/systemone-protocol.js.map +1 -0
  21. package/dist/{jev-review-Cw06AKuF.d.ts → systemone-review-DGTKkLMG.d.ts} +16 -16
  22. package/dist/systemone-review-DGTKkLMG.d.ts.map +1 -0
  23. package/dist/{jev-review-DZEjDzlF.js → systemone-review-DTClwgmE.js} +11 -11
  24. package/dist/systemone-review-DTClwgmE.js.map +1 -0
  25. package/dist/systemone.d.ts +60 -0
  26. package/dist/systemone.d.ts.map +1 -0
  27. package/dist/{jev.js → systemone.js} +16 -16
  28. package/dist/systemone.js.map +1 -0
  29. package/docs/changes/jev-evidence-review.md +1 -1
  30. package/docs/changes/systemone-provider-neutral.md +36 -0
  31. package/docs/public-api.md +93 -68
  32. package/docs/{jev-behavior-review.md → systemone-behavior-review.md} +17 -17
  33. package/docs/{jev-integrations.md → systemone-integrations.md} +4 -4
  34. package/docs/{jev-replay.md → systemone-replay.md} +6 -6
  35. package/docs/{jev.md → systemone.md} +84 -33
  36. package/package.json +9 -9
  37. package/dist/jev-protocol-BQLxwbqD.d.ts +0 -99
  38. package/dist/jev-protocol-BQLxwbqD.d.ts.map +0 -1
  39. package/dist/jev-protocol.d.ts +0 -2
  40. package/dist/jev-protocol.js +0 -114
  41. package/dist/jev-protocol.js.map +0 -1
  42. package/dist/jev-review-Cw06AKuF.d.ts.map +0 -1
  43. package/dist/jev-review-DZEjDzlF.js.map +0 -1
  44. package/dist/jev.d.ts +0 -60
  45. package/dist/jev.d.ts.map +0 -1
  46. package/dist/jev.js.map +0 -1
@@ -0,0 +1,132 @@
1
+ //#region src/systemone-protocol.d.ts
2
+ /**
3
+ * The System One wire contract (TypeSafe-originated, https://api.typesafe.ai/openapi.json; also
4
+ * served by Cloudflare Workers AI and Perplexity). This module names no endpoint, credential or
5
+ * model; callers can use TypeSafe's SDK builders unchanged.
6
+ */
7
+ type SystemOneJson = string | number | boolean | null | SystemOneJson[] | {
8
+ [key: string]: SystemOneJson;
9
+ };
10
+ /** What the TypeSafe route accepts as `state` and as a score level: text or JSON, never null. */
11
+ type SystemOneState = string | {
12
+ [key: string]: SystemOneJson;
13
+ } | SystemOneJson[];
14
+ /** Instructions and choice or noul descriptions, which TypeSafe also accepts as null. */
15
+ type SystemOneDescription = SystemOneState | null;
16
+ type SystemOneScoreCriteria = readonly [SystemOneState, SystemOneState, ...SystemOneState[]];
17
+ type SystemOneQuestion = {
18
+ type: 'noul';
19
+ instructions?: SystemOneDescription;
20
+ criteria?: {
21
+ true?: SystemOneDescription;
22
+ false?: SystemOneDescription;
23
+ } | null;
24
+ } | {
25
+ type: 'score';
26
+ instructions?: SystemOneDescription;
27
+ criteria: SystemOneScoreCriteria;
28
+ } | {
29
+ type: 'choice';
30
+ instructions?: SystemOneDescription;
31
+ criteria: Record<string, SystemOneDescription>;
32
+ };
33
+ type SystemOneQuestions = Record<string, SystemOneQuestion>;
34
+ interface SystemOneRequest<Q extends SystemOneQuestions = SystemOneQuestions> {
35
+ model: string;
36
+ state: SystemOneState;
37
+ questions: Q;
38
+ }
39
+ /** Historical Tangle observations accepted null state and score levels. Not a live request. */
40
+ type SystemOneRecordedQuestion = Exclude<SystemOneQuestion, {
41
+ type: 'score';
42
+ }> | {
43
+ type: 'score';
44
+ instructions?: SystemOneDescription;
45
+ criteria: readonly [SystemOneDescription, SystemOneDescription, ...SystemOneDescription[]];
46
+ };
47
+ type SystemOneRecordedQuestions = Record<string, SystemOneRecordedQuestion>;
48
+ interface SystemOneRecordedRequest<Q extends SystemOneRecordedQuestions = SystemOneRecordedQuestions> {
49
+ model: string;
50
+ state: SystemOneDescription;
51
+ questions: Q;
52
+ }
53
+ type ScoreKeys<T extends readonly SystemOneDescription[]> = number extends T['length'] ? number : Extract<keyof T, `${number}`>;
54
+ type SystemOneAnswerFor<Q extends SystemOneRecordedQuestion> = Q extends {
55
+ type: 'noul';
56
+ } ? {
57
+ readonly type: 'noul';
58
+ readonly noul: number;
59
+ } : Q extends {
60
+ type: 'score';
61
+ criteria: infer C extends readonly SystemOneDescription[];
62
+ } ? {
63
+ readonly type: 'score';
64
+ readonly score: number;
65
+ readonly confidence: number;
66
+ readonly legend: { readonly [K in ScoreKeys<C>]: C[K]; };
67
+ readonly probabilities: { readonly [K in ScoreKeys<C>]: number; };
68
+ } : Q extends {
69
+ type: 'choice';
70
+ criteria: infer C;
71
+ } ? {
72
+ readonly type: 'choice';
73
+ readonly choice: keyof C & string;
74
+ readonly confidence: number;
75
+ readonly probabilities: { readonly [K in keyof C]: number; };
76
+ } : never;
77
+ type SystemOneAnswer = SystemOneAnswerFor<SystemOneQuestion>;
78
+ interface SystemOneResult<Q extends SystemOneRecordedQuestions = SystemOneQuestions> {
79
+ readonly model: string;
80
+ readonly answers: { readonly [K in keyof Q]: SystemOneAnswerFor<Q[K]>; };
81
+ readonly usage: {
82
+ readonly input_tokens: number;
83
+ readonly output_tokens: number;
84
+ };
85
+ }
86
+ declare class SystemOneResponseError extends Error {
87
+ constructor(message: string);
88
+ }
89
+ /** Validate named questions without a state, as a judge does before it has input. */
90
+ declare function parseSystemOneQuestions(raw: unknown): SystemOneQuestions;
91
+ declare function parseSystemOneRequest(raw: unknown): SystemOneRequest;
92
+ /** Read immutable historical evidence without rewriting it or authorizing new inference.
93
+ * Live transports must still call parseSystemOneRequest, even for re-execution of an old request. */
94
+ declare function parseSystemOneRecordedRequest(raw: unknown): SystemOneRecordedRequest;
95
+ declare function systemOneUsage(raw: unknown): SystemOneResult['usage'];
96
+ /** Validate native evidence, not model alias policy or the caller's scoring rules. */
97
+ declare function parseSystemOneResult<Q extends SystemOneRecordedQuestions>(raw: unknown, request: SystemOneRecordedRequest<Q>): SystemOneResult<Q>;
98
+ /**
99
+ * How one provider reports results, measured from its responses. The caller that owns the
100
+ * provider route supplies it; this module names no provider.
101
+ */
102
+ interface SystemOneResultProfile {
103
+ /** Decimal places the provider rounds probabilities and scores to. Omit when it reports exact values. */
104
+ readonly decimals?: number;
105
+ /**
106
+ * `canonical`: the provider's `confidence` already follows `systemOneConfidence`.
107
+ * `provider-defined`: it follows another definition, kept as `provider_confidence`.
108
+ */
109
+ readonly confidence: 'canonical' | 'provider-defined';
110
+ }
111
+ /**
112
+ * The one confidence definition every route reports, TypeSafe's published formulas
113
+ * (https://docs.typesafe.ai/confidence). Choice: (p_max − 1/n)/(1 − 1/n), and 1 for one option.
114
+ * Score: 1 − Σ p_i·|i − m| / MAD_uniform, where m is the most likely level (the lowest on ties)
115
+ * and MAD_uniform = (1/n)·Σ|i − (n − 1)/2|. Expects a normalized distribution; noul has none.
116
+ */
117
+ declare function systemOneConfidence(answer: {
118
+ readonly type: 'choice' | 'score';
119
+ readonly probabilities: Readonly<Record<string, number>>;
120
+ }): number;
121
+ /**
122
+ * Remove a provider's declared rounding and apply the one confidence definition, before
123
+ * `parseSystemOneResult`. An answer that already passes the strict checks keeps its
124
+ * probabilities and score. One that fails them only within the declared rounding is renormalized
125
+ * and its score recomputed from that distribution; larger error throws. Noul answers never change.
126
+ * Returns `raw` itself when nothing changes and never mutates it; shapes it cannot read are left
127
+ * for the strict parser to refuse.
128
+ */
129
+ declare function normalizeSystemOneResult(raw: unknown, request: SystemOneRecordedRequest, profile: SystemOneResultProfile): unknown;
130
+ //#endregion
131
+ export { systemOneUsage as S, parseSystemOneQuestions as _, SystemOneQuestion as a, parseSystemOneResult as b, SystemOneRecordedQuestions as c, SystemOneResponseError as d, SystemOneResult as f, normalizeSystemOneResult as g, SystemOneState as h, SystemOneJson as i, SystemOneRecordedRequest as l, SystemOneScoreCriteria as m, SystemOneAnswerFor as n, SystemOneQuestions as o, SystemOneResultProfile as p, SystemOneDescription as r, SystemOneRecordedQuestion as s, SystemOneAnswer as t, SystemOneRequest as u, parseSystemOneRecordedRequest as v, systemOneConfidence as x, parseSystemOneRequest as y };
132
+ //# sourceMappingURL=systemone-protocol-DKoi1NdK.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemone-protocol-DKoi1NdK.d.ts","names":[],"sources":["../src/systemone-protocol.ts"],"mappings":";;;;;;KAQY,mDAKR;GACG,cAAc;;;KAET;GAA6B,cAAc;IAAkB;;KAE7D,uBAAuB;KACvB,mCAAmC,gBAAgB,mBAAmB;KACtE;EAEN;EACA,eAAe;EACf;IAAa,OAAO;IAAsB,QAAQ;;;EAElD;EAAe,eAAe;EAAsB,UAAU;;EAE9D;EACA,eAAe;EACf,UAAU,eAAe;;KAEnB,qBAAqB,eAAe;UAC/B,iBAAiB,UAAU,qBAAqB;EAC/D;EACA,OAAO;EACP,WAAW;;;KAID,4BACR,QAAQ;EAAqB;;EAE3B;EACA,eAAe;EACf,oBAAoB,sBAAsB,yBAAyB;;KAE7D,6BAA6B,eAAe;UACvC,yBACf,UAAU,6BAA6B;EAEvC;EACA,OAAO;EACP,WAAW;;KAGR,UAAU,mBAAmB,yCAAyC,uBAEvE,cAAc;KACN,mBAAmB,UAAU,6BAA6B;EAAY;;WACnE;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,kBAAkB,mBAAmB;UAChC,gBAAgB,UAAU,6BAA6B;WAC7D;WACA,qBAAqB,WAAW,IAAI,mBAAmB,EAAE;WACzD;aAAkB;aAA+B;;;cAG/C,+BAA+B;EAC1C,YAAY;;;iBA6BE,wBAAwB,eAAe;iBAyCvC,sBAAsB,eAAe;;;iBAMrC,8BAA8B,eAAe;iBAe7C,eAAe,eAAe;;iBA2C9B,qBAAqB,UAAU,4BAC7C,cACA,SAAS,yBAAyB,KACjC,gBAAgB;;;;;UA0DF;;WAEN;;;;;WAKA;;;;;;;;iBASK,oBAAoB;WACzB;WACA,eAAe,SAAS;;;;;;;;;;iBAwHnB,yBACd,cACA,SAAS,0BACT,SAAS"}
@@ -0,0 +1,2 @@
1
+ import { S as systemOneUsage, _ as parseSystemOneQuestions, a as SystemOneQuestion, b as parseSystemOneResult, c as SystemOneRecordedQuestions, d as SystemOneResponseError, f as SystemOneResult, g as normalizeSystemOneResult, h as SystemOneState, i as SystemOneJson, l as SystemOneRecordedRequest, m as SystemOneScoreCriteria, n as SystemOneAnswerFor, o as SystemOneQuestions, p as SystemOneResultProfile, r as SystemOneDescription, s as SystemOneRecordedQuestion, t as SystemOneAnswer, u as SystemOneRequest, v as parseSystemOneRecordedRequest, x as systemOneConfidence, y as parseSystemOneRequest } from "./systemone-protocol-DKoi1NdK.js";
2
+ export { SystemOneAnswer, SystemOneAnswerFor, SystemOneDescription, SystemOneJson, SystemOneQuestion, SystemOneQuestions, SystemOneRecordedQuestion, SystemOneRecordedQuestions, SystemOneRecordedRequest, SystemOneRequest, SystemOneResponseError, SystemOneResult, SystemOneResultProfile, SystemOneScoreCriteria, SystemOneState, normalizeSystemOneResult, parseSystemOneQuestions, parseSystemOneRecordedRequest, parseSystemOneRequest, parseSystemOneResult, systemOneConfidence, systemOneUsage };
@@ -0,0 +1,214 @@
1
+ import { r as canonicalString } from "./canonical-BsZVgBhW.js";
2
+ import { isDeepStrictEqual } from "node:util";
3
+ //#region src/systemone-protocol.ts
4
+ var SystemOneResponseError = class extends Error {
5
+ constructor(message) {
6
+ super(`System One: ${message}`);
7
+ this.name = "SystemOneResponseError";
8
+ }
9
+ };
10
+ function object(value) {
11
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new SystemOneResponseError("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 parseSystemOneQuestions(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 parseSystemOneRequest(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 parseSystemOneRequest, even for re-execution of an old request. */
57
+ function parseSystemOneRecordedRequest(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 systemOneUsage(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 SystemOneResponseError("Missing or invalid usage");
71
+ return usage;
72
+ }
73
+ /** The strict parser's allowance for floating-point error; provider rounding is normalized first. */
74
+ const TOLERANCE = 1e-4;
75
+ function levelsOf(question) {
76
+ return question.type === "score" ? question.criteria.map((_, index) => String(index)) : question.type === "choice" ? Object.keys(question.criteria) : [];
77
+ }
78
+ /** Σ level·p over score levels "0".."n-1". */
79
+ function expectation(levels, probabilities) {
80
+ return levels.reduce((total, level) => total + Number(level) * Number(probabilities[level]), 0);
81
+ }
82
+ function probability(value) {
83
+ if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1) throw new SystemOneResponseError("Invalid probability");
84
+ return value;
85
+ }
86
+ function exactKeys(value, names) {
87
+ if (Object.keys(value).length !== names.length || names.some((key) => !Object.hasOwn(value, key))) throw new SystemOneResponseError("Response keys differ from the request");
88
+ }
89
+ /** Validate native evidence, not model alias policy or the caller's scoring rules. */
90
+ function parseSystemOneResult(raw, request) {
91
+ canonicalString(raw);
92
+ const response = object(raw);
93
+ if (typeof response.model !== "string" || !response.model.trim()) throw new SystemOneResponseError("Missing served model");
94
+ const answers = object(response.answers);
95
+ exactKeys(answers, Object.keys(request.questions));
96
+ for (const [name, question] of Object.entries(request.questions)) {
97
+ const answer = object(answers[name]);
98
+ if (answer.type !== question.type) throw new SystemOneResponseError("Wrong answer type");
99
+ if (question.type === "noul") {
100
+ probability(answer.noul);
101
+ continue;
102
+ }
103
+ probability(answer.confidence);
104
+ const levels = levelsOf(question);
105
+ const probabilities = object(answer.probabilities);
106
+ exactKeys(probabilities, levels);
107
+ const sum = levels.reduce((total, level) => total + probability(probabilities[level]), 0);
108
+ if (Math.abs(sum - 1) > TOLERANCE) throw new SystemOneResponseError("Invalid probability distribution");
109
+ if (question.type === "score") {
110
+ const legend = object(answer.legend);
111
+ exactKeys(legend, levels);
112
+ if (levels.some((level) => !isDeepStrictEqual(legend[level], question.criteria[Number(level)]))) throw new SystemOneResponseError("Provider changed the rubric");
113
+ if (typeof answer.score !== "number" || !Number.isFinite(answer.score) || Math.abs(answer.score - expectation(levels, probabilities)) > TOLERANCE) throw new SystemOneResponseError("Score differs from its distribution");
114
+ } else if (typeof answer.choice !== "string" || !Object.hasOwn(probabilities, answer.choice) || levels.some((level) => Number(probabilities[level]) > Number(probabilities[String(answer.choice)]) + TOLERANCE)) throw new SystemOneResponseError("Choice is not a highest-probability option");
115
+ }
116
+ systemOneUsage(raw);
117
+ return raw;
118
+ }
119
+ /**
120
+ * The one confidence definition every route reports, TypeSafe's published formulas
121
+ * (https://docs.typesafe.ai/confidence). Choice: (p_max − 1/n)/(1 − 1/n), and 1 for one option.
122
+ * Score: 1 − Σ p_i·|i − m| / MAD_uniform, where m is the most likely level (the lowest on ties)
123
+ * and MAD_uniform = (1/n)·Σ|i − (n − 1)/2|. Expects a normalized distribution; noul has none.
124
+ */
125
+ function systemOneConfidence(answer) {
126
+ const labels = Object.keys(answer.probabilities);
127
+ const n = labels.length;
128
+ const p = labels.map((label, index) => answer.probabilities[answer.type === "score" ? String(index) : label]);
129
+ if (!n || answer.type === "score" && n < 2 || p.some((value) => typeof value !== "number" || !Number.isFinite(value) || value < 0 || value > 1)) throw new TypeError("Confidence requires a probability for every option or score level");
130
+ const values = p;
131
+ const peak = Math.max(...values);
132
+ let confidence;
133
+ if (answer.type === "choice") confidence = n === 1 ? 1 : (peak - 1 / n) / (1 - 1 / n);
134
+ else {
135
+ const mode = values.indexOf(peak);
136
+ const center = (n - 1) / 2;
137
+ const uniform = values.reduce((total, _, level) => total + Math.abs(level - center), 0) / n;
138
+ confidence = 1 - values.reduce((total, value, level) => total + value * Math.abs(level - mode), 0) / uniform;
139
+ }
140
+ return Math.min(1, Math.max(0, confidence));
141
+ }
142
+ function readProfile(profile) {
143
+ if (profile === null || typeof profile !== "object" || profile.decimals !== void 0 && (!Number.isSafeInteger(profile.decimals) || profile.decimals < 0 || profile.decimals > 15) || profile.confidence !== "canonical" && profile.confidence !== "provider-defined") throw new TypeError("Invalid System One result profile");
144
+ }
145
+ function normalizeAnswer(answer, question, profile) {
146
+ const levels = levelsOf(question);
147
+ const probabilities = answer.probabilities;
148
+ const keys = Object.keys(probabilities);
149
+ if (keys.length !== levels.length || levels.some((level) => {
150
+ const value = probabilities[level];
151
+ return !Object.hasOwn(probabilities, level) || typeof value !== "number" || !(value >= 0 && value <= 1);
152
+ })) return answer;
153
+ const q = probabilities;
154
+ const sum = keys.reduce((total, key) => total + q[key], 0);
155
+ const scored = question.type === "score";
156
+ const score = answer.score;
157
+ if (scored && (typeof score !== "number" || !Number.isFinite(score))) return answer;
158
+ let next = answer;
159
+ if (!(Math.abs(sum - 1) <= TOLERANCE && (!scored || Math.abs(score - expectation(levels, q)) <= TOLERANCE)) && profile.decimals !== void 0) {
160
+ const unit = 10 ** -profile.decimals;
161
+ if (Math.abs(sum - 1) > levels.length * unit / 2) throw new SystemOneResponseError("Distribution error exceeds declared rounding");
162
+ const levelTotal = levels.length * (levels.length - 1) / 2;
163
+ if (scored && Math.abs(score - expectation(levels, q)) > unit / 2 + unit * levelTotal) throw new SystemOneResponseError("Score error exceeds declared rounding");
164
+ const p = Math.abs(sum - 1) <= TOLERANCE ? q : Object.fromEntries(keys.map((key) => [key, q[key] / sum]));
165
+ next = {
166
+ ...answer,
167
+ probabilities: p,
168
+ ...scored ? { score: expectation(levels, p) } : {}
169
+ };
170
+ }
171
+ if (profile.confidence === "provider-defined" && typeof answer.confidence === "number" && !Object.hasOwn(answer, "provider_confidence")) next = {
172
+ ...next,
173
+ provider_confidence: answer.confidence,
174
+ confidence: systemOneConfidence({
175
+ type: question.type,
176
+ probabilities: next.probabilities
177
+ })
178
+ };
179
+ return next;
180
+ }
181
+ /**
182
+ * Remove a provider's declared rounding and apply the one confidence definition, before
183
+ * `parseSystemOneResult`. An answer that already passes the strict checks keeps its
184
+ * probabilities and score. One that fails them only within the declared rounding is renormalized
185
+ * and its score recomputed from that distribution; larger error throws. Noul answers never change.
186
+ * Returns `raw` itself when nothing changes and never mutates it; shapes it cannot read are left
187
+ * for the strict parser to refuse.
188
+ */
189
+ function normalizeSystemOneResult(raw, request, profile) {
190
+ readProfile(profile);
191
+ if (raw === null || typeof raw !== "object" || Array.isArray(raw)) return raw;
192
+ const response = raw;
193
+ const original = response.answers;
194
+ if (original === null || typeof original !== "object" || Array.isArray(original)) return raw;
195
+ const answers = { ...original };
196
+ let changed = false;
197
+ for (const [name, question] of Object.entries(request.questions)) {
198
+ const answer = answers[name];
199
+ if (question.type === "noul" || answer === null || typeof answer !== "object" || Array.isArray(answer) || answer.type !== question.type || answer.probabilities === null || typeof answer.probabilities !== "object" || Array.isArray(answer.probabilities)) continue;
200
+ const next = normalizeAnswer(answer, question, profile);
201
+ if (next !== answer) {
202
+ answers[name] = next;
203
+ changed = true;
204
+ }
205
+ }
206
+ return changed ? {
207
+ ...response,
208
+ answers
209
+ } : raw;
210
+ }
211
+ //#endregion
212
+ export { SystemOneResponseError, normalizeSystemOneResult, parseSystemOneQuestions, parseSystemOneRecordedRequest, parseSystemOneRequest, parseSystemOneResult, systemOneConfidence, systemOneUsage };
213
+
214
+ //# sourceMappingURL=systemone-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemone-protocol.js","names":[],"sources":["../src/systemone-protocol.ts"],"sourcesContent":["import { isDeepStrictEqual } from 'node:util'\nimport { canonicalString } from './ledger-core/canonical'\n\n/**\n * The System One wire contract (TypeSafe-originated, https://api.typesafe.ai/openapi.json; also\n * served by Cloudflare Workers AI and Perplexity). This module names no endpoint, credential or\n * model; callers can use TypeSafe's SDK builders unchanged.\n */\nexport type SystemOneJson =\n | string\n | number\n | boolean\n | null\n | SystemOneJson[]\n | { [key: string]: SystemOneJson }\n/** What the TypeSafe route accepts as `state` and as a score level: text or JSON, never null. */\nexport type SystemOneState = string | { [key: string]: SystemOneJson } | SystemOneJson[]\n/** Instructions and choice or noul descriptions, which TypeSafe also accepts as null. */\nexport type SystemOneDescription = SystemOneState | null\nexport type SystemOneScoreCriteria = readonly [SystemOneState, SystemOneState, ...SystemOneState[]]\nexport type SystemOneQuestion =\n | {\n type: 'noul'\n instructions?: SystemOneDescription\n criteria?: { true?: SystemOneDescription; false?: SystemOneDescription } | null\n }\n | { type: 'score'; instructions?: SystemOneDescription; criteria: SystemOneScoreCriteria }\n | {\n type: 'choice'\n instructions?: SystemOneDescription\n criteria: Record<string, SystemOneDescription>\n }\nexport type SystemOneQuestions = Record<string, SystemOneQuestion>\nexport interface SystemOneRequest<Q extends SystemOneQuestions = SystemOneQuestions> {\n model: string\n state: SystemOneState\n questions: Q\n}\n\n/** Historical Tangle observations accepted null state and score levels. Not a live request. */\nexport type SystemOneRecordedQuestion =\n | Exclude<SystemOneQuestion, { type: 'score' }>\n | {\n type: 'score'\n instructions?: SystemOneDescription\n criteria: readonly [SystemOneDescription, SystemOneDescription, ...SystemOneDescription[]]\n }\nexport type SystemOneRecordedQuestions = Record<string, SystemOneRecordedQuestion>\nexport interface SystemOneRecordedRequest<\n Q extends SystemOneRecordedQuestions = SystemOneRecordedQuestions,\n> {\n model: string\n state: SystemOneDescription\n questions: Q\n}\n\ntype ScoreKeys<T extends readonly SystemOneDescription[]> = number extends T['length']\n ? number\n : Extract<keyof T, `${number}`>\nexport type SystemOneAnswerFor<Q extends SystemOneRecordedQuestion> = Q extends { type: 'noul' }\n ? { readonly type: 'noul'; readonly noul: number }\n : Q extends { type: 'score'; criteria: infer C extends readonly SystemOneDescription[] }\n ? {\n readonly type: 'score'\n readonly score: number\n readonly confidence: number\n readonly legend: { readonly [K in ScoreKeys<C>]: C[K] }\n readonly probabilities: { readonly [K in ScoreKeys<C>]: number }\n }\n : Q extends { type: 'choice'; criteria: infer C }\n ? {\n readonly type: 'choice'\n readonly choice: keyof C & string\n readonly confidence: number\n readonly probabilities: { readonly [K in keyof C]: number }\n }\n : never\nexport type SystemOneAnswer = SystemOneAnswerFor<SystemOneQuestion>\nexport interface SystemOneResult<Q extends SystemOneRecordedQuestions = SystemOneQuestions> {\n readonly model: string\n readonly answers: { readonly [K in keyof Q]: SystemOneAnswerFor<Q[K]> }\n readonly usage: { readonly input_tokens: number; readonly output_tokens: number }\n}\n\nexport class SystemOneResponseError extends Error {\n constructor(message: string) {\n super(`System One: ${message}`)\n this.name = 'SystemOneResponseError'\n }\n}\n\nfunction object(value: unknown): Record<string, unknown> {\n if (value === null || typeof value !== 'object' || Array.isArray(value)) {\n throw new SystemOneResponseError('Expected an object')\n }\n return value as Record<string, unknown>\n}\n\n// Providers answer 422 for a null state, and TypeSafe also for a null score level. Refusing them\n// here reports the caller's mistake before a paid round trip, not as a provider failure after one.\nfunction textOrJson(value: unknown, name: string): void {\n if (typeof value === 'string') return\n if (value === null || typeof value !== 'object') {\n throw new TypeError(`${name} must be text or a JSON object/array`)\n }\n // Reuse the canonical JSON validator rather than accepting lossy Map/Date coercions.\n canonicalString(value)\n}\n\nfunction optionalTextOrJson(value: unknown, name: string): void {\n if (value !== null) textOrJson(value, name)\n}\n\n/** Validate named questions without a state, as a judge does before it has input. */\nexport function parseSystemOneQuestions(raw: unknown): SystemOneQuestions {\n return readQuestions(raw, false) as SystemOneQuestions\n}\n\nfunction readQuestions(raw: unknown, recorded: boolean): SystemOneRecordedQuestions {\n const questions = object(raw)\n if (!Object.keys(questions).length) throw new TypeError('At least one question is required')\n for (const [name, rawQuestion] of Object.entries(questions)) {\n const question = object(rawQuestion)\n if (question.instructions !== undefined) {\n optionalTextOrJson(question.instructions, `${name} instructions`)\n }\n if (question.type === 'noul') {\n if (question.criteria != null) {\n const criteria = object(question.criteria)\n if (Object.keys(criteria).some((key) => key !== 'true' && key !== 'false')) {\n throw new TypeError('Noul criteria must describe true and/or false')\n }\n for (const value of Object.values(criteria)) {\n if (value !== undefined) optionalTextOrJson(value, `${name} criteria`)\n }\n }\n } else if (question.type === 'score') {\n if (!Array.isArray(question.criteria) || question.criteria.length < 2) {\n throw new TypeError('Score criteria require at least two ordered entries')\n }\n for (const value of question.criteria) {\n if (recorded && value === null) continue\n textOrJson(value, `${name} score level`)\n }\n } else if (question.type === 'choice') {\n const criteria = object(question.criteria)\n if (!Object.keys(criteria).length) throw new TypeError('Choice criteria cannot be empty')\n for (const value of Object.values(criteria)) optionalTextOrJson(value, `${name} choice`)\n } else {\n throw new TypeError('Unsupported native question type')\n }\n }\n return raw as SystemOneRecordedQuestions\n}\n\nexport function parseSystemOneRequest(raw: unknown): SystemOneRequest {\n return readRequest(raw, false) as SystemOneRequest\n}\n\n/** Read immutable historical evidence without rewriting it or authorizing new inference.\n * Live transports must still call parseSystemOneRequest, even for re-execution of an old request. */\nexport function parseSystemOneRecordedRequest(raw: unknown): SystemOneRecordedRequest {\n canonicalString(raw)\n return readRequest(raw, true)\n}\n\nfunction readRequest(raw: unknown, recorded: boolean): SystemOneRecordedRequest {\n const request = object(raw)\n if (typeof request.model !== 'string' || !request.model.trim()) {\n throw new TypeError('Evaluation requires a model')\n }\n if (!recorded || request.state !== null) textOrJson(request.state, 'Evaluation state')\n readQuestions(request.questions, recorded)\n return raw as SystemOneRecordedRequest\n}\n\nexport function systemOneUsage(raw: unknown): SystemOneResult['usage'] {\n const usage = object(object(raw).usage)\n for (const key of ['input_tokens', 'output_tokens']) {\n if (!Number.isSafeInteger(usage[key]) || Number(usage[key]) < 0) {\n throw new SystemOneResponseError('Missing or invalid usage')\n }\n }\n return usage as unknown as SystemOneResult['usage']\n}\n\n/** The strict parser's allowance for floating-point error; provider rounding is normalized first. */\nconst TOLERANCE = 0.0001\n\nfunction levelsOf(question: SystemOneRecordedQuestion): string[] {\n return question.type === 'score'\n ? question.criteria.map((_, index) => String(index))\n : question.type === 'choice'\n ? Object.keys(question.criteria)\n : []\n}\n\n/** Σ level·p over score levels \"0\"..\"n-1\". */\nfunction expectation(levels: string[], probabilities: Record<string, unknown>): number {\n return levels.reduce((total, level) => total + Number(level) * Number(probabilities[level]), 0)\n}\n\nfunction probability(value: unknown): number {\n if (typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 1) {\n throw new SystemOneResponseError('Invalid probability')\n }\n return value\n}\n\nfunction exactKeys(value: Record<string, unknown>, names: string[]): void {\n if (\n Object.keys(value).length !== names.length ||\n names.some((key) => !Object.hasOwn(value, key))\n ) {\n throw new SystemOneResponseError('Response keys differ from the request')\n }\n}\n\n/** Validate native evidence, not model alias policy or the caller's scoring rules. */\nexport function parseSystemOneResult<Q extends SystemOneRecordedQuestions>(\n raw: unknown,\n request: SystemOneRecordedRequest<Q>,\n): SystemOneResult<Q> {\n // Preserve extension metadata, rejecting values that change when persisted as JSON.\n canonicalString(raw)\n const response = object(raw)\n if (typeof response.model !== 'string' || !response.model.trim()) {\n throw new SystemOneResponseError('Missing served model')\n }\n const answers = object(response.answers)\n exactKeys(answers, Object.keys(request.questions))\n for (const [name, question] of Object.entries(request.questions)) {\n const answer = object(answers[name])\n if (answer.type !== question.type) throw new SystemOneResponseError('Wrong answer type')\n if (question.type === 'noul') {\n probability(answer.noul)\n continue\n }\n probability(answer.confidence)\n const levels = levelsOf(question)\n const probabilities = object(answer.probabilities)\n exactKeys(probabilities, levels)\n const sum = levels.reduce((total, level) => total + probability(probabilities[level]), 0)\n if (Math.abs(sum - 1) > TOLERANCE) {\n throw new SystemOneResponseError('Invalid probability distribution')\n }\n if (question.type === 'score') {\n const legend = object(answer.legend)\n exactKeys(legend, levels)\n if (\n levels.some((level) => !isDeepStrictEqual(legend[level], question.criteria[Number(level)]))\n ) {\n throw new SystemOneResponseError('Provider changed the rubric')\n }\n if (\n typeof answer.score !== 'number' ||\n !Number.isFinite(answer.score) ||\n Math.abs(answer.score - expectation(levels, probabilities)) > TOLERANCE\n ) {\n throw new SystemOneResponseError('Score differs from its distribution')\n }\n } else if (\n typeof answer.choice !== 'string' ||\n !Object.hasOwn(probabilities, answer.choice) ||\n levels.some(\n (level) =>\n Number(probabilities[level]) > Number(probabilities[String(answer.choice)]) + TOLERANCE,\n )\n ) {\n throw new SystemOneResponseError('Choice is not a highest-probability option')\n }\n }\n systemOneUsage(raw)\n return raw as SystemOneResult<Q>\n}\n\n/**\n * How one provider reports results, measured from its responses. The caller that owns the\n * provider route supplies it; this module names no provider.\n */\nexport interface SystemOneResultProfile {\n /** Decimal places the provider rounds probabilities and scores to. Omit when it reports exact values. */\n readonly decimals?: number\n /**\n * `canonical`: the provider's `confidence` already follows `systemOneConfidence`.\n * `provider-defined`: it follows another definition, kept as `provider_confidence`.\n */\n readonly confidence: 'canonical' | 'provider-defined'\n}\n\n/**\n * The one confidence definition every route reports, TypeSafe's published formulas\n * (https://docs.typesafe.ai/confidence). Choice: (p_max − 1/n)/(1 − 1/n), and 1 for one option.\n * Score: 1 − Σ p_i·|i − m| / MAD_uniform, where m is the most likely level (the lowest on ties)\n * and MAD_uniform = (1/n)·Σ|i − (n − 1)/2|. Expects a normalized distribution; noul has none.\n */\nexport function systemOneConfidence(answer: {\n readonly type: 'choice' | 'score'\n readonly probabilities: Readonly<Record<string, number>>\n}): number {\n const labels = Object.keys(answer.probabilities)\n const n = labels.length\n const p = labels.map(\n (label, index) => answer.probabilities[answer.type === 'score' ? String(index) : label],\n )\n if (\n !n ||\n (answer.type === 'score' && n < 2) ||\n p.some(\n (value) => typeof value !== 'number' || !Number.isFinite(value) || value < 0 || value > 1,\n )\n ) {\n throw new TypeError('Confidence requires a probability for every option or score level')\n }\n const values = p as number[]\n const peak = Math.max(...values)\n let confidence: number\n if (answer.type === 'choice') {\n confidence = n === 1 ? 1 : (peak - 1 / n) / (1 - 1 / n)\n } else {\n const mode = values.indexOf(peak)\n const center = (n - 1) / 2\n const uniform = values.reduce((total, _, level) => total + Math.abs(level - center), 0) / n\n const spread = values.reduce((total, value, level) => total + value * Math.abs(level - mode), 0)\n confidence = 1 - spread / uniform\n }\n return Math.min(1, Math.max(0, confidence))\n}\n\nfunction readProfile(profile: SystemOneResultProfile): void {\n if (\n profile === null ||\n typeof profile !== 'object' ||\n (profile.decimals !== undefined &&\n (!Number.isSafeInteger(profile.decimals) || profile.decimals < 0 || profile.decimals > 15)) ||\n (profile.confidence !== 'canonical' && profile.confidence !== 'provider-defined')\n ) {\n throw new TypeError('Invalid System One result profile')\n }\n}\n\nfunction normalizeAnswer(\n answer: Record<string, unknown>,\n question: Exclude<SystemOneRecordedQuestion, { type: 'noul' }>,\n profile: SystemOneResultProfile,\n): Record<string, unknown> {\n const levels = levelsOf(question)\n const probabilities = answer.probabilities as Record<string, unknown>\n const keys = Object.keys(probabilities)\n if (\n keys.length !== levels.length ||\n levels.some((level) => {\n const value = probabilities[level]\n return (\n !Object.hasOwn(probabilities, level) ||\n typeof value !== 'number' ||\n !(value >= 0 && value <= 1)\n )\n })\n ) {\n // Leave shapes the strict parser refuses for it to name.\n return answer\n }\n const q = probabilities as Record<string, number>\n const sum = keys.reduce((total, key) => total + q[key]!, 0)\n const scored = question.type === 'score'\n const score = answer.score\n if (scored && (typeof score !== 'number' || !Number.isFinite(score))) return answer\n let next = answer\n const consistent =\n Math.abs(sum - 1) <= TOLERANCE &&\n (!scored || Math.abs((score as number) - expectation(levels, q)) <= TOLERANCE)\n if (!consistent && profile.decimals !== undefined) {\n // Rounding to `decimals` moves each reported probability by at most one unit in the last\n // place, and the reported score by half a unit; anything larger is a provider defect.\n const unit = 10 ** -profile.decimals\n if (Math.abs(sum - 1) > (levels.length * unit) / 2) {\n throw new SystemOneResponseError('Distribution error exceeds declared rounding')\n }\n const levelTotal = (levels.length * (levels.length - 1)) / 2\n if (\n scored &&\n Math.abs((score as number) - expectation(levels, q)) > unit / 2 + unit * levelTotal\n ) {\n throw new SystemOneResponseError('Score error exceeds declared rounding')\n }\n const p =\n Math.abs(sum - 1) <= TOLERANCE\n ? q\n : Object.fromEntries(keys.map((key) => [key, q[key]! / sum]))\n next = { ...answer, probabilities: p, ...(scored ? { score: expectation(levels, p) } : {}) }\n }\n // An answer that already carries provider_confidence was normalized before.\n if (\n profile.confidence === 'provider-defined' &&\n typeof answer.confidence === 'number' &&\n !Object.hasOwn(answer, 'provider_confidence')\n ) {\n next = {\n ...next,\n provider_confidence: answer.confidence,\n confidence: systemOneConfidence({\n type: question.type,\n probabilities: next.probabilities as Record<string, number>,\n }),\n }\n }\n return next\n}\n\n/**\n * Remove a provider's declared rounding and apply the one confidence definition, before\n * `parseSystemOneResult`. An answer that already passes the strict checks keeps its\n * probabilities and score. One that fails them only within the declared rounding is renormalized\n * and its score recomputed from that distribution; larger error throws. Noul answers never change.\n * Returns `raw` itself when nothing changes and never mutates it; shapes it cannot read are left\n * for the strict parser to refuse.\n */\nexport function normalizeSystemOneResult(\n raw: unknown,\n request: SystemOneRecordedRequest,\n profile: SystemOneResultProfile,\n): unknown {\n readProfile(profile)\n if (raw === null || typeof raw !== 'object' || Array.isArray(raw)) return raw\n const response = raw as Record<string, unknown>\n const original = response.answers\n if (original === null || typeof original !== 'object' || Array.isArray(original)) return raw\n const answers: Record<string, unknown> = { ...original }\n let changed = false\n for (const [name, question] of Object.entries(request.questions)) {\n const answer = answers[name]\n if (\n question.type === 'noul' ||\n answer === null ||\n typeof answer !== 'object' ||\n Array.isArray(answer) ||\n (answer as Record<string, unknown>).type !== question.type ||\n (answer as Record<string, unknown>).probabilities === null ||\n typeof (answer as Record<string, unknown>).probabilities !== 'object' ||\n Array.isArray((answer as Record<string, unknown>).probabilities)\n ) {\n continue\n }\n const next = normalizeAnswer(answer as Record<string, unknown>, question, profile)\n if (next !== answer) {\n answers[name] = next\n changed = true\n }\n }\n return changed ? { ...response, answers } : raw\n}\n"],"mappings":"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"}
@@ -1,7 +1,7 @@
1
1
  import { i as AnalystFinding } from "./types-6VEehmEg.js";
2
- import { f as JevResult, o as JevQuestions, u as JevRequest } from "./jev-protocol-BQLxwbqD.js";
2
+ import { f as SystemOneResult, o as SystemOneQuestions, u as SystemOneRequest } from "./systemone-protocol-DKoi1NdK.js";
3
3
  import { z } from "zod";
4
- //#region src/jev-review.d.ts
4
+ //#region src/systemone-review.d.ts
5
5
  declare const checkSchema: z.ZodObject<{
6
6
  claim: z.ZodString;
7
7
  area: z.ZodString;
@@ -35,17 +35,17 @@ declare const checkSchema: z.ZodObject<{
35
35
  }, z.core.$strict>>;
36
36
  }, z.core.$strict>;
37
37
  /** Optional interpretation of native choices/scores. Policy and evidence belong to the caller. */
38
- type JevReviewCheck = z.infer<typeof checkSchema>;
39
- interface JevReviewInput<Q extends JevQuestions = JevQuestions> {
38
+ type SystemOneReviewCheck = z.infer<typeof checkSchema>;
39
+ interface SystemOneReviewInput<Q extends SystemOneQuestions = SystemOneQuestions> {
40
40
  version: string;
41
- request: JevRequest<Q>;
42
- checks: { [K in keyof Q]: JevReviewCheck; };
41
+ request: SystemOneRequest<Q>;
42
+ checks: { [K in keyof Q]: SystemOneReviewCheck; };
43
43
  }
44
- interface PreparedJevReview<Q extends JevQuestions = JevQuestions> extends JevReviewInput<Q> {
44
+ interface PreparedSystemOneReview<Q extends SystemOneQuestions = SystemOneQuestions> extends SystemOneReviewInput<Q> {
45
45
  /** Binds questions, option order, context, evidence, thresholds and definition version. */
46
46
  digest: string;
47
47
  }
48
- interface JevReviewAssessment {
48
+ interface SystemOneReviewAssessment {
49
49
  question: string;
50
50
  status: 'supported' | 'refuted' | 'unresolved';
51
51
  reason: 'support-threshold' | 'refutation-threshold' | 'missing-evidence' | 'partial-negative-evidence' | 'below-threshold' | 'ambiguous-thresholds';
@@ -54,23 +54,23 @@ interface JevReviewAssessment {
54
54
  refutationProbability: number;
55
55
  unresolvedProbability: number;
56
56
  modelConfidence: number | null;
57
- check: JevReviewCheck;
57
+ check: SystemOneReviewCheck;
58
58
  }
59
- interface JevReviewReport {
59
+ interface SystemOneReviewReport {
60
60
  reviewDigest: string;
61
61
  requestedModel: string;
62
62
  servedModel: string;
63
- assessments: JevReviewAssessment[];
63
+ assessments: SystemOneReviewAssessment[];
64
64
  }
65
65
  /** Validate before paid admission; make a detached, frozen snapshot without rewriting native JSON. */
66
- declare function prepareJevReview<const Q extends JevQuestions>(input: JevReviewInput<Q>): PreparedJevReview<Q>;
66
+ declare function prepareSystemOneReview<const Q extends SystemOneQuestions>(input: SystemOneReviewInput<Q>): PreparedSystemOneReview<Q>;
67
67
  /** Re-score the same retained distribution without new inference or any authorization effect. */
68
- declare function assessJevReview<Q extends JevQuestions>(review: PreparedJevReview<Q>, raw: unknown): JevReviewReport;
68
+ declare function assessSystemOneReview<Q extends SystemOneQuestions>(review: PreparedSystemOneReview<Q>, raw: unknown): SystemOneReviewReport;
69
69
  /** Ordinary analyst findings; a negative review is not a global safety certificate. */
70
- declare function jevReviewFindings<Q extends JevQuestions>(review: PreparedJevReview<Q>, result: JevResult<Q>, options: {
70
+ declare function systemOneReviewFindings<Q extends SystemOneQuestions>(review: PreparedSystemOneReview<Q>, result: SystemOneResult<Q>, options: {
71
71
  analystId: string;
72
72
  producedAt?: string;
73
73
  }): AnalystFinding[];
74
74
  //#endregion
75
- export { PreparedJevReview as a, prepareJevReview as c, JevReviewReport as i, JevReviewCheck as n, assessJevReview as o, JevReviewInput as r, jevReviewFindings as s, JevReviewAssessment as t };
76
- //# sourceMappingURL=jev-review-Cw06AKuF.d.ts.map
75
+ export { SystemOneReviewReport as a, systemOneReviewFindings as c, SystemOneReviewInput as i, SystemOneReviewAssessment as n, assessSystemOneReview as o, SystemOneReviewCheck as r, prepareSystemOneReview as s, PreparedSystemOneReview as t };
76
+ //# sourceMappingURL=systemone-review-DGTKkLMG.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemone-review-DGTKkLMG.d.ts","names":[],"sources":["../src/systemone-review.ts"],"mappings":";;;;cAcM,aAAW,EAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0Bb,EAAA,KAAA;;KAGQ,uBAAuB,EAAE,aAAa;UACjC,qBAAqB,UAAU,qBAAqB;EACnE;EACA,SAAS,iBAAiB;EAC1B,WAAW,WAAW,IAAI;;UAGX,wBAAwB,UAAU,qBAAqB,4BAC9D,qBAAqB;;EAE7B;;UAGe;EACf;EACA;EACA;;EAQA;EACA;EACA;EACA;EACA,OAAO;;UAGQ;EACf;EACA;EACA;EACA,aAAa;;;iBAWC,6BAA6B,UAAU,oBACrD,OAAO,qBAAqB,KAC3B,wBAAwB;;iBAuCX,sBAAsB,UAAU,oBAC9C,QAAQ,wBAAwB,IAChC,eACC;;iBAyDa,wBAAwB,UAAU,oBAChD,QAAQ,wBAAwB,IAChC,QAAQ,gBAAgB,IACxB;EAAW;EAAmB;IAC7B"}
@@ -1,9 +1,9 @@
1
1
  import { a as hashCanonical, o as jsonDocument, r as canonicalString } from "./canonical-BsZVgBhW.js";
2
2
  import { t as deepFreezeCanonicalJson } from "./deep-freeze-CurcOQg3.js";
3
3
  import { r as makeFinding, t as ANALYST_SEVERITIES } from "./types-CW5b90JH.js";
4
- import { parseJevRequest, parseJevResult } from "./jev-protocol.js";
4
+ import { parseSystemOneRequest, parseSystemOneResult } from "./systemone-protocol.js";
5
5
  import { z } from "zod";
6
- //#region src/jev-review.ts
6
+ //#region src/systemone-review.ts
7
7
  const name = z.string().trim().min(1);
8
8
  const probability = z.number().finite().gt(0).max(1);
9
9
  const checkSchema = z.object({
@@ -39,9 +39,9 @@ function alternatives(question) {
39
39
  return question.type === "choice" ? Object.keys(question.criteria) : question.criteria.map((_, index) => String(index));
40
40
  }
41
41
  /** Validate before paid admission; make a detached, frozen snapshot without rewriting native JSON. */
42
- function prepareJevReview(input) {
42
+ function prepareSystemOneReview(input) {
43
43
  if (!input.version?.trim()) throw new TypeError("Review version is required");
44
- parseJevRequest(input.request);
44
+ parseSystemOneRequest(input.request);
45
45
  const document = jsonDocument(input);
46
46
  canonicalString(document);
47
47
  const snapshot = structuredClone(document);
@@ -65,11 +65,11 @@ function prepareJevReview(input) {
65
65
  });
66
66
  }
67
67
  /** Re-score the same retained distribution without new inference or any authorization effect. */
68
- function assessJevReview(review, raw) {
68
+ function assessSystemOneReview(review, raw) {
69
69
  const { digest, ...input } = review;
70
- const prepared = prepareJevReview(input);
70
+ const prepared = prepareSystemOneReview(input);
71
71
  if (prepared.digest !== digest) throw new TypeError("Review definition changed after preparation");
72
- const result = parseJevResult(raw, prepared.request);
72
+ const result = parseSystemOneResult(raw, prepared.request);
73
73
  const assessments = Object.entries(prepared.checks).map(([question, check]) => {
74
74
  const answer = result.answers[question];
75
75
  const probabilities = answer.type === "noul" ? {
@@ -114,9 +114,9 @@ function assessJevReview(review, raw) {
114
114
  };
115
115
  }
116
116
  /** Ordinary analyst findings; a negative review is not a global safety certificate. */
117
- function jevReviewFindings(review, result, options) {
117
+ function systemOneReviewFindings(review, result, options) {
118
118
  if (!options.analystId.trim()) throw new TypeError("Analyst id is required");
119
- const report = assessJevReview(review, result);
119
+ const report = assessSystemOneReview(review, result);
120
120
  return report.assessments.filter((item) => item.status !== "refuted").map((item) => makeFinding({
121
121
  analyst_id: options.analystId,
122
122
  ...options.producedAt === void 0 ? {} : { produced_at: options.producedAt },
@@ -152,6 +152,6 @@ function jevReviewFindings(review, result, options) {
152
152
  }));
153
153
  }
154
154
  //#endregion
155
- export { jevReviewFindings as n, prepareJevReview as r, assessJevReview as t };
155
+ export { prepareSystemOneReview as n, systemOneReviewFindings as r, assessSystemOneReview as t };
156
156
 
157
- //# sourceMappingURL=jev-review-DZEjDzlF.js.map
157
+ //# sourceMappingURL=systemone-review-DTClwgmE.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"systemone-review-DTClwgmE.js","names":[],"sources":["../src/systemone-review.ts"],"sourcesContent":["import { z } from 'zod'\nimport {\n ANALYST_SEVERITIES,\n type AnalystFinding,\n type EvidenceRef,\n makeFinding,\n} from './analyst/types'\nimport { canonicalString, hashCanonical, jsonDocument } from './ledger-core/canonical'\nimport { deepFreezeCanonicalJson } from './ledger-core/deep-freeze'\nimport type { SystemOneQuestions, SystemOneRequest, SystemOneResult } from './systemone-protocol'\nimport { parseSystemOneRequest, parseSystemOneResult } from './systemone-protocol'\n\nconst name = z.string().trim().min(1)\nconst probability = z.number().finite().gt(0).max(1)\nconst checkSchema = z\n .object({\n claim: name,\n area: name,\n subject: name,\n severity: z.enum(ANALYST_SEVERITIES),\n /** Choice labels or score-level keys, never scores invented from category order. */\n supports: z.array(z.string()).min(1),\n refutes: z.array(z.string()).min(1),\n supportAtLeast: probability,\n refuteAtLeast: probability,\n /** Host-supplied coverage of the question's required evidence, not model self-assessment. */\n coverage: z.enum(['complete', 'partial', 'missing']),\n evidence: z.array(\n z\n .object({\n kind: z.enum(['span', 'event', 'artifact', 'finding', 'metric']),\n uri: name,\n excerpt: z.string().optional(),\n })\n .strict(),\n ),\n })\n .strict()\n .refine((value) => value.supportAtLeast + value.refuteAtLeast > 1, {\n message: 'Support and refutation thresholds must not overlap',\n })\n\n/** Optional interpretation of native choices/scores. Policy and evidence belong to the caller. */\nexport type SystemOneReviewCheck = z.infer<typeof checkSchema>\nexport interface SystemOneReviewInput<Q extends SystemOneQuestions = SystemOneQuestions> {\n version: string\n request: SystemOneRequest<Q>\n checks: { [K in keyof Q]: SystemOneReviewCheck }\n}\n\nexport interface PreparedSystemOneReview<Q extends SystemOneQuestions = SystemOneQuestions>\n extends SystemOneReviewInput<Q> {\n /** Binds questions, option order, context, evidence, thresholds and definition version. */\n digest: string\n}\n\nexport interface SystemOneReviewAssessment {\n question: string\n status: 'supported' | 'refuted' | 'unresolved'\n reason:\n | 'support-threshold'\n | 'refutation-threshold'\n | 'missing-evidence'\n | 'partial-negative-evidence'\n | 'below-threshold'\n | 'ambiguous-thresholds'\n /** Unnormalized marginal mass of caller-designated native alternatives. Not calibrated risk. */\n supportProbability: number\n refutationProbability: number\n unresolvedProbability: number\n modelConfidence: number | null\n check: SystemOneReviewCheck\n}\n\nexport interface SystemOneReviewReport {\n reviewDigest: string\n requestedModel: string\n servedModel: string\n assessments: SystemOneReviewAssessment[]\n}\n\nfunction alternatives(question: SystemOneQuestions[string]): string[] {\n if (question.type === 'noul') return ['true', 'false']\n return question.type === 'choice'\n ? Object.keys(question.criteria)\n : question.criteria.map((_, index) => String(index))\n}\n\n/** Validate before paid admission; make a detached, frozen snapshot without rewriting native JSON. */\nexport function prepareSystemOneReview<const Q extends SystemOneQuestions>(\n input: SystemOneReviewInput<Q>,\n): PreparedSystemOneReview<Q> {\n if (!input.version?.trim()) throw new TypeError('Review version is required')\n parseSystemOneRequest(input.request)\n // Document form drops only optional undefined object fields; canonicalization rejects loss.\n const document = jsonDocument(input)\n canonicalString(document)\n // Canonical bytes are for hashing, not dispatch: option order can affect a classifier.\n const snapshot = structuredClone(document) as SystemOneReviewInput<Q>\n const keys = Object.keys(snapshot.request.questions)\n if (\n !snapshot.checks ||\n Object.keys(snapshot.checks).length !== keys.length ||\n keys.some((key) => !Object.hasOwn(snapshot.checks, key))\n ) {\n throw new TypeError('Review checks must match the exact question names')\n }\n for (const key of keys) {\n const check = checkSchema.parse(snapshot.checks[key])\n const labels = [...check.supports, ...check.refutes]\n const allowed = alternatives(snapshot.request.questions[key]!)\n if (\n new Set(labels).size !== labels.length ||\n labels.some((label) => !allowed.includes(label))\n ) {\n throw new TypeError('Review alternatives must exist and be disjoint')\n }\n if (check.coverage !== 'missing' && check.evidence.length === 0) {\n throw new TypeError('Review evidence references are required for non-missing coverage')\n }\n // Validation must not normalize a label into a different native option.\n if (canonicalString(jsonDocument(check)) !== canonicalString(snapshot.checks[key])) {\n throw new TypeError('Review metadata must not require normalization')\n }\n }\n const order = keys.map((key) => [key, alternatives(snapshot.request.questions[key]!)])\n return deepFreezeCanonicalJson({ ...snapshot, digest: hashCanonical({ snapshot, order }) })\n}\n\n/** Re-score the same retained distribution without new inference or any authorization effect. */\nexport function assessSystemOneReview<Q extends SystemOneQuestions>(\n review: PreparedSystemOneReview<Q>,\n raw: unknown,\n): SystemOneReviewReport {\n const { digest, ...input } = review\n const prepared = prepareSystemOneReview(input)\n if (prepared.digest !== digest) throw new TypeError('Review definition changed after preparation')\n const result = parseSystemOneResult(raw, prepared.request)\n const assessments = Object.entries(prepared.checks).map(([question, check]) => {\n const answer = result.answers[question]!\n const probabilities: Record<string, number> =\n answer.type === 'noul' ? { true: answer.noul, false: 1 - answer.noul } : answer.probabilities\n const sum = (labels: string[]) =>\n labels.reduce((total, label) => total + probabilities[label]!, 0)\n const supportProbability = sum(check.supports)\n const refutationProbability = sum(check.refutes)\n const used = new Set([...check.supports, ...check.refutes])\n const unresolvedProbability = sum(\n Object.keys(probabilities).filter((label) => !used.has(label)),\n )\n let status: SystemOneReviewAssessment['status'] = 'unresolved'\n let reason: SystemOneReviewAssessment['reason'] = 'below-threshold'\n if (supportProbability > 1 || refutationProbability > 1 || unresolvedProbability > 1) {\n throw new TypeError('Review probability mass exceeds one; do not silently normalize it')\n }\n if (check.coverage === 'missing') reason = 'missing-evidence'\n else if (\n supportProbability >= check.supportAtLeast &&\n refutationProbability >= check.refuteAtLeast\n ) {\n reason = 'ambiguous-thresholds'\n } else if (supportProbability >= check.supportAtLeast) {\n status = 'supported'\n reason = 'support-threshold'\n } else if (refutationProbability >= check.refuteAtLeast) {\n if (check.coverage === 'complete') {\n status = 'refuted'\n reason = 'refutation-threshold'\n } else reason = 'partial-negative-evidence'\n }\n return {\n question,\n status,\n reason,\n supportProbability,\n refutationProbability,\n unresolvedProbability,\n modelConfidence: answer.type === 'noul' ? null : answer.confidence,\n check: structuredClone(check),\n }\n })\n return {\n reviewDigest: digest,\n requestedModel: review.request.model,\n servedModel: result.model,\n assessments,\n }\n}\n\n/** Ordinary analyst findings; a negative review is not a global safety certificate. */\nexport function systemOneReviewFindings<Q extends SystemOneQuestions>(\n review: PreparedSystemOneReview<Q>,\n result: SystemOneResult<Q>,\n options: { analystId: string; producedAt?: string },\n): AnalystFinding[] {\n if (!options.analystId.trim()) throw new TypeError('Analyst id is required')\n const report = assessSystemOneReview(review, result)\n return report.assessments\n .filter((item) => item.status !== 'refuted')\n .map((item) =>\n makeFinding({\n analyst_id: options.analystId,\n ...(options.producedAt === undefined ? {} : { produced_at: options.producedAt }),\n subject: item.check.subject,\n area: item.status === 'unresolved' ? 'assessment-coverage' : item.check.area,\n severity: item.status === 'unresolved' ? 'info' : item.check.severity,\n claim:\n item.status === 'supported'\n ? `Model-supported hypothesis: ${item.check.claim}`\n : `Unresolved review: ${item.check.claim}`,\n evidence_refs: structuredClone(item.check.evidence) as EvidenceRef[],\n // For unresolved findings, confidence describes the deterministic unresolved status only.\n confidence: item.status === 'supported' ? item.supportProbability : 1,\n derived_from_judge: true,\n id_basis: hashCanonical([item.question, item.status, review.version, item.check.claim]),\n metadata: {\n review_digest: report.reviewDigest,\n question: item.question,\n requested_model: report.requestedModel,\n served_model: report.servedModel,\n assessment: item.status,\n assessment_reason: item.reason,\n evidence_coverage: item.check.coverage,\n support_probability: item.supportProbability,\n refutation_probability: item.refutationProbability,\n unresolved_probability: item.unresolvedProbability,\n model_confidence: item.modelConfidence,\n calibration: 'not-established',\n confidence_basis:\n item.status === 'supported' ? 'model-support-mass' : 'deterministic-status',\n native_answer: structuredClone(result.answers[item.question]),\n },\n }),\n )\n}\n"],"mappings":"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"}