wicked-core-ts 0.7.29 → 0.7.33

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 +291 -15
  2. package/package.json +6 -6
package/index.d.ts CHANGED
@@ -97,6 +97,23 @@ export interface LaunchOptions {
97
97
  * cost tools, not the run. Omit for the per-repo behaviour, unchanged.
98
98
  */
99
99
  projectGraph?: ProjectGraphOptions
100
+ /**
101
+ * (DES-TEAMING-002 T3; wicked-core-ts ≥ the release carrying seam T3) A USER-COMPOSED plan,
102
+ * as JSON: `{"steps":[{"catalog":"build"}, …], "touch"?: ["src/x.rs"], "override"?: {…}}`.
103
+ * The engine publishes `plan.proposed{by:"human"}`, scores it from `touch` (a creator plan
104
+ * with no `touch` scores 100, "no declared scope"), floor-fills and composes it into the run's
105
+ * `<run>:plan-1`, and pauses at a `plan_approval` gate when the approval matrix requires it —
106
+ * in manual mode always, in auto mode (`humanConfirm` omitted / `none`) when high risk.
107
+ * Mutually exclusive with `workflow` (a plan or a preset). A refused plan REJECTS the launch.
108
+ */
109
+ planJson?: string
110
+ /**
111
+ * (DES-TEAMING-002 §8.5, T3) The run DELIVERS: the launcher's `deliver` step as JSON — catalog
112
+ * `deliver`, id `deliver`, `executor: {type: "tool", cmd: [...]}` (crew's push-and-PR script).
113
+ * Only with `planJson` or a preset `workflow`: appended to the plan (unless it has its own
114
+ * `deliver` step) and put in the floor. Without a plan or preset the launch is REJECTED.
115
+ */
116
+ deliverStepJson?: string
100
117
  }
101
118
  /**
102
119
  * A handle to a wicked-core runtime. Construct with [`Core::spawn`] (production engine: real
@@ -119,6 +136,53 @@ export declare class Core {
119
136
  * as a JSON array of `AgenticCli` — pass straight into `launchRun`'s `clisJson`.
120
137
  */
121
138
  static registryRoster(): string
139
+ /**
140
+ * Whether this addon carries DES-TEAMING-002 T3's plan launch: `LaunchOptions.planJson` /
141
+ * `deliverStepJson` and `confirmGate(…, planJson)`. napi IGNORES an undeclared object field,
142
+ * so a launcher keys on this static's presence before it sends a plan — an older addon would
143
+ * drop the plan and run the launch unplanned and ungated.
144
+ */
145
+ static supportsPlanLaunch(): boolean
146
+ /**
147
+ * What this process's engine knows about its connection to the bus file at `path`
148
+ * (DES-TEAMING-002 T0 connection rule: one connection per bus file per process, opened by a bus
149
+ * thread, never closed): the JSON `{ "opens": <connections opened>, "opener": "<thread name>" }`,
150
+ * or `null` when the engine in this process never opened that file. An addon without this static
151
+ * predates the rule — crew's two-library stress suite keys on its presence.
152
+ */
153
+ static busConnectionStats(path: string): string | null
154
+ /**
155
+ * What arming the engine's launch bridge came to when this `Core` spawned (DES-TEAMING-002 T0),
156
+ * as JSON: `{ "state": "none" }` (no `WICKED_BUS_DB`), `{ "state": "armed", "floor": <event id> }`,
157
+ * or `{ "state": "not-armed", "reason": "…" }` — the bus did not open or answer within the arming
158
+ * bound, so this engine launches nothing from the bus. crew reports `not-armed` on
159
+ * `/health.warnings` (`bus.unavailable`).
160
+ */
161
+ busBridgeState(): string
162
+ /**
163
+ * Publish one event on this engine's bus (`WICKED_BUS_DB`), given as wicked-bus `emit()`
164
+ * takes it: JSON `{ event_type, domain, subdomain?, payload, idempotency_key?, producer_id?,
165
+ * ttl_hours? }`. Resolves to the row's `event_id`; a key already on the bus resolves to the
166
+ * existing row's id (where wicked-bus raises WB-002). Rejects with `WB-001 …` for an event
167
+ * wicked-bus would refuse (and for a field this emit does not write), and when the engine has
168
+ * no bus. Unlike wicked-bus `emit()`, it runs no schema registry or CAS offload and takes no
169
+ * causality fields (`correlation_id`, `session_id`, `parent_event_id`) from the environment
170
+ * (wicked-core#631: the engine is the one writer and the one SQLite library on its bus,
171
+ * so crew writes through here). Runs on the libuv pool over the engine's one bus connection;
172
+ * never through the actor.
173
+ */
174
+ busEmit(eventJson: string): Promise<number>
175
+ /**
176
+ * Read this engine's bus: live rows (`expires_at` in the future; every row when
177
+ * `includeExpired` — history readers) strictly after `afterId`,
178
+ * oldest first, whose `event_type` starts with `typePrefix` (a literal prefix; omitted = every
179
+ * type), at most `limit` of them (capped at 1000). Resolves to JSON `{ next, rows }`: `rows` are
180
+ * whole wicked-bus `events` rows with `payload` parsed; `next` is the cursor to pass back (the
181
+ * last row's id when the page is full, else the bus tail, `0` when `afterId` is past the tail
182
+ * — the bus file was replaced and its ids restarted). `limit` 0 reads no rows and resolves the
183
+ * tail as `next`. Rejects when the engine has no bus. Runs like `busEmit`.
184
+ */
185
+ busRead(afterId: number, limit: number, typePrefix?: string | undefined | null, includeExpired?: boolean | undefined | null): Promise<string>
122
186
  /**
123
187
  * EVENT nodes on the estate store at `dbPath` — the shared store the emit seam writes
124
188
  * governance events to (`WICKED_ESTATE_DB`; wicked-crew#495) — as a JSON number string, over
@@ -192,11 +256,12 @@ export declare class Core {
192
256
  chatSeats(chatId: string): Promise<string>
193
257
  /**
194
258
  * Every chat currently holding pool state — JSON array of
195
- * `[{chatId, seats, idleSecs, cwd, codeGraphDb, readRoots}]`, sorted by id. `cwd` /
259
+ * `[{chatId, seats, idleSecs, cwd, codeGraphDb, readRoots, heldBy}]`, sorted by id. `cwd` /
196
260
  * `codeGraphDb` / `readRoots` are the scope recorded at `chatOpen` (wicked-core#410): where the
197
261
  * seats run, the estate graph their read-only estate MCP is bound to (`null` ⇒ none), and the
198
262
  * repository roots in scope (`[]` when none); `cwd` is `null` only for a pool entry whose scope
199
- * is gone (a chat mid-close).
263
+ * is gone (a chat mid-close). `heldBy` lists the runs launched from the chat that keep it
264
+ * warm (`chatHold`, crew#619).
200
265
  *
201
266
  * Each warm seat pins an ACP bridge plus an agent child (~520 MB resident) and clients mint
202
267
  * chat ids freely, so without this an accumulation is invisible until the host runs out of
@@ -209,6 +274,13 @@ export declare class Core {
209
274
  * value that never meant a duration.
210
275
  */
211
276
  chatList(): Promise<string>
277
+ /**
278
+ * Hold a chat warm for a run launched from it (crew#619): the engine's idle reaper passes the
279
+ * chat over until that run is terminal, and its idle clock restarts then. Resolves `"true"`,
280
+ * or `"false"` when the chat is not open on this engine (nothing held). Call it right after
281
+ * `launchRun` resolves the run id.
282
+ */
283
+ chatHold(chatId: string, runId: string): Promise<string>
212
284
  /**
213
285
  * Close a chat's warm sessions (idempotent); emits
214
286
  * `chatClosed` with `reason: "requested"`.
@@ -237,8 +309,26 @@ export declare class Core {
237
309
  * the cursor unit (default) or the first creator phase at/after it. A disagreement
238
310
  * (`action=request_changes` with `approve=true`, `action=approve` with `approve=false`, an
239
311
  * unknown token) rejects before the engine is asked.
312
+ *
313
+ * (core#469 / core#467, additive.) Four more approve-shaped arms (`approve=true`, no `amend`
314
+ * / `amendScope`): `extend` | `targeted` | `accept_partial` answer the escalation gate of a
315
+ * repo-checks floor that did not finish (`repo_checks_timeout`) — the floor re-runs on the
316
+ * tree as it stands with 2× bounds, the targeted test set, or the unfinished checks waived —
317
+ * and `accept_suggestion` adopts the evaluator's discarded, pinned edit as the creator's
318
+ * amendment. The engine refuses each at any other gate.
319
+ *
320
+ * (core#555, additive.) `amend_intent` (`approve=true`, the text in `amend`, no `amendScope`)
321
+ * approves the gate AND AMENDS THE RUN'S INTENT: the text is appended to every unit at or after
322
+ * the cursor, so the acceptance list each LATER EVALUATOR is handed changes with the decision,
323
+ * and it is recorded on the run (`intent_amendments`) plus an `intentAmended` event. It is the
324
+ * only arm that can descope a run mid-flight; refused at a plan or team gate, and with no text.
325
+ *
326
+ * (DES-TEAMING-002 T3, additive.) `planJson` answers a `plan_approval` gate WITH AN EDIT: the
327
+ * edited plan as JSON (`approve=true`, `action` omitted or `edit_plan`). The engine accepts it
328
+ * as the next plan rev (floor phases added, never refused for being below the floor) or, if it
329
+ * refuses it, re-opens the gate with a new gate id.
240
330
  */
241
- confirmGate(runId: string, approve: boolean, amend?: string | undefined | null, action?: string | undefined | null, amendScope?: string | undefined | null): Promise<string>
331
+ confirmGate(runId: string, approve: boolean, amend?: string | undefined | null, action?: string | undefined | null, amendScope?: string | undefined | null, planJson?: string | undefined | null): Promise<string>
242
332
  /**
243
333
  * Cancel a run — mark it terminally `Cancelled` and stop advancing it. Resolves to the status
244
334
  * token. Safe whether the run is executing or paused.
@@ -342,6 +432,101 @@ export declare class Core {
342
432
  registerRepo(name: string, rootPath: string): Promise<string>
343
433
  /** List every registered repository, as a JSON array of `RepoEntry` objects. */
344
434
  listRepos(): Promise<string>
435
+ /**
436
+ * Save a preset: a named phase selection over the catalog. `stepsJson` is a JSON array of
437
+ * plan steps (`{catalog, id, …step fields}`); `projectId` null ⇒ global, else that project's
438
+ * scope; `createdBy` defaults to `api`. Resolves to the stored `Preset` JSON object
439
+ * (`{ name, scope, steps, created_by, updated_at }`). Rejects with a message led by the
440
+ * reason token: `preset_invalid_name`, `preset_builtin_readonly`, `preset_reserved_created_by`,
441
+ * `preset_unknown_project`, `preset_invalid_steps` (then the catalog's step refusal).
442
+ */
443
+ putPreset(name: string, stepsJson: string, projectId?: string | undefined | null, createdBy?: string | undefined | null): Promise<string>
444
+ /**
445
+ * Delete a preset in its scope (`projectId` null ⇒ global). Resolves to the JSON literal
446
+ * `true`, or `false` when no such live preset exists there. Rejects `preset_builtin_readonly`
447
+ * for a built-in.
448
+ */
449
+ deletePreset(name: string, projectId?: string | undefined | null): Promise<string>
450
+ /**
451
+ * The presets a launch in `projectId` sees (null ⇒ the global set), sorted by name, as a JSON
452
+ * array of `Preset` objects: every global preset (built-ins included, `created_by: "builtin"`),
453
+ * with a project row replacing the global row of the same name.
454
+ */
455
+ listPresets(projectId?: string | undefined | null): Promise<string>
456
+ /**
457
+ * A team run's transport and its units' team snapshots — the persisted state behind crew's
458
+ * `GET /api/v1/runs/:id/team` — as JSON `{ runId, transport, reason, streamFloor, planRev,
459
+ * pending, units: [{ ord, transport, reason, ledgerSource, ledgerRef, finalPass, teamPause,
460
+ * findings }] }`. Per unit (the last four `null` until the unit's attempt folded):
461
+ * `ledgerSource` is where its ledger came from (`"folded"` by the supervisor, `"synthesized"`
462
+ * by the worker on the final-pass timeout, `"no_bus"`); `ledgerRef` is the supervisor row the
463
+ * gate read (`"ledger.folded#<ord>:<attempt>"`, `null` for a synthesized or local ledger);
464
+ * `finalPass` is the ledger's `final_pass` (`"completed"`, `"timed_out"`, `"skipped"`,
465
+ * `"stream_gap"`); `teamPause` true means an unresolved HIGH (or an incomplete record) stands
466
+ * without a council YES, so the run pauses `team_dispute` before the next dispatch;
467
+ * `findings` is how many findings the ledger holds. The run's `transport` is `"bus"`,
468
+ * `"none"` (un-teamed: render the "team transport unavailable" banner with `reason`),
469
+ * `"pending"` (not decided yet) or `"unavailable"` (teamed, but this daemon has no bus: the run
470
+ * is paused `team_transport` until the operator answers or a restart brings the bus back).
471
+ * Resolves to `"null"` for a run that is not a team run;
472
+ * rejects for an unknown run.
473
+ */
474
+ runTeam(runId: string): Promise<string>
475
+ /**
476
+ * Replay the team outbox (`<state home>/team-outbox.ndjson`) onto the bus: every lane in
477
+ * order, superseded lines skipped and compacted, idempotent (a line replayed twice lands
478
+ * once). Resolves to the JSON report `{ published: [[key, eventId]], superseded, invalid,
479
+ * remaining, failures: [[runId, reason]] }`; rejects when the engine has no bus or no state
480
+ * home. Runs off the actor.
481
+ */
482
+ replayTeamOutbox(): Promise<string>
483
+ /**
484
+ * The phase catalog (`src/catalog.rs`) for studio's phase picker, in catalog order, as a JSON
485
+ * array of `{ id, kind, role, gate, gate_type, executes_code, executor, validator_pin, pinned,
486
+ * evidence_floor, verified_evidence, skill_ref, description }` (`executor` is `"agent"` |
487
+ * `"tool"`; `pinned` = the entry carries a validator pin; `evidence_floor` = that pin is the
488
+ * evidence floor; `verified_evidence` = the entry declares re-verified evidence, so a step of it
489
+ * is an acceptance requirement of the run that contains it; `description` is `null` when the
490
+ * entry has none).
491
+ */
492
+ catalog(): Promise<string>
493
+ /**
494
+ * What a launch of `planJson` (`{ steps, touch?, override? }`) with `humanConfirm` on
495
+ * `repoRef` (the registered repo the launch would run on) with `deliverStepJson` (the
496
+ * launch's deliver step) would compute, persisting and publishing nothing — the launch's own
497
+ * precheck, intent score, floor fill, approval matrix and planning checks. `projectId` only
498
+ * matters to a preset name, so it does not change a plan's preview. For a behavioural touch
499
+ * set the score reads `repoRef`'s code graph at the base a launch would start from, read
500
+ * locally with NO fetch (the local remote-default tip, else HEAD).
501
+ * Resolves to JSON `{ score, deterministic, reasons, destructive, band, high_risk, floor,
502
+ * floor_override, steps, def, pauses, pause_reason, graph }`: `floor` is the floor phase
503
+ * types the plan owes; the steps the floor ADDED are the `steps` with `added_by: "floor"`
504
+ * (each with its `floor_reason`); `pauses` / `pause_reason` (`manual_mode` | `high_risk` |
505
+ * `override`) say whether the launch would pause at a `plan_approval` gate; `graph` is
506
+ * `"ready"` (the score read the repo's graph), `"not_needed"` (a docs-only touch set),
507
+ * `"unavailable"` (the fail-closed score: no repo, no or a stale graph) or `"pending_pa_scope"` (a
508
+ * creator plan with no touch set: the PA scopes it after launch, so the score is pending).
509
+ * Rejects with the launch's refusal (compose, supplied provenance, an override in auto mode,
510
+ * a planning check), an unregistered `repoRef` or one whose base cannot be resolved, or a bad
511
+ * `humanConfirm` / `deliverStepJson`.
512
+ */
513
+ previewPlan(planJson: string, projectId?: string | undefined | null, humanConfirm?: string | undefined | null, repoRef?: string | undefined | null, deliverStepJson?: string | undefined | null): Promise<string>
514
+ /**
515
+ * A mid-run plan edit (`POST /api/v1/runs/:id/plan`): `planJson` is `{ steps }`, the steps to
516
+ * ADD. Held and applied at the run's next step boundary through the engine's revision path
517
+ * (the ratchet and floor fill apply), which publishes `plan.proposed{by:"human", kind:"edit"}`
518
+ * then `plan.accepted{by:"human"}`: its author approved it, so no `plan_approval` gate opens
519
+ * for it (as for an edit at the gate). Idempotent by `requestId`.
520
+ * Resolves to JSON `{ proposal_id, duplicate, band, high_risk, floor_added }`: what the edit
521
+ * does to the run (the floor band and high-risk rule of the rev it makes, the floor phase
522
+ * types it adds), from the dry run it is validated by; `duplicate: true` = this request id was
523
+ * already taken (nothing new is held or published; `band` / `high_risk` null, `floor_added`
524
+ * empty). Rejects for an unknown, finished or un-planned run, a plan awaiting approval (edit
525
+ * it at the gate), a started deliver step, an edit the revision refuses, an empty request id,
526
+ * or an edit carrying `touch` / `override`. An edit still held when the run ends is refused
527
+ * on the bus (`plan.refused`).
528
+ */
529
+ proposePlan(runId: string, planJson: string, requestId: string): Promise<string>
345
530
  /**
346
531
  * Create a project. Resolves to the persisted `Project` as a JSON object
347
532
  * (`{ id, name, description, status, scope, created_at, updated_at }`). Rejects on an
@@ -596,6 +781,59 @@ export declare class Core {
596
781
  * array of `ConformanceRule` objects, severity-first then id.
597
782
  */
598
783
  recallRulesPreview(queryJson: string): Promise<string>
784
+ /**
785
+ * Judge and record ONE brokered MCP call (DES-MCP-TOOLS-001 §6 step 3; crew's broker calls
786
+ * this before it invokes anything). `request_json` is `{ token, call: { server, tool, args?,
787
+ * annotations?, classOverride?, registered, kind?, carrier? } }` — `token` is the worker's
788
+ * `WICKED_MCP_TOKEN`, the rest is the broker's registry resolution. Resolves to the verdict
789
+ * JSON `{ decision: "allow"|"ask"|"deny", subject, class, ruleIds, obligations, reason?,
790
+ * remedy?, claimId, unit: { runId, ord, attempt, phase, seat } }`; the decision is already
791
+ * recorded in the unit's decisions log. Rejects with `invalid_token: …`, `bad_request: …` or
792
+ * `guard_error: …` — every rejection is a refusal (a `guard_error` means the call could not be
793
+ * recorded, D-3: fail closed). Static: the token registry is process-global, so the broker
794
+ * needs no `Core` handle.
795
+ */
796
+ static evaluateMcpCall(requestJson: string): Promise<string>
797
+ /**
798
+ * The unit's visible MCP tool list (DES-MCP-TOOLS-001 §8 `GET /mcp/tools?token=`; slice S4,
799
+ * the garden shim's `list`). `request_json` is `{ token, calls: [{ server, tool, annotations?,
800
+ * classOverride?, registered, kind? }] }` — the worker's `WICKED_MCP_TOKEN` and the registry's
801
+ * tools. Each is judged for the token's unit with the SAME evaluation `evaluateMcpCall` runs,
802
+ * with no arguments, and NOTHING is recorded; a certain deny is left out. Resolves to
803
+ * `{ unit: { runId, ord, attempt, phase, seat }, tools: [{ subject, class, decision:
804
+ * "allow"|"ask", ruleIds, reason? }] }`. Rejects with `invalid_token: …`, `bad_request: …` or
805
+ * `guard_error: …`. Static, like `evaluateMcpCall`.
806
+ */
807
+ static listMcpTools(requestJson: string): Promise<string>
808
+ /**
809
+ * The MCP policy PREVIEW (DES-MCP-TOOLS-001 §4.7, §8 `POST /mcp/policies/preview`; slice
810
+ * S6): judge each call for each synthetic unit cell with the SAME evaluation
811
+ * `evaluateMcpCall` runs, over this Core's policy store, and record NOTHING. `request_json`
812
+ * is `{ calls: [{ server, tool, args?, annotations?, classOverride?, registered, kind? }],
813
+ * cells: [{ role: "creator"|"evaluator"|"recon", seat, mode: "ask"|"balanced"|"autonomous",
814
+ * phaseId? }] }`. Resolves to `[{ subject, cells: [{ role, seat, mode, phaseId?, decision,
815
+ * class, ruleIds, obligations, reason? }] }]`. Rejects with `bad_request: …` or
816
+ * `guard_error: …`.
817
+ */
818
+ previewMcpCalls(requestJson: string): Promise<string>
819
+ /**
820
+ * The ONE MCP tool class derivation (D-4): `annotations_json` is the tool's `tools/list`
821
+ * annotations object (or `null`), `class_override` an operator override (`read` | `write` |
822
+ * `destructive`). Returns the class; a tool with no annotations is `write`.
823
+ */
824
+ static mcpToolClass(annotationsJson?: string | undefined | null, classOverride?: string | undefined | null): string
825
+ /**
826
+ * The broker's OUTPUT decision for one brokered MCP call (DES-MCP-TOOLS-001 §6 step 8; crew's
827
+ * broker calls this after the upstream answered and the result was scrubbed). `request_json`
828
+ * is `{ token, call: { server, tool, args?, annotations?, classOverride?, registered, kind?,
829
+ * carrier? }, raw }` — the same call `evaluateMcpCall` judged, plus `raw`, the scrubbed result
830
+ * text (the output decision reads `raw` in place of the args). Resolves to `{ decision:
831
+ * "allow"|"deny", subject, ruleIds, reason?, remedy?, claimId? }`; a deny withholds the result
832
+ * and is already recorded as an advisory `mcp-deny:` claim, an allow records nothing. Rejects
833
+ * with `invalid_token: …`, `bad_request: …` or `guard_error: …` — every rejection is a refusal
834
+ * (withhold the result).
835
+ */
836
+ static evaluateMcpOutput(requestJson: string): Promise<string>
599
837
  /**
600
838
  * Front-half coverage gate report — JSON-serialized `CoverageReport`, or the JSON literal
601
839
  * `null` when the store has no domain-model nodes yet. Opens a read-only connection so it
@@ -753,11 +991,34 @@ export declare class Subscription {
753
991
  * entry carries `outcome`, `boundS`, `boundNote`, `failureIds`, `classification: 'regression' |
754
992
  * 'pre_existing_in_sandbox' | 'floor_env_mismatch' | null` (only a regression denies), `preExisting`,
755
993
  * `regressions` and `base: {head, cached, run, error} | null` (the same check run on the run base).
756
- * core#461 (additive): unitDistributed.distinctnessFallback ('creator_seat' | null — the
757
- * evaluator ≠ creator fallback as a field, see UnitDistributedEventJson); gateEscalated.condition
994
+ * core#481/#546/#553 (additive): `classification` gains `'env_cannot_run'` (every failure carries the
995
+ * nested-sandbox launcher signature on both trees) and `'flaky_under_load'` (a head-only set of ≤ 2
996
+ * that passed an isolated re-run) — neither denies; equal failure sets are now
997
+ * `'pre_existing_in_sandbox'` (`'floor_env_mismatch'` is no longer produced); libtest ids are
998
+ * qualified by binary (`test t::name [-p crate --lib]`); every `checks[]` entry carries
999
+ * `envCannotRun: string[]` and `reruns: CheckRun[]` (each re-run's `boundNote` carries the host load).
1000
+ * core#461/#591 (additive): unitDistributed.distinctnessFallback ('creator_seat' |
1001
+ * 'same_cli_instance' | null — the evaluator ≠ creator fallback as a field, see
1002
+ * UnitDistributedEventJson); gateEscalated.condition
758
1003
  * gains the class 'dead_seat' (denialSource 'dead_seat'): a worker exited on a dead-seat refusal
759
1004
  * (signed out / quota / not installed) and no eligible seat remains — the attended run pauses at
760
1005
  * the escalation gate instead of failing.
1006
+ * core#549 (additive): gateEscalated gains `verdictSummaryTrimmed` (boolean) — true when the
1007
+ * evaluator's output exceeded EVALUATOR_FINDINGS_CAP chars and `verdictSummary` is a tail-trim
1008
+ * (the full text was too long; the trimmed portion is marked with a leading '…'). WorkUnit
1009
+ * gains `rework_amendment` (string | absent) — the full findings+note text stored at request_changes
1010
+ * so the creator's re-dispatch receives the amendment whole, never capped; unitContextInjected's
1011
+ * `outputBytes` per item reflects the full amendment byte length.
1012
+ * DES-TEAMING-002 T6 (removal): the DES-001 team events unitCheckpoint, monitorAttached,
1013
+ * monitorFinding, adviceDelivered and workerAdviceResponse are no longer emitted. Team
1014
+ * communication is the `wicked.team.*` bus stream (crew relays it as `teamEvent` frames).
1015
+ * core#416 (no shape change, a new VALUE): repoChecksEvaluated.sandboxLevel — and the same field
1016
+ * on `env` — can now read `'none'`, beside 'sandboxed' | 'network-only' | 'best-effort'. It means
1017
+ * the repository's own check scripts RAN with no OS write boundary, on the operator's explicit
1018
+ * `WICKED_REPO_CHECKS_UNSANDBOXED=1` opt-in (the hosts where none can be armed: Windows, a Linux
1019
+ * box without `bwrap`). The check results are real; a consumer folding enforcement must read
1020
+ * 'none' as UNENFORCED containment, never as a contained pass. 'best-effort' still means the
1021
+ * checks did NOT run.
761
1022
  */
762
1023
  export interface CoreEventJson {
763
1024
  type: string
@@ -780,9 +1041,11 @@ export interface UnitDistributedEventJson extends CoreEventJson {
780
1041
  ord: number
781
1042
  /** The roster key of the assigned seat. */
782
1043
  cli: string
783
- /** How the seat was chosen: the council verdict, a degrade to the first candidate, an
784
- * evaluator ≠ creator reassignment, or a deterministic tool execution. */
785
- routingMethod: 'council' | 'degraded' | 'evaluator_distinct' | 'tool'
1044
+ /** How the seat was chosen: `'teamed'` — the deterministic pick, no council (core#590 S5,
1045
+ * what every seated unit gets now) — an evaluator ≠ creator reassignment, or a deterministic
1046
+ * tool execution. `'council'` and `'degraded'` are no longer emitted by a new run; they stay
1047
+ * in the set because a recorded run's replayed frames carry them. */
1048
+ routingMethod: 'council' | 'degraded' | 'evaluator_distinct' | 'tool' | 'teamed'
786
1049
  agreementPct: number | null
787
1050
  returned: number | null
788
1051
  /** Seats convened for the council that produced this assignment (`null` = unknown). */
@@ -798,13 +1061,26 @@ export interface UnitDistributedEventJson extends CoreEventJson {
798
1061
  */
799
1062
  seatConstraint: string | null
800
1063
  /**
801
- * (core#461) The evaluator ≠ creator DISCLOSURE as a field: `'creator_seat'` when a review/test
802
- * unit STAYS on a seat that built what it checks because no eligible seat distinct from the
803
- * builders admits it — a single-eligible-seat roster, or a bench that emptied the pool
804
- * (`degradedReason` then says which). `null` otherwise. The fallback seat is always a
805
- * still-eligible one: a benched or dead seat is never the fallback. Additive.
806
- */
807
- distinctnessFallback: 'creator_seat' | null
1064
+ * (core#461, core#591) The evaluator ≠ creator DISCLOSURE as a field. `null` when there is
1065
+ * nothing to disclose. Two values:
1066
+ *
1067
+ * - `'creator_seat'` — a review/test unit STAYS on a seat that built what it checks because no
1068
+ * eligible seat distinct from the builders admits it.
1069
+ * - `'same_cli_instance'` — the unit IS on a seat distinct from every builder seat, but that
1070
+ * seat runs the SAME cli as a builder (`claude#2` grading `claude#1`: two seat INSTANCES of
1071
+ * one cli). Instance distinctness removes the creator's CONTEXT, not the model's blind spots
1072
+ * — same weights, same failure modes. Read it as a model-distinct evaluator and you are
1073
+ * accepting a degraded gate, so it is on the wire. `'creator_seat'` dominates when both
1074
+ * would apply.
1075
+ *
1076
+ * The paragraph below is about `'creator_seat'` only. The roster is always BENCH-FREE when it
1077
+ * is set (core#560/#567): a bench that leaves a review/test unit no distinct seat REFUSES the
1078
+ * plan instead, so that case never reaches the wire. Three shapes set it — a one-seat roster; a
1079
+ * roster whose every seat was assigned a Build/Recon unit; and one whose only non-builder seats
1080
+ * the unit's skills refuse. `degradedReason` does NOT name either value: the field is the
1081
+ * disclosure. The seat the unit stays on is therefore always a still-eligible one. Additive.
1082
+ */
1083
+ distinctnessFallback: 'creator_seat' | 'same_cli_instance' | null
808
1084
  }
809
1085
 
810
1086
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wicked-core-ts",
3
- "version": "0.7.29",
3
+ "version": "0.7.33",
4
4
  "description": "Node/TypeScript bindings (napi-rs) for wicked-core: drive the in-process orchestration engine from JS/TS.",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -43,11 +43,11 @@
43
43
  "typecheck": "tsc --noEmit -p types-test/tsconfig.json"
44
44
  },
45
45
  "optionalDependencies": {
46
- "wicked-core-ts-darwin-arm64": "0.7.29",
47
- "wicked-core-ts-darwin-x64": "0.7.29",
48
- "wicked-core-ts-linux-arm64-gnu": "0.7.29",
49
- "wicked-core-ts-linux-x64-gnu": "0.7.29",
50
- "wicked-core-ts-win32-x64-msvc": "0.7.29"
46
+ "wicked-core-ts-darwin-arm64": "0.7.33",
47
+ "wicked-core-ts-darwin-x64": "0.7.33",
48
+ "wicked-core-ts-linux-arm64-gnu": "0.7.33",
49
+ "wicked-core-ts-linux-x64-gnu": "0.7.33",
50
+ "wicked-core-ts-win32-x64-msvc": "0.7.33"
51
51
  },
52
52
  "devDependencies": {
53
53
  "@napi-rs/cli": "^2.18.4",