wicked-crew-api-types 0.38.0 → 0.39.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 +216 -7
  2. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -191,6 +191,17 @@ export interface HealthCapabilities {
191
191
  * the field — read as `false`: do not send `revisesPr` to such a daemon.
192
192
  */
193
193
  revisesPr?: boolean;
194
+ /**
195
+ * `LaunchRunBody.chatId` is accepted (crew#619; crew ≥ 0.7.39). ABSENT on a daemon before
196
+ * the field — read as `false`: do not send `chatId` to such a daemon.
197
+ */
198
+ chatIdOnLaunch?: boolean;
199
+ /**
200
+ * `InteractiveDocCreateRequest.clisJson` (and the same field on demo/video and testing bodies)
201
+ * is accepted (crew#631; crew ≥ 0.7.40). ABSENT on a daemon before the field — omit `clisJson`
202
+ * on such a daemon.
203
+ */
204
+ seatChipOnCreate?: boolean;
194
205
  }
195
206
 
196
207
  /** One `GET /health.warnings[]` entry (additive; wicked-core#411 / wicked-crew#497). */
@@ -399,6 +410,37 @@ export interface AgentSession {
399
410
  /** Wave 6 (F-7R2-006): the seats BENCHED for this run — never convened, never a failover or
400
411
  * judge target. Absent (never `[]`) when none / on an older engine. */
401
412
  benched_seats?: BenchedSeat[];
413
+ /** crew#661: the declared skills this run's phases ran WITHOUT (the published skills snapshot did not
414
+ * hold them when the launching subsystem armed) — the run proceeded DEGRADED, and says so here.
415
+ * ABSENT (never `[]`) when the run launched fully armed, and on a daemon before this field. */
416
+ skill_gaps?: RunSkillGap[];
417
+ /**
418
+ * The surface that triggered this launch (crew#632; crew ≥ 0.7.40): `'studio'` (web UI),
419
+ * `'cli'` (wicked-crew CLI), or `'api'` (programmatic). ABSENT when the launch did not include
420
+ * the field (an older daemon or a caller that omitted it).
421
+ */
422
+ channel?: 'studio' | 'cli' | 'api';
423
+ /**
424
+ * An opaque caller-supplied identifier for the user or system that triggered the launch
425
+ * (crew#632; crew ≥ 0.7.40). ABSENT when the launch did not name one. Use `AgentSession.actor`
426
+ * (the authenticated crew actor) for the identity of WHO launched; `launch_actor` is an
427
+ * ADDITIONAL annotation the caller may attach (e.g. a CI job name or a studio tab id).
428
+ */
429
+ launch_actor?: string;
430
+ /**
431
+ * The number of warm seats in the chat this run was promoted from (crew#641/#642, item 5).
432
+ * ABSENT — never `null` — when the run was not promoted from a chat (`chatId` absent at launch)
433
+ * or on a daemon predating this field. A value of `1` means the intent was authored by a single
434
+ * model that could not disagree with itself.
435
+ */
436
+ chat_seat_count?: number;
437
+ /**
438
+ * Whether the chat this run was promoted from was graph-grounded at launch (crew#641/#642,
439
+ * item 5). `true` = at least one repo graph was bound and held entities; `false` = ungrounded.
440
+ * ABSENT — never `null` — when the run was not promoted from a chat or on a daemon predating
441
+ * this field.
442
+ */
443
+ chat_grounded?: boolean;
402
444
  }
403
445
 
404
446
  /** An ordered unit of work within a run (`WorkUnit`). */
@@ -885,7 +927,7 @@ export interface CoreEvent {
885
927
  seatConstraint?: string | null;
886
928
  /** `unitDistributed` (wicked-core#461): the evaluator ≠ creator fallback as a field — see
887
929
  * `UnitDistributedEvent.distinctnessFallback`. */
888
- distinctnessFallback?: 'creator_seat' | null;
930
+ distinctnessFallback?: 'creator_seat' | 'same_cli_instance' | null;
889
931
  /** `gateEvaluated` (wave 6, F-7R2-005): `true` when NOTHING gated the unit — render as UNGATED. */
890
932
  ungated?: boolean;
891
933
  /** `gateEvaluated` (wave 6): why, when `ungated`. */
@@ -1995,8 +2037,14 @@ export interface UnitDistributedEvent {
1995
2037
  * never absent — the `seatConstraint` rule) from the wicked-core release carrying #461 on, but an
1996
2038
  * older engine does not send it at all, and this contract must read frames from both. Consumers
1997
2039
  * guard with `== null`, never `=== undefined`.
2040
+ *
2041
+ * `'same_cli_instance'` (wicked-core#591/#595): the unit IS on a seat distinct from every builder
2042
+ * seat, but that seat runs the SAME cli as a builder (`claude#2` grading `claude#1`) — instance
2043
+ * distinctness removes the creator's context, not the model's blind spots, so it is a degraded
2044
+ * gate and disclosed. `'creator_seat'` dominates when both would apply. Consumers must treat an
2045
+ * unrecognised value as a disclosure too, never as "distinct".
1998
2046
  */
1999
- distinctnessFallback?: 'creator_seat' | null;
2047
+ distinctnessFallback?: 'creator_seat' | 'same_cli_instance' | null;
2000
2048
  /** @deprecated api-types 0.36.0 — the engine emits `routingMethod`; removed in 0.37. */
2001
2049
  routing_method?: 'council' | 'degraded' | 'evaluator_distinct' | 'tool';
2002
2050
  /** @deprecated api-types 0.36.0 — the engine emits `agreementPct`; removed in 0.37. */
@@ -3361,6 +3409,15 @@ export interface LaunchRunBody {
3361
3409
  * launch schema rejects the key with a 400.
3362
3410
  */
3363
3411
  revisesPr?: number;
3412
+ /**
3413
+ * Promote-from-chat linkage (crew#619; api-types 0.39.0, additive): the id of the chat this
3414
+ * run was promoted from. When present, the daemon retains that chat's conversation transcript
3415
+ * on disk for the run's lifetime, so the Continue-in-Build prefill is always reproducible
3416
+ * even if the chat is idle-reclaimed before the run finishes. Optional; omit when the launch
3417
+ * is not promoted from a chat. Check `GET /health.capabilities.chatIdOnLaunch` before sending —
3418
+ * an older daemon's strict launch schema rejects the key with a 400.
3419
+ */
3420
+ chatId?: string;
3364
3421
  /**
3365
3422
  * Retry lineage (DES-UX-001 §8.3, CREW-UX-3; api-types 0.8.0): the id of the run this
3366
3423
  * launch retries. Must name an EXISTING run id — an unknown id fails the launch (400 with
@@ -3392,6 +3449,21 @@ export interface LaunchRunBody {
3392
3449
  * `AgentSession.group_label`. Mutually exclusive with `campaignId` (both ⇒ 400).
3393
3450
  */
3394
3451
  groupLabel?: string;
3452
+ /**
3453
+ * The surface that triggered this launch (crew#632; additive). `'studio'` (web UI), `'cli'`
3454
+ * (wicked-crew CLI), or `'api'` (programmatic caller). Persisted in the `run.launched` audit
3455
+ * entry and echoed as `AgentSession.channel`. Absent ⇒ origin unknown. Check
3456
+ * `GET /health.capabilities.seatChipOnCreate` to confirm the daemon accepts the field before
3457
+ * sending — an older daemon's strict schema rejects unknown keys with a 400.
3458
+ */
3459
+ channel?: 'studio' | 'cli' | 'api';
3460
+ /**
3461
+ * An opaque caller-supplied identifier for the user or system that triggered the launch
3462
+ * (crew#632; additive). Persisted in the `run.launched` audit entry and echoed as
3463
+ * `AgentSession.launch_actor`. Absent ⇒ caller omitted it. Subject to the same daemon-version
3464
+ * guard as `channel` above.
3465
+ */
3466
+ actor?: string;
3395
3467
  }
3396
3468
 
3397
3469
  /**
@@ -4043,6 +4115,18 @@ export interface InteractiveDocCreateRequest {
4043
4115
  repo_ref?: string;
4044
4116
  /** SEVERAL subject repositories (at most 8); the union with `repo_ref`, de-duplicated. */
4045
4117
  repo_refs?: string[];
4118
+ /**
4119
+ * Per-doc council roster override (crew#631; crew ≥ 0.7.40 — check `GET /health` capabilities
4120
+ * `seatChipOnCreate` before sending). JSON-serialised `AgenticCli[]`; defaults to the daemon's
4121
+ * full roster when absent. Seat keys not present in `GET /roster` → 400.
4122
+ */
4123
+ clisJson?: string;
4124
+ /** Launch channel (crew#632). Persisted to the run's `run.launched` audit entry and served on
4125
+ * run DTOs as `channel`. ABSENT when the caller does not know the channel. */
4126
+ channel?: 'studio' | 'cli' | 'api';
4127
+ /** Launch actor (crew#632). Free-form string (≤ 256 chars) identifying the human or service
4128
+ * that triggered the launch. ABSENT when unknown. */
4129
+ actor?: string;
4046
4130
  }
4047
4131
 
4048
4132
  /**
@@ -4288,10 +4372,32 @@ export interface ChatOpenBody {
4288
4372
  /** File the chat into a project (`crew.chat` membership, attached on open) — and, when no
4289
4373
  * `repoRefs` are given, scope it to every registered `crew.repo` member of that project. */
4290
4374
  projectId?: string;
4375
+ /**
4376
+ * The scope the caller NAMES (api-types 0.39.0, studio#323 R4). Omitted ⇒ the legacy inference
4377
+ * above (`repoRefs` ⇒ `repos`, else `projectId` ⇒ `project`, else `none`) — unchanged for older
4378
+ * skins. Named, the daemon resolves exactly that kind or refuses with 400:
4379
+ * - `system` — the platform itself (daemon, seats, runs, config): NO repository and no code
4380
+ * graph. The seats have no live read of the daemon; what they know of it is what
4381
+ * the message carries. Takes no `repoRefs`; `projectId` only files the chat.
4382
+ * - `everything` — EVERY repository registered with the daemon, across all projects, as read
4383
+ * roots — never an enumerated list (no 1–32 cap). No single code graph spans
4384
+ * them, so none is bound. Takes no `repoRefs`; `projectId` only files the chat.
4385
+ * - `project` — requires `projectId`; takes no `repoRefs` (name `repo` to narrow).
4386
+ * - `repo` — requires `repoRefs`; `repos` is the same kind in its legacy spelling.
4387
+ * - `none` — the legacy unscoped chat; takes neither `projectId` nor `repoRefs`.
4388
+ */
4389
+ scopeKind?: ChatScopeRequestKind;
4291
4390
  }
4292
4391
 
4293
- /** How a chat's scope was chosen (crew#502). */
4294
- export type ChatScopeKind = 'project' | 'repos' | 'none';
4392
+ /** The scope a `POST /chats` caller may name (api-types 0.39.0, studio#323 R4). */
4393
+ export type ChatScopeRequestKind = 'system' | 'everything' | 'project' | 'repo' | 'repos' | 'none';
4394
+
4395
+ /**
4396
+ * How a chat's scope was chosen (crew#502). `system` and `everything` (api-types 0.39.0,
4397
+ * studio#323 R4) come back only for a request that named them (`ChatOpenBody.scopeKind`); a named
4398
+ * `repo` comes back as `repos`, the kind for an explicit repo list.
4399
+ */
4400
+ export type ChatScopeKind = 'system' | 'everything' | 'project' | 'repos' | 'none';
4295
4401
 
4296
4402
  /** One repository a chat's seats may read. */
4297
4403
  export interface ChatScopeRepo {
@@ -4310,7 +4416,7 @@ export interface ChatScope {
4310
4416
  kind: ChatScopeKind;
4311
4417
  /** The project the chat is filed into, when any. */
4312
4418
  projectId?: string;
4313
- /** The repositories in scope (read-only). Empty for `kind: 'none'`. */
4419
+ /** The repositories in scope (read-only). Empty for `kind: 'none'` and `kind: 'system'`. */
4314
4420
  repos: ChatScopeRepo[];
4315
4421
  /** The seats' working directory: the chat's private scratch root under the OS temp dir. */
4316
4422
  cwd: string;
@@ -4356,6 +4462,47 @@ export interface ChatSeatRefusal {
4356
4462
  source?: ChatRefusalSource;
4357
4463
  }
4358
4464
 
4465
+ /**
4466
+ * Single-seat degradation disclosure (crew#641/#650): present on `POST /chats` → 201 and on
4467
+ * `POST /chats/:id/messages` → 202 whenever exactly ONE seat is warm — refusals or not, since a
4468
+ * one-seat chat cannot disagree with itself either way. Named here so callers do not have to reason
4469
+ * about the `refused[]` array. The root cause is tracked as wicked-core#563.
4470
+ */
4471
+ export interface ChatSingleSeatDegradation {
4472
+ degraded: true;
4473
+ /** The one warm seat key (e.g. `"claude"`). */
4474
+ warmed: string;
4475
+ /**
4476
+ * The seats currently ON RECORD as refused, with each reason and source — EVIDENCE, not the
4477
+ * trigger. It describes the daemon's RECORD (what the open, or the last `POST /chats/:id/seats`,
4478
+ * observed); `warmed` describes the roster NOW, and the two are different moments.
4479
+ *
4480
+ * `[]` with `refusalsKnown: true` therefore means **no refusal is on record** — NOT "no seat was
4481
+ * ever refused": a seat re-seated through `POST /chats/:id/seats` is removed from the record when
4482
+ * it warms, and a seat RELEASED mid-session (it blew its turn budget) was never refused at all,
4483
+ * yet either can leave a chat with one warm seat and an empty record. `[]` with `refusalsKnown:
4484
+ * false` means the record is GONE — see that field.
4485
+ */
4486
+ refused: ChatSeatRefusal[];
4487
+ /**
4488
+ * Whether `refused` is the record this daemon actually holds (crew#650, review follow-up). `true`
4489
+ * on every 201 (the daemon just opened the chat) and on a 202 for a chat it still holds. `false`
4490
+ * on a 202 for a chat this daemon did not open — the engine keeps a warm session across a restart,
4491
+ * the daemon's in-memory scope index does not — where `refused: []` means THE RECORD IS GONE, not
4492
+ * that nothing was refused, and `message` says so instead of asserting either way. Absent on a
4493
+ * daemon predating this field, where `[]` was ambiguous.
4494
+ */
4495
+ refusalsKnown?: boolean;
4496
+ /**
4497
+ * Human-readable summary naming the degradation, its cause, and wicked-core#563. It states only
4498
+ * what the answering route witnessed: the 201 performed the open, so it may say the chat was
4499
+ * opened with a single seat; a 202 knows the roster NOW and the refusal record and says nothing
4500
+ * about how the chat came to look this way — the one warm seat may be the survivor of a two-seat
4501
+ * chat whose other seat was released.
4502
+ */
4503
+ message: string;
4504
+ }
4505
+
4359
4506
  /** `POST /chats` → 201. */
4360
4507
  export interface ChatOpenResponse {
4361
4508
  chatId: string;
@@ -4367,6 +4514,33 @@ export interface ChatOpenResponse {
4367
4514
  /** Every seat that was asked for or defaulted and is NOT in `seats` as warm, with its reason
4368
4515
  * (api-types 0.35.0). Empty when every seat warmed; absent on a daemon predating the field. */
4369
4516
  refused?: ChatSeatRefusal[];
4517
+ /**
4518
+ * crew#641/#650: present whenever exactly ONE seat is warm — the chat cannot disagree with
4519
+ * itself, which is equally true when nothing was refused (a chat opened with one seat on
4520
+ * purpose). ABSENT only when two or more seats are warm. Absent on a daemon predating this
4521
+ * field; a daemon between #641 and #650 emitted it only when `refused` was non-empty.
4522
+ */
4523
+ singleSeat?: ChatSingleSeatDegradation;
4524
+ }
4525
+
4526
+ /** `POST /chats/:id/messages` → 202. */
4527
+ export interface ChatMessageResponse {
4528
+ /** The seats the engine delivered the message to (warm seat keys). */
4529
+ seats: string[];
4530
+ /** The turn id stamped on every `chatDelta` / `chatReply` frame for this message. Absent on a
4531
+ * daemon predating the turn index (crew ≥ 0.7.35). */
4532
+ turnId?: string;
4533
+ /**
4534
+ * crew#641/#650: re-stated on every turn when the chat has exactly one WARM seat — decided from
4535
+ * the warm roster, never from the seats this turn reached, and never from whether refusals are
4536
+ * still on record (a restarted daemon has none and the chat is still single-seated). ABSENT when
4537
+ * two or more seats are warm. Absent on a daemon predating this field.
4538
+ *
4539
+ * This is a statement about NOW. It never describes how the chat was opened — the single warm seat
4540
+ * may be the survivor of a multi-seat chat whose other seats were refused, re-seated or released —
4541
+ * and only `POST /chats` → 201, which performed the open, says anything about that moment.
4542
+ */
4543
+ singleSeat?: ChatSingleSeatDegradation;
4370
4544
  }
4371
4545
 
4372
4546
  /**
@@ -5151,7 +5325,9 @@ export interface DiagnosticsSkillsFinding {
5151
5325
  * the configured BASE skill (`SystemSettings.baseSkillRef`) is not in the current generation —
5152
5326
  * a `warning` under `baseSkillPolicy: 'warn'` (runs proceed without the discipline directive),
5153
5327
  * an `error` under `'require'` (the engine refuses every launch at intake); cleared by a publish
5154
- * that hands it. Also carried as `DiagnosticsSkills.baseSkill.finding`. */
5328
+ * that hands it. Also carried as `DiagnosticsSkills.baseSkill.finding`; `skills.phase-skill`
5329
+ * (`warning`, crew#661) = a subsystem's phases declare a skill the published snapshot did not hold
5330
+ * when it armed, so they run without it — one per `DiagnosticsSkills.phaseSkillGaps` entry. */
5155
5331
  kind:
5156
5332
  | 'skills.fallback'
5157
5333
  | 'skills.blocked'
@@ -5159,7 +5335,8 @@ export interface DiagnosticsSkillsFinding {
5159
5335
  | 'skills.source'
5160
5336
  | 'skills.manifest'
5161
5337
  | 'skills.stale-rules'
5162
- | 'skills.base-skill';
5338
+ | 'skills.base-skill'
5339
+ | 'skills.phase-skill';
5163
5340
  severity: 'warning' | 'error';
5164
5341
  message: string;
5165
5342
  }
@@ -5193,8 +5370,40 @@ export interface DiagnosticsSkills {
5193
5370
  * when the setting is off or the seam is `disabled`. A daemon before this field omits the key
5194
5371
  * (read it as `null`). */
5195
5372
  baseSkill: BaseSkillPosture | null;
5373
+ /** Subsystems whose phases run WITHOUT a skill their workflow declares (crew#661; additive) — one
5374
+ * entry per subsystem, judged when that seam ARMED (the decision holds until the daemon restarts).
5375
+ * Each entry also rides `findings` as a `skills.phase-skill` warning. `[]` when every armed seam
5376
+ * holds its skill; ABSENT on a daemon before this field (read it as unknown, not as `[]`). */
5377
+ phaseSkillGaps?: DiagnosticsPhaseSkillGap[];
5378
+ }
5379
+
5380
+ /**
5381
+ * One subsystem whose phases declare a skill the published snapshot did not hold when the subsystem
5382
+ * armed (crew#661) — today the interactive seams' `wicked-garden-draft` quality floor. The phases
5383
+ * run DEGRADED (no `skill_ref`, no quality floor) and every run launched on it says so in
5384
+ * `AgentSession.skill_gaps`; the engine would refuse a `skill_ref` its snapshot lacks, so the seam
5385
+ * cannot simply stamp it.
5386
+ */
5387
+ export interface DiagnosticsPhaseSkillGap {
5388
+ /** The subsystem (`interactive-draft` / `interactive-edit` / `interactive-chat`). */
5389
+ subsystem: string;
5390
+ /** The workflow id the subsystem launches. */
5391
+ workflow: string;
5392
+ /** The agent phases that declare the skill and run without it. */
5393
+ phases: string[];
5394
+ /** The declared skill (`wicked-garden-draft`). */
5395
+ skill: string;
5396
+ /** The published skills generation judged at arm time, or `null` when none was published. */
5397
+ gen: number | null;
5398
+ /** Epoch ms of the arm-time judgement. */
5399
+ armedAt: number;
5400
+ /** The fix: republish the skills snapshot from a wicked-garden that carries the skill, then restart. */
5401
+ remedy: string;
5196
5402
  }
5197
5403
 
5404
+ /** A skill gap a run LAUNCHED with (`AgentSession.skill_gaps[]`, crew#661) — the arm-time gap without its timestamp. */
5405
+ export type RunSkillGap = Omit<DiagnosticsPhaseSkillGap, 'armedAt'>;
5406
+
5198
5407
  /**
5199
5408
  * The BASE skill in force for the next launch (crew#554 — the launcher half of wicked-core#468).
5200
5409
  * The engine leads EVERY agent unit's prompt with one role-keyed directive naming this skill and
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wicked-crew-api-types",
3
- "version": "0.38.0",
3
+ "version": "0.39.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",