@sublang/playbook 1.0.0 → 2.0.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.
@@ -66,3 +66,14 @@ playbooks:
66
66
  # host: claude-opus
67
67
  # participant: codex-gpt
68
68
  # committer: host
69
+
70
+ # Non-interactive `playbook run` defaults (optional). Each value is an
71
+ # agent string <adapter>[:<model>][@<effort>]; `player` is the catch-all
72
+ # for any required role without its own `players.<role>` entry, across
73
+ # every playbook. Flags override per role (--player / --captain), and
74
+ # `playbook run resume` keeps the lineup stored with the parked session.
75
+ #run:
76
+ # captain: claude:claude-opus-4-8@high
77
+ # player: claude:claude-opus-4-8@high
78
+ # players:
79
+ # coder: claude:claude-opus-4-8[1m]@xhigh
@@ -266,7 +266,7 @@ export declare const discussMachine: import("xstate").StateMachine<DiscussContex
266
266
  } | {
267
267
  type: "mixedReview";
268
268
  params: unknown;
269
- }, never, "done" | "failed" | "ready" | "awaitBossReply" | "hostWritesAgreement" | "commitInitialChanges" | "reviewSpecInitialCommit" | "reviewSpecHostChanges" | "reviewDrInitialCommit" | "reviewDrHostChanges" | "reviewMixedInitialCommit" | "reviewMixedHostChanges" | "hostAddressesFindings" | "participantAddressesRebuttals" | "commitReviewedChanges" | {
269
+ }, never, "done" | "failed" | "awaitBossReply" | "ready" | "hostWritesAgreement" | "commitInitialChanges" | "reviewSpecInitialCommit" | "reviewSpecHostChanges" | "reviewDrInitialCommit" | "reviewDrHostChanges" | "reviewMixedInitialCommit" | "reviewMixedHostChanges" | "hostAddressesFindings" | "participantAddressesRebuttals" | "commitReviewedChanges" | {
270
270
  initialProposalRound: {
271
271
  host: "working" | "waiting" | "complete";
272
272
  participant: "working" | "waiting" | "complete";
package/slc/link.md CHANGED
@@ -257,15 +257,21 @@ array requests a tool-free call, while omission preserves the host Captain's
257
257
  configured tools.
258
258
  `CaptainResult` carries no resume token or player-continuation selection.
259
259
  A non-`ok`
260
- result, or an `ok` result without `finalText`, shall reject the actor through
261
- the FSM's error path.
262
- Outside a signal-driven abort, those invalid direct-Captain results are
263
- latched control-plane failures. The runtime shall let the actor take `onError`,
264
- drive it to quiescence, and drain ordered emissions before the public method
265
- rejects with the original failure. It shall never translate either case into
266
- a recoverable workflow `{ outcome: 'failed' }` result. If the combined signal
267
- has aborted, an aborted host result follows the ordinary abort settlement
268
- instead of being promoted to a control-plane failure.
260
+ result, or an `ok` result without non-empty `finalText`, shall record that
261
+ failure on the call's single finish trace and reject the actor through the
262
+ FSM's error path. These structured host-result failures are recoverable
263
+ workflow failures, not control-plane failures: the runtime shall let the actor
264
+ take `onError`, drive it to quiescence, drain ordered emissions, and resolve
265
+ the public method with `{ outcome: 'failed' }` carrying the failure state's
266
+ error. This matches the delegated-player result boundary.
267
+ A non-abort thrown `callCaptain` port, a malformed host result, and a rejecting
268
+ trace sink remain control-plane failures that reject the public method. If the
269
+ required finish sink rejects after a structured host-result failure, the
270
+ actor's error and failure-state evidence shall remain the host-result failure,
271
+ while the public method rejects with the sink failure surfaced by the turn's
272
+ emission drain. Absent such a control-plane failure, if the combined signal
273
+ has aborted, ordinary abort settlement remains authoritative after the actor
274
+ reaches its error path.
269
275
 
270
276
  Every linked runtime owns a map from resolved player id to its latest non-empty `resumeToken`.
271
277
  Before reading a resolved direct-Captain or delegated-player result, the
@@ -753,8 +759,11 @@ Adjudicator failures are control-plane errors.
753
759
  The runtime shall propagate them by throwing out of `handleBossInput` after attempting cleanup.
754
760
  The host adapter surfaces the throw on its control-plane channel (cligent surfaces such throws as `runtime_error` per [TMUX-025](https://github.com/sublang-ai/cligent/blob/main/specs/user/tmux-play.md#tmux-025)).
755
761
  The host's player-result channels (`player_finished` and equivalents) are reserved for failures the player itself produced; the host emits them when `callPlayer` resolves with `status !== 'ok'`.
756
- Captain call failures stay on the Captain/control boundary and shall not be
757
- reported as player failures.
762
+ Direct-Captain host-result failures stay on the Captain actor boundary and
763
+ shall not be reported as player failures; they follow the recoverable FSM
764
+ failure path specified above. Captain transport, result-shape, trace-sink, and
765
+ adjudication failures remain control-plane errors unless the transport failure
766
+ is causally identical to the active abort signal.
758
767
  Because XState still needs the invoked promise to settle, the linked runtime
759
768
  shall latch an adjudicator, actor-output JSON-validation, or nested-boundary
760
769
  control error outside machine context, allow the invocation's `onError` path to
@@ -779,8 +788,9 @@ independent cleanup evidence.
779
788
  ## Script execution
780
789
 
781
790
  Where the FSM declares the typed `script` actor from
782
- [gears2fsm "Setup"](gears2fsm.md#setup), the linker shall provide its
783
- implementation inside the emitted module.
791
+ [gears2fsm "Setup"](gears2fsm.md#setup), the linked runtime shall provide
792
+ its implementation through the shared factory (§Output); the linker shall
793
+ not regenerate a script executor inside each emitted module.
784
794
  A script invocation is the one actor kind that runs without any agent:
785
795
  it makes no `callPlayer`, `callCaptain`, or `callJudge` call and needs no
786
796
  adjudication.
@@ -791,7 +801,8 @@ The provided actor shall:
791
801
  (`sh -c`), with the working directory taken from the emitted
792
802
  `PlaybookRuntimeOptions.cwd` when the caller supplies it, else the process
793
803
  working directory. The linker shall declare the optional `cwd` option on the
794
- emitted options interface whenever the FSM contains a script state.
804
+ emitted options interface whenever the FSM contains a script state; the
805
+ validated option reaches the shared script actor through the spec.
795
806
  - Resolve deterministically from the child's exit status: status zero resolves
796
807
  `{ guard: <first declared guard>, exitStatus: 0 }`; any nonzero status
797
808
  resolves the second declared guard with that status. Guard selection is
@@ -816,9 +827,9 @@ them in machine context, prompts, or trace payloads.
816
827
 
817
828
  Where the FSM declares the typed `playbook` actor from
818
829
  [gears2fsm](gears2fsm.md#nested-playbook-calls), the linked runtime shall provide
819
- it with the shared `createNestedPlaybookBridge(...).actorLogic`; it shall not
820
- regenerate a second pending-call, identity-validation, or abort-cleanup
821
- substrate inside each linked artifact.
830
+ it with the shared `createNestedPlaybookBridge(...).actorLogic` wired by the
831
+ shared factory per §Output — and shall not regenerate a second pending-call,
832
+ identity-validation, or abort-cleanup substrate inside each linked artifact.
822
833
  Instantiate the generic bridge with the FSM-exported `PlaybookInput` type so
823
834
  XState `.provide(...)` receives the exact declared actor input rather than a
824
835
  structurally similar local type.
@@ -1122,7 +1133,9 @@ At a safe capture point it shall return a JSON-safe
1122
1133
  - `playerResumeTokens`: the resume-token map as a plain object
1123
1134
  (§PlaybookPorts contract).
1124
1135
  - `sequences`: the live `trace`, `turn`, `judgeCall`, `playerCall`, and
1125
- `playbookCall` counters.
1136
+ `playbookCall` counters, plus `captainCall` when the runtime supports direct
1137
+ Captain calls. `captainCall` remains optional under schema version `1` for
1138
+ backward compatibility; a direct-Captain-capable runtime shall persist it.
1126
1139
  - `state`: the current normalized state descriptor.
1127
1140
  - `pendingBossQuestions`: the pending Boss question(s) from FSM context as
1128
1141
  a list of `{ questionId, player, question, sourceItem? }`, empty when the
@@ -1141,7 +1154,9 @@ module identity — that the factory constructing this runtime still
1141
1154
  belongs to the snapshot's playbook — is likewise the host's check to
1142
1155
  make before calling `restore`.
1143
1156
  `restore` shall bind the session, restore the resume-token map, the
1144
- sequence counters, and the prior-state descriptor from the snapshot,
1157
+ sequence counters (using the persisted global `trace` counter as a
1158
+ collision-safe floor for an absent legacy `captainCall`), and the
1159
+ prior-state descriptor from the snapshot,
1145
1160
  construct the actor with the persisted `machine` snapshot, and start it
1146
1161
  with root inspection emissions suppressed so rehydration emits no
1147
1162
  `session.started` trace, no transition trace, and no human status — the
@@ -1227,7 +1242,19 @@ The `playbook.trace` copies are the host-agnostic runtime-boundary record requir
1227
1242
 
1228
1243
  ## Output
1229
1244
 
1230
- The link compiler emits **one** TypeScript module that:
1245
+ The link compiler emits **one thin** TypeScript module per playbook.
1246
+ The FSM-interpreter machinery — actor wiring, boundary tracing, Boss-event
1247
+ mapping, adjudication, script execution, nested-playbook bridging, session
1248
+ lifecycle, abort handling, and the optional parked-session snapshot
1249
+ capability — is not regenerated per artifact: it ships once as the shared
1250
+ `createXStatePlaybookRuntime(machine, spec)` factory exported by
1251
+ `@sublang/playbook/xstate-runtime`, and the emitted module hands its FSM and
1252
+ a small per-playbook `spec` to that factory. Every behavioral section of
1253
+ this definition still binds the emitted module's runtime; the shared factory
1254
+ is how the emitted module satisfies them, so a runtime fix ships as a
1255
+ package release instead of a re-link of every artifact.
1256
+
1257
+ The emitted module:
1231
1258
 
1232
1259
  - Imports the FSM artifact by relative path with an extension-bearing
1233
1260
  runtime specifier. When the linked TypeScript is part of a package that
@@ -1240,34 +1267,82 @@ The link compiler emits **one** TypeScript module that:
1240
1267
  that strip cleanly, no constructor parameter properties, `enum`s, or
1241
1268
  namespaces — so a host running under type stripping loads it
1242
1269
  directly.
1243
- - Imports XState's actor primitives (`createActor`, `fromPromise`,
1244
- `setup`'s `.provide`).
1245
- - Imports `PQueue` from `p-queue` for its single serialized emission channel.
1246
- - Imports the FSM's exported machine/actor input and output types and uses
1247
- those exact types in `.provide(...)`; it shall not redeclare look-alike
1248
- Captain, player, playbook, question, or output contracts beside the linked
1249
- runtime.
1250
- - Imports the applicable shared helpers from the extension-bearing
1251
- `xstate-runtime.js` sibling of the resolved shared `--link` contract module,
1252
- with that sibling path relativized from the emitted artifact exactly as the
1253
- contract import is. Every runtime uses `assertJsonSafe`, `snapshotJsonValue`,
1254
- `snapshotPlaybookSession`, `normalizeError`,
1255
- `normalizePlaybookSnapshot`, and `waitForPlaybookQuiescence`; it additionally
1256
- imports `combineAbortSignals`, result validators, and
1257
- `createNestedPlaybookBridge` only when its actor and composition paths need
1258
- them. It shall use those helpers instead of emitting weaker local JSON,
1259
- error, snapshot, nested-call, or imperative-wait implementations.
1260
- - Exports `createPlaybookRuntime` and the typed `PlaybookRuntimeOptions`
1261
- interface for that playbook.
1270
+ - Imports `createXStatePlaybookRuntime` (plus any shared strategy defaults
1271
+ its `_internal` surface re-exports) from the shared engine module through
1272
+ its bare package specifier `@sublang/playbook/xstate-runtime`, and the
1273
+ contract types through `@sublang/playbook/runtime`. It shall not copy,
1274
+ inline, or re-derive interpreter machinery actor bridges, trace
1275
+ emission, judge-JSON recovery, lifecycle guards beside the factory
1276
+ call, and shall not import `xstate`, `p-queue`, or `node:child_process`
1277
+ itself; those are the shared engine's dependencies.
1278
+ - Declares and exports the typed `PlaybookRuntimeOptions` interface for that
1279
+ playbook, derived from every required FSM input field that is not supplied
1280
+ by `PlaybookSession` or another linker-owned source (§PlaybookRuntime
1281
+ contract), plus the optional `cwd` option whenever the FSM contains a
1282
+ `script` state (§Script execution).
1283
+ - Supplies the spec's `snapshotOptions` with the same options-validation
1284
+ semantics previously generated inline: validate and JSON-snapshot the
1285
+ caller's options, rejecting undeclared keys and non-conforming values, so
1286
+ the factory binds an immutable options record before constructing any
1287
+ actor.
1288
+ - Supplies in `spec` only what the factory cannot read from the FSM
1289
+ artifact's own data: the deterministic textual entry event where
1290
+ §Boss-event mapping prescribes deterministic entry; compact `bossEvents`
1291
+ metadata for each additional Boss-union arm whose exact required/optional
1292
+ judge fields, runtime-owned text fields, or closed string values disappear
1293
+ under TypeScript erasure; `placeholderFields` only for authored token/field
1294
+ exceptions not covered by the canonical kebab-token-to-camel-field mapping
1295
+ and the canonical `<#>` → `irNumber` special case; the
1296
+ transition-event payload fields the FSM's Boss union declares; a
1297
+ non-default player binding where the linker inputs supplied one; and any
1298
+ per-playbook strategy override (classifier, prompt composers,
1299
+ required-field extraction, status formatting) an earlier section of this
1300
+ definition requires for that playbook. The metadata shall keep the shared
1301
+ classifier's reply contract exactly flat `{ type, ...declaredFields }` and
1302
+ distinguish judge-authored routing fields from exact-text fields the
1303
+ runtime attaches itself. Everything else — player/script/captain/nested actor
1304
+ provisioning, prompt composition, classification, adjudication, statuses,
1305
+ resumable-state derivation — comes from the factory's generic defaults,
1306
+ which implement the behavioral sections of this definition.
1307
+
1308
+ ```ts
1309
+ interface XStateBossEventFieldSpec {
1310
+ source: 'judge' | 'text';
1311
+ required?: boolean;
1312
+ values?: readonly string[];
1313
+ }
1314
+
1315
+ interface XStateBossEventSpec {
1316
+ type: string;
1317
+ fields?: Readonly<Record<string, XStateBossEventFieldSpec>>;
1318
+ }
1319
+
1320
+ bossEvents?: readonly XStateBossEventSpec[];
1321
+ placeholderFields?: Readonly<Record<string, string>>;
1322
+ ```
1323
+
1324
+ Supplied `bossEvents` metadata shall merge with, and shall not replace or
1325
+ weaken, runtime-derived entry text ownership or closed interrupt targets.
1326
+ A conflicting duplicate field contract is a linker/runtime construction
1327
+ error.
1328
+ `NO_ACTION` and `BOSS_REPLY` are runtime-owned event types the factory
1329
+ supplies itself — `NO_ACTION` as exactly `{ type: 'NO_ACTION' }`, and
1330
+ `BOSS_REPLY` as an optional judge-selected `questionId` plus the exact-text
1331
+ `answer` the runtime attaches. `bossEvents` shall carry no entry for either
1332
+ type; supplying one is a construction error, so a linker that judges a
1333
+ runtime-owned arm to have lost payload detail under erasure shall report
1334
+ that gap rather than emit the entry.
1335
+ - Default-exports the factory call as `createPlaybookRuntime`, typed
1336
+ `PlaybookRuntimeFactory<PlaybookRuntimeOptions>`.
1262
1337
  - Exposes, under an `_internal` export, the pure helpers verification
1263
1338
  needs — at least the player-prompt and Captain-prompt composers
1264
- (`composePlayerPrompt` and `composeCaptainPrompt`) so
1339
+ (`composePlayerPrompt` and `composeCaptainPrompt`), which may re-export
1340
+ the shared defaults when the spec does not override composition — so
1265
1341
  compilation-correctness tests can exercise composition without a host.
1266
1342
  - Holds no host-specific types and no host primitive calls. The runtime
1267
- speaks only `PlaybookPorts` for every agent and host concern; the sole
1268
- exception is `node:child_process`, imported only when the FSM declares a
1269
- `script` actor, so §Script execution can run its deterministic commands
1270
- locally.
1343
+ speaks only `PlaybookPorts` for every agent and host concern; the
1344
+ `node:child_process` dependency of §Script execution lives in the shared
1345
+ factory, not in the emitted module.
1271
1346
  - Records the linker inputs (FSM path, player binding, strategies) in a
1272
1347
  top-of-file header comment so the file is reproducible from the same
1273
1348
  inputs.
@@ -1276,12 +1351,12 @@ The link compiler emits **one** TypeScript module that:
1276
1351
  `PlaybookTraceEvent`,
1277
1352
  `PlaybookCallRequest`, `PlaybookCallResult`, `PlaybookCallStart`,
1278
1353
  `PlaybookStateValue`, `PlaybookState`, `PlaybookRunResult`,
1279
- `PlaybookRuntime`, `PlaybookRuntimeFactory`) from a single shared
1354
+ `PlaybookRuntime`, `PlaybookRuntimeFactory`) from the single shared
1280
1355
  type-only module instead of redefining them, and re-exports the names
1281
1356
  its consumers import, so every linked playbook shares one contract
1282
- definition. The shared module imports no FSM or host types, so the
1357
+ definition. The shared modules import no FSM or host types, so the
1283
1358
  dependency runs one way — from each linked module to the shared
1284
- contract, never the reverse.
1359
+ engine and contract, never the reverse.
1285
1360
 
1286
1361
  When a co-located integration test for the linked runtime already exists, the
1287
1362
  link compiler shall run it before reporting success and treat any failure as a
package/slc/optimize.md CHANGED
@@ -56,9 +56,9 @@ For each eligible item, the pass shall:
56
56
 
57
57
  - Keep the item's ID, heading form, and condition text unchanged.
58
58
  - Replace the acting clause with the literal script form `Captain shall run:`.
59
- Like guard names, the script clause is fixed machine syntax and stays in
60
- this exact English form even when the surrounding item text is in another
61
- language.
59
+ Like guard names, the script clause is fixed machine syntax [[1]] and
60
+ stays in this exact English form even when the surrounding item text is
61
+ in another language.
62
62
  - Replace the blockquoted prompt with the exact POSIX shell script that
63
63
  performs the behavior, static text only.
64
64
  - Emit exactly two `Results:` bullets per
@@ -86,3 +86,7 @@ with no `## Optimizations` section.
86
86
  - Reordering, merging, splitting, or deleting items.
87
87
  - Any change to prompts, conditions, or result contracts of items the pass
88
88
  does not rewrite.
89
+
90
+ ## References
91
+
92
+ [1]: GEARS definition shipped by the installed `@sublang/spex` package: `@sublang/spex/scaffold/specs/meta.md` (English) and `@sublang/spex/scaffold/i18n/zh/specs/meta.md` (Chinese); canonical renditions [GEARS: AI-Ready Spec Syntax](https://sublang.ai/ref/gears-ai-ready-spec-syntax) (en) and [GEARS:面向 AI 的规约语法](https://sublang.ai/zh/ref/gears-ai-ready-spec-syntax) (zh)
package/slc/text2gears.md CHANGED
@@ -287,7 +287,13 @@ Results:
287
287
  - `failed`: The command exited with a nonzero status.
288
288
  ```
289
289
 
290
- Target should be written in the same language as Source.
290
+ Target shall be written in the same language as Source: an item's condition
291
+ prose, acting prompts, and result descriptions follow the Source language,
292
+ read per the matching localization of the GEARS definition [[1]].
293
+ The four `Captain shall` acting-clause forms defined above (direct,
294
+ delegated, nested playbook call, and script), guard names, and the
295
+ `Players:` and `Results:` labels are fixed machine syntax and stay in this
296
+ exact English form regardless of Source language.
291
297
 
292
298
  ## Transformation-spec sources
293
299
 
@@ -324,4 +330,4 @@ Dead branches mislead readers and downstream phases.
324
330
 
325
331
  ## References
326
332
 
327
- [1]: [GEARS syntax](/specs/meta.md#item-syntax)
333
+ [1]: GEARS definition shipped by the installed `@sublang/spex` package: `@sublang/spex/scaffold/specs/meta.md` (English) and `@sublang/spex/scaffold/i18n/zh/specs/meta.md` (Chinese); canonical renditions [GEARS: AI-Ready Spec Syntax](https://sublang.ai/ref/gears-ai-ready-spec-syntax) (en) and [GEARS:面向 AI 的规约语法](https://sublang.ai/zh/ref/gears-ai-ready-spec-syntax) (zh)
package/src/runtime.d.ts CHANGED
@@ -143,6 +143,7 @@ export interface PlaybookRuntimeSnapshot {
143
143
  judgeCall: number;
144
144
  playerCall: number;
145
145
  playbookCall: number;
146
+ captainCall?: number;
146
147
  };
147
148
  state: PlaybookState;
148
149
  pendingBossQuestions: readonly PlaybookPendingBossQuestion[];
package/src/runtime.ts CHANGED
@@ -200,6 +200,7 @@ export interface PlaybookRuntimeSnapshot {
200
200
  judgeCall: number;
201
201
  playerCall: number;
202
202
  playbookCall: number;
203
+ captainCall?: number;
203
204
  };
204
205
  state: PlaybookState;
205
206
  pendingBossQuestions: readonly PlaybookPendingBossQuestion[];
@@ -0,0 +1,201 @@
1
+ import type { AnyStateMachine, EventObject, PromiseActorLogic } from 'xstate';
2
+ import type { CaptainResult, JsonValue, PlaybookPorts, PlaybookRuntimeFactory, PlaybookSession, PlaybookState, PlayerResult } from './runtime.js';
3
+ export interface PlaybookPendingBossQuestionContext {
4
+ questionId: string;
5
+ resumeStateId: string;
6
+ sourceItem: string;
7
+ player: string;
8
+ question: string;
9
+ }
10
+ export interface PlaybookPlayerInput {
11
+ stateId: string;
12
+ player: string;
13
+ sourceItem: string;
14
+ prompt: string;
15
+ result: Readonly<Record<string, string>>;
16
+ pendingBossQuestion?: {
17
+ readonly question: string;
18
+ };
19
+ bossReply?: string;
20
+ }
21
+ export interface PlaybookCaptainInput {
22
+ stateId: string;
23
+ sourceItem: string;
24
+ prompt: string;
25
+ result: Readonly<Record<string, string>>;
26
+ allowedTools?: readonly string[];
27
+ pendingBossQuestion?: {
28
+ readonly question: string;
29
+ };
30
+ bossReply?: string;
31
+ }
32
+ export interface PlaybookScriptInput {
33
+ stateId: string;
34
+ sourceItem: string;
35
+ command: string;
36
+ result: Readonly<Record<string, string>>;
37
+ }
38
+ /** Adjudicated actor output: the selected guard plus payload fields. */
39
+ export type PlaybookActorOutput = Record<string, unknown> & {
40
+ guard: string;
41
+ };
42
+ export type JudgePurpose = 'boss-input-classification' | 'player-output-adjudication' | 'captain-output-adjudication';
43
+ /**
44
+ * Traced runtime boundary used by the provided actors. The factory's runtime
45
+ * implements it; standalone helpers accept it optionally so verification can
46
+ * exercise composition/adjudication without a live runtime.
47
+ */
48
+ export interface RuntimeBoundaryCalls {
49
+ callPlayer(input: PlaybookPlayerInput, playerId: string, prompt: string, signal: AbortSignal): Promise<PlayerResult>;
50
+ callJudge(purpose: JudgePurpose, stateId: string | undefined, prompt: string, signal: AbortSignal): Promise<string>;
51
+ callCaptain?(input: PlaybookCaptainInput, prompt: string, signal: AbortSignal): Promise<CaptainResult>;
52
+ }
53
+ export interface ScheduledStatus {
54
+ message: string;
55
+ data?: JsonValue;
56
+ }
57
+ export interface XStateBossEventFieldSpec {
58
+ /** The judge supplies routing data; the runtime supplies exact Boss text. */
59
+ source: 'judge' | 'text';
60
+ /** Judge-authored fields are optional unless explicitly required. */
61
+ required?: boolean;
62
+ /** Optional closed set for a string-valued judge field. */
63
+ values?: readonly string[];
64
+ }
65
+ export interface XStateBossEventSpec {
66
+ type: string;
67
+ fields?: Readonly<Record<string, XStateBossEventFieldSpec>>;
68
+ }
69
+ export declare const BOSS_REPLY_ERRORS: {
70
+ readonly missingQuestion: "needsBossReply outcome missing 'question' field";
71
+ readonly unregisteredState: (stateId: string) => string;
72
+ };
73
+ export interface XStatePlaybookRuntimeSpec<TOptions> {
74
+ /** Diagnostic label used in internal invariant errors. Default 'playbook'. */
75
+ label?: string;
76
+ /** Validate and JSON-snapshot the caller's per-run options. */
77
+ snapshotOptions: (value: unknown) => TOptions;
78
+ /** Derive the FSM machine input from validated options. Default: identity. */
79
+ machineInput?: (options: TOptions, session: PlaybookSession) => unknown;
80
+ /**
81
+ * Deterministic textual entry event (slc/link.md §Boss-event mapping):
82
+ * where the ready or reconstructed terminal machine accepts exactly one
83
+ * ordinary textual entry event, send it without a judge call, carrying the
84
+ * exact Boss text in `textField`. Absent: every non-empty turn classifies.
85
+ */
86
+ entryEvent?: {
87
+ type: string;
88
+ textField: string;
89
+ };
90
+ /**
91
+ * Exact flat Boss-event contracts whose non-text fields the judge may
92
+ * select. `entryEvent` and scalar `BOSS_REPLY` contracts are supplied by
93
+ * the factory; linkers emit entries here for additional typed events such
94
+ * as `BOSS_INTERRUPT` when their erased payload cannot be recovered from
95
+ * the XState machine alone.
96
+ */
97
+ bossEvents?: readonly XStateBossEventSpec[];
98
+ /** Boss-input classifier override; default: generic parked-state classifier. */
99
+ classifyBossText?: (text: string, ports: PlaybookPorts, signal: AbortSignal, snapshotOrState: unknown, boundary?: RuntimeBoundaryCalls) => Promise<EventObject | undefined>;
100
+ /** Status line emitted after classification names an event. Default: none. */
101
+ classificationStatus?: (event: EventObject) => string | undefined;
102
+ /** Map a player-invoking state's input to the host player id. Default: lowercased player name. */
103
+ resolvePlayerId?: (input: PlaybookPlayerInput, options: TOptions) => string;
104
+ /** Compose the player prompt. Default: continuation blocks + `<field>` placeholder substitution. */
105
+ composePlayerPrompt?: (input: PlaybookPlayerInput) => string;
106
+ /** Compose the direct-Captain prompt. Default: continuation blocks + placeholder substitution with deterministic JSON rendering. */
107
+ composeCaptainPrompt?: (input: PlaybookCaptainInput) => string;
108
+ /** Linker-known exceptions to the default kebab-token → camel-field mapping. */
109
+ placeholderFields?: Readonly<Record<string, string>>;
110
+ /** Adjudicator prompt for delegated players. Default: generic guard menu. */
111
+ buildJudgePrompt?: (input: PlaybookPlayerInput, finalText: string) => string;
112
+ /** Required-payload-field extraction from a `result` description. Default: bilingual `Output shall include` clause scan. */
113
+ extractRequiredFields?: (description: string) => string[];
114
+ /** Required fields carried verbatim from the player's finalText instead of judge JSON. Default: none. */
115
+ verbatimPayloadFields?: ReadonlySet<string>;
116
+ /** States that may suspend for a Boss reply. Default: targets of the FSM's `awaitBossReply` BOSS_REPLY transitions. */
117
+ resumableStateIds?: ReadonlySet<string>;
118
+ /** Human status lines for a root transition. Default: entry lines with question/failure surfacing. */
119
+ statusesForState?: (state: PlaybookState, context: Record<string, unknown>, event: unknown) => readonly ScheduledStatus[];
120
+ /** Detached JSON-safe transition-event descriptor. Default: `type` + `transitionEventFields` strings + validated output + normalized error. */
121
+ normalizeTransitionEvent?: (event: unknown) => JsonValue | undefined;
122
+ /** String payload fields the default transition-event descriptor copies. */
123
+ transitionEventFields?: readonly string[];
124
+ /** Working directory for `script` actors. Default: the validated options' string `cwd`, else the process working directory. */
125
+ scriptCwd?: (options: TOptions) => string | undefined;
126
+ }
127
+ /** Strip a single Markdown code fence that wraps the whole string. */
128
+ export declare function stripCodeFence(text: string): string;
129
+ export declare function extractJsonValue(text: string, start: number, repair: boolean): string | undefined;
130
+ export declare function parseJudgeJson(raw: string): unknown;
131
+ export declare function normalizeErrorCompact(err: unknown): {
132
+ name: string;
133
+ message: string;
134
+ } | undefined;
135
+ export declare function normalizeErrorFull(err: unknown): {
136
+ name: string;
137
+ message: string;
138
+ stack?: string;
139
+ } | undefined;
140
+ /** Read the FSM context's single pending Boss question, when well-formed. */
141
+ export declare function pendingBossQuestionFromContext(context: Record<string, unknown>): PlaybookPendingBossQuestionContext | undefined;
142
+ /**
143
+ * Default player-prompt composer (slc/link.md §Player prompt composition).
144
+ * One callback-based pass substitutes each `<fieldName>` placeholder whose
145
+ * typed input field is a string; replacement text is literal, and
146
+ * placeholder-looking text inside a value is never re-substituted. The
147
+ * continuation preamble and Q/A blocks precede the domain body on resume.
148
+ */
149
+ export declare function defaultComposePlayerPrompt(input: PlaybookPlayerInput, placeholderFields?: Readonly<Record<string, string>>): string;
150
+ /**
151
+ * Default direct-Captain prompt composer (slc/link.md §Captain prompt
152
+ * composition). Placeholder substitution is presence-based: string fields
153
+ * substitute verbatim; JSON-safe arrays/objects render as deterministic JSON
154
+ * with lexicographically sorted keys at every depth.
155
+ */
156
+ export declare function defaultComposeCaptainPrompt(input: PlaybookCaptainInput, placeholderFields?: Readonly<Record<string, string>>): string;
157
+ /** Default player binding: each player to its lowercased name. */
158
+ export declare function defaultResolvePlayerId(input: PlaybookPlayerInput): string;
159
+ /**
160
+ * Default required-field extraction (slc/link.md §Captain adjudication).
161
+ * Limited to the description's `Output shall include` / `输出应包含` clause;
162
+ * recognizes both the bare backticked name and the annotated `name: <...>`
163
+ * form.
164
+ */
165
+ export declare function defaultExtractRequiredFields(description: string): string[];
166
+ /** Default delegated-player adjudicator prompt. */
167
+ export declare function defaultBuildJudgePrompt(input: PlaybookPlayerInput, finalText: string): string;
168
+ export interface PlayerAdjudicationSpec {
169
+ buildJudgePrompt?: (input: PlaybookPlayerInput, finalText: string) => string;
170
+ extractRequiredFields?: (description: string) => string[];
171
+ verbatimPayloadFields?: ReadonlySet<string>;
172
+ }
173
+ /**
174
+ * LLM-judge adjudicator for delegated players. Coerces the player's
175
+ * finalText into one of the state's declared guards, extracts every required
176
+ * payload field from the judge reply, and fails loudly (throws) on a missing
177
+ * JSON object, an undeclared guard, or a missing required field. Fields in
178
+ * `verbatimPayloadFields` carry `finalText.trim()` rather than round-tripping
179
+ * long-form prose through judge JSON.
180
+ */
181
+ export declare function adjudicatePlayerOutput(spec: PlayerAdjudicationSpec, input: PlaybookPlayerInput, finalText: string, ports: PlaybookPorts, signal: AbortSignal, boundary?: RuntimeBoundaryCalls): Promise<PlaybookActorOutput>;
182
+ export interface PlayerBridgeSpec {
183
+ resolvePlayerId: (input: PlaybookPlayerInput) => string;
184
+ composePlayerPrompt: (input: PlaybookPlayerInput) => string;
185
+ adjudication: PlayerAdjudicationSpec;
186
+ resumableStateIds: ReadonlySet<string>;
187
+ }
188
+ export declare function createPlayerBridge(spec: PlayerBridgeSpec, ports: PlaybookPorts, getActiveSignal?: () => AbortSignal | undefined, boundary?: RuntimeBoundaryCalls, onControlPlaneError?: (error: unknown) => void): PromiseActorLogic<PlaybookActorOutput, PlaybookPlayerInput>;
189
+ /** Targets of the FSM's `awaitBossReply` BOSS_REPLY transitions. */
190
+ export declare function resumableStateIdsFromMachine(machine: AnyStateMachine): ReadonlySet<string>;
191
+ /**
192
+ * Build a `PlaybookRuntimeFactory` that interprets the given FSM artifact
193
+ * under the slc/link.md contract. The factory provides every actor kind the
194
+ * machine declares — `player`, `script`, `captain`, and nested `playbook`
195
+ * (literal and dynamic) — and implements the full runtime lifecycle including
196
+ * the optional parked-session snapshot capability (DR-014).
197
+ *
198
+ * Scope: single-region root machines (each snapshot exposes exactly one
199
+ * playbook state id). Parallel-region FSMs keep their own linked runtimes.
200
+ */
201
+ export declare function createXStatePlaybookRuntime<TOptions>(machine: AnyStateMachine, spec: XStatePlaybookRuntimeSpec<TOptions>): PlaybookRuntimeFactory<TOptions>;