wicked-crew-api-types 0.139.0 → 0.143.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/index.d.ts +510 -5
  2. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -292,6 +292,14 @@ export interface HealthCapabilities {
292
292
  * ({@link SystemSnapshot}). ABSENT on an older daemon — show the older Health cards instead.
293
293
  */
294
294
  system?: boolean;
295
+ /**
296
+ * (api-types 0.140.0) `GET /system.attention[]` follows the one "needs you" rule (root causes with
297
+ * `blockedRunIds`, `kind`, `waitedSince`, ranked by impact) and the snapshot carries
298
+ * `unresolved[]` + `toReview`; `POST /runs/:id/resolve` is served. A skin shows
299
+ * `attention.length` as its "needs you" number only when this is true; ABSENT on an older daemon,
300
+ * which keeps its own fold.
301
+ */
302
+ attentionRanked?: boolean;
295
303
  /**
296
304
  * (api-types 0.137.0, DES-SYSTEM-CHAT) The chat history is served: `GET /chats` carries `items` +
297
305
  * `nextCursor`, `GET /chats/:id/messages` reopens a chat, `POST /chats/:id/close` ends one and keeps
@@ -303,6 +311,13 @@ export interface HealthCapabilities {
303
311
  * ABSENT on an older daemon — hide upload.
304
312
  */
305
313
  chatAttachments?: boolean;
314
+ /**
315
+ * (api-types 0.141.0, crew#1157) The read-only workflows `ChatOpenBody.workflow` runs on this
316
+ * daemon's engine — `['analyze']` on a core-ts that carries the built-in `analyze` preset, `[]` on
317
+ * one that does not. ABSENT on an older daemon (its strict schema refuses `workflow`): open a plain
318
+ * chat instead.
319
+ */
320
+ chatWorkflows?: string[];
306
321
  }
307
322
 
308
323
  /** One `GET /health.warnings[]` entry (additive; wicked-core#411 / wicked-crew#497). */
@@ -6695,6 +6710,14 @@ export interface ChatOpenBody {
6695
6710
  primary?: string;
6696
6711
  /** (api-types 0.137.0, DES-SYSTEM-CHAT) The page the chat was started on, for the history list. */
6697
6712
  startedOn?: ChatStartedOn;
6713
+ /**
6714
+ * (api-types 0.141.0, crew#1157) Run every turn of this chat as a READ-ONLY workflow: `analyze`
6715
+ * answers questions about the repositories in scope from the code graph and the files, each claim
6716
+ * cited, changing nothing. The chat seats ONE helper (`primary`, else the first eligible), asks for
6717
+ * no reviewer, never delivers, and its seats propose no work. A name chats do not run is a 400; an
6718
+ * engine without it is a 409. Send it only when `GET /health.capabilities.chatWorkflows` names it.
6719
+ */
6720
+ workflow?: string;
6698
6721
  }
6699
6722
 
6700
6723
  /** The scope a `POST /chats` caller may name (api-types 0.39.0, studio#323 R4). */
@@ -6842,6 +6865,8 @@ export interface ChatOpenResponse {
6842
6865
  * field; a daemon between #641 and #650 emitted it only when `refused` was non-empty.
6843
6866
  */
6844
6867
  singleSeat?: ChatSingleSeatDegradation;
6868
+ /** (api-types 0.141.0, crew#1157) The workflow every turn runs, when the open named one. */
6869
+ workflow?: string;
6845
6870
  }
6846
6871
 
6847
6872
  /** `POST /chats/:id/messages` → 202. */
@@ -8288,7 +8313,9 @@ export interface NoEligibleSeatBody {
8288
8313
  export type SystemState = 'ok' | 'degraded' | 'down' | 'unknown' | 'off';
8289
8314
 
8290
8315
  /** The Nerve Center light: `red` when work is blocked, `yellow` when something needs a look but
8291
- * work still flows, `green` when `attention[]` is empty. Derived from `attention[]` only. */
8316
+ * work still flows, `green` when `attention[]` is empty. Derived from `attention[]` only.
8317
+ * (api-types 0.140.0, `capabilities.attentionRanked`) `green` ONLY when `attention[]` AND
8318
+ * `unresolved[]` are both empty: unresolved work alone reads `yellow`. */
8292
8319
  export type SystemLevel = 'green' | 'yellow' | 'red';
8293
8320
 
8294
8321
  /** The existing action an attention item or row offers (the snapshot itself is read-only):
@@ -8318,11 +8345,36 @@ export interface SystemSnapshot {
8318
8345
  budgetMs: number;
8319
8346
  /** How long assembling it took, in ms. */
8320
8347
  tookMs: number;
8321
- /** `red` iff some attention item is `red`, else `yellow` iff any item, else `green`. */
8348
+ /** `red` iff some attention item is `red`, else `yellow` iff any item, else `green`. (api-types
8349
+ * 0.140.0, `capabilities.attentionRanked`) `yellow` also when `unresolved[]` is not empty: `green`
8350
+ * only when both are empty. */
8322
8351
  level: SystemLevel;
8323
8352
  /** Every item that needs a look, worst first (red before yellow, then by how many runs it
8324
- * blocks, then infra › cli › run › governance). Empty when all is clear. */
8353
+ * blocks, then infra › cli › run › governance). Empty when all is clear.
8354
+ *
8355
+ * (api-types 0.140.0, `capabilities.attentionRanked`) The ONE "needs you" list: each item is one
8356
+ * root cause holding work up right now, either because work cannot move until a person acts
8357
+ * (`kind: 'prevents'`) or because the system itself slows it (`kind: 'slows'`). One cause that
8358
+ * holds several runs is ONE item naming them in `blockedRunIds`. Superseded runs, answered asks,
8359
+ * failed runs older than 7 days, benches with an alternative and pending proposals are not in it
8360
+ * (the first three move to `unresolved[]`; proposals are `toReview`). Sorted by runs held, then
8361
+ * prevents before slows, then a component (infra, or no seat at all) before one run's own cause,
8362
+ * then the longest wait, then the units left. Its length is the number. */
8325
8363
  attention: SystemAttentionItem[];
8364
+ /**
8365
+ * (api-types 0.140.0) Work nobody has resolved: failed runs not retried and not archived,
8366
+ * superseded runs still open, asks parked at their turn gate past a day. Each carries what it cost
8367
+ * and how to resolve it (retry, archive with a reason, or close as superseded). Never counted in
8368
+ * `attention[]`, never dropped by age. ABSENT on an older daemon.
8369
+ */
8370
+ unresolved?: SystemUnresolvedItem[];
8371
+ /** (api-types 0.140.0) `unresolved[]`'s summed cost: `costUsd` is `null` when no item's cost is
8372
+ * known; `costKnown` says how many items carried one. ABSENT on an older daemon. */
8373
+ unresolvedSpend?: { costUsd: number | null; tokens: { input: number; output: number } | null; costKnown: number };
8374
+ /** (api-types 0.140.0) Pending proposals waiting on review: shown as "N to review", never in the
8375
+ * "needs you" number (no run waits on them). `null` when the queue did not answer in time. ABSENT
8376
+ * on an older daemon. */
8377
+ toReview?: number | null;
8326
8378
  /** One entry per CLI on the roster, in roster order. */
8327
8379
  clis: SystemCli[];
8328
8380
  /** Every unfinished run (not completed / cancelled / failed), worst first:
@@ -8349,6 +8401,72 @@ export interface SystemAttentionItem {
8349
8401
  target: SystemTarget;
8350
8402
  /** The one existing action that helps, or `null`. */
8351
8403
  action: SystemAction | null;
8404
+ /** (api-types 0.140.0) `prevents`: work cannot move until someone acts; `slows`: the system
8405
+ * slows it (host load). ABSENT on an older daemon. */
8406
+ kind?: 'prevents' | 'slows';
8407
+ /** (api-types 0.140.0) The runs this one cause holds (`blocks` is its length). For a `slows`
8408
+ * item, the runs whose next step it slows. ABSENT on an older daemon. */
8409
+ blockedRunIds?: string[];
8410
+ /** (api-types 0.140.0) ISO-8601 of the oldest open gate among the held runs (the gate's
8411
+ * arrival, never the run's launch); a failed run's end; `null` when unknown. ABSENT on an older
8412
+ * daemon. */
8413
+ waitedSince?: string | null;
8414
+ /** (api-types 0.140.0) Units not yet done across the held runs. ABSENT on an older daemon. */
8415
+ unitsLeft?: number;
8416
+ }
8417
+
8418
+ /** (api-types 0.140.0) Why a run is in `unresolved[]`. `failed`: it failed and was neither retried
8419
+ * (`retry_of`) nor archived; `superseded`: a retry or a later completed run with the same repo,
8420
+ * workflow and title replaced it, but it is still open or unarchived; `parked`: an ask waits at its
8421
+ * turn gate past a day. */
8422
+ export type SystemUnresolvedWhy = 'failed' | 'superseded' | 'parked';
8423
+
8424
+ /** (api-types 0.140.0) The ways to resolve an unresolved run: `retry` (`POST /runs {retryOf}`),
8425
+ * `archive` (`POST /runs/:id/resolve {action: 'archive', reason}`, a reason is required) and
8426
+ * `close_superseded` (`POST /runs/:id/resolve {action: 'superseded', by}`). */
8427
+ export type SystemResolveKind = 'retry' | 'archive' | 'close_superseded';
8428
+
8429
+ /** (api-types 0.140.0) One run nobody has resolved (`SystemSnapshot.unresolved[]`). */
8430
+ export interface SystemUnresolvedItem {
8431
+ /** `unresolved:<runId>`. */
8432
+ id: string;
8433
+ runId: string;
8434
+ title: string;
8435
+ /** (api-types 0.142.0) The run's repo (`repo_ref`) and workflow, so a skin can group look-alike items; `null` when none. ABSENT before. */
8436
+ repo?: string | null;
8437
+ workflow?: string | null;
8438
+ /** The engine's status. */
8439
+ status: string;
8440
+ why: SystemUnresolvedWhy;
8441
+ /** Plain words ("failed 9 days ago", "superseded by 6f11390c, which delivered"). */
8442
+ reason: string;
8443
+ /** The run that superseded it, for `why: 'superseded'`. */
8444
+ supersededBy?: string;
8445
+ /** ISO-8601 of when it stopped moving (its end, or its gate's arrival); `null` when unknown. */
8446
+ since: string | null;
8447
+ /** What it cost. `costUsd`/`tokens` are `null` when the run's log carried no usage frame (or was
8448
+ * not read yet); `wallMs` is launch to end (or to now while open), `null` for an undated run. */
8449
+ cost: { costUsd: number | null; tokens: { input: number; output: number } | null; wallMs: number | null };
8450
+ /** The resolutions that apply, best first. */
8451
+ actions: SystemResolveKind[];
8452
+ }
8453
+
8454
+ /** (api-types 0.140.0) `POST /runs/:id/resolve`: resolve an unresolved run. `archive` needs a
8455
+ * non-blank `reason` (a blank or missing one is a 400); `superseded` names the run that replaced it
8456
+ * in `by` (an existing run, not itself). A run parked at a gate is stopped first, then archived; a
8457
+ * run that is executing is refused (409). The archive note keeps the reason. */
8458
+ export type ResolveRunRequest =
8459
+ | { action: 'archive'; reason: string }
8460
+ | { action: 'superseded'; by: string; reason?: string };
8461
+
8462
+ export interface ResolveRunResponse {
8463
+ runId: string;
8464
+ action: 'archive' | 'superseded';
8465
+ archived: true;
8466
+ /** The run was parked at a gate and was stopped before it was archived. */
8467
+ cancelled: boolean;
8468
+ /** The archive note written (`resolved: <reason>` or `superseded by <id>[: <reason>]`). */
8469
+ note: string;
8352
8470
  }
8353
8471
 
8354
8472
  // ── clis[] ──
@@ -8475,8 +8593,9 @@ export interface SystemRun {
8475
8593
  /** The thresholds the verdict used (from `workerStallMinutes`). */
8476
8594
  quietAfterMs: number;
8477
8595
  stallAfterMs: number;
8478
- /** The open gate or question, when the run waits on one. */
8479
- gate?: { interactionId: string | null; ord: number | null; kind: string | null; prompt: string | null };
8596
+ /** The open gate or question, when the run waits on one. `receivedAt` (api-types 0.140.0): ISO-8601
8597
+ * of the gate's arrival; `null`/ABSENT when unknown. */
8598
+ gate?: { interactionId: string | null; ord: number | null; kind: string | null; prompt: string | null; receivedAt?: string | null };
8480
8599
  /** ISO-8601 the run was launched, when known. */
8481
8600
  createdAt: string | null;
8482
8601
  }
@@ -11724,6 +11843,187 @@ export interface LearnTopicsResponse {
11724
11843
  topics: LearnTopic[];
11725
11844
  }
11726
11845
 
11846
+ // ── workflow schedules + the run review (DES-RUNS-REVIEW-001) ─────────────────────────────────
11847
+ // `/api/v1/schedules`: any workflow on a cadence (the default entry reviews recent work every 48 h).
11848
+ // `/api/v1/insights`: every review of recent work, its numbers and what happened to each recommendation.
11849
+
11850
+ /** A schedule's last outcome: `launched` while its run is open; `refused` = the launch failed. */
11851
+ /** `launching` = the run id is reserved and the engine is being asked; it holds the slot across a restart. */
11852
+ export type ScheduleOutcome = 'launching' | 'launched' | 'refused' | 'completed' | 'failed' | 'cancelled' | 'skipped';
11853
+
11854
+ /** One workflow schedule (`GET /schedules`). */
11855
+ export interface WorkflowSchedule {
11856
+ /** Kebab-case; the default entry is `review-recent-work`. */
11857
+ id: string;
11858
+ workflow: string;
11859
+ /** Interval, 24..2160 hours. */
11860
+ everyHours: number;
11861
+ enabled: boolean;
11862
+ /** Projects the run covers; empty = all. */
11863
+ projectIds: string[];
11864
+ repoRef: string | null;
11865
+ problem: string | null;
11866
+ /** ISO-8601. Missed intervals coalesce into one launch; a schedule whose last run is open is skipped. */
11867
+ nextDueAt: string;
11868
+ lastRunId: string | null;
11869
+ lastRunAt: string | null;
11870
+ lastOutcome: ScheduleOutcome | null;
11871
+ /** Why the last attempt was skipped or refused, in plain words; null after a launch. */
11872
+ lastNote: string | null;
11873
+ /** Consecutive refused launches (backoff = min(2^failures, 24) h). */
11874
+ failures: number;
11875
+ createdAt: string;
11876
+ updatedAt: string;
11877
+ /** The `review-recent-work` schedule only: the latest review's date and outcome. */
11878
+ lastReview?: { runId: string; launchedAt: string; endedAt: string | null; status: InsightsReviewStatus } | null;
11879
+ }
11880
+
11881
+ export interface SchedulesResponse {
11882
+ schedules: WorkflowSchedule[];
11883
+ }
11884
+
11885
+ /** `PUT /schedules/:id` (human-only). */
11886
+ export interface SchedulePutBody {
11887
+ workflow: string;
11888
+ everyHours: number;
11889
+ enabled?: boolean;
11890
+ projectIds?: string[];
11891
+ repoRef?: string | null;
11892
+ problem?: string | null;
11893
+ }
11894
+
11895
+ /** `POST /schedules/:id/run` ("Run it now", human-only): 409 when its last run is still going or another run works. */
11896
+ export interface ScheduleRunResponse {
11897
+ runId: string;
11898
+ schedule: WorkflowSchedule;
11899
+ }
11900
+
11901
+ export type InsightsMetricId = 'pass_rate' | 'override_rate' | 'unresolved_rate' | 'time_to_pr' | 'floor_minutes' | 'wait_on_people' | 'spend' | 'retries';
11902
+ /** `too-few` = below the minimum sample (n < 5) in the window or the baseline: no trend is called. */
11903
+ export type InsightsVerdict = 'too-few' | 'no-change' | 'improved' | 'regressed';
11904
+ export type InsightsRecommendationKind = 'steering-rule' | 'memory' | 'setting' | 'issue' | 'resolve-stale';
11905
+ export type InsightsReviewStatus = 'running' | 'completed' | 'failed' | 'cancelled';
11906
+
11907
+ export interface InsightsInterval {
11908
+ lo: number;
11909
+ hi: number;
11910
+ }
11911
+
11912
+ /** A sample: a rate (Wilson 95 % interval) or a median (bootstrap 95 % interval, with p75/p90). */
11913
+ export interface InsightsSampleStat {
11914
+ n: number;
11915
+ value: number | null;
11916
+ interval: InsightsInterval | null;
11917
+ p75?: number | null;
11918
+ p90?: number | null;
11919
+ }
11920
+
11921
+ export interface InsightsMetricDef {
11922
+ id: InsightsMetricId;
11923
+ label: string;
11924
+ kind: 'rate' | 'median';
11925
+ unit: 'ratio' | 'minutes' | 'usd' | 'count';
11926
+ higherIsBetter: boolean;
11927
+ }
11928
+
11929
+ export interface InsightsRecommendation {
11930
+ /** `<review run id>:<candidate id>`. */
11931
+ id: string;
11932
+ candidate: string;
11933
+ kind: InsightsRecommendationKind;
11934
+ title: string;
11935
+ evidence: {
11936
+ line: string;
11937
+ runs: Array<{ id: string; title: string }>;
11938
+ metric?: InsightsMetricId;
11939
+ segment?: string;
11940
+ n: number;
11941
+ value?: number | null;
11942
+ baseline?: number | null;
11943
+ interval?: InsightsInterval | null;
11944
+ };
11945
+ expectedEffect: string;
11946
+ confidence: 'high' | 'medium' | 'low';
11947
+ /** What evidence would change our mind. */
11948
+ changeMind: string;
11949
+ /** Crew's ranking key: runs affected + hours at stake + dollars at stake. */
11950
+ impact: number;
11951
+ basis: 'notable' | 'pattern';
11952
+ action: {
11953
+ setting?: string;
11954
+ issue?: { repoRef: string | null; title: string; body: string };
11955
+ runs?: string[];
11956
+ proposal?: { kindType: string; content: string; severity?: string };
11957
+ };
11958
+ state: 'new' | 'accepted' | 'dismissed';
11959
+ reason: string | null;
11960
+ decidedAt: string | null;
11961
+ /** The approve-queue proposal filed for a steering-rule or memory recommendation. */
11962
+ proposalId: string | null;
11963
+ proposalError: string | null;
11964
+ }
11965
+
11966
+ export interface InsightsReview {
11967
+ runId: string;
11968
+ trigger: 'schedule' | 'manual';
11969
+ scheduleId: string | null;
11970
+ launchedAt: string;
11971
+ endedAt: string | null;
11972
+ status: InsightsReviewStatus;
11973
+ window: { startMs: number; endMs: number };
11974
+ baselineWindows: Array<{ startMs: number; endMs: number }>;
11975
+ projectIds: string[];
11976
+ summary: string | null;
11977
+ /** false = the seat wrote no usable report; crew's own wording is shown, labelled "not interpreted". */
11978
+ interpreted: boolean;
11979
+ totals: Record<string, number> | null;
11980
+ /** The all-runs metrics of this review: one point per metric on the trend lines. */
11981
+ series: Array<{ metric: InsightsMetricId; window: InsightsSampleStat; baseline: InsightsSampleStat; verdict: InsightsVerdict }>;
11982
+ /** What got better, and what is working. */
11983
+ improvements: Array<{ metric: InsightsMetricId; segment: string; line: string }>;
11984
+ regressions: Array<{ metric: InsightsMetricId; segment: string; line: string }>;
11985
+ /** At most five, ranked by impact. */
11986
+ recommendations: InsightsRecommendation[];
11987
+ watching: Array<{ id: string; title: string; line: string }>;
11988
+ error: string | null;
11989
+ }
11990
+
11991
+ /** `GET /insights`: the review history, newest first. */
11992
+ export interface InsightsResponse {
11993
+ reviews: InsightsReview[];
11994
+ /** Recommendations nobody has accepted or dismissed yet, across the history. */
11995
+ newRecommendations: number;
11996
+ running: boolean;
11997
+ lastReview: { runId: string; launchedAt: string; endedAt: string | null; status: InsightsReviewStatus } | null;
11998
+ metrics: InsightsMetricDef[];
11999
+ /** Below this n no trend is called. */
12000
+ minSample: number;
12001
+ }
12002
+
12003
+ /** What studio opens on Accept: the proposal (approval stays in the approve queue), a settings section, a
12004
+ * prefilled new-issue page, or the runs list filtered to these runs. */
12005
+ export type InsightsAcceptTarget =
12006
+ | { kind: 'proposal'; proposalId: string }
12007
+ | { kind: 'settings'; section: string }
12008
+ | { kind: 'issue'; repoRef: string | null; title: string; body: string; url: string | null }
12009
+ | { kind: 'runs'; runIds: string[] }
12010
+ | { kind: 'none' };
12011
+
12012
+ /** `POST /insights/recommendations/:id/accept` (human-only). */
12013
+ export interface AcceptRecommendationResponse {
12014
+ recommendation: InsightsRecommendation;
12015
+ open: InsightsAcceptTarget;
12016
+ }
12017
+
12018
+ /** `POST /insights/recommendations/:id/dismiss` (human-only). A proposal-backed one rejects its proposal. */
12019
+ export interface DismissRecommendationBody {
12020
+ reason: string;
12021
+ }
12022
+
12023
+ export interface DismissRecommendationResponse {
12024
+ recommendation: InsightsRecommendation;
12025
+ }
12026
+
11727
12027
  // ── MCP inspector bridge (DES-MCP-INSPECTOR-001 §3) ───────────────────────────────────────────
11728
12028
  // `/api/v1/mcp-inspect/sessions`: one live connection to an MCP server per session, driven by
11729
12029
  // studio's host for an `mcp-server` editor. Start, send and delete are human-only; the log is
@@ -11910,3 +12210,208 @@ export interface SearchResponse {
11910
12210
  partial: boolean;
11911
12211
  took_ms: number;
11912
12212
  }
12213
+
12214
+ // ── Default evals (DES-DEFAULT-EVALS-001; api-types 0.143.0) ─────────────────────────────────────────────
12215
+ // `/api/v1/testing/default-evals*`: the system's own judgments (needs-you, floor class, QE verdict, attribution,
12216
+ // steering firing, recall, prompt routing, normalization) scored against what really happened. One case shape for
12217
+ // every suite; real, synthetic, combined and model-labelled figures are always reported apart.
12218
+
12219
+ /** The eight inference points. */
12220
+ export type DefaultEvalSuiteId =
12221
+ | 'needs-you'
12222
+ | 'floor-class'
12223
+ | 'qe-verdict'
12224
+ | 'attribution'
12225
+ | 'steering'
12226
+ | 'recall'
12227
+ | 'archetype'
12228
+ | 'normalization';
12229
+
12230
+ export type DefaultEvalCaseSource = 'real' | 'synthetic';
12231
+
12232
+ /**
12233
+ * Who said what the answer should be. `operator`: the person's choice at a gate (or a ruling); `rule`: a
12234
+ * deterministic consistency rule over the case's own evidence; `fixture`: written into a corpus or the generator;
12235
+ * `model:<seat>`: a model labelled it because nothing else could. Model labels are reported in their own row and
12236
+ * never in the headline (DES §3, determinism).
12237
+ */
12238
+ export type DefaultEvalLabelBy = 'operator' | 'rule' | 'fixture' | `model:${string}`;
12239
+
12240
+ /** What the system answered: a class, a set (attribution), or a cluster key (needs-you merge). */
12241
+ export interface DefaultEvalAnswer {
12242
+ label?: string;
12243
+ labels?: string[];
12244
+ cluster?: string;
12245
+ }
12246
+
12247
+ export interface DefaultEvalObserved extends DefaultEvalAnswer {
12248
+ /** The classifier's own confidence in `label`, in [0, 1], when it gives one (calibration). */
12249
+ confidence?: number;
12250
+ /** `recorded`: read from the run store as the system said it then. `replay`: the current classifier, run now. */
12251
+ by: 'recorded' | 'replay';
12252
+ }
12253
+
12254
+ export interface DefaultEvalExpected extends DefaultEvalAnswer {
12255
+ by: DefaultEvalLabelBy;
12256
+ /** Why this is the answer, in a line (the operator's words, or the rule that fired). */
12257
+ why?: string;
12258
+ }
12259
+
12260
+ export interface DefaultEvalCaseEvidence {
12261
+ runId?: string;
12262
+ ord?: number;
12263
+ seq?: number;
12264
+ decisionId?: string;
12265
+ /** A repo-relative or program-relative file the case was read from (seed cases). */
12266
+ file?: string;
12267
+ }
12268
+
12269
+ export interface DefaultEvalCase {
12270
+ /** Stable identity: capture is idempotent by it. */
12271
+ id: string;
12272
+ suite: DefaultEvalSuiteId;
12273
+ source: DefaultEvalCaseSource;
12274
+ /** The project (or repo, when the run has no project) the case belongs to; `null` when neither is known. */
12275
+ project: string | null;
12276
+ /** The surface that produced `observed`, when several surfaces answer one question (needs-you). */
12277
+ surface?: string;
12278
+ /**
12279
+ * The canonical input fingerprint: two cases with the same key asked the system the same question. The
12280
+ * normalization suite compares observations per key across projects and surfaces.
12281
+ */
12282
+ inputKey: string;
12283
+ /** The case's input, small and scrubbed (no paths, no prompts beyond a title). */
12284
+ input: Record<string, unknown>;
12285
+ /** `null` when the system's answer is not known yet: a synthetic case waiting on a replay adapter. */
12286
+ observed: DefaultEvalObserved | null;
12287
+ expected: DefaultEvalExpected;
12288
+ evidence?: DefaultEvalCaseEvidence;
12289
+ /** A case from the shipped baseline (the 2026-10-27 rig capture and the needs-you ruling), not this daemon's own
12290
+ * run store. Only counted when a run asks for the baseline; always disclosed in the counts. */
12291
+ baseline?: true;
12292
+ }
12293
+
12294
+ /** A proportion with its Wilson 95 % interval. `tooFew` when n is below the minimum (DES §6). */
12295
+ export interface DefaultEvalRate {
12296
+ k: number;
12297
+ n: number;
12298
+ value: number | null;
12299
+ lo: number | null;
12300
+ hi: number | null;
12301
+ tooFew: boolean;
12302
+ }
12303
+
12304
+ export interface DefaultEvalClassScore {
12305
+ label: string;
12306
+ precision: DefaultEvalRate;
12307
+ recall: DefaultEvalRate;
12308
+ }
12309
+
12310
+ export interface DefaultEvalCalibration {
12311
+ n: number;
12312
+ /** DefaultEvalExpected calibration error over 10 equal-width bins. `null` below the calibration minimum. */
12313
+ ece: number | null;
12314
+ brier: number | null;
12315
+ tooFew: boolean;
12316
+ }
12317
+
12318
+ /** One slice of a suite's cases (real, synthetic, combined, model-labelled, or one project). */
12319
+ export interface DefaultEvalSliceScore {
12320
+ /** Cases in the slice, including those that could not be scored. */
12321
+ cases: number;
12322
+ /** Cases with no observation (a synthetic case with no replay adapter). Never counted as right or wrong. */
12323
+ unscored: number;
12324
+ /** DefaultEvalObserved matched expected: exact class, set equality, or the pair agreement for merges. */
12325
+ agreement: DefaultEvalRate;
12326
+ perClass: DefaultEvalClassScore[];
12327
+ /** Set-valued suites (attribution): micro precision / recall over the set members. */
12328
+ members?: { precision: DefaultEvalRate; recall: DefaultEvalRate };
12329
+ /** Cluster suites (needs-you merge): pairwise precision / recall over "these two are one item". */
12330
+ pairs?: { precision: DefaultEvalRate; recall: DefaultEvalRate };
12331
+ calibration?: DefaultEvalCalibration;
12332
+ }
12333
+
12334
+ export type DefaultEvalTrend = 'too-few' | 'no-change' | 'improved' | 'regressed' | 'first-run';
12335
+
12336
+ export interface DefaultEvalSuiteScore {
12337
+ suite: DefaultEvalSuiteId;
12338
+ title: string;
12339
+ /** Slices that always appear. `model` holds only model-labelled cases; the other three exclude them. */
12340
+ real: DefaultEvalSliceScore;
12341
+ synthetic: DefaultEvalSliceScore;
12342
+ combined: DefaultEvalSliceScore;
12343
+ model: DefaultEvalSliceScore;
12344
+ /** Per project (cross-project runs only), over real + synthetic. */
12345
+ byProject?: Record<string, DefaultEvalSliceScore>;
12346
+ /** Per answerer, when several surfaces answer the same question (needs-you). */
12347
+ bySurface?: Record<string, DefaultEvalSliceScore>;
12348
+ /** Against the last stored run of the same suite and scope, on the combined agreement. */
12349
+ trend: { word: DefaultEvalTrend; previous: number | null; previousRunId: string | null };
12350
+ /** Plain-words notes the suite must carry (why synthetic is unscored, which adapter is missing, …). */
12351
+ notes: string[];
12352
+ }
12353
+
12354
+ /** One input judged differently by place: the normalization drift a cross-project run surfaces. */
12355
+ export interface DefaultEvalDriftKey {
12356
+ inputKey: string;
12357
+ suite: DefaultEvalSuiteId;
12358
+ /** `project` or `surface`: what differed. */
12359
+ axis: 'project' | 'surface';
12360
+ /** place → the observed labels there (sorted, distinct). */
12361
+ observed: Record<string, string[]>;
12362
+ caseIds: string[];
12363
+ }
12364
+
12365
+ export interface DefaultEvalReport {
12366
+ id: string;
12367
+ createdAt: string;
12368
+ /** `null` = every project (a cross-project run). */
12369
+ project: string | null;
12370
+ suites: DefaultEvalSuiteScore[];
12371
+ drift: DefaultEvalDriftKey[];
12372
+ counts: { real: number; synthetic: number; modelLabelled: number; unscored: number; baseline: number };
12373
+ /** The minimum n a figure needs before it is called (and the calibration minimum). */
12374
+ minimums: { rate: number; calibration: number };
12375
+ }
12376
+
12377
+ export interface DefaultEvalSummary {
12378
+ id: string;
12379
+ createdAt: string;
12380
+ project: string | null;
12381
+ suites: Array<{ suite: DefaultEvalSuiteId; agreement: number | null; n: number; tooFew: boolean; trend: DefaultEvalTrend }>;
12382
+ drift: number;
12383
+ counts: DefaultEvalReport['counts'];
12384
+ }
12385
+
12386
+ /** `GET /testing/default-evals/suites`. */
12387
+ export interface DefaultEvalSuitesResponse {
12388
+ suites: Array<{
12389
+ id: DefaultEvalSuiteId;
12390
+ title: string;
12391
+ /** Crew can run the current classifier on a case's input (so synthetic cases are scored). */
12392
+ replay: boolean;
12393
+ /** The generator makes synthetic cases for it. */
12394
+ synthetic: boolean;
12395
+ /** Why it cannot replay, when it cannot. */
12396
+ note: string | null;
12397
+ }>;
12398
+ }
12399
+
12400
+ /** `POST /testing/default-evals/run` body. `project`: one project (or repo) id, or `"all"` (the default). */
12401
+ export interface RunDefaultEvalsBody {
12402
+ project?: string;
12403
+ suites?: DefaultEvalSuiteId[];
12404
+ /** Count the shipped baseline cases too (the 2026-10-27 rig capture and the needs-you ruling). */
12405
+ baseline?: boolean;
12406
+ }
12407
+
12408
+ /** `GET /testing/default-evals`. Newest first. */
12409
+ export interface ListDefaultEvalRunsResponse {
12410
+ runs: DefaultEvalSummary[];
12411
+ }
12412
+
12413
+ /** `GET /testing/default-evals/:id`. */
12414
+ export interface DefaultEvalDetail {
12415
+ report: DefaultEvalReport;
12416
+ cases: DefaultEvalCase[];
12417
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wicked-crew-api-types",
3
- "version": "0.139.0",
3
+ "version": "0.143.0",
4
4
  "description": "The wire contract of the wicked-crew daemon's /api/v1 REST surface and /ws CoreEvent frames \u2014 types only, zero runtime",
5
5
  "type": "module",
6
6
  "types": "./index.d.ts",