@artemiskit/core 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @artemiskit/core
2
2
 
3
+ ## 0.5.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Qualify standard-run comparisons from bounded workload, rubric, and execution evidence. Changed
8
+ workloads or rubrics withhold deltas, while incomplete historical evidence and changed target
9
+ configuration remain explicitly qualified across storage, CLI, SDK, and reports.
10
+
3
11
  ## 0.5.2
4
12
 
5
13
  ### Patch Changes
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Compatibility decisions for comparisons of saved scenario-evaluation runs.
3
+ *
4
+ * This contract compares declared evidence only. A matching digest proves the
5
+ * same canonical workload/rubric was declared; it does not attest to provider
6
+ * behaviour or replace a future assessment-profile compatibility decision.
7
+ */
8
+ import type { RunManifest } from '../artifacts/types';
9
+ export type ComparisonEligibilityStatus = 'compatible' | 'qualified' | 'incomparable';
10
+ export type ComparisonEligibilityReasonCode = 'scenario_mismatch' | 'workload_identity_missing' | 'rubric_identity_missing' | 'workload_mismatch' | 'rubric_mismatch' | 'execution_provenance_missing' | 'target_provider_changed' | 'target_model_changed' | 'generation_settings_changed';
11
+ /** A bounded, machine-readable reason for a comparison decision. */
12
+ export interface ComparisonEligibilityReason {
13
+ code: ComparisonEligibilityReasonCode;
14
+ }
15
+ /**
16
+ * Versioned decision that accompanies every comparison. `qualified` permits
17
+ * a visibly-qualified delta; `incomparable` prohibits a delta entirely.
18
+ */
19
+ export interface ComparisonEligibility {
20
+ schema_version: '1';
21
+ status: ComparisonEligibilityStatus;
22
+ reasons: ComparisonEligibilityReason[];
23
+ }
24
+ export declare function assessComparisonEligibility(baseline: RunManifest, current: RunManifest): ComparisonEligibility;
25
+ export declare function isComparisonAvailable(eligibility: ComparisonEligibility): boolean;
26
+ //# sourceMappingURL=eligibility.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eligibility.d.ts","sourceRoot":"","sources":["../../src/comparison/eligibility.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEtD,MAAM,MAAM,2BAA2B,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,CAAC;AAEtF,MAAM,MAAM,+BAA+B,GACvC,mBAAmB,GACnB,2BAA2B,GAC3B,yBAAyB,GACzB,mBAAmB,GACnB,iBAAiB,GACjB,8BAA8B,GAC9B,yBAAyB,GACzB,sBAAsB,GACtB,6BAA6B,CAAC;AAElC,oEAAoE;AACpE,MAAM,WAAW,2BAA2B;IAC1C,IAAI,EAAE,+BAA+B,CAAC;CACvC;AAED;;;GAGG;AACH,MAAM,WAAW,qBAAqB;IACpC,cAAc,EAAE,GAAG,CAAC;IACpB,MAAM,EAAE,2BAA2B,CAAC;IACpC,OAAO,EAAE,2BAA2B,EAAE,CAAC;CACxC;AAED,wBAAgB,2BAA2B,CACzC,QAAQ,EAAE,WAAW,EACrB,OAAO,EAAE,WAAW,GACnB,qBAAqB,CAmDvB;AAED,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,qBAAqB,GAAG,OAAO,CAEjF"}
@@ -0,0 +1,2 @@
1
+ export { assessComparisonEligibility, isComparisonAvailable, type ComparisonEligibility, type ComparisonEligibilityReason, type ComparisonEligibilityReasonCode, type ComparisonEligibilityStatus, } from './eligibility';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/comparison/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,2BAA2B,EAC3B,qBAAqB,EACrB,KAAK,qBAAqB,EAC1B,KAAK,2BAA2B,EAChC,KAAK,+BAA+B,EACpC,KAAK,2BAA2B,GACjC,MAAM,eAAe,CAAC"}
package/dist/index.d.ts CHANGED
@@ -9,6 +9,7 @@ export * from './runner';
9
9
  export * from './storage';
10
10
  export * from './artifacts';
11
11
  export * from './provenance';
12
+ export * from './comparison';
12
13
  export * from './utils';
13
14
  export * from './redaction';
14
15
  export * from './cost';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,YAAY,CAAC;AAG3B,cAAc,YAAY,CAAC;AAG3B,cAAc,cAAc,CAAC;AAG7B,cAAc,UAAU,CAAC;AAGzB,cAAc,WAAW,CAAC;AAG1B,cAAc,aAAa,CAAC;AAG5B,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC;AAGxB,cAAc,aAAa,CAAC;AAG5B,cAAc,QAAQ,CAAC;AAGvB,cAAc,SAAS,CAAC;AAGxB,cAAc,oBAAoB,CAAC;AAGnC,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,cAAc,YAAY,CAAC;AAG3B,cAAc,YAAY,CAAC;AAG3B,cAAc,cAAc,CAAC;AAG7B,cAAc,UAAU,CAAC;AAGzB,cAAc,WAAW,CAAC;AAG1B,cAAc,aAAa,CAAC;AAG5B,cAAc,cAAc,CAAC;AAG7B,cAAc,cAAc,CAAC;AAG7B,cAAc,SAAS,CAAC;AAGxB,cAAc,aAAa,CAAC;AAG5B,cAAc,QAAQ,CAAC;AAGvB,cAAc,SAAS,CAAC;AAGxB,cAAc,oBAAoB,CAAC;AAGnC,cAAc,aAAa,CAAC"}
package/dist/index.js CHANGED
@@ -21562,6 +21562,65 @@ function chunkArray(array, size) {
21562
21562
  // src/storage/local.ts
21563
21563
  import { mkdir, readFile as readFile2, readdir as readdir2, unlink, writeFile } from "fs/promises";
21564
21564
  import { join as join2, resolve as resolve2 } from "path";
21565
+
21566
+ // src/comparison/eligibility.ts
21567
+ function assessComparisonEligibility(baseline, current) {
21568
+ const reasons = [];
21569
+ if (baseline.config.scenario !== current.config.scenario) {
21570
+ reasons.push({ code: "scenario_mismatch" });
21571
+ }
21572
+ const baselineIdentity = baseline.workload_identity;
21573
+ const currentIdentity = current.workload_identity;
21574
+ if (!baselineIdentity || !currentIdentity) {
21575
+ if (!baselineIdentity || !currentIdentity)
21576
+ reasons.push({ code: "workload_identity_missing" });
21577
+ if (!baselineIdentity || !currentIdentity)
21578
+ reasons.push({ code: "rubric_identity_missing" });
21579
+ } else {
21580
+ if (baselineIdentity.workload.digest !== currentIdentity.workload.digest) {
21581
+ reasons.push({ code: "workload_mismatch" });
21582
+ }
21583
+ if (baselineIdentity.rubric.digest !== currentIdentity.rubric.digest) {
21584
+ reasons.push({ code: "rubric_mismatch" });
21585
+ }
21586
+ }
21587
+ if (reasons.some((reason) => isIncomparableReason(reason.code))) {
21588
+ return { schema_version: "1", status: "incomparable", reasons };
21589
+ }
21590
+ const baselineExecution = baseline.execution_provenance;
21591
+ const currentExecution = current.execution_provenance;
21592
+ if (!baselineExecution || !currentExecution) {
21593
+ reasons.push({ code: "execution_provenance_missing" });
21594
+ } else {
21595
+ if (baselineExecution.target.provider !== currentExecution.target.provider) {
21596
+ reasons.push({ code: "target_provider_changed" });
21597
+ }
21598
+ if (!sameStringSet(baselineExecution.target.requested_models, currentExecution.target.requested_models)) {
21599
+ reasons.push({ code: "target_model_changed" });
21600
+ }
21601
+ if (!sameGeneration(baselineExecution.target.generation, currentExecution.target.generation)) {
21602
+ reasons.push({ code: "generation_settings_changed" });
21603
+ }
21604
+ }
21605
+ return {
21606
+ schema_version: "1",
21607
+ status: reasons.length === 0 ? "compatible" : "qualified",
21608
+ reasons
21609
+ };
21610
+ }
21611
+ function isComparisonAvailable(eligibility) {
21612
+ return eligibility.status !== "incomparable";
21613
+ }
21614
+ function isIncomparableReason(code) {
21615
+ return code === "scenario_mismatch" || code === "workload_mismatch" || code === "rubric_mismatch";
21616
+ }
21617
+ function sameStringSet(left, right) {
21618
+ return JSON.stringify([...left ?? []].sort()) === JSON.stringify([...right ?? []].sort());
21619
+ }
21620
+ function sameGeneration(left, right) {
21621
+ return left?.temperature === right?.temperature && left?.max_tokens === right?.max_tokens && left?.seed === right?.seed;
21622
+ }
21623
+ // src/storage/local.ts
21565
21624
  function getManifestType(manifest) {
21566
21625
  if ("type" in manifest) {
21567
21626
  if (manifest.type === "redteam")
@@ -21701,9 +21760,14 @@ class LocalStorageAdapter {
21701
21760
  this.loadRun(baselineId),
21702
21761
  this.loadRun(currentId)
21703
21762
  ]);
21763
+ const eligibility = assessComparisonEligibility(baseline, current);
21764
+ if (!isComparisonAvailable(eligibility)) {
21765
+ return { baseline, current, eligibility };
21766
+ }
21704
21767
  return {
21705
21768
  baseline,
21706
21769
  current,
21770
+ eligibility,
21707
21771
  delta: {
21708
21772
  successRate: current.metrics.success_rate - baseline.metrics.success_rate,
21709
21773
  latency: current.metrics.median_latency_ms - baseline.metrics.median_latency_ms,
@@ -21802,7 +21866,7 @@ class LocalStorageAdapter {
21802
21866
  return null;
21803
21867
  }
21804
21868
  const comparison = await this.compare(baseline.runId, runId);
21805
- const hasRegression = comparison.delta.successRate < -regressionThreshold;
21869
+ const hasRegression = comparison.delta !== undefined && comparison.delta.successRate < -regressionThreshold;
21806
21870
  return {
21807
21871
  baseline,
21808
21872
  comparison,
@@ -30448,9 +30512,14 @@ class SupabaseStorageAdapter {
30448
30512
  }
30449
30513
  async compare(baselineId, currentId) {
30450
30514
  const [baseline, current] = await Promise.all([this.load(baselineId), this.load(currentId)]);
30515
+ const eligibility = assessComparisonEligibility(baseline, current);
30516
+ if (!isComparisonAvailable(eligibility)) {
30517
+ return { baseline, current, eligibility };
30518
+ }
30451
30519
  return {
30452
30520
  baseline,
30453
30521
  current,
30522
+ eligibility,
30454
30523
  delta: {
30455
30524
  successRate: current.metrics.success_rate - baseline.metrics.success_rate,
30456
30525
  latency: current.metrics.median_latency_ms - baseline.metrics.median_latency_ms,
@@ -30581,7 +30650,7 @@ class SupabaseStorageAdapter {
30581
30650
  return null;
30582
30651
  }
30583
30652
  const comparison = await this.compare(baseline.runId, runId);
30584
- const hasRegression = comparison.delta.successRate < -regressionThreshold;
30653
+ const hasRegression = comparison.delta !== undefined && comparison.delta.successRate < -regressionThreshold;
30585
30654
  return {
30586
30655
  baseline,
30587
30656
  comparison,
@@ -32924,6 +32993,7 @@ export {
32924
32993
  actionBudgetExceeded,
32925
32994
  adapterRegistry,
32926
32995
  assertRunManifestIntegrity,
32996
+ assessComparisonEligibility,
32927
32997
  createAdapter,
32928
32998
  createDefaultRedactor,
32929
32999
  createExecutionProvenance,
@@ -32945,6 +33015,7 @@ export {
32945
33015
  getModelPricing,
32946
33016
  hashText,
32947
33017
  isArtemisError,
33018
+ isComparisonAvailable,
32948
33019
  isRedTeamManifest,
32949
33020
  isRunManifest,
32950
33021
  isStressManifest,
@@ -1 +1 @@
1
- {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,cAAc,EAGpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EACV,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAyDjB,qBAAa,mBAAoB,YAAW,sBAAsB;IAChE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAS;gBAElB,QAAQ,SAAmB;IAKjC,IAAI,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAa5C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAczC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAS5C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAQpD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAQlD,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IA0DnD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;YAiBjE,eAAe;YASf,SAAS;IAWvB;;OAEG;YACW,iBAAiB;IAS/B;;OAEG;YACW,iBAAiB;IAM/B;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA4B3F;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKrE;;OAEG;IACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAMzE;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAOlD;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUxD;;OAEG;IACG,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW5D;;OAEG;IACG,iBAAiB,CACrB,KAAK,EAAE,MAAM,EACb,mBAAmB,SAAO,GACzB,OAAO,CAAC;QACT,QAAQ,EAAE,gBAAgB,CAAC;QAC3B,UAAU,EAAE,gBAAgB,CAAC;QAC7B,aAAa,EAAE,OAAO,CAAC;QACvB,mBAAmB,EAAE,MAAM,CAAC;KAC7B,GAAG,IAAI,CAAC;CAwBV"}
1
+ {"version":3,"file":"local.d.ts","sourceRoot":"","sources":["../../src/storage/local.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,cAAc,EAGpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EACV,gBAAgB,EAChB,sBAAsB,EACtB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACZ,MAAM,SAAS,CAAC;AAyDjB,qBAAa,mBAAoB,YAAW,sBAAsB;IAChE,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,aAAa,CAAS;gBAElB,QAAQ,SAAmB;IAKjC,IAAI,CAAC,QAAQ,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAa5C,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAczC,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC;IAS5C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAQpD,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAQlD,IAAI,CAAC,OAAO,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IA0DnD,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYpC,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;YAuBjE,eAAe;YASf,SAAS;IAWvB;;OAEG;YACW,iBAAiB;IAS/B;;OAEG;YACW,iBAAiB;IAM/B;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IA4B3F;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKrE;;OAEG;IACG,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAMzE;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAOlD;;OAEG;IACG,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUxD;;OAEG;IACG,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAW5D;;OAEG;IACG,iBAAiB,CACrB,KAAK,EAAE,MAAM,EACb,mBAAmB,SAAO,GACzB,OAAO,CAAC;QACT,QAAQ,EAAE,gBAAgB,CAAC;QAC3B,UAAU,EAAE,gBAAgB,CAAC;QAC7B,aAAa,EAAE,OAAO,CAAC;QACvB,mBAAmB,EAAE,MAAM,CAAC;KAC7B,GAAG,IAAI,CAAC;CAyBV"}
@@ -1 +1 @@
1
- {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/storage/supabase.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/storage/supabase.ts"],"names":[],"mappings":"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"}
@@ -2,6 +2,7 @@
2
2
  * Storage types and interfaces
3
3
  */
4
4
  import type { AnyManifest, CaseEvaluationEvidence, RedTeamManifest, RunManifest, StressManifest } from '../artifacts/types';
5
+ import type { ComparisonEligibility } from '../comparison';
5
6
  /**
6
7
  * Run listing item
7
8
  */
@@ -21,7 +22,10 @@ export interface RunListItem {
21
22
  export interface ComparisonResult {
22
23
  baseline: RunManifest;
23
24
  current: RunManifest;
24
- delta: {
25
+ /** Compatibility decision made before any metric delta is calculated. */
26
+ eligibility: ComparisonEligibility;
27
+ /** Absent when workloads or rubrics are incomparable. */
28
+ delta?: {
25
29
  successRate: number;
26
30
  latency: number;
27
31
  tokens: number;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/storage/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/storage/types.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@artemiskit/core",
3
- "version": "0.5.2",
3
+ "version": "0.5.3",
4
4
  "description": "Core runner, evaluators, and storage for ArtemisKit LLM evaluation toolkit",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -0,0 +1,101 @@
1
+ import { describe, expect, test } from 'bun:test';
2
+ import type { RunManifest } from '../artifacts';
3
+ import { assessComparisonEligibility, isComparisonAvailable } from './eligibility';
4
+
5
+ function manifest(overrides: Partial<RunManifest> = {}): RunManifest {
6
+ return {
7
+ version: '1.3',
8
+ run_id: 'run-id',
9
+ project: 'project',
10
+ start_time: '2026-09-10T00:00:00.000Z',
11
+ end_time: '2026-09-10T00:00:01.000Z',
12
+ duration_ms: 1000,
13
+ config: { scenario: 'customer-service', provider: 'openai', model: 'model-a' },
14
+ workload_identity: {
15
+ schema_version: '1',
16
+ workload: { schema_version: '1', algorithm: 'sha256', digest: 'a'.repeat(64) },
17
+ rubric: { schema_version: '1', algorithm: 'sha256', digest: 'b'.repeat(64) },
18
+ },
19
+ execution_provenance: {
20
+ schema_version: '1',
21
+ target: { provider: 'openai', requested_models: ['model-a'], generation: { temperature: 0 } },
22
+ },
23
+ metrics: {
24
+ success_rate: 1,
25
+ total_cases: 1,
26
+ passed_cases: 1,
27
+ failed_cases: 0,
28
+ median_latency_ms: 1,
29
+ p95_latency_ms: 1,
30
+ total_tokens: 1,
31
+ total_prompt_tokens: 1,
32
+ total_completion_tokens: 0,
33
+ },
34
+ git: { commit: 'commit', branch: 'main', dirty: false },
35
+ provenance: { run_by: 'test' },
36
+ cases: [],
37
+ environment: { node_version: 'test', platform: 'test', arch: 'test' },
38
+ ...overrides,
39
+ };
40
+ }
41
+
42
+ describe('assessComparisonEligibility', () => {
43
+ test('accepts matching declared workload, rubric, and execution configuration', () => {
44
+ const eligibility = assessComparisonEligibility(manifest(), manifest({ run_id: 'current' }));
45
+
46
+ expect(eligibility).toEqual({ schema_version: '1', status: 'compatible', reasons: [] });
47
+ expect(isComparisonAvailable(eligibility)).toBe(true);
48
+ });
49
+
50
+ test('qualifies legacy artifacts instead of presenting them as fully compatible', () => {
51
+ const legacy = manifest({ workload_identity: undefined, execution_provenance: undefined });
52
+ const eligibility = assessComparisonEligibility(legacy, manifest({ run_id: 'current' }));
53
+
54
+ expect(eligibility.status).toBe('qualified');
55
+ expect(eligibility.reasons.map((reason) => reason.code)).toEqual([
56
+ 'workload_identity_missing',
57
+ 'rubric_identity_missing',
58
+ 'execution_provenance_missing',
59
+ ]);
60
+ expect(isComparisonAvailable(eligibility)).toBe(true);
61
+ });
62
+
63
+ test('qualifies a deliberate target-model change without treating it as the same execution', () => {
64
+ const current = manifest({
65
+ run_id: 'current',
66
+ execution_provenance: {
67
+ schema_version: '1',
68
+ target: {
69
+ provider: 'openai',
70
+ requested_models: ['model-b'],
71
+ generation: { temperature: 0 },
72
+ },
73
+ },
74
+ });
75
+
76
+ const eligibility = assessComparisonEligibility(manifest(), current);
77
+
78
+ expect(eligibility.status).toBe('qualified');
79
+ expect(eligibility.reasons).toEqual([{ code: 'target_model_changed' }]);
80
+ });
81
+
82
+ test('refuses deltas when workload or rubric evidence differs', () => {
83
+ const current = manifest({
84
+ run_id: 'current',
85
+ workload_identity: {
86
+ schema_version: '1',
87
+ workload: { schema_version: '1', algorithm: 'sha256', digest: 'c'.repeat(64) },
88
+ rubric: { schema_version: '1', algorithm: 'sha256', digest: 'd'.repeat(64) },
89
+ },
90
+ });
91
+
92
+ const eligibility = assessComparisonEligibility(manifest(), current);
93
+
94
+ expect(eligibility.status).toBe('incomparable');
95
+ expect(eligibility.reasons.map((reason) => reason.code)).toEqual([
96
+ 'workload_mismatch',
97
+ 'rubric_mismatch',
98
+ ]);
99
+ expect(isComparisonAvailable(eligibility)).toBe(false);
100
+ });
101
+ });
@@ -0,0 +1,116 @@
1
+ /**
2
+ * Compatibility decisions for comparisons of saved scenario-evaluation runs.
3
+ *
4
+ * This contract compares declared evidence only. A matching digest proves the
5
+ * same canonical workload/rubric was declared; it does not attest to provider
6
+ * behaviour or replace a future assessment-profile compatibility decision.
7
+ */
8
+
9
+ import type { RunManifest } from '../artifacts/types';
10
+
11
+ export type ComparisonEligibilityStatus = 'compatible' | 'qualified' | 'incomparable';
12
+
13
+ export type ComparisonEligibilityReasonCode =
14
+ | 'scenario_mismatch'
15
+ | 'workload_identity_missing'
16
+ | 'rubric_identity_missing'
17
+ | 'workload_mismatch'
18
+ | 'rubric_mismatch'
19
+ | 'execution_provenance_missing'
20
+ | 'target_provider_changed'
21
+ | 'target_model_changed'
22
+ | 'generation_settings_changed';
23
+
24
+ /** A bounded, machine-readable reason for a comparison decision. */
25
+ export interface ComparisonEligibilityReason {
26
+ code: ComparisonEligibilityReasonCode;
27
+ }
28
+
29
+ /**
30
+ * Versioned decision that accompanies every comparison. `qualified` permits
31
+ * a visibly-qualified delta; `incomparable` prohibits a delta entirely.
32
+ */
33
+ export interface ComparisonEligibility {
34
+ schema_version: '1';
35
+ status: ComparisonEligibilityStatus;
36
+ reasons: ComparisonEligibilityReason[];
37
+ }
38
+
39
+ export function assessComparisonEligibility(
40
+ baseline: RunManifest,
41
+ current: RunManifest
42
+ ): ComparisonEligibility {
43
+ const reasons: ComparisonEligibilityReason[] = [];
44
+
45
+ if (baseline.config.scenario !== current.config.scenario) {
46
+ reasons.push({ code: 'scenario_mismatch' });
47
+ }
48
+
49
+ const baselineIdentity = baseline.workload_identity;
50
+ const currentIdentity = current.workload_identity;
51
+ if (!baselineIdentity || !currentIdentity) {
52
+ if (!baselineIdentity || !currentIdentity) reasons.push({ code: 'workload_identity_missing' });
53
+ if (!baselineIdentity || !currentIdentity) reasons.push({ code: 'rubric_identity_missing' });
54
+ } else {
55
+ if (baselineIdentity.workload.digest !== currentIdentity.workload.digest) {
56
+ reasons.push({ code: 'workload_mismatch' });
57
+ }
58
+ if (baselineIdentity.rubric.digest !== currentIdentity.rubric.digest) {
59
+ reasons.push({ code: 'rubric_mismatch' });
60
+ }
61
+ }
62
+
63
+ if (reasons.some((reason) => isIncomparableReason(reason.code))) {
64
+ return { schema_version: '1', status: 'incomparable', reasons };
65
+ }
66
+
67
+ const baselineExecution = baseline.execution_provenance;
68
+ const currentExecution = current.execution_provenance;
69
+ if (!baselineExecution || !currentExecution) {
70
+ reasons.push({ code: 'execution_provenance_missing' });
71
+ } else {
72
+ if (baselineExecution.target.provider !== currentExecution.target.provider) {
73
+ reasons.push({ code: 'target_provider_changed' });
74
+ }
75
+ if (
76
+ !sameStringSet(
77
+ baselineExecution.target.requested_models,
78
+ currentExecution.target.requested_models
79
+ )
80
+ ) {
81
+ reasons.push({ code: 'target_model_changed' });
82
+ }
83
+ if (!sameGeneration(baselineExecution.target.generation, currentExecution.target.generation)) {
84
+ reasons.push({ code: 'generation_settings_changed' });
85
+ }
86
+ }
87
+
88
+ return {
89
+ schema_version: '1',
90
+ status: reasons.length === 0 ? 'compatible' : 'qualified',
91
+ reasons,
92
+ };
93
+ }
94
+
95
+ export function isComparisonAvailable(eligibility: ComparisonEligibility): boolean {
96
+ return eligibility.status !== 'incomparable';
97
+ }
98
+
99
+ function isIncomparableReason(code: ComparisonEligibilityReasonCode): boolean {
100
+ return code === 'scenario_mismatch' || code === 'workload_mismatch' || code === 'rubric_mismatch';
101
+ }
102
+
103
+ function sameStringSet(left?: string[], right?: string[]): boolean {
104
+ return JSON.stringify([...(left ?? [])].sort()) === JSON.stringify([...(right ?? [])].sort());
105
+ }
106
+
107
+ function sameGeneration(
108
+ left?: { temperature?: number; max_tokens?: number; seed?: number },
109
+ right?: { temperature?: number; max_tokens?: number; seed?: number }
110
+ ): boolean {
111
+ return (
112
+ left?.temperature === right?.temperature &&
113
+ left?.max_tokens === right?.max_tokens &&
114
+ left?.seed === right?.seed
115
+ );
116
+ }
@@ -0,0 +1,8 @@
1
+ export {
2
+ assessComparisonEligibility,
3
+ isComparisonAvailable,
4
+ type ComparisonEligibility,
5
+ type ComparisonEligibilityReason,
6
+ type ComparisonEligibilityReasonCode,
7
+ type ComparisonEligibilityStatus,
8
+ } from './eligibility';
package/src/index.ts CHANGED
@@ -24,6 +24,9 @@ export * from './artifacts';
24
24
  // Provenance
25
25
  export * from './provenance';
26
26
 
27
+ // Comparison eligibility
28
+ export * from './comparison';
29
+
27
30
  // Utilities
28
31
  export * from './utils';
29
32
 
@@ -179,6 +179,45 @@ describe('LocalStorageAdapter', () => {
179
179
  expect(comparison.delta.successRate).toBeCloseTo(0.1, 2);
180
180
  expect(comparison.delta.latency).toBe(-30);
181
181
  expect(comparison.delta.tokens).toBe(100);
182
+ expect(comparison.eligibility.status).toBe('qualified');
183
+ });
184
+
185
+ test('withholds deltas for incompatible workload evidence', async () => {
186
+ const baseline = {
187
+ ...mockManifest,
188
+ run_id: 'incompatible-baseline',
189
+ workload_identity: {
190
+ schema_version: '1' as const,
191
+ workload: {
192
+ schema_version: '1' as const,
193
+ algorithm: 'sha256' as const,
194
+ digest: 'a'.repeat(64),
195
+ },
196
+ rubric: {
197
+ schema_version: '1' as const,
198
+ algorithm: 'sha256' as const,
199
+ digest: 'b'.repeat(64),
200
+ },
201
+ },
202
+ execution_provenance: { schema_version: '1' as const, target: { provider: 'openai' } },
203
+ };
204
+ const current = {
205
+ ...baseline,
206
+ run_id: 'incompatible-current',
207
+ workload_identity: {
208
+ ...baseline.workload_identity,
209
+ workload: { ...baseline.workload_identity.workload, digest: 'c'.repeat(64) },
210
+ },
211
+ };
212
+
213
+ await storage.save(baseline);
214
+ await storage.save(current);
215
+
216
+ const comparison = await storage.compare('incompatible-baseline', 'incompatible-current');
217
+
218
+ expect(comparison.eligibility.status).toBe('incomparable');
219
+ expect(comparison.eligibility.reasons).toEqual([{ code: 'workload_mismatch' }]);
220
+ expect(comparison.delta).toBeUndefined();
182
221
  });
183
222
 
184
223
  test('handles empty storage gracefully', async () => {
@@ -12,6 +12,7 @@ import {
12
12
  assertRunManifestIntegrity,
13
13
  isRunManifest,
14
14
  } from '../artifacts/types';
15
+ import { assessComparisonEligibility, isComparisonAvailable } from '../comparison';
15
16
  import type {
16
17
  BaselineMetadata,
17
18
  BaselineStorageAdapter,
@@ -212,9 +213,15 @@ export class LocalStorageAdapter implements BaselineStorageAdapter {
212
213
  this.loadRun(currentId),
213
214
  ]);
214
215
 
216
+ const eligibility = assessComparisonEligibility(baseline, current);
217
+ if (!isComparisonAvailable(eligibility)) {
218
+ return { baseline, current, eligibility };
219
+ }
220
+
215
221
  return {
216
222
  baseline,
217
223
  current,
224
+ eligibility,
218
225
  delta: {
219
226
  successRate: current.metrics.success_rate - baseline.metrics.success_rate,
220
227
  latency: current.metrics.median_latency_ms - baseline.metrics.median_latency_ms,
@@ -375,7 +382,8 @@ export class LocalStorageAdapter implements BaselineStorageAdapter {
375
382
  const comparison = await this.compare(baseline.runId, runId);
376
383
 
377
384
  // Check for regression (negative delta in success rate)
378
- const hasRegression = comparison.delta.successRate < -regressionThreshold;
385
+ const hasRegression =
386
+ comparison.delta !== undefined && comparison.delta.successRate < -regressionThreshold;
379
387
 
380
388
  return {
381
389
  baseline,
@@ -9,6 +9,7 @@ import {
9
9
  assertRunManifestIntegrity,
10
10
  getCaseEvaluationStatus,
11
11
  } from '../artifacts/types';
12
+ import { assessComparisonEligibility, isComparisonAvailable } from '../comparison';
12
13
  import type {
13
14
  AnalyticsStorageAdapter,
14
15
  BaselineMetadata,
@@ -199,9 +200,15 @@ export class SupabaseStorageAdapter implements AnalyticsStorageAdapter {
199
200
  async compare(baselineId: string, currentId: string): Promise<ComparisonResult> {
200
201
  const [baseline, current] = await Promise.all([this.load(baselineId), this.load(currentId)]);
201
202
 
203
+ const eligibility = assessComparisonEligibility(baseline, current);
204
+ if (!isComparisonAvailable(eligibility)) {
205
+ return { baseline, current, eligibility };
206
+ }
207
+
202
208
  return {
203
209
  baseline,
204
210
  current,
211
+ eligibility,
205
212
  delta: {
206
213
  successRate: current.metrics.success_rate - baseline.metrics.success_rate,
207
214
  latency: current.metrics.median_latency_ms - baseline.metrics.median_latency_ms,
@@ -400,7 +407,8 @@ export class SupabaseStorageAdapter implements AnalyticsStorageAdapter {
400
407
  const comparison = await this.compare(baseline.runId, runId);
401
408
 
402
409
  // Check for regression (success rate dropped by more than threshold)
403
- const hasRegression = comparison.delta.successRate < -regressionThreshold;
410
+ const hasRegression =
411
+ comparison.delta !== undefined && comparison.delta.successRate < -regressionThreshold;
404
412
 
405
413
  return {
406
414
  baseline,
@@ -9,6 +9,7 @@ import type {
9
9
  RunManifest,
10
10
  StressManifest,
11
11
  } from '../artifacts/types';
12
+ import type { ComparisonEligibility } from '../comparison';
12
13
 
13
14
  /**
14
15
  * Run listing item
@@ -30,7 +31,10 @@ export interface RunListItem {
30
31
  export interface ComparisonResult {
31
32
  baseline: RunManifest;
32
33
  current: RunManifest;
33
- delta: {
34
+ /** Compatibility decision made before any metric delta is calculated. */
35
+ eligibility: ComparisonEligibility;
36
+ /** Absent when workloads or rubrics are incomparable. */
37
+ delta?: {
34
38
  successRate: number;
35
39
  latency: number;
36
40
  tokens: number;