@smthrs/evals 0.0.0-stage → 1.0.0-rc.4

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 (143) hide show
  1. package/CHANGELOG.md +142 -0
  2. package/LICENSE +21 -0
  3. package/README.md +62 -2
  4. package/dist/cjs/Baseline.d.ts +118 -0
  5. package/dist/cjs/Baseline.d.ts.map +1 -0
  6. package/dist/cjs/Baseline.js +158 -0
  7. package/dist/cjs/Baseline.js.map +7 -0
  8. package/dist/cjs/CaseExecutor.d.ts +85 -0
  9. package/dist/cjs/CaseExecutor.d.ts.map +1 -0
  10. package/dist/cjs/CaseExecutor.js +59 -0
  11. package/dist/cjs/CaseExecutor.js.map +7 -0
  12. package/dist/cjs/EvalError.d.ts +64 -0
  13. package/dist/cjs/EvalError.d.ts.map +1 -0
  14. package/dist/cjs/EvalError.js +54 -0
  15. package/dist/cjs/EvalError.js.map +7 -0
  16. package/dist/cjs/Gate.d.ts +55 -0
  17. package/dist/cjs/Gate.d.ts.map +1 -0
  18. package/dist/cjs/Gate.js +88 -0
  19. package/dist/cjs/Gate.js.map +7 -0
  20. package/dist/cjs/Regression.d.ts +116 -0
  21. package/dist/cjs/Regression.d.ts.map +1 -0
  22. package/dist/cjs/Regression.js +191 -0
  23. package/dist/cjs/Regression.js.map +7 -0
  24. package/dist/cjs/Report.d.ts +114 -0
  25. package/dist/cjs/Report.d.ts.map +1 -0
  26. package/dist/cjs/Report.js +161 -0
  27. package/dist/cjs/Report.js.map +7 -0
  28. package/dist/cjs/Runner.d.ts +229 -0
  29. package/dist/cjs/Runner.d.ts.map +1 -0
  30. package/dist/cjs/Runner.js +430 -0
  31. package/dist/cjs/Runner.js.map +7 -0
  32. package/dist/cjs/Suite.d.ts +139 -0
  33. package/dist/cjs/Suite.d.ts.map +1 -0
  34. package/dist/cjs/Suite.js +221 -0
  35. package/dist/cjs/Suite.js.map +7 -0
  36. package/dist/cjs/Trials.d.ts +93 -0
  37. package/dist/cjs/Trials.d.ts.map +1 -0
  38. package/dist/cjs/Trials.js +82 -0
  39. package/dist/cjs/Trials.js.map +7 -0
  40. package/dist/cjs/index.d.ts +76 -0
  41. package/dist/cjs/index.d.ts.map +1 -0
  42. package/dist/cjs/index.js +51 -0
  43. package/dist/cjs/index.js.map +7 -0
  44. package/dist/cjs/internal/CanonicalJson.d.ts +44 -0
  45. package/dist/cjs/internal/CanonicalJson.d.ts.map +1 -0
  46. package/dist/cjs/internal/CanonicalJson.js +114 -0
  47. package/dist/cjs/internal/CanonicalJson.js.map +7 -0
  48. package/dist/cjs/internal/controlCharacters.d.ts +44 -0
  49. package/dist/cjs/internal/controlCharacters.d.ts.map +1 -0
  50. package/dist/cjs/internal/controlCharacters.js +42 -0
  51. package/dist/cjs/internal/controlCharacters.js.map +7 -0
  52. package/dist/cjs/internal/scorerLabel.d.ts +33 -0
  53. package/dist/cjs/internal/scorerLabel.d.ts.map +1 -0
  54. package/dist/cjs/internal/scorerLabel.js +28 -0
  55. package/dist/cjs/internal/scorerLabel.js.map +7 -0
  56. package/dist/cjs/internal/tupleKey.d.ts +20 -0
  57. package/dist/cjs/internal/tupleKey.d.ts.map +1 -0
  58. package/dist/cjs/internal/tupleKey.js +25 -0
  59. package/dist/cjs/internal/tupleKey.js.map +7 -0
  60. package/dist/cjs/package.json +1 -0
  61. package/dist/esm/Baseline.d.ts +118 -0
  62. package/dist/esm/Baseline.d.ts.map +1 -0
  63. package/dist/esm/Baseline.js +203 -0
  64. package/dist/esm/Baseline.js.map +1 -0
  65. package/dist/esm/CaseExecutor.d.ts +85 -0
  66. package/dist/esm/CaseExecutor.d.ts.map +1 -0
  67. package/dist/esm/CaseExecutor.js +60 -0
  68. package/dist/esm/CaseExecutor.js.map +1 -0
  69. package/dist/esm/EvalError.d.ts +64 -0
  70. package/dist/esm/EvalError.d.ts.map +1 -0
  71. package/dist/esm/EvalError.js +65 -0
  72. package/dist/esm/EvalError.js.map +1 -0
  73. package/dist/esm/Gate.d.ts +55 -0
  74. package/dist/esm/Gate.d.ts.map +1 -0
  75. package/dist/esm/Gate.js +90 -0
  76. package/dist/esm/Gate.js.map +1 -0
  77. package/dist/esm/Regression.d.ts +116 -0
  78. package/dist/esm/Regression.d.ts.map +1 -0
  79. package/dist/esm/Regression.js +195 -0
  80. package/dist/esm/Regression.js.map +1 -0
  81. package/dist/esm/Report.d.ts +114 -0
  82. package/dist/esm/Report.d.ts.map +1 -0
  83. package/dist/esm/Report.js +188 -0
  84. package/dist/esm/Report.js.map +1 -0
  85. package/dist/esm/Runner.d.ts +229 -0
  86. package/dist/esm/Runner.d.ts.map +1 -0
  87. package/dist/esm/Runner.js +430 -0
  88. package/dist/esm/Runner.js.map +1 -0
  89. package/dist/esm/Suite.d.ts +139 -0
  90. package/dist/esm/Suite.d.ts.map +1 -0
  91. package/dist/esm/Suite.js +255 -0
  92. package/dist/esm/Suite.js.map +1 -0
  93. package/dist/esm/Trials.d.ts +93 -0
  94. package/dist/esm/Trials.d.ts.map +1 -0
  95. package/dist/esm/Trials.js +116 -0
  96. package/dist/esm/Trials.js.map +1 -0
  97. package/dist/esm/index.d.ts +76 -0
  98. package/dist/esm/index.d.ts.map +1 -0
  99. package/dist/esm/index.js +76 -0
  100. package/dist/esm/index.js.map +1 -0
  101. package/dist/esm/internal/CanonicalJson.d.ts +44 -0
  102. package/dist/esm/internal/CanonicalJson.d.ts.map +1 -0
  103. package/dist/esm/internal/CanonicalJson.js +202 -0
  104. package/dist/esm/internal/CanonicalJson.js.map +1 -0
  105. package/dist/esm/internal/controlCharacters.d.ts +44 -0
  106. package/dist/esm/internal/controlCharacters.d.ts.map +1 -0
  107. package/dist/esm/internal/controlCharacters.js +65 -0
  108. package/dist/esm/internal/controlCharacters.js.map +1 -0
  109. package/dist/esm/internal/scorerLabel.d.ts +33 -0
  110. package/dist/esm/internal/scorerLabel.d.ts.map +1 -0
  111. package/dist/esm/internal/scorerLabel.js +33 -0
  112. package/dist/esm/internal/scorerLabel.js.map +1 -0
  113. package/dist/esm/internal/tupleKey.d.ts +20 -0
  114. package/dist/esm/internal/tupleKey.d.ts.map +1 -0
  115. package/dist/esm/internal/tupleKey.js +20 -0
  116. package/dist/esm/internal/tupleKey.js.map +1 -0
  117. package/docs/README.md +130 -0
  118. package/docs/api.md +626 -0
  119. package/docs/concepts/determinism.md +64 -0
  120. package/docs/concepts/fixed-suites.md +71 -0
  121. package/docs/concepts/step-keys.md +60 -0
  122. package/docs/guides/author-a-suite.md +115 -0
  123. package/docs/guides/gate-a-run-in-ci.md +129 -0
  124. package/docs/guides/maintain-a-baseline.md +91 -0
  125. package/docs/guides/run-a-suite.md +150 -0
  126. package/docs/installation.md +46 -0
  127. package/docs/quickstart.md +238 -0
  128. package/docs/troubleshooting.md +148 -0
  129. package/package.json +198 -3
  130. package/src/Baseline.ts +259 -0
  131. package/src/CaseExecutor.ts +104 -0
  132. package/src/EvalError.ts +74 -0
  133. package/src/Gate.ts +128 -0
  134. package/src/Regression.ts +314 -0
  135. package/src/Report.ts +268 -0
  136. package/src/Runner.ts +759 -0
  137. package/src/Suite.ts +358 -0
  138. package/src/Trials.ts +154 -0
  139. package/src/index.ts +76 -0
  140. package/src/internal/CanonicalJson.ts +234 -0
  141. package/src/internal/controlCharacters.ts +66 -0
  142. package/src/internal/scorerLabel.ts +35 -0
  143. package/src/internal/tupleKey.ts +20 -0
@@ -0,0 +1,59 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var CaseExecutor_exports = {};
30
+ __export(CaseExecutor_exports, {
31
+ CaseExecutor: () => CaseExecutor,
32
+ layerNoop: () => layerNoop,
33
+ make: () => make,
34
+ makeNoop: () => makeNoop
35
+ });
36
+ module.exports = __toCommonJS(CaseExecutor_exports);
37
+ var Context = __toESM(require("effect/Context"), 1);
38
+ var Effect = __toESM(require("effect/Effect"), 1);
39
+ var Layer = __toESM(require("effect/Layer"), 1);
40
+ var import_EvalError = require("./EvalError.js");
41
+ class CaseExecutor extends Context.Service()("flows/evals/CaseExecutor") {
42
+ }
43
+ const make = (run) => {
44
+ if (typeof run !== "function") {
45
+ throw new TypeError("CaseExecutor.make needs a callback");
46
+ }
47
+ return CaseExecutor.of({ run });
48
+ };
49
+ const makeNoop = () => CaseExecutor.of({
50
+ run: (suiteCase) => Effect.fail(
51
+ new import_EvalError.EvalError({
52
+ code: "executor",
53
+ message: `No executor is available for case '${suiteCase.name}'`,
54
+ path: `cases['${suiteCase.name}']`
55
+ })
56
+ )
57
+ });
58
+ const layerNoop = Layer.succeed(CaseExecutor)(makeNoop());
59
+ //# sourceMappingURL=CaseExecutor.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/CaseExecutor.ts"],
4
+ "sourcesContent": ["/**\n * Injectable target-flow execution boundary.\n *\n * A suite says what to run; this service says how. Keeping it injectable is\n * what lets the same suite run against a real flow, a scripted host, or nothing\n * at all, and it is the only place a target's failure is converted into a typed\n * evaluation failure.\n *\n * @since 0.1.0\n */\n\nimport type { Flow } from \"@smthrs/core\"\nimport * as Context from \"effect/Context\"\nimport * as Effect from \"effect/Effect\"\nimport * as Layer from \"effect/Layer\"\nimport { EvalError } from \"./EvalError.ts\"\nimport type { Case } from \"./Suite.ts\"\n\n/**\n * The result of executing one target-flow case.\n *\n * `target` is the flow value the case actually executed. A run matches it\n * against each binding's `appliesTo` by reference identity, so it has to be the\n * declared flow itself rather than a copy of it.\n *\n * @category models\n * @since 0.1.0\n */\nexport interface Execution {\n readonly output: unknown\n readonly stepKey: string\n readonly latencyMs: number\n readonly target: Pick<Flow.Any, \"name\">\n}\n\n/**\n * The one callback a case executor is.\n *\n * @category models\n * @since 0.1.0\n */\nexport type Run = (suiteCase: Case) => Effect.Effect<Execution, EvalError>\n\n/**\n * Runtime shape for an injectable target-flow executor.\n *\n * @category services\n * @since 0.1.0\n */\nexport interface Service {\n readonly run: Run\n}\n\n/**\n * Injectable execution boundary for a target flow.\n *\n * @category services\n * @since 0.1.0\n */\nexport class CaseExecutor extends Context.Service<CaseExecutor, Service>()(\"flows/evals/CaseExecutor\") {}\n\n/**\n * Builds an executor from its one callback.\n *\n * Throws a `TypeError` when there is no callback. An executor that silently\n * degraded to {@link makeNoop} turned one wiring mistake into a whole suite of\n * cases failing with `executor`, which reads as a broken target rather than a\n * missing one.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const make = (run: Run): Service => {\n if (typeof run !== \"function\") {\n throw new TypeError(\"CaseExecutor.make needs a callback\")\n }\n return CaseExecutor.of({ run })\n}\n\n/**\n * Builds an executor that fails every case with a typed executor error.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const makeNoop = (): Service =>\n CaseExecutor.of({\n run: (suiteCase) =>\n Effect.fail(\n new EvalError({\n code: \"executor\",\n message: `No executor is available for case '${suiteCase.name}'`,\n path: `cases['${suiteCase.name}']`\n })\n )\n })\n\n/**\n * Provides the unavailable executor.\n *\n * @category layers\n * @since 0.1.0\n */\nexport const layerNoop: Layer.Layer<CaseExecutor> = Layer.succeed(CaseExecutor)(makeNoop())\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAYA,cAAyB;AACzB,aAAwB;AACxB,YAAuB;AACvB,uBAA0B;AA4CnB,MAAM,qBAAqB,QAAQ,QAA+B,EAAE,0BAA0B,EAAE;AAAC;AAajG,MAAM,OAAO,CAAC,QAAsB;AACzC,MAAI,OAAO,QAAQ,YAAY;AAC7B,UAAM,IAAI,UAAU,oCAAoC;AAAA,EAC1D;AACA,SAAO,aAAa,GAAG,EAAE,IAAI,CAAC;AAChC;AAQO,MAAM,WAAW,MACtB,aAAa,GAAG;AAAA,EACd,KAAK,CAAC,cACJ,OAAO;AAAA,IACL,IAAI,2BAAU;AAAA,MACZ,MAAM;AAAA,MACN,SAAS,sCAAsC,UAAU,IAAI;AAAA,MAC7D,MAAM,UAAU,UAAU,IAAI;AAAA,IAChC,CAAC;AAAA,EACH;AACJ,CAAC;AAQI,MAAM,YAAuC,MAAM,QAAQ,YAAY,EAAE,SAAS,CAAC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * The typed failures evaluation raises, with the stable codes a gate or a
3
+ * report branches on.
4
+ *
5
+ * @since 0.1.0
6
+ */
7
+ import * as Schema from "effect/Schema";
8
+ /**
9
+ * Stable evaluation failure codes.
10
+ *
11
+ * Each code names one thing a caller can do about it, so a gate that branches
12
+ * on the code routes the failure to the right owner:
13
+ *
14
+ * - `invalid_suite`: the suite declaration is wrong. Fix the suite.
15
+ * - `invalid_run_options`: `Runner.run`'s own options are wrong, not the suite.
16
+ * - `invalid_baseline`: the committed baseline is unreadable, belongs to
17
+ * another suite, or holds a record the schema rejects. Regenerate it.
18
+ * - `invalid_tolerance`: the caller passed a tolerance that is not a finite
19
+ * non-negative number. Fix the call, not the baseline.
20
+ * - `invalid_trials`: the caller passed run, pass, or `k` counts to `Trials`
21
+ * outside their bounds. Fix the call.
22
+ * - `executor`: the target flow failed for a case.
23
+ * - `ambiguous_score_job`: two score jobs shared a step key and a scorer, so
24
+ * an order-only batch runner's results cannot be attributed to a case. Give
25
+ * each case its own step key, or use a runner that implements
26
+ * `runBatchCorrelated`.
27
+ * - `scorer_protocol`: a batch runner broke the `runBatch` contract by returning
28
+ * the wrong number of observations, or observations that identify jobs other
29
+ * than the ones it was given. Nothing it returned can be trusted.
30
+ * - `scorer_unavailable`: no batch runner was available to score with.
31
+ *
32
+ * @category models
33
+ * @since 0.1.0
34
+ */
35
+ export declare const EvalErrorCode: Schema.Literals<readonly ["invalid_suite", "invalid_run_options", "invalid_baseline", "invalid_tolerance", "invalid_trials", "executor", "ambiguous_score_job", "scorer_protocol", "scorer_unavailable"]>;
36
+ /**
37
+ * Stable evaluation failure code.
38
+ *
39
+ * @category models
40
+ * @since 0.1.0
41
+ */
42
+ export type EvalErrorCode = typeof EvalErrorCode.Type;
43
+ declare const EvalError_base: Schema.Class<EvalError, Schema.TaggedStruct<"flows/evals/EvalError", {
44
+ readonly code: Schema.Literals<readonly ["invalid_suite", "invalid_run_options", "invalid_baseline", "invalid_tolerance", "invalid_trials", "executor", "ambiguous_score_job", "scorer_protocol", "scorer_unavailable"]>;
45
+ readonly message: Schema.String;
46
+ readonly path: Schema.optional<Schema.String>;
47
+ readonly cause: Schema.optional<Schema.Defect>;
48
+ }>, import("effect/Cause").YieldableError>;
49
+ /**
50
+ * A typed failure raised while loading or executing an evaluation.
51
+ *
52
+ * `code` is the stable branch point, `message` is the sentence a CI log shows,
53
+ * and `path` locates the offending value inside the input the caller supplied
54
+ * (`records[3].score`, `cases[1].input`, `options.at`). `cause` retains the
55
+ * original failure; it is never rendered on its own, so a message that matters
56
+ * to an operator has to say so itself.
57
+ *
58
+ * @category errors
59
+ * @since 0.1.0
60
+ */
61
+ export declare class EvalError extends EvalError_base {
62
+ }
63
+ export {};
64
+ //# sourceMappingURL=EvalError.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EvalError.d.ts","sourceRoot":"","sources":["../../src/EvalError.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAEvC;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,eAAO,MAAM,aAAa,2MAUxB,CAAA;AAEF;;;;;GAKG;AACH,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;;;;;;;AAErD;;;;;;;;;;;GAWG;AACH,qBAAa,SAAU,SAAQ,cAK7B;CAAG"}
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var EvalError_exports = {};
30
+ __export(EvalError_exports, {
31
+ EvalError: () => EvalError,
32
+ EvalErrorCode: () => EvalErrorCode
33
+ });
34
+ module.exports = __toCommonJS(EvalError_exports);
35
+ var Schema = __toESM(require("effect/Schema"), 1);
36
+ const EvalErrorCode = Schema.Literals([
37
+ "invalid_suite",
38
+ "invalid_run_options",
39
+ "invalid_baseline",
40
+ "invalid_tolerance",
41
+ "invalid_trials",
42
+ "executor",
43
+ "ambiguous_score_job",
44
+ "scorer_protocol",
45
+ "scorer_unavailable"
46
+ ]);
47
+ class EvalError extends Schema.TaggedError()("flows/evals/EvalError", {
48
+ code: EvalErrorCode,
49
+ message: Schema.String,
50
+ path: Schema.optional(Schema.String),
51
+ cause: Schema.optional(Schema.Defect())
52
+ }) {
53
+ }
54
+ //# sourceMappingURL=EvalError.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/EvalError.ts"],
4
+ "sourcesContent": ["/**\n * The typed failures evaluation raises, with the stable codes a gate or a\n * report branches on.\n *\n * @since 0.1.0\n */\n\nimport * as Schema from \"effect/Schema\"\n\n/**\n * Stable evaluation failure codes.\n *\n * Each code names one thing a caller can do about it, so a gate that branches\n * on the code routes the failure to the right owner:\n *\n * - `invalid_suite`: the suite declaration is wrong. Fix the suite.\n * - `invalid_run_options`: `Runner.run`'s own options are wrong, not the suite.\n * - `invalid_baseline`: the committed baseline is unreadable, belongs to\n * another suite, or holds a record the schema rejects. Regenerate it.\n * - `invalid_tolerance`: the caller passed a tolerance that is not a finite\n * non-negative number. Fix the call, not the baseline.\n * - `invalid_trials`: the caller passed run, pass, or `k` counts to `Trials`\n * outside their bounds. Fix the call.\n * - `executor`: the target flow failed for a case.\n * - `ambiguous_score_job`: two score jobs shared a step key and a scorer, so\n * an order-only batch runner's results cannot be attributed to a case. Give\n * each case its own step key, or use a runner that implements\n * `runBatchCorrelated`.\n * - `scorer_protocol`: a batch runner broke the `runBatch` contract by returning\n * the wrong number of observations, or observations that identify jobs other\n * than the ones it was given. Nothing it returned can be trusted.\n * - `scorer_unavailable`: no batch runner was available to score with.\n *\n * @category models\n * @since 0.1.0\n */\nexport const EvalErrorCode = Schema.Literals([\n \"invalid_suite\",\n \"invalid_run_options\",\n \"invalid_baseline\",\n \"invalid_tolerance\",\n \"invalid_trials\",\n \"executor\",\n \"ambiguous_score_job\",\n \"scorer_protocol\",\n \"scorer_unavailable\"\n])\n\n/**\n * Stable evaluation failure code.\n *\n * @category models\n * @since 0.1.0\n */\nexport type EvalErrorCode = typeof EvalErrorCode.Type\n\n/**\n * A typed failure raised while loading or executing an evaluation.\n *\n * `code` is the stable branch point, `message` is the sentence a CI log shows,\n * and `path` locates the offending value inside the input the caller supplied\n * (`records[3].score`, `cases[1].input`, `options.at`). `cause` retains the\n * original failure; it is never rendered on its own, so a message that matters\n * to an operator has to say so itself.\n *\n * @category errors\n * @since 0.1.0\n */\nexport class EvalError extends Schema.TaggedError<EvalError>()(\"flows/evals/EvalError\", {\n code: EvalErrorCode,\n message: Schema.String,\n path: Schema.optional(Schema.String),\n cause: Schema.optional(Schema.Defect())\n}) {}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,aAAwB;AA6BjB,MAAM,gBAAgB,OAAO,SAAS;AAAA,EAC3C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAsBM,MAAM,kBAAkB,OAAO,YAAuB,EAAE,yBAAyB;AAAA,EACtF,MAAM;AAAA,EACN,SAAS,OAAO;AAAA,EAChB,MAAM,OAAO,SAAS,OAAO,MAAM;AAAA,EACnC,OAAO,OAAO,SAAS,OAAO,OAAO,CAAC;AACxC,CAAC,EAAE;AAAC;",
6
+ "names": []
7
+ }
@@ -0,0 +1,55 @@
1
+ /**
2
+ * The pass/fail decision over a finished evaluation run: how a threshold
3
+ * is applied and what a failing gate reports.
4
+ *
5
+ * @since 0.1.0
6
+ */
7
+ import { type ScoreGateError, type Verdict } from "@smthrs/scorers/ScoreGate";
8
+ import * as Effect from "effect/Effect";
9
+ import type { Report } from "./Regression.ts";
10
+ /**
11
+ * Thresholds accepted by a CI score gate.
12
+ *
13
+ * `mean` gates the arithmetic mean of every score observation, `min` gates the
14
+ * lowest one, and `perCase` gates each named case's lowest score. With none of
15
+ * them set the gate still runs, as `mean(0)`, so a run with no score at all is
16
+ * undecidable rather than a pass.
17
+ *
18
+ * @since 0.1.0
19
+ * @category models
20
+ */
21
+ export interface Options {
22
+ readonly mean?: number | undefined;
23
+ readonly min?: number | undefined;
24
+ readonly perCase?: Readonly<Record<string, number>> | undefined;
25
+ }
26
+ /**
27
+ * Checks thresholds through `@smthrs/scorers`' shared ScoreGate arithmetic.
28
+ *
29
+ * The threshold gates always run: an unobserved case cannot excuse the cases
30
+ * that were observed. Faults and findings are kept apart, and the verdict
31
+ * carries both, so a regression is a red while an unusable harness stays
32
+ * undecided.
33
+ *
34
+ * @category constructors
35
+ * @since 0.1.0
36
+ */
37
+ export declare const check: (report: Report, options?: Options) => Effect.Effect<Verdict, ScoreGateError>;
38
+ /**
39
+ * Maps a gate verdict to the shared CI convention: a finding is exit code 1,
40
+ * an undecidable run is exit code 5.
41
+ *
42
+ * The summary is one log line: every C0 control and DEL in it becomes a
43
+ * space, the way a report cell is written, so a value that reached a verdict
44
+ * reason from a baseline, a step key or a target's failure cannot emit its own
45
+ * line, which on GitHub Actions would be a workflow command, or a terminal
46
+ * escape.
47
+ *
48
+ * @category grading
49
+ * @since 0.1.0
50
+ */
51
+ export declare const ciGrade: (verdict: Verdict) => {
52
+ readonly exitCode: 0 | 1 | 5;
53
+ readonly summary: string;
54
+ };
55
+ //# sourceMappingURL=Gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Gate.d.ts","sourceRoot":"","sources":["../../src/Gate.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAIL,KAAK,cAAc,EAEnB,KAAK,OAAO,EACb,MAAM,2BAA2B,CAAA;AAClC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAE7C;;;;;;;;;;GAUG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAA;CAChE;AAkDD;;;;;;;;;;GAUG;AACH,eAAO,MAAM,KAAK,GAAI,QAAQ,MAAM,EAAE,UAAS,OAAY,KAAG,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,cAAc,CAa/F,CAAA;AAEJ;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,OAAO,GAAI,SAAS,OAAO,KAAG;IAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAGlG,CAAA"}
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var Gate_exports = {};
30
+ __export(Gate_exports, {
31
+ check: () => check,
32
+ ciGrade: () => ciGrade
33
+ });
34
+ module.exports = __toCommonJS(Gate_exports);
35
+ var import_ScoreGate = require("@smthrs/scorers/ScoreGate");
36
+ var Effect = __toESM(require("effect/Effect"), 1);
37
+ var import_controlCharacters = require("./internal/controlCharacters.js");
38
+ var import_scorerLabel = require("./internal/scorerLabel.js");
39
+ const samples = (report) => report.run.observations.map(
40
+ (observation) => observation.kind === "score" ? {
41
+ case: observation.case,
42
+ scorer: observation.scorer,
43
+ stepKey: observation.stepKey,
44
+ kind: "score",
45
+ value: observation.score,
46
+ reason: observation.reason
47
+ } : {
48
+ case: observation.case,
49
+ scorer: observation.scorer,
50
+ stepKey: observation.stepKey,
51
+ kind: "inconclusive",
52
+ reason: observation.reason
53
+ }
54
+ );
55
+ const environmentFaults = (report) => [
56
+ ...report.run.cases.flatMap(
57
+ (result) => result.error === void 0 ? [] : [`case '${result.case}' failed: ${result.error.code}: ${result.error.message}`]
58
+ ),
59
+ ...report.missing.map(
60
+ (item) => `missing ${item.side} observation for ${item.case}/${(0, import_scorerLabel.scorerLabel)(item)}/${item.stepKey}`
61
+ )
62
+ ];
63
+ const findings = (report) => [
64
+ ...report.regressions.map(
65
+ (item) => `regression for ${item.case}/${(0, import_scorerLabel.scorerLabel)({ scorer: item.scorer, scorerName: item.actual.scorerName })}`
66
+ ),
67
+ ...report.nondeterminism.map(
68
+ (item) => `nondeterminism for ${item.case}/${(0, import_scorerLabel.scorerLabel)({ scorer: item.scorer, scorerName: item.actual.scorerName })}`
69
+ )
70
+ ];
71
+ const check = (report, options = {}) => Effect.gen(function* () {
72
+ const expectation = (0, import_ScoreGate.expectScores)(samples(report));
73
+ const verdicts = [];
74
+ if (options.mean !== void 0) verdicts.push(yield* expectation.mean(options.mean));
75
+ if (options.min !== void 0) verdicts.push(yield* expectation.min(options.min));
76
+ if (options.perCase !== void 0) verdicts.push(yield* expectation.perCase(options.perCase));
77
+ if (options.mean === void 0 && options.min === void 0 && options.perCase === void 0) {
78
+ verdicts.push(yield* expectation.mean(0));
79
+ }
80
+ const reasons = findings(report);
81
+ if (reasons.length > 0) verdicts.push({ _tag: "Failed", reasons, inconclusive: [] });
82
+ return (0, import_ScoreGate.combine)(verdicts, environmentFaults(report));
83
+ });
84
+ const ciGrade = (verdict) => {
85
+ const graded = (0, import_ScoreGate.grade)(verdict);
86
+ return { exitCode: graded.exitCode, summary: (0, import_controlCharacters.flattenControlCharacters)(graded.summary) };
87
+ };
88
+ //# sourceMappingURL=Gate.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../src/Gate.ts"],
4
+ "sourcesContent": ["/**\n * The pass/fail decision over a finished evaluation run: how a threshold\n * is applied and what a failing gate reports.\n *\n * @since 0.1.0\n */\n\nimport {\n combine,\n expectScores,\n grade,\n type ScoreGateError,\n type ScoreSample,\n type Verdict\n} from \"@smthrs/scorers/ScoreGate\"\nimport * as Effect from \"effect/Effect\"\nimport { flattenControlCharacters } from \"./internal/controlCharacters.ts\"\nimport { scorerLabel } from \"./internal/scorerLabel.ts\"\nimport type { Report } from \"./Regression.ts\"\n\n/**\n * Thresholds accepted by a CI score gate.\n *\n * `mean` gates the arithmetic mean of every score observation, `min` gates the\n * lowest one, and `perCase` gates each named case's lowest score. With none of\n * them set the gate still runs, as `mean(0)`, so a run with no score at all is\n * undecidable rather than a pass.\n *\n * @since 0.1.0\n * @category models\n */\nexport interface Options {\n readonly mean?: number | undefined\n readonly min?: number | undefined\n readonly perCase?: Readonly<Record<string, number>> | undefined\n}\n\nconst samples = (report: Report): ReadonlyArray<ScoreSample> =>\n report.run.observations.map((observation) =>\n observation.kind === \"score\"\n ? {\n case: observation.case,\n scorer: observation.scorer,\n stepKey: observation.stepKey,\n kind: \"score\",\n value: observation.score,\n reason: observation.reason\n }\n : {\n case: observation.case,\n scorer: observation.scorer,\n stepKey: observation.stepKey,\n kind: \"inconclusive\",\n reason: observation.reason\n }\n )\n\n/**\n * An environment fault: something the comparison needed was never observed, so\n * the harness owes an answer it cannot give. A fault withholds a decision;\n * it does not make one.\n */\nconst environmentFaults = (report: Report): ReadonlyArray<string> => [\n ...report.run.cases.flatMap((result) =>\n result.error === undefined ? [] : [`case '${result.case}' failed: ${result.error.code}: ${result.error.message}`]\n ),\n ...report.missing.map((item) =>\n `missing ${item.side} observation for ${item.case}/${scorerLabel(item)}/${item.stepKey}`\n )\n]\n\n/**\n * A finding: the run measured something the baseline says it should not have.\n * A regression scored lower at a changed step key, and nondeterminism moved a\n * score at an unchanged one. Both are results, so both are red.\n */\nconst findings = (report: Report): ReadonlyArray<string> => [\n ...report.regressions.map((item) =>\n `regression for ${item.case}/${scorerLabel({ scorer: item.scorer, scorerName: item.actual.scorerName })}`\n ),\n ...report.nondeterminism.map((item) =>\n `nondeterminism for ${item.case}/${scorerLabel({ scorer: item.scorer, scorerName: item.actual.scorerName })}`\n )\n]\n\n/**\n * Checks thresholds through `@smthrs/scorers`' shared ScoreGate arithmetic.\n *\n * The threshold gates always run: an unobserved case cannot excuse the cases\n * that were observed. Faults and findings are kept apart, and the verdict\n * carries both, so a regression is a red while an unusable harness stays\n * undecided.\n *\n * @category constructors\n * @since 0.1.0\n */\nexport const check = (report: Report, options: Options = {}): Effect.Effect<Verdict, ScoreGateError> =>\n Effect.gen(function*() {\n const expectation = expectScores(samples(report))\n const verdicts: Array<Verdict> = []\n if (options.mean !== undefined) verdicts.push(yield* expectation.mean(options.mean))\n if (options.min !== undefined) verdicts.push(yield* expectation.min(options.min))\n if (options.perCase !== undefined) verdicts.push(yield* expectation.perCase(options.perCase))\n if (options.mean === undefined && options.min === undefined && options.perCase === undefined) {\n verdicts.push(yield* expectation.mean(0))\n }\n const reasons = findings(report)\n if (reasons.length > 0) verdicts.push({ _tag: \"Failed\", reasons, inconclusive: [] })\n return combine(verdicts, environmentFaults(report))\n })\n\n/**\n * Maps a gate verdict to the shared CI convention: a finding is exit code 1,\n * an undecidable run is exit code 5.\n *\n * The summary is one log line: every C0 control and DEL in it becomes a\n * space, the way a report cell is written, so a value that reached a verdict\n * reason from a baseline, a step key or a target's failure cannot emit its own\n * line, which on GitHub Actions would be a workflow command, or a terminal\n * escape.\n *\n * @category grading\n * @since 0.1.0\n */\nexport const ciGrade = (verdict: Verdict): { readonly exitCode: 0 | 1 | 5; readonly summary: string } => {\n const graded = grade(verdict)\n return { exitCode: graded.exitCode, summary: flattenControlCharacters(graded.summary) }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOA,uBAOO;AACP,aAAwB;AACxB,+BAAyC;AACzC,yBAA4B;AAoB5B,MAAM,UAAU,CAAC,WACf,OAAO,IAAI,aAAa;AAAA,EAAI,CAAC,gBAC3B,YAAY,SAAS,UACjB;AAAA,IACA,MAAM,YAAY;AAAA,IAClB,QAAQ,YAAY;AAAA,IACpB,SAAS,YAAY;AAAA,IACrB,MAAM;AAAA,IACN,OAAO,YAAY;AAAA,IACnB,QAAQ,YAAY;AAAA,EACtB,IACE;AAAA,IACA,MAAM,YAAY;AAAA,IAClB,QAAQ,YAAY;AAAA,IACpB,SAAS,YAAY;AAAA,IACrB,MAAM;AAAA,IACN,QAAQ,YAAY;AAAA,EACtB;AACJ;AAOF,MAAM,oBAAoB,CAAC,WAA0C;AAAA,EACnE,GAAG,OAAO,IAAI,MAAM;AAAA,IAAQ,CAAC,WAC3B,OAAO,UAAU,SAAY,CAAC,IAAI,CAAC,SAAS,OAAO,IAAI,aAAa,OAAO,MAAM,IAAI,KAAK,OAAO,MAAM,OAAO,EAAE;AAAA,EAClH;AAAA,EACA,GAAG,OAAO,QAAQ;AAAA,IAAI,CAAC,SACrB,WAAW,KAAK,IAAI,oBAAoB,KAAK,IAAI,QAAI,gCAAY,IAAI,CAAC,IAAI,KAAK,OAAO;AAAA,EACxF;AACF;AAOA,MAAM,WAAW,CAAC,WAA0C;AAAA,EAC1D,GAAG,OAAO,YAAY;AAAA,IAAI,CAAC,SACzB,kBAAkB,KAAK,IAAI,QAAI,gCAAY,EAAE,QAAQ,KAAK,QAAQ,YAAY,KAAK,OAAO,WAAW,CAAC,CAAC;AAAA,EACzG;AAAA,EACA,GAAG,OAAO,eAAe;AAAA,IAAI,CAAC,SAC5B,sBAAsB,KAAK,IAAI,QAAI,gCAAY,EAAE,QAAQ,KAAK,QAAQ,YAAY,KAAK,OAAO,WAAW,CAAC,CAAC;AAAA,EAC7G;AACF;AAaO,MAAM,QAAQ,CAAC,QAAgB,UAAmB,CAAC,MACxD,OAAO,IAAI,aAAY;AACrB,QAAM,kBAAc,+BAAa,QAAQ,MAAM,CAAC;AAChD,QAAM,WAA2B,CAAC;AAClC,MAAI,QAAQ,SAAS,OAAW,UAAS,KAAK,OAAO,YAAY,KAAK,QAAQ,IAAI,CAAC;AACnF,MAAI,QAAQ,QAAQ,OAAW,UAAS,KAAK,OAAO,YAAY,IAAI,QAAQ,GAAG,CAAC;AAChF,MAAI,QAAQ,YAAY,OAAW,UAAS,KAAK,OAAO,YAAY,QAAQ,QAAQ,OAAO,CAAC;AAC5F,MAAI,QAAQ,SAAS,UAAa,QAAQ,QAAQ,UAAa,QAAQ,YAAY,QAAW;AAC5F,aAAS,KAAK,OAAO,YAAY,KAAK,CAAC,CAAC;AAAA,EAC1C;AACA,QAAM,UAAU,SAAS,MAAM;AAC/B,MAAI,QAAQ,SAAS,EAAG,UAAS,KAAK,EAAE,MAAM,UAAU,SAAS,cAAc,CAAC,EAAE,CAAC;AACnF,aAAO,0BAAQ,UAAU,kBAAkB,MAAM,CAAC;AACpD,CAAC;AAeI,MAAM,UAAU,CAAC,YAAiF;AACvG,QAAM,aAAS,wBAAM,OAAO;AAC5B,SAAO,EAAE,UAAU,OAAO,UAAU,aAAS,mDAAyB,OAAO,OAAO,EAAE;AACxF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Step-key-aware evaluation regression comparison.
3
+ *
4
+ * The step key is what separates the two findings this module reports. A score
5
+ * that moved at a *changed* step key is a regression: the target produced
6
+ * different work and it graded worse. A score that moved at an *unchanged* step
7
+ * key is nondeterminism: the same work graded differently twice. Both are
8
+ * results, and a gate reads both as red.
9
+ *
10
+ * @since 0.1.0
11
+ */
12
+ import * as Effect from "effect/Effect";
13
+ import type { Baseline, BaselineRecord } from "./Baseline.ts";
14
+ import { EvalError } from "./EvalError.ts";
15
+ import type { Observation, RunResult } from "./Runner.ts";
16
+ /**
17
+ * Tolerances used for score comparisons.
18
+ *
19
+ * A move is reported only when it exceeds both tolerances, so either one alone
20
+ * is enough to silence it. Both default to `0`, which reports every move.
21
+ *
22
+ * @category models
23
+ * @since 0.1.0
24
+ */
25
+ export interface Tolerances {
26
+ readonly absolute?: number | undefined;
27
+ readonly relative?: number | undefined;
28
+ }
29
+ /**
30
+ * A score drop at a changed step key.
31
+ *
32
+ * @category models
33
+ * @since 0.1.0
34
+ */
35
+ export interface Regression {
36
+ readonly case: string;
37
+ readonly scorer: string;
38
+ readonly baseline: BaselineRecord;
39
+ readonly actual: Extract<Observation, {
40
+ readonly kind: "score";
41
+ }>;
42
+ readonly drop: number;
43
+ }
44
+ /**
45
+ * A changed score at the same step key, indicating nondeterminism.
46
+ *
47
+ * @category models
48
+ * @since 0.1.0
49
+ */
50
+ export interface Nondeterminism {
51
+ readonly case: string;
52
+ readonly scorer: string;
53
+ readonly baseline: BaselineRecord;
54
+ readonly actual: Extract<Observation, {
55
+ readonly kind: "score";
56
+ }>;
57
+ readonly delta: number;
58
+ }
59
+ /**
60
+ * An observation present on only one side of a comparison.
61
+ *
62
+ * `side` names the side it is missing from: `"run"` for a baseline record the
63
+ * run never reproduced, `"baseline"` for a score the run produced that no
64
+ * baseline record accounts for. `scorerName` comes from the observation that
65
+ * is present, when that artifact carried one.
66
+ *
67
+ * @category models
68
+ * @since 0.1.0
69
+ */
70
+ export interface MissingObservation {
71
+ readonly side: "baseline" | "run";
72
+ readonly case: string;
73
+ readonly scorer: string;
74
+ readonly scorerName?: string | undefined;
75
+ readonly stepKey: string;
76
+ }
77
+ /**
78
+ * Complete regression comparison.
79
+ *
80
+ * @category models
81
+ * @since 0.1.0
82
+ */
83
+ export interface Report {
84
+ readonly suite: string;
85
+ readonly baseline: Baseline;
86
+ readonly run: RunResult;
87
+ readonly regressions: ReadonlyArray<Regression>;
88
+ readonly nondeterminism: ReadonlyArray<Nondeterminism>;
89
+ readonly missing: ReadonlyArray<MissingObservation>;
90
+ readonly samples: ReadonlyArray<Extract<Observation, {
91
+ readonly kind: "score";
92
+ }>>;
93
+ readonly inconclusive: ReadonlyArray<Extract<Observation, {
94
+ readonly kind: "inconclusive";
95
+ }>>;
96
+ }
97
+ /**
98
+ * Compares a run to a baseline, preserving missing and inconclusive observations.
99
+ *
100
+ * Records and observations are grouped by `(case, scorer)` and then paired by
101
+ * step key, so a scorer that ran several times against one case is compared
102
+ * pairwise instead of by array position. A pair whose step key is unchanged and
103
+ * whose score moved is nondeterminism; a pair whose step key changed and whose
104
+ * score dropped is a regression; an unpaired record on either side is a missing
105
+ * observation. Inconclusive observations are carried through untouched, because
106
+ * they decide nothing and a gate has to see them.
107
+ *
108
+ * Fails with `invalid_tolerance` when a tolerance is not finite and
109
+ * non-negative, and with `invalid_baseline` when the artifact or any of its
110
+ * records belongs to a suite other than the one the run reports.
111
+ *
112
+ * @category constructors
113
+ * @since 0.1.0
114
+ */
115
+ export declare const compare: (baseline: Baseline, run: RunResult, tolerances?: Tolerances) => Effect.Effect<Report, EvalError>;
116
+ //# sourceMappingURL=Regression.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Regression.d.ts","sourceRoot":"","sources":["../../src/Regression.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AAC7D,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAI1C,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAEzD;;;;;;;;GAQG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACtC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACvC;AAED;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IACjE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,QAAQ,EAAE,cAAc,CAAA;IACjC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAA;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED;;;;;;;;;;GAUG;AACH,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,KAAK,CAAA;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAA;IACvB,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAAA;IAC/C,QAAQ,CAAC,cAAc,EAAE,aAAa,CAAC,cAAc,CAAC,CAAA;IACtD,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,kBAAkB,CAAC,CAAA;IACnD,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC,OAAO,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC,CAAA;IACjF,QAAQ,CAAC,YAAY,EAAE,aAAa,CAAC,OAAO,CAAC,WAAW,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;KAAE,CAAC,CAAC,CAAA;CAC9F;AA2ED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,OAAO,GAClB,UAAU,QAAQ,EAClB,KAAK,SAAS,EACd,aAAY,UAAe,KAC1B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,SAAS,CAwHjC,CAAA"}