@thinkai/tai-api-contract 2.171.0 → 2.172.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.
@@ -1,7 +1,7 @@
1
1
  openapi: 3.0.3
2
2
  info:
3
3
  title: ThinkAI API
4
- version: 2.171.0
4
+ version: 2.172.0
5
5
  description: >
6
6
  Contract surface for the AI Driven SDLC backend used by ThinkAI.
7
7
  Workspace-scoped routes use `/workspaces/{workspaceId}/...`.
@@ -92,6 +92,12 @@ tags:
92
92
  classified test-file inventory (unit, integration, acceptance/BDD, contract, E2E)
93
93
  with count-based presence and advisory 70/20/10 shape. Distinct from Agentic
94
94
  Foundation readiness `/readiness/test-pyramid*` (signal-inclusive presence).
95
+ - name: Evals
96
+ description: >
97
+ Workspace prompt/model eval suites (`/evals/*`) — authored golden cases with
98
+ deterministic expected-signal scoring, async runs (never scored on the request
99
+ path), and an Insights surface for regressions and token efficiency. Distinct
100
+ from AI Usage & Spend ingest and Agentic Foundation Token Efficiency (rubric I).
95
101
 
96
102
  paths:
97
103
  /admin/users/{userId}:
@@ -11939,6 +11945,358 @@ paths:
11939
11945
  "403":
11940
11946
  $ref: "#/components/responses/Forbidden"
11941
11947
 
11948
+ /workspaces/{workspaceId}/evals/suites:
11949
+ get:
11950
+ tags: [Evals]
11951
+ summary: List eval suites for a workspace
11952
+ description: >
11953
+ Returns the latest version of each eval suite in the workspace (max 50 suites).
11954
+ Requires workspace membership (`requireWorkspaceMember`). Empty workspace →
11955
+ `{ "suites": [] }`.
11956
+ operationId: listEvalSuites
11957
+ x-test-coverage-skip: contract-only; HTTP/store coverage lands with evals-storage-api
11958
+ parameters:
11959
+ - $ref: "#/components/parameters/WorkspaceId"
11960
+ responses:
11961
+ "200":
11962
+ description: Suite list (latest version per suite)
11963
+ content:
11964
+ application/json:
11965
+ schema:
11966
+ $ref: "#/components/schemas/EvalSuiteListDto"
11967
+ example:
11968
+ suites: []
11969
+ "401":
11970
+ $ref: "#/components/responses/Unauthorized"
11971
+ "403":
11972
+ $ref: "#/components/responses/Forbidden"
11973
+ "404":
11974
+ description: Workspace not found
11975
+ content:
11976
+ application/json:
11977
+ schema:
11978
+ $ref: "#/components/schemas/ErrorMessageDto"
11979
+ post:
11980
+ tags: [Evals]
11981
+ summary: Create an eval suite
11982
+ description: >
11983
+ Creates a suite at `version: 1`. Requires workspace editor or admin
11984
+ (`requireWorkspaceEditor`). Rejects when both `target.promptBody` is empty
11985
+ and model fields are missing; when `cases` is empty (`400`
11986
+ `eval_suite_cases_required`); or when the workspace already has 50 suites.
11987
+ Each case must include at least one expected signal.
11988
+ operationId: createEvalSuite
11989
+ x-test-coverage-skip: contract-only; HTTP/store coverage lands with evals-storage-api
11990
+ parameters:
11991
+ - $ref: "#/components/parameters/WorkspaceId"
11992
+ requestBody:
11993
+ required: true
11994
+ content:
11995
+ application/json:
11996
+ schema:
11997
+ $ref: "#/components/schemas/CreateEvalSuiteBodyDto"
11998
+ example:
11999
+ name: Greeting quality
12000
+ description: Fixture-backed smoke suite for the support greeting prompt
12001
+ target:
12002
+ promptBody: "You are a support agent. Greet the user by name."
12003
+ promptKey: support-greeting
12004
+ provider: cursor
12005
+ modelName: gpt-4.1-mini
12006
+ cases:
12007
+ - id: case-hello
12008
+ name: Hello Alice
12009
+ input: '{"name":"Alice"}'
12010
+ fixtureCompletion: "Hello Alice, how can I help you today?"
12011
+ expectedSignals:
12012
+ - id: sig-contains-hello
12013
+ kind: contains
12014
+ value: "Hello Alice"
12015
+ - id: sig-not-sorry
12016
+ kind: not_contains
12017
+ value: "I cannot"
12018
+ responses:
12019
+ "201":
12020
+ description: Suite created
12021
+ content:
12022
+ application/json:
12023
+ schema:
12024
+ $ref: "#/components/schemas/EvalSuiteDto"
12025
+ "400":
12026
+ description: >
12027
+ Validation failed — empty cases (`eval_suite_cases_required`), missing
12028
+ target (prompt and model), invalid name/description lengths, case/signal
12029
+ bounds, or malformed body.
12030
+ content:
12031
+ application/json:
12032
+ schema:
12033
+ $ref: "#/components/schemas/ErrorMessageDto"
12034
+ examples:
12035
+ cases_required:
12036
+ value:
12037
+ error: At least one case is required
12038
+ code: eval_suite_cases_required
12039
+ target_required:
12040
+ value:
12041
+ error: Suite target requires promptBody or provider+modelName
12042
+ code: eval_suite_target_required
12043
+ "401":
12044
+ $ref: "#/components/responses/Unauthorized"
12045
+ "403":
12046
+ description: Authenticated but not a workspace editor/admin
12047
+ content:
12048
+ application/json:
12049
+ schema:
12050
+ $ref: "#/components/schemas/ErrorMessageDto"
12051
+ example:
12052
+ error: Workspace editor role required
12053
+ code: workspace_editor_required
12054
+ "404":
12055
+ description: Workspace not found
12056
+ content:
12057
+ application/json:
12058
+ schema:
12059
+ $ref: "#/components/schemas/ErrorMessageDto"
12060
+ "409":
12061
+ description: Workspace already has the maximum of 50 suites
12062
+ content:
12063
+ application/json:
12064
+ schema:
12065
+ $ref: "#/components/schemas/ErrorMessageDto"
12066
+ example:
12067
+ error: Maximum of 50 eval suites per workspace
12068
+ code: eval_suite_limit_reached
12069
+
12070
+ /workspaces/{workspaceId}/evals/suites/{suiteId}:
12071
+ get:
12072
+ tags: [Evals]
12073
+ summary: Get an eval suite (latest version)
12074
+ description: >
12075
+ Returns the latest version of the suite. Historical versions are retained for
12076
+ runs via `suiteVersion` + snapshot on each run; this endpoint does not expose
12077
+ prior versions. Requires workspace membership.
12078
+ operationId: getEvalSuite
12079
+ x-test-coverage-skip: contract-only; HTTP/store coverage lands with evals-storage-api
12080
+ parameters:
12081
+ - $ref: "#/components/parameters/WorkspaceId"
12082
+ - $ref: "#/components/parameters/EvalSuiteId"
12083
+ responses:
12084
+ "200":
12085
+ description: Suite (latest version)
12086
+ content:
12087
+ application/json:
12088
+ schema:
12089
+ $ref: "#/components/schemas/EvalSuiteDto"
12090
+ "401":
12091
+ $ref: "#/components/responses/Unauthorized"
12092
+ "403":
12093
+ $ref: "#/components/responses/Forbidden"
12094
+ "404":
12095
+ description: Workspace or suite not found
12096
+ content:
12097
+ application/json:
12098
+ schema:
12099
+ $ref: "#/components/schemas/ErrorMessageDto"
12100
+ put:
12101
+ tags: [Evals]
12102
+ summary: Update an eval suite
12103
+ description: >
12104
+ Replaces mutable suite fields. Requires workspace editor or admin.
12105
+ Changing `target`, `cases`, or `promptBody` increments `version` by 1 and
12106
+ keeps prior versions immutable for historical runs. Cosmetic
12107
+ name/description-only updates do not bump `version`. Same validation rules
12108
+ as create (cases required, target required, bounds).
12109
+ operationId: updateEvalSuite
12110
+ x-test-coverage-skip: contract-only; HTTP/store coverage lands with evals-storage-api
12111
+ parameters:
12112
+ - $ref: "#/components/parameters/WorkspaceId"
12113
+ - $ref: "#/components/parameters/EvalSuiteId"
12114
+ requestBody:
12115
+ required: true
12116
+ content:
12117
+ application/json:
12118
+ schema:
12119
+ $ref: "#/components/schemas/UpdateEvalSuiteBodyDto"
12120
+ responses:
12121
+ "200":
12122
+ description: Suite updated (possibly with bumped version)
12123
+ content:
12124
+ application/json:
12125
+ schema:
12126
+ $ref: "#/components/schemas/EvalSuiteDto"
12127
+ "400":
12128
+ description: Validation failed (same codes as create)
12129
+ content:
12130
+ application/json:
12131
+ schema:
12132
+ $ref: "#/components/schemas/ErrorMessageDto"
12133
+ "401":
12134
+ $ref: "#/components/responses/Unauthorized"
12135
+ "403":
12136
+ description: Authenticated but not a workspace editor/admin
12137
+ content:
12138
+ application/json:
12139
+ schema:
12140
+ $ref: "#/components/schemas/ErrorMessageDto"
12141
+ example:
12142
+ error: Workspace editor role required
12143
+ code: workspace_editor_required
12144
+ "404":
12145
+ description: Workspace or suite not found
12146
+ content:
12147
+ application/json:
12148
+ schema:
12149
+ $ref: "#/components/schemas/ErrorMessageDto"
12150
+
12151
+ /workspaces/{workspaceId}/evals/suites/{suiteId}/runs:
12152
+ get:
12153
+ tags: [Evals]
12154
+ summary: List recent eval runs for a suite
12155
+ description: >
12156
+ Returns the last 50 runs for the suite (newest first). Empty → `{ "runs": [] }`.
12157
+ Requires workspace membership. Does not trigger scoring.
12158
+ operationId: listEvalRuns
12159
+ x-test-coverage-skip: contract-only; HTTP/store coverage lands with evals-storage-api
12160
+ parameters:
12161
+ - $ref: "#/components/parameters/WorkspaceId"
12162
+ - $ref: "#/components/parameters/EvalSuiteId"
12163
+ responses:
12164
+ "200":
12165
+ description: Run history (max 50)
12166
+ content:
12167
+ application/json:
12168
+ schema:
12169
+ $ref: "#/components/schemas/EvalRunListDto"
12170
+ example:
12171
+ runs: []
12172
+ "401":
12173
+ $ref: "#/components/responses/Unauthorized"
12174
+ "403":
12175
+ $ref: "#/components/responses/Forbidden"
12176
+ "404":
12177
+ description: Workspace or suite not found
12178
+ content:
12179
+ application/json:
12180
+ schema:
12181
+ $ref: "#/components/schemas/ErrorMessageDto"
12182
+ post:
12183
+ tags: [Evals]
12184
+ summary: Enqueue an eval suite run
12185
+ description: >
12186
+ Enqueues an async eval run. Returns `202` with `{ runId, status: "queued" }`.
12187
+ Never scores on the request path — a worker claims the run, uses
12188
+ `fixtureCompletion` when present (or live completion when provider credentials
12189
+ exist), applies deterministic expected-signal scoring, and persists results.
12190
+ Requires workspace editor or admin. At most one active (`queued`|`running`)
12191
+ run per suite; a second POST returns `409` `eval_run_in_progress`.
12192
+ operationId: enqueueEvalRun
12193
+ x-test-coverage-skip: contract-only; HTTP/store coverage lands with evals-storage-api
12194
+ parameters:
12195
+ - $ref: "#/components/parameters/WorkspaceId"
12196
+ - $ref: "#/components/parameters/EvalSuiteId"
12197
+ responses:
12198
+ "202":
12199
+ description: Run queued
12200
+ content:
12201
+ application/json:
12202
+ schema:
12203
+ $ref: "#/components/schemas/EvalRunEnqueueResponseDto"
12204
+ example:
12205
+ runId: "22222222-2222-4222-8222-222222222222"
12206
+ status: queued
12207
+ "401":
12208
+ $ref: "#/components/responses/Unauthorized"
12209
+ "403":
12210
+ description: Authenticated but not a workspace editor/admin
12211
+ content:
12212
+ application/json:
12213
+ schema:
12214
+ $ref: "#/components/schemas/ErrorMessageDto"
12215
+ example:
12216
+ error: Workspace editor role required
12217
+ code: workspace_editor_required
12218
+ "404":
12219
+ description: Workspace or suite not found
12220
+ content:
12221
+ application/json:
12222
+ schema:
12223
+ $ref: "#/components/schemas/ErrorMessageDto"
12224
+ "409":
12225
+ description: An active queued or running eval already exists for this suite
12226
+ content:
12227
+ application/json:
12228
+ schema:
12229
+ $ref: "#/components/schemas/ErrorMessageDto"
12230
+ example:
12231
+ error: An eval run is already in progress for this suite
12232
+ code: eval_run_in_progress
12233
+
12234
+ /workspaces/{workspaceId}/evals/suites/{suiteId}/runs/{runId}:
12235
+ get:
12236
+ tags: [Evals]
12237
+ summary: Get an eval run with case results
12238
+ description: >
12239
+ Returns persisted run status and case results. While `queued` or `running`,
12240
+ `caseResults` may be empty and `score` null. Requires workspace membership.
12241
+ Does not trigger scoring.
12242
+ operationId: getEvalRun
12243
+ x-test-coverage-skip: contract-only; HTTP/store coverage lands with evals-storage-api
12244
+ parameters:
12245
+ - $ref: "#/components/parameters/WorkspaceId"
12246
+ - $ref: "#/components/parameters/EvalSuiteId"
12247
+ - $ref: "#/components/parameters/EvalRunId"
12248
+ responses:
12249
+ "200":
12250
+ description: Run detail
12251
+ content:
12252
+ application/json:
12253
+ schema:
12254
+ $ref: "#/components/schemas/EvalRunDto"
12255
+ "401":
12256
+ $ref: "#/components/responses/Unauthorized"
12257
+ "403":
12258
+ $ref: "#/components/responses/Forbidden"
12259
+ "404":
12260
+ description: Workspace, suite, or run not found
12261
+ content:
12262
+ application/json:
12263
+ schema:
12264
+ $ref: "#/components/schemas/ErrorMessageDto"
12265
+
12266
+ /workspaces/{workspaceId}/evals/insights:
12267
+ get:
12268
+ tags: [Evals]
12269
+ summary: Eval insights (regressions, tips, efficiency, model comparison)
12270
+ description: >
12271
+ Workspace-level Insights for prompt/model evals. Computes regressions when
12272
+ prior score − current score ≥ 0.10 on the same suiteId+suiteVersion case set
12273
+ (or suite score drop ≥ 0.10); prompt tips from failed signal notes / case
12274
+ names; token efficiency averages over successful cases in the last succeeded
12275
+ run per suite; and model comparison rollups. No succeeded runs → empty arrays
12276
+ and null `tokenEfficiency`. Requires workspace membership. Distinct from
12277
+ `/insights-recommendations` and AI Usage & Spend.
12278
+ operationId: getEvalInsights
12279
+ x-test-coverage-skip: contract-only; HTTP/store coverage lands with evals-storage-api
12280
+ parameters:
12281
+ - $ref: "#/components/parameters/WorkspaceId"
12282
+ responses:
12283
+ "200":
12284
+ description: Insights payload
12285
+ content:
12286
+ application/json:
12287
+ schema:
12288
+ $ref: "#/components/schemas/EvalInsightsDto"
12289
+ "401":
12290
+ $ref: "#/components/responses/Unauthorized"
12291
+ "403":
12292
+ $ref: "#/components/responses/Forbidden"
12293
+ "404":
12294
+ description: Workspace not found
12295
+ content:
12296
+ application/json:
12297
+ schema:
12298
+ $ref: "#/components/schemas/ErrorMessageDto"
12299
+
11942
12300
  components:
11943
12301
  securitySchemes:
11944
12302
  bearerAuth:
@@ -11954,6 +12312,22 @@ components:
11954
12312
  required: true
11955
12313
  schema:
11956
12314
  type: string
12315
+ EvalSuiteId:
12316
+ name: suiteId
12317
+ in: path
12318
+ required: true
12319
+ schema:
12320
+ type: string
12321
+ format: uuid
12322
+ description: Eval suite id (`tai_workspace_eval_suites.id`).
12323
+ EvalRunId:
12324
+ name: runId
12325
+ in: path
12326
+ required: true
12327
+ schema:
12328
+ type: string
12329
+ format: uuid
12330
+ description: Eval run id (`tai_workspace_eval_runs.id`).
11957
12331
  RepoId:
11958
12332
  name: repoId
11959
12333
  in: path
@@ -25489,3 +25863,539 @@ components:
25489
25863
  total: { type: integer, minimum: 0 }
25490
25864
  limit: { type: integer, minimum: 1 }
25491
25865
  offset: { type: integer, minimum: 0 }
25866
+ EvalExpectedSignalKindDto:
25867
+ type: string
25868
+ description: >
25869
+ Deterministic scorer kinds for golden-case expected signals. Case pass =
25870
+ all signals pass. No LLM-as-judge in v1.
25871
+ enum: [contains, not_contains, regex, json_path_equals]
25872
+
25873
+ EvalAiProviderDto:
25874
+ type: string
25875
+ description: >
25876
+ Model provider vocabulary aligned with AI Usage `modelName` surfaces
25877
+ (`cursor` | `claude`).
25878
+ enum: [cursor, claude]
25879
+
25880
+ EvalExpectedSignalDto:
25881
+ type: object
25882
+ additionalProperties: false
25883
+ required: [id, kind]
25884
+ description: >
25885
+ One expected signal on a golden case. Use `value` for `contains` /
25886
+ `not_contains` (substring) and for `json_path_equals` (expected value as
25887
+ string). Use `pattern` for `regex`. Use `path` (JSONPath) for
25888
+ `json_path_equals`.
25889
+ properties:
25890
+ id:
25891
+ type: string
25892
+ minLength: 1
25893
+ maxLength: 64
25894
+ kind:
25895
+ $ref: "#/components/schemas/EvalExpectedSignalKindDto"
25896
+ value:
25897
+ type: string
25898
+ maxLength: 8000
25899
+ description: >
25900
+ Substring for `contains` / `not_contains`, or expected value for
25901
+ `json_path_equals`.
25902
+ pattern:
25903
+ type: string
25904
+ maxLength: 2000
25905
+ description: Regular expression source for `regex`.
25906
+ path:
25907
+ type: string
25908
+ maxLength: 500
25909
+ description: JSONPath expression for `json_path_equals`.
25910
+
25911
+ EvalCaseDto:
25912
+ type: object
25913
+ additionalProperties: false
25914
+ required: [id, name, input, expectedSignals]
25915
+ description: >
25916
+ One golden case in a suite. 1–20 cases per suite; each case requires ≥1
25917
+ expected signal. When `fixtureCompletion` is set, the worker scores that
25918
+ text without calling a live model (CI/demo path).
25919
+ properties:
25920
+ id:
25921
+ type: string
25922
+ minLength: 1
25923
+ maxLength: 64
25924
+ name:
25925
+ type: string
25926
+ minLength: 1
25927
+ maxLength: 200
25928
+ input:
25929
+ type: string
25930
+ minLength: 1
25931
+ maxLength: 20000
25932
+ description: Case input payload (opaque string; often JSON text).
25933
+ fixtureCompletion:
25934
+ type: string
25935
+ maxLength: 100000
25936
+ description: >
25937
+ Optional fixture completion. When present, the worker uses it instead
25938
+ of a live provider call.
25939
+ expectedSignals:
25940
+ type: array
25941
+ minItems: 1
25942
+ maxItems: 20
25943
+ items:
25944
+ $ref: "#/components/schemas/EvalExpectedSignalDto"
25945
+
25946
+ EvalSuiteTargetDto:
25947
+ type: object
25948
+ additionalProperties: false
25949
+ description: >
25950
+ Suite target — at least one of prompt or model. Prompt path requires
25951
+ non-empty `promptBody` (text snapshot) and may include optional `promptKey`
25952
+ slug. Model path requires `provider` + `modelName` (vendor string, same
25953
+ vocabulary as AI Usage `modelName`). Create/update reject when both
25954
+ prompt body is empty and model fields are missing. No separate
25955
+ prompt-template registry in v1; versioning is the suite `version`.
25956
+ properties:
25957
+ promptBody:
25958
+ type: string
25959
+ maxLength: 100000
25960
+ description: Prompt text snapshot. Empty string allowed only when model fields are set.
25961
+ promptKey:
25962
+ type: string
25963
+ maxLength: 120
25964
+ nullable: true
25965
+ description: Optional slug for the prompt (not a registry foreign key in v1).
25966
+ provider:
25967
+ type: string
25968
+ nullable: true
25969
+ enum: [cursor, claude]
25970
+ description: Model provider; null when suite is prompt-only.
25971
+ modelName:
25972
+ type: string
25973
+ maxLength: 200
25974
+ nullable: true
25975
+ description: Vendor model id string (aligned with AI Usage `modelName`).
25976
+
25977
+ EvalSuiteDto:
25978
+ type: object
25979
+ additionalProperties: false
25980
+ required:
25981
+ - id
25982
+ - name
25983
+ - description
25984
+ - version
25985
+ - createdAt
25986
+ - updatedAt
25987
+ - createdByUserId
25988
+ - target
25989
+ - cases
25990
+ description: >
25991
+ Latest version of a workspace eval suite. Max 50 suites per workspace.
25992
+ Name 1–120 chars; description ≤ 2000; version starts at 1.
25993
+ properties:
25994
+ id:
25995
+ type: string
25996
+ format: uuid
25997
+ name:
25998
+ type: string
25999
+ minLength: 1
26000
+ maxLength: 120
26001
+ description:
26002
+ type: string
26003
+ maxLength: 2000
26004
+ version:
26005
+ type: integer
26006
+ minimum: 1
26007
+ description: Monotonic suite version; bumps when target/cases/promptBody change.
26008
+ createdAt:
26009
+ type: string
26010
+ format: date-time
26011
+ updatedAt:
26012
+ type: string
26013
+ format: date-time
26014
+ createdByUserId:
26015
+ type: string
26016
+ format: uuid
26017
+ target:
26018
+ $ref: "#/components/schemas/EvalSuiteTargetDto"
26019
+ cases:
26020
+ type: array
26021
+ minItems: 1
26022
+ maxItems: 20
26023
+ items:
26024
+ $ref: "#/components/schemas/EvalCaseDto"
26025
+
26026
+ EvalSuiteListDto:
26027
+ type: object
26028
+ additionalProperties: false
26029
+ required: [suites]
26030
+ properties:
26031
+ suites:
26032
+ type: array
26033
+ maxItems: 50
26034
+ items:
26035
+ $ref: "#/components/schemas/EvalSuiteDto"
26036
+
26037
+ CreateEvalSuiteBodyDto:
26038
+ type: object
26039
+ additionalProperties: false
26040
+ required: [name, target, cases]
26041
+ properties:
26042
+ name:
26043
+ type: string
26044
+ minLength: 1
26045
+ maxLength: 120
26046
+ description:
26047
+ type: string
26048
+ maxLength: 2000
26049
+ default: ""
26050
+ target:
26051
+ $ref: "#/components/schemas/EvalSuiteTargetDto"
26052
+ cases:
26053
+ type: array
26054
+ minItems: 1
26055
+ maxItems: 20
26056
+ items:
26057
+ $ref: "#/components/schemas/EvalCaseDto"
26058
+
26059
+ UpdateEvalSuiteBodyDto:
26060
+ type: object
26061
+ additionalProperties: false
26062
+ required: [name, target, cases]
26063
+ description: >
26064
+ Full replace of mutable suite fields. Version bumps only when `target`,
26065
+ `cases`, or `promptBody` change versus the stored latest version.
26066
+ properties:
26067
+ name:
26068
+ type: string
26069
+ minLength: 1
26070
+ maxLength: 120
26071
+ description:
26072
+ type: string
26073
+ maxLength: 2000
26074
+ default: ""
26075
+ target:
26076
+ $ref: "#/components/schemas/EvalSuiteTargetDto"
26077
+ cases:
26078
+ type: array
26079
+ minItems: 1
26080
+ maxItems: 20
26081
+ items:
26082
+ $ref: "#/components/schemas/EvalCaseDto"
26083
+
26084
+ EvalRunStatusDto:
26085
+ type: string
26086
+ enum: [queued, running, succeeded, failed, cancelled]
26087
+
26088
+ EvalCaseResultStatusDto:
26089
+ type: string
26090
+ description: >
26091
+ Per-case outcome. `error` is used when completion is unavailable
26092
+ (`code: completion_unavailable`) or another non-score failure occurs.
26093
+ enum: [passed, failed, error]
26094
+
26095
+ EvalCaseResultDto:
26096
+ type: object
26097
+ additionalProperties: false
26098
+ required:
26099
+ - caseId
26100
+ - name
26101
+ - status
26102
+ - pass
26103
+ - failedSignalIds
26104
+ description: >
26105
+ Persisted result for one case. `pass` is true only when `status` is
26106
+ `passed` (all expected signals matched). On signal failure, `pass` is
26107
+ false and `failedSignalIds` lists the failing signal ids. On
26108
+ `completion_unavailable`, `status` is `error` and `code` is set.
26109
+ properties:
26110
+ caseId:
26111
+ type: string
26112
+ name:
26113
+ type: string
26114
+ status:
26115
+ $ref: "#/components/schemas/EvalCaseResultStatusDto"
26116
+ pass:
26117
+ type: boolean
26118
+ failedSignalIds:
26119
+ type: array
26120
+ items:
26121
+ type: string
26122
+ completion:
26123
+ type: string
26124
+ nullable: true
26125
+ description: Completion text used for scoring (fixture or live).
26126
+ inputTokens:
26127
+ type: integer
26128
+ nullable: true
26129
+ minimum: 0
26130
+ outputTokens:
26131
+ type: integer
26132
+ nullable: true
26133
+ minimum: 0
26134
+ costCents:
26135
+ type: number
26136
+ nullable: true
26137
+ minimum: 0
26138
+ description: Provider-reported cost in cents when available.
26139
+ code:
26140
+ type: string
26141
+ nullable: true
26142
+ description: >
26143
+ Machine-readable error when `status` is `error`
26144
+ (e.g. `completion_unavailable`).
26145
+ error:
26146
+ type: string
26147
+ nullable: true
26148
+ description: Human-readable error detail when `status` is `error`.
26149
+
26150
+ EvalSuiteSnapshotDto:
26151
+ type: object
26152
+ additionalProperties: false
26153
+ required: [name, description, version, target, cases]
26154
+ description: >
26155
+ Immutable suite snapshot pinned on a run (`suiteVersion` + JSON). Used so
26156
+ historical runs stay interpretable after later suite edits.
26157
+ properties:
26158
+ name:
26159
+ type: string
26160
+ description:
26161
+ type: string
26162
+ version:
26163
+ type: integer
26164
+ minimum: 1
26165
+ target:
26166
+ $ref: "#/components/schemas/EvalSuiteTargetDto"
26167
+ cases:
26168
+ type: array
26169
+ items:
26170
+ $ref: "#/components/schemas/EvalCaseDto"
26171
+
26172
+ EvalRunDto:
26173
+ type: object
26174
+ additionalProperties: false
26175
+ required:
26176
+ - id
26177
+ - suiteId
26178
+ - suiteVersion
26179
+ - status
26180
+ - startedAt
26181
+ - finishedAt
26182
+ - passCount
26183
+ - failCount
26184
+ - errorCount
26185
+ - score
26186
+ - caseResults
26187
+ description: >
26188
+ Persisted eval run. Suite score = `passedCases / scoredCases` in [0,1]
26189
+ when at least one case was scored; `null` when the run ends with all
26190
+ cases in `error` (status `failed`). List endpoints return at most the
26191
+ last 50 runs per suite.
26192
+ properties:
26193
+ id:
26194
+ type: string
26195
+ format: uuid
26196
+ suiteId:
26197
+ type: string
26198
+ format: uuid
26199
+ suiteVersion:
26200
+ type: integer
26201
+ minimum: 1
26202
+ status:
26203
+ $ref: "#/components/schemas/EvalRunStatusDto"
26204
+ startedAt:
26205
+ type: string
26206
+ format: date-time
26207
+ nullable: true
26208
+ description: Set when the worker claims the run (`running`).
26209
+ finishedAt:
26210
+ type: string
26211
+ format: date-time
26212
+ nullable: true
26213
+ passCount:
26214
+ type: integer
26215
+ minimum: 0
26216
+ failCount:
26217
+ type: integer
26218
+ minimum: 0
26219
+ errorCount:
26220
+ type: integer
26221
+ minimum: 0
26222
+ score:
26223
+ type: number
26224
+ nullable: true
26225
+ minimum: 0
26226
+ maximum: 1
26227
+ description: >
26228
+ `passedCases / scoredCases` in [0,1], or null when no case was scored
26229
+ (all-error run).
26230
+ caseResults:
26231
+ type: array
26232
+ items:
26233
+ $ref: "#/components/schemas/EvalCaseResultDto"
26234
+ suiteSnapshot:
26235
+ type: object
26236
+ nullable: true
26237
+ allOf:
26238
+ - $ref: "#/components/schemas/EvalSuiteSnapshotDto"
26239
+ description: Pinned suite snapshot for this run (present on persisted runs).
26240
+
26241
+ EvalRunListDto:
26242
+ type: object
26243
+ additionalProperties: false
26244
+ required: [runs]
26245
+ properties:
26246
+ runs:
26247
+ type: array
26248
+ maxItems: 50
26249
+ items:
26250
+ $ref: "#/components/schemas/EvalRunDto"
26251
+
26252
+ EvalRunEnqueueResponseDto:
26253
+ type: object
26254
+ additionalProperties: false
26255
+ required: [runId, status]
26256
+ properties:
26257
+ runId:
26258
+ type: string
26259
+ format: uuid
26260
+ status:
26261
+ type: string
26262
+ enum: [queued]
26263
+ description: Always `queued` on enqueue; poll GET run for progress.
26264
+
26265
+ EvalRegressionDto:
26266
+ type: object
26267
+ additionalProperties: false
26268
+ required:
26269
+ - suiteId
26270
+ - suiteVersion
26271
+ - priorScore
26272
+ - currentScore
26273
+ - scoreDrop
26274
+ description: >
26275
+ Regression when prior score − current score ≥ 0.10 on the same
26276
+ suiteId+suiteVersion case set, or suite score drop ≥ 0.10.
26277
+ properties:
26278
+ suiteId:
26279
+ type: string
26280
+ format: uuid
26281
+ suiteName:
26282
+ type: string
26283
+ suiteVersion:
26284
+ type: integer
26285
+ minimum: 1
26286
+ caseId:
26287
+ type: string
26288
+ nullable: true
26289
+ description: Set for case-level regressions; null for suite-level score drops.
26290
+ caseName:
26291
+ type: string
26292
+ nullable: true
26293
+ priorRunId:
26294
+ type: string
26295
+ format: uuid
26296
+ currentRunId:
26297
+ type: string
26298
+ format: uuid
26299
+ priorScore:
26300
+ type: number
26301
+ minimum: 0
26302
+ maximum: 1
26303
+ currentScore:
26304
+ type: number
26305
+ minimum: 0
26306
+ maximum: 1
26307
+ scoreDrop:
26308
+ type: number
26309
+ minimum: 0
26310
+ maximum: 1
26311
+ description: priorScore − currentScore (always ≥ 0.10 for listed items).
26312
+
26313
+ EvalPromptTipDto:
26314
+ type: object
26315
+ additionalProperties: false
26316
+ required: [suiteId, message]
26317
+ description: Tip derived from failed signal notes / case names on recent runs.
26318
+ properties:
26319
+ suiteId:
26320
+ type: string
26321
+ format: uuid
26322
+ suiteName:
26323
+ type: string
26324
+ caseId:
26325
+ type: string
26326
+ nullable: true
26327
+ caseName:
26328
+ type: string
26329
+ nullable: true
26330
+ signalId:
26331
+ type: string
26332
+ nullable: true
26333
+ message:
26334
+ type: string
26335
+ maxLength: 2000
26336
+
26337
+ EvalTokenEfficiencyDto:
26338
+ type: object
26339
+ additionalProperties: false
26340
+ required: [avgInputTokens, avgOutputTokens, avgCostCents]
26341
+ description: >
26342
+ Averages over successful cases in the last succeeded run per suite
26343
+ (workspace rollup). Nullables when token/cost fields were not returned.
26344
+ properties:
26345
+ avgInputTokens:
26346
+ type: number
26347
+ nullable: true
26348
+ minimum: 0
26349
+ avgOutputTokens:
26350
+ type: number
26351
+ nullable: true
26352
+ minimum: 0
26353
+ avgCostCents:
26354
+ type: number
26355
+ nullable: true
26356
+ minimum: 0
26357
+
26358
+ EvalModelComparisonDto:
26359
+ type: object
26360
+ additionalProperties: false
26361
+ required: [provider, modelName, suiteCount, avgScore]
26362
+ properties:
26363
+ provider:
26364
+ $ref: "#/components/schemas/EvalAiProviderDto"
26365
+ modelName:
26366
+ type: string
26367
+ suiteCount:
26368
+ type: integer
26369
+ minimum: 0
26370
+ avgScore:
26371
+ type: number
26372
+ nullable: true
26373
+ minimum: 0
26374
+ maximum: 1
26375
+ description: Average suite score across succeeded runs for this model; null when none.
26376
+
26377
+ EvalInsightsDto:
26378
+ type: object
26379
+ additionalProperties: false
26380
+ required: [regressions, promptTips, tokenEfficiency, modelComparison]
26381
+ description: >
26382
+ Insights hub payload for Prompt & model evals. Empty succeeded-run history
26383
+ → empty arrays and null `tokenEfficiency`.
26384
+ properties:
26385
+ regressions:
26386
+ type: array
26387
+ items:
26388
+ $ref: "#/components/schemas/EvalRegressionDto"
26389
+ promptTips:
26390
+ type: array
26391
+ items:
26392
+ $ref: "#/components/schemas/EvalPromptTipDto"
26393
+ tokenEfficiency:
26394
+ type: object
26395
+ nullable: true
26396
+ allOf:
26397
+ - $ref: "#/components/schemas/EvalTokenEfficiencyDto"
26398
+ modelComparison:
26399
+ type: array
26400
+ items:
26401
+ $ref: "#/components/schemas/EvalModelComparisonDto"