@iris-eval/mcp-server 0.9.0 → 0.10.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 (48) hide show
  1. package/README.md +1 -1
  2. package/dist/config/defaults.js +15 -0
  3. package/dist/dashboard/assets/{index-Cz8_oOqG.js → index-CeJbaq6m.js} +1 -1
  4. package/dist/dashboard/index.html +1 -1
  5. package/dist/dashboard/routes/traces.js +2 -2
  6. package/dist/dashboard/seed-demo-data.js +1 -1
  7. package/dist/eval/citation-verify/verifier.d.ts +16 -1
  8. package/dist/eval/citation-verify/verifier.js +14 -4
  9. package/dist/eval/compose.d.ts +57 -0
  10. package/dist/eval/compose.js +179 -0
  11. package/dist/eval/criticality.d.ts +7 -0
  12. package/dist/eval/decision-moment.js +33 -4
  13. package/dist/eval/engine.d.ts +5 -2
  14. package/dist/eval/engine.js +81 -13
  15. package/dist/eval/llm-judge/evaluator.d.ts +20 -0
  16. package/dist/eval/llm-judge/evaluator.js +10 -1
  17. package/dist/eval/published-accuracy.d.ts +22 -22
  18. package/dist/eval/published-accuracy.js +11 -11
  19. package/dist/eval/risk.d.ts +60 -0
  20. package/dist/eval/risk.js +187 -0
  21. package/dist/eval/rules/completeness.js +5 -1
  22. package/dist/eval/rules/cost.d.ts +1 -1
  23. package/dist/eval/rules/cost.js +6 -6
  24. package/dist/eval/rules/custom.js +1 -0
  25. package/dist/eval/rules/relevance.js +7 -2
  26. package/dist/eval/rules/safety.d.ts +6 -2
  27. package/dist/eval/rules/safety.js +55 -59
  28. package/dist/eval/seeded-random.d.ts +4 -0
  29. package/dist/eval/seeded-random.js +36 -0
  30. package/dist/eval/stamp.d.ts +1 -1
  31. package/dist/eval/stamp.js +1 -0
  32. package/dist/eval/text/checksums.d.ts +23 -0
  33. package/dist/eval/text/checksums.js +97 -0
  34. package/dist/eval/text/normalise.d.ts +30 -0
  35. package/dist/eval/text/normalise.js +265 -0
  36. package/dist/eval/text/sentences.d.ts +15 -0
  37. package/dist/eval/text/sentences.js +149 -0
  38. package/dist/self-test.js +3 -3
  39. package/dist/storage/sqlite-adapter.js +16 -2
  40. package/dist/tools/evaluate-output.js +2 -2
  41. package/dist/tools/evaluate-with-llm-judge.d.ts +3 -0
  42. package/dist/tools/evaluate-with-llm-judge.js +29 -1
  43. package/dist/tools/verify-citations.d.ts +2 -1
  44. package/dist/tools/verify-citations.js +25 -4
  45. package/dist/types/config.d.ts +35 -0
  46. package/dist/types/eval.d.ts +51 -0
  47. package/package.json +1 -1
  48. package/server.json +2 -2
@@ -54,6 +54,41 @@ export interface IrisConfig {
54
54
  * name in both lists is a config error: it does not say what you want.
55
55
  */
56
56
  nonCriticalRules?: string[];
57
+ /** `risk` composes by kind (gates, vetoes, unknown, then the risk); `legacy` runs the pre-0.10.0 weighted mean. */
58
+ composer?: 'risk' | 'legacy';
59
+ /**
60
+ * How many wrongly blocked builds one shipped failure is worth. The risk
61
+ * threshold is 1 / (1 + this), so 1 means a false pass and a false block
62
+ * cost the same; a continuous-integration gate that hates flakiness sets
63
+ * it low, a compliance gate sets it high.
64
+ */
65
+ falsePassCost?: number;
66
+ /**
67
+ * What a critical rule that was ASKED and could not answer does to the
68
+ * verdict — defeated by the output, or configured invalidly. Not the
69
+ * same as never asked, which is coverage. Today's behaviour is `pass`,
70
+ * which is the fail-open seam; the default is `unknown`.
71
+ */
72
+ onCriticalSkipped?: 'unknown' | 'fail' | 'pass';
73
+ /** Inputs every evaluation must carry; an absent one makes the verdict unknown rather than clean. */
74
+ requiredEvidence?: string[];
75
+ /**
76
+ * Whether a threshold IRIS ships decides the verdict, or only advises.
77
+ * A default is our guess about a deployment we have never seen; a
78
+ * threshold you set is your decision. A policy with no number in it —
79
+ * "the output is empty" — gates either way.
80
+ */
81
+ defaultsGate?: boolean;
82
+ /** The prior that an output is bad before any rule speaks. 0.5 matches the proof corpus, not your traffic. */
83
+ prior?: number;
84
+ /**
85
+ * How that prior is spread over the failure classes the detectors
86
+ * examine. `per-output` keeps it at the stated value for the output as a
87
+ * whole; `per-class` applies it to each class independently, which makes
88
+ * installing another detector raise the prior before that detector has
89
+ * looked at anything.
90
+ */
91
+ priorMode?: 'per-output' | 'per-class';
57
92
  };
58
93
  logging: {
59
94
  level: 'debug' | 'info' | 'warn' | 'error';
@@ -59,6 +59,14 @@ export interface EvalRule {
59
59
  classes?: readonly FailureClass[];
60
60
  /** Bumped when the rule's meaning changes, so a stored result names the definition that produced it. */
61
61
  version?: number;
62
+ /**
63
+ * Who wrote this rule. `custom` marks anything `createCustomRule`
64
+ * produced — a deployed rule or one passed inline in the call. The
65
+ * composer needs it: for OUR rule a shipped threshold is a guess and only
66
+ * advises, while for THEIRS the severity they deployed it at is their own
67
+ * statement of how much it matters. Absent means built-in.
68
+ */
69
+ origin?: 'built-in' | 'custom';
62
70
  evaluate(context: EvalContext): EvalRuleResult;
63
71
  }
64
72
  export interface EvalContext {
@@ -97,6 +105,20 @@ export interface EvalContext {
97
105
  regexBudget?: {
98
106
  breaches: number;
99
107
  };
108
+ /**
109
+
110
+ * Whether this evaluation may call a paid provider. Set ONLY by the tools
111
+
112
+ * whose whole purpose is to do so — the LLM judge and the citation
113
+
114
+ * verifier. The engine refuses to run a judgment rule without it, which
115
+
116
+ * is what makes "evaluate_output never spends" a property of the engine
117
+
118
+ * rather than a promise in a tool description.
119
+
120
+ */
121
+ allowPaid?: boolean;
100
122
  }
101
123
  /**
102
124
  * What the composer DID with a result under this deployment's configuration
@@ -157,6 +179,11 @@ export type Evidence = {
157
179
  value: number;
158
180
  threshold?: number;
159
181
  thresholdSource?: 'default' | 'config' | 'call' | 'rule';
182
+ } | {
183
+ type: 'sample';
184
+ score: number;
185
+ selfReportedPass?: boolean;
186
+ rationaleHash: string;
160
187
  };
161
188
  /** A measurement's statistic — the number the rule computed, with its unit, before any score transform. */
162
189
  export interface MeasuredValue {
@@ -194,6 +221,26 @@ export interface Coverage {
194
221
  * a detector's veto, nothing judged, or the score against the threshold.
195
222
  * `risk` is null until the compose-by-kind release computes it.
196
223
  */
224
+ /**
225
+ * A sentence a reader needs that the verdict alone does not carry, with who
226
+ * it is for and what to change. The one that must exist: when a rule
227
+ * visibly FIRED and the verdict still passed, say why and name the setting
228
+ * that would change it — "cost_under_threshold failed" beside
229
+ * "passed: true" reads as a bug to anyone who has not read the composer.
230
+ *
231
+ * `suggestions` remains for now and is rendered from these; it is deprecated
232
+ * from 0.13.0 and removed at 1.0, per VERSIONING.md's two-minor rule.
233
+ */
234
+ export interface Interpretation {
235
+ severity: 'block' | 'warn' | 'note';
236
+ addressee: 'agent' | 'operator' | 'author';
237
+ /** The rule this is about, when it is about one. */
238
+ rule?: string;
239
+ text: string;
240
+ /** The configuration key that changes this behaviour, when there is one. */
241
+ configKey?: string;
242
+ }
243
+ /** Placed on EvalResult by the engine; see Interpretation above. */
197
244
  export interface Verdict {
198
245
  state: 'pass' | 'fail' | 'unknown';
199
246
  passed: boolean;
@@ -303,6 +350,8 @@ export interface EvalRuleResult {
303
350
  classes?: FailureClass[];
304
351
  /** The version of the rule definition that produced this result. */
305
352
  ruleVersion?: number;
353
+ /** Who wrote the rule: `custom` for anything createCustomRule produced. See EvalRule.origin. */
354
+ origin?: 'built-in' | 'custom';
306
355
  /** Which of the rule's declared needs the call actually carried — what the rule SAW. */
307
356
  saw?: Need[];
308
357
  /** Present only when `skipped`; says whether the rule was never asked or was asked and could not answer. */
@@ -418,6 +467,8 @@ export interface EvalResult {
418
467
  categories?: Partial<Record<EvalType, EvalCategoryResult>>;
419
468
  /** The verdict with its basis (0.9.0) — computed by the engine, derived on read for stored rows that carry provenance. */
420
469
  verdict?: Verdict;
470
+ /** Sentences a reader needs that the verdict alone does not carry (0.10.0). */
471
+ interpretations?: Interpretation[];
421
472
  /** Coverage by evaluation question (0.9.0) — computed by the engine, derived on read from the stamped rule results. */
422
473
  coverage?: Coverage;
423
474
  /** What produced this verdict (0.9.0) — persisted; absent on rows written before it, never fabricated. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@iris-eval/mcp-server",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "description": "Stop shipping agents on vibes. Score every agent output for quality, safety, and cost.",
5
5
  "mcpName": "io.github.iris-eval/mcp-server",
6
6
  "type": "module",
package/server.json CHANGED
@@ -6,12 +6,12 @@
6
6
  "url": "https://github.com/iris-eval/mcp-server",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.9.0",
9
+ "version": "0.10.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "identifier": "@iris-eval/mcp-server",
14
- "version": "0.9.0",
14
+ "version": "0.10.0",
15
15
  "transport": {
16
16
  "type": "stdio"
17
17
  },