/** * Boundary types for the wicked-core-ts JSON surface. * * core-ts returns every complex result as a JSON string, which the adapter * `JSON.parse`s. The WIRE-SHAPE types — everything that flows on through the * daemon's `/api/v1` + `/ws` surface (SessionView, CoreEvent, governance and * workflow shapes, …) — live in the shared contract package * `wicked-crew-api-types` and are re-exported here verbatim, so the route * layer and the studio SPA compile against the SAME definitions and the two * can no longer drift (task #84; `tests/wire-contract.test.ts` is the guard). * * What remains in THIS file is engine-internal: inputs the adapter maps onto * the native addon (`LaunchRunInput`) and runtime constants (`DEFAULT_SETTINGS`) — a types-only * contract package cannot carry values. * * ONLY `core/adapter.ts` imports from the native addon itself; the rest of the * daemon speaks these daemon-owned shapes, which is what quarantines the * FINALIZING core-ts `subscribe` seam to a single file (DES-STUDIO-001 §5.2). */ export type * from 'wicked-crew-api-types'; /** Bound identity is read before opening, so queued asks produce no events. */ export interface AskUnit { runId: string; ord: number; attempt: number; seat: string; timeoutSecs: number; } export interface AskTicket extends AskUnit { elicitationId: string; } export interface AskRequest { token: string; question: string; choices?: string[]; recommended?: number; } export interface AskAdapter { askUnit(token: string): Promise; openAsk(request: AskRequest): Promise; closeAsk(id: string, reason: 'timeout' | 'teardown'): Promise; } export declare class AskError extends Error { readonly code: 'invalid_token' | 'bad_request' | 'run_ended'; constructor(code: 'invalid_token' | 'bad_request' | 'run_ended', message: string); } export declare class AskUnsupportedError extends Error { constructor(); } import type { RunTeamResponse, RunTeamUnit, SystemSettings } from 'wicked-crew-api-types'; /** `Core.runTeam`'s JSON (DES-TEAMING-002 P1): the persisted half of `GET /runs/:id/team`, before * crew joins the bus rows and the folded ledger onto it. */ export type RunTeamView = Omit & { transport: NonNullable; units: Array>; }; import { type BaseSkillPolicy } from '../skills/base-skill.js'; /** The daemon's launch-run input (mapped by the adapter onto the addon's `LaunchOptions`). */ export interface LaunchRunInput { /** Free-text problem, decomposed into ordered work units. */ problem: string; /** Stable run id. */ sessionId: string; /** JSON array of `AgenticCli` seats — the council roster. */ clisJson: string; /** (DES-TEAMING-002 §8.1; core ASK-K1a) The PA the operator chose; omitted ⇒ a random eligible seat. */ primary?: string; /** `shared` (default) | `isolated`. */ entityMode?: string; /** Human-confirm gate policy: `none` (default) | `all` | `before:`. */ humanConfirm?: string; /** * EXPLICIT opt-out of the engine's deliver gate (F-E2E-030). The composed `deliver` Tool phase * pauses for a human before it pushes the run branch and opens the PR — whatever `humanConfirm` * says — unless this is `true` (wicked-core `LaunchSpec.auto_deliver`). The HTTP boundary sets * it ONLY from an explicit `deliverGate: 'auto'` on `POST /runs`; omitted, `false`, and * `deliverGate: 'human'` all reach the engine as the gate. Never derived from `humanConfirm`: * `none` is that field's default and typo fallback, not a statement about delivery. */ autoDeliver?: boolean; /** Id of a registered repo to run within. Omit for a repo-less run. */ repoRef?: string; /** * DES-L9 / crew#550 (`revisesPr`): the head BRANCH of the open pull request this run revises, * resolved by the HTTP boundary from the PR number via `gh pr view` — the engine bases the run * worktree on `origin/` (wicked-core `LaunchSpec.base_ref`, core-ts ≥ 0.7.27) and the * composed deliver phase pushes the run's commits onto that branch instead of opening a second * PR. Crew-INTERNAL: never on the wire (`LaunchRunBody` carries `revisesPr` only). The adapter * fails CLOSED on an addon without the field — an older engine would base on the default branch * and push a duplicate PR. */ baseRef?: string; /** * The pull request `baseRef` was resolved from (DES-L9): number, head branch and URL — carried * to the deliver phase so its script pushes `wicked/` onto `refs/heads/`, proves * the tip, comments the run record on the PR (`gh pr comment`) and prints the PR URL last. */ revisesPr?: { number: number; headRef: string; url: string; }; /** Workflow def id to drive (e.g. `domain-extraction`). Omit ⇒ free-text planning. */ workflow?: string; /** * A USER-COMPOSED plan (DES-TEAMING-002 §8.4, seam T3; `LaunchRunBody.plan`), handed to the * engine as `LaunchOptions.planJson`. The engine owns every fact about it (`plan.proposed`, the * score, the floor, the approval matrix); crew only forwards the command. Mutually exclusive * with `workflow`. The adapter fails CLOSED on an addon without `Core.supportsPlanLaunch` — napi * ignores an undeclared field, so an older engine would run the launch unplanned and ungated. */ plan?: import('wicked-crew-api-types').LaunchPlan; /** * Project to file this run into (DES-PROJECT-001 §2.2). The engine attaches the `crew.run` * membership atomically with the launch record; unknown/archived ⇒ the launch fails with no * session persisted. Omit ⇒ unfiled (the synthesized `default` project). */ projectId?: string; /** * ADDITIONAL absolute write roots for the run's deliverables (wicked-core#259 / crew#263) — * e.g. the interactive-draft inbox the workflow contract names as the output destination. * The engine validates each root at launch (absolute, never the engine config/pin tree) and * widens the governed units' filesystem boundary by exactly these roots; an invalid root * fails the launch with no session persisted. Omit for runs that deliver inside their workdir. */ extraWriteRoots?: string[]; /** * ADDITIONAL absolute READ-ONLY roots for the run (wicked-core#294): reads inside them pass the * governed units' boundary, writes stay denied. A chat's ask run declares its scope's * repositories here (crew#1034), so a project chat reads its repositories whether or not the * project's code graph is built. The engine validates each root at launch; an invalid root * fails the launch with no session persisted. */ extraReadRoots?: string[]; /** * The PROJECT's co-located code graph this run's governed workers should query instead of the * run repo's own — resolved by `projects/graph.ts::resolveProjectGraphBinding`, which is the ONE * thing that knows where a project graph lives and what each repo is labelled inside it. * * `repoLabel` is optional in the TYPE because a repo-LESS run legitimately has none — there is * no own repo to name. It is not optional in MEANING for a repo-bound run: the engine uses it to * confirm the co-located graph actually holds this run's repo. * * TypeScript cannot catch a missing label here — the invariant ties this field to `repoRef`, a * sibling field — so `CoreAdapter.launchRun` enforces it at RUNTIME. Two failure modes, and they * are NOT the same thing: * * - **crew refuses the launch outright.** Passing `projectGraph` without `projectId`, or with * `repoRef` set and no `repoLabel`, THROWS: no session is created and nothing runs. These are * caller bugs with no sensible degraded reading, so they fail before anything is persisted. * - **the ENGINE declines the binding.** A well-formed binding whose graph turns out not to hold * the named label is refused engine-side and the run proceeds against its own repo graph — a * real launch, quietly narrower. That is the fallback; it is not what a missing `repoLabel` * gets you. * * Omit the whole field for the per-repo behaviour. */ projectGraph?: { dbPath: string; repoLabel?: string; }; /** * Delivery mode (crew#293). `"pr"` ⇒ the adapter appends the hardened deliver Tool phase * (push the run branch + `gh pr create`, see `core/deliver.ts`) to a PER-RUN copy of the * selected workflow def and launches that copy — the shared def is never mutated. Requires * `workflow`; a free-text run has no def to append to. Omit ⇒ no delivery phase. * * NOTE (crew#393): "omit" here is the ADAPTER's spelling of no-delivery — the HTTP boundary * is where the wire's `deliver: 'pr' | 'none'` and the DEFAULT (`'pr'` for repo-scoped * launches of code-work workflows — defs with an `executes_code` phase — flippable via the * `deliverDefault` daemon setting) are resolved; `'none'` and the repo-less/free-text/ * read-only-workflow defaults all reach this input as an omitted field. See `POST /runs` * in api/routes.ts. */ deliver?: 'pr'; /** * THE DELIVERABLE FLOOR (crew#311) — absolute paths this run MUST have produced by the time * it finishes. When non-empty (and `workflow` is set), the adapter appends a deterministic * verification Tool phase to a PER-RUN copy of the def (see `core/deliverable-floor.ts`) * which re-derives "done" from the artifacts: every declared path must exist and carry bytes, * or the phase exits non-zero and the RUN FAILS, naming what was expected and what was found. * * This is the instrument for runs whose deliverable is a FILE in a declared write root rather * than a worktree diff — every crew interactive seam. The engine's own two floors do not * reach them: the built-in evidence floor re-verifies a git diff and is fail-closed on a * repo-less run, and `required_deliverables` is checked only by the wrapped-CLI runner and * only against the unit's cwd (an absolute path counts as missing there by construction). * * Omit for runs whose evidence is the worktree diff — those are the engine's to floor. */ requireDeliverables?: string[]; /** * (EP-K3, wicked-core-ts >= 0.7.35) Seats never to convene as a JUDGE on this run — cli keys or * seat instances (`claude#2`). The engine UNIONS them into its own computed exclusion (the work * author, the team monitors), so the list can only narrow the judge choice, never widen it. The * interactive-review seam fills it with the seats that wrote the document under review (EP-C2). */ excludeSeats?: string[]; /** * (wicked-core#850 EX-01/EX-02, wicked-core-ts >= 0.7.46) The EXPLICIT opt-in to reduced * assurance: the creator's seat may evaluate its own work and a gate may pass with its judge * skipped for want of a distinct seat, both disclosed on every receipt. Sent only when `true`; * crew never sets it on a caller's behalf (`core/assurance.ts`). */ reducedAssurance?: boolean; /** * (QE-IN-APP-WORKFLOWS, wicked-core-ts >= 0.7.49) The operator's EXPLICIT skip of a required QE * acceptance, with this reason (core-ts `skipQeAcceptanceReason`), or its explicit force * (`forceQeAcceptance`). Sent only when the caller sent them; crew never sets either. */ skipQeAcceptanceReason?: string; forceQeAcceptance?: boolean; } /** Default `workerStallMinutes` (crew#287): silent minutes before the stall watchdog fires. */ export declare const DEFAULT_WORKER_STALL_MINUTES = 15; /** * Default `workerStallEscalateMinutes` (perf#4): silent minutes before the watchdog ACTS. * The escalation ladder is ON BY DEFAULT as of perf#4 — run 616c8661 sat wedged for a full 2h * turn ceiling (106 min of output silence) while the detection-only watchdog fired once and * watched; the engine's `reassignUnit` supersedes the wedged turn safely (attempt bump + epoch * cancel: the stale turn's late output drops, no double-charge), so acting is strictly better * than watching. An explicit `workerStallEscalateMinutes: 0` disarms it (the crew#341 opt-out). * * WHY 30: the trigger clock (silence since the last CoreEvent) is exactly the clock a slow but * legitimate first turn rides — the recon's max legitimate time-to-first-output across 68 units * was 1,161s ≈ 19.35 min, which leaves only a 3–6% margin at a 20-minute threshold. 30 minutes * gives ~55% headroom over that observed worst case while still recovering ~4x faster than the * 2h ceiling. The 15-minute detection (notify) rung is unchanged. */ export declare const DEFAULT_WORKER_STALL_ESCALATE_MINUTES = 30; /** * Default `workerSilentTurnMinutes` (crew#972): minutes a seat's turn may stream NO output at all * since its dispatch before the armed watchdog acts early (rig run 115fabdb: a codex review sat 30 * min silent with ~1 s of seat CPU, and pi did it in 2). A busy process tree or seat container * still re-arms the clock. `0` turns the rung off. */ export declare const DEFAULT_WORKER_SILENT_TURN_MINUTES = 8; /** * Default `workerStallEscalateAction` (crew#341) when escalation is armed: recycle the wedged * cursor unit via the engine's `reassignUnit` — routed to a DIFFERENT seat from the run's pool * when one is available (perf#4), in place otherwise. */ export declare const DEFAULT_WORKER_STALL_ESCALATE_ACTION: "reassign"; /** * Default `workerStallMaxEscalations` (crew#341): automatic reassigns per run before the * watchdog stops acting and hands the run to a human (`outcome: 'exhausted'`, `needsYou`). */ export declare const DEFAULT_WORKER_STALL_MAX_ESCALATIONS = 2; /** * LOCAL extension of the published `SystemSettings`. The stall-watchdog knobs * (`workerStallMinutes`, crew#287; `workerStallEscalateMinutes` / * `workerStallEscalateAction` / `workerStallMaxEscalations`, crew#341) live in the published * contract as of api-types 0.18.0 and are INHERITED here — what remains local is the * `studio.*` restatement below. Note the escalation ladder is ON BY DEFAULT as of perf#4 * (`workerStallEscalateMinutes` defaults to [`DEFAULT_WORKER_STALL_ESCALATE_MINUTES`]); an * explicit `0` disarms it. */ export interface CrewSystemSettings extends SystemSettings { /** * Skin-owned preference blobs, round-tripped verbatim (crew#323). RESTATED here rather than * merely inherited from `SystemSettings` so the daemon's own type SAYS the settings store is * shared with the experience plane — the fact that used to live only in a comment in the * studio's client, which is how `studio.appearance` / `studio.notifications` could be * silently dropped by `PUT /settings` without either side's types objecting. * * The daemon never interprets a value here; it enforces only "JSON-serializable, under the * per-key byte cap" at the PUT boundary (`api/routes.ts` `STUDIO_SETTINGS_MAX_BYTES`). */ [key: `studio.${string}`]: unknown; /** * RESTATED narrow (DES-L4 PR-⑧, D-8b): `'require'` is the only policy this daemon reads or writes. * The published wire (`wicked-crew-api-types` 0.38.0 `SystemSettings.baseSkillPolicy`) still spells * `'warn' | 'require'` — it predates the deletion; the union loses `'warn'` in the next api-types * field list. `PUT /settings` refuses `'warn'` (400) and the settings.json loader refuses it by * name, so nothing typed by the wire reaches a reader as `'warn'`. (The one-way wire pins — * produced ⊆ published — hold: `'require'` ⊆ `'warn' | 'require'`.) */ baseSkillPolicy?: BaseSkillPolicy; } export declare const DEFAULT_SETTINGS: CrewSystemSettings; //# sourceMappingURL=types.d.ts.map