@sublang/playbook 4.0.0 → 6.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.
Files changed (73) hide show
  1. package/README.md +69 -122
  2. package/docs/assets/playbook-venn.svg +13 -0
  3. package/docs/cli.md +43 -26
  4. package/docs/configuration.md +63 -18
  5. package/docs/embedding.md +24 -16
  6. package/package.json +43 -22
  7. package/reference/sdlc/captain.md +70 -83
  8. package/reference/sdlc/captain.playbook/captain.fsm.d.ts +127 -142
  9. package/reference/sdlc/captain.playbook/captain.fsm.js +349 -470
  10. package/reference/sdlc/captain.playbook/captain.fsm.ts +535 -598
  11. package/reference/sdlc/captain.playbook/captain.gears.md +37 -41
  12. package/reference/sdlc/captain.playbook/captain.playbook.d.ts +90 -15
  13. package/reference/sdlc/captain.playbook/captain.playbook.js +466 -976
  14. package/reference/sdlc/captain.playbook/captain.playbook.ts +698 -1001
  15. package/reference/sdlc/code.md +55 -97
  16. package/reference/sdlc/code.playbook/code.fsm.d.ts +229 -94
  17. package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +26 -44
  18. package/reference/sdlc/code.playbook/code.fsm.introspect.js +61 -66
  19. package/reference/sdlc/code.playbook/code.fsm.introspect.ts +100 -149
  20. package/reference/sdlc/code.playbook/code.fsm.js +587 -1347
  21. package/reference/sdlc/code.playbook/code.fsm.ts +809 -1650
  22. package/reference/sdlc/code.playbook/code.gears.md +51 -263
  23. package/reference/sdlc/code.playbook/code.playbook.d.ts +8 -47
  24. package/reference/sdlc/code.playbook/code.playbook.js +69 -639
  25. package/reference/sdlc/code.playbook/code.playbook.ts +90 -850
  26. package/reference/sdlc/code.playbook/code.registry.d.ts +9 -25
  27. package/reference/sdlc/code.playbook/code.registry.js +20 -78
  28. package/reference/sdlc/code.playbook/code.registry.ts +58 -122
  29. package/reference/sdlc/code.playbook/playbook-captain.d.ts +2 -0
  30. package/reference/sdlc/code.playbook/playbook-captain.js +1877 -251
  31. package/reference/sdlc/code.playbook/playbook-captain.ts +2385 -352
  32. package/reference/sdlc/code.playbook/playbook.config.template.yaml +33 -22
  33. package/reference/sdlc/decide.md +54 -0
  34. package/reference/sdlc/decide.playbook/decide.fsm.d.ts +261 -0
  35. package/reference/sdlc/decide.playbook/decide.fsm.js +894 -0
  36. package/reference/sdlc/decide.playbook/decide.fsm.ts +1152 -0
  37. package/reference/sdlc/decide.playbook/decide.gears.md +88 -0
  38. package/reference/sdlc/decide.playbook/decide.playbook.d.ts +67 -0
  39. package/reference/sdlc/{discuss.playbook/discuss.playbook.js → decide.playbook/decide.playbook.js} +511 -370
  40. package/reference/sdlc/{discuss.playbook/discuss.playbook.ts → decide.playbook/decide.playbook.ts} +616 -451
  41. package/reference/sdlc/decide.playbook/decide.registry.d.ts +41 -0
  42. package/reference/sdlc/decide.playbook/decide.registry.js +60 -0
  43. package/reference/sdlc/decide.playbook/decide.registry.ts +125 -0
  44. package/reference/sdlc/review.md +81 -0
  45. package/reference/sdlc/review.playbook/review.fsm.d.ts +183 -0
  46. package/reference/sdlc/review.playbook/review.fsm.js +524 -0
  47. package/reference/sdlc/review.playbook/review.fsm.ts +652 -0
  48. package/reference/sdlc/review.playbook/review.gears.md +112 -0
  49. package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -0
  50. package/reference/sdlc/review.playbook/review.playbook.js +112 -0
  51. package/reference/sdlc/review.playbook/review.playbook.ts +201 -0
  52. package/reference/sdlc/review.playbook/review.registry.d.ts +43 -0
  53. package/reference/sdlc/review.playbook/review.registry.js +73 -0
  54. package/reference/sdlc/review.playbook/review.registry.ts +138 -0
  55. package/slc/gears2fsm.md +67 -6
  56. package/slc/link.md +339 -25
  57. package/slc/text2gears.md +22 -2
  58. package/src/runtime.d.ts +36 -1
  59. package/src/runtime.ts +59 -0
  60. package/src/xstate-playbook-runtime.d.ts +96 -7
  61. package/src/xstate-playbook-runtime.js +1018 -49
  62. package/src/xstate-playbook-runtime.ts +1283 -59
  63. package/src/xstate-runtime.js +25 -0
  64. package/src/xstate-runtime.ts +51 -0
  65. package/reference/sdlc/discuss.md +0 -93
  66. package/reference/sdlc/discuss.playbook/discuss.fsm.d.ts +0 -396
  67. package/reference/sdlc/discuss.playbook/discuss.fsm.js +0 -2067
  68. package/reference/sdlc/discuss.playbook/discuss.fsm.ts +0 -2465
  69. package/reference/sdlc/discuss.playbook/discuss.gears.md +0 -258
  70. package/reference/sdlc/discuss.playbook/discuss.playbook.d.ts +0 -113
  71. package/reference/sdlc/discuss.playbook/discuss.registry.d.ts +0 -58
  72. package/reference/sdlc/discuss.playbook/discuss.registry.js +0 -97
  73. package/reference/sdlc/discuss.playbook/discuss.registry.ts +0 -153
package/slc/text2gears.md CHANGED
@@ -65,6 +65,20 @@ Those requirements remain in the item's condition or `Results:` metadata.
65
65
  Adding control-oriented prompt lines merely to restate them changes the
66
66
  Boss-visible contract and is nonconformant.
67
67
 
68
+ ### Authored prompt fragments
69
+
70
+ Source may compose one acting prompt from authored Markdown instruction blocks and runtime context that it explicitly says to relay in quotes (`>`).
71
+ A fenced `markdown` block introduced as an instruction or prompt is an authored static prompt fragment: its fence delimiters are Source syntax, while every interior line and blank line is prompt content preserved after documented Markdown unescaping.
72
+
73
+ An instruction fence and a relayed-context fragment that apply to one behavior shall appear in the target blockquote in their Source order.
74
+ Distinct non-empty fragments shall be separated by one blank prompt line unless Source explicitly supplies a different boundary.
75
+ text2gears shall not move a shared instruction ahead of behavior-specific context, move quoted evidence after an instruction that Source says follows the evidence, or otherwise regroup fragments for convenience.
76
+
77
+ Where Source says that a runtime value is relayed in quotes, the leading `>` is prompt content rather than Source-only blockquote syntax.
78
+ If Source supplies a blockquoted template for that relay, text2gears shall keep one literal leading `>` on every quoted line; the target GEARS line therefore uses its outer blockquote marker followed by the literal marker, such as `> > Coder output: <coder-output>`.
79
+ If Source names the relayed value but supplies no template, text2gears shall emit its canonical typed placeholder on a line beginning with literal `> ` and shall not summarize, paraphrase, or invent a value in its place.
80
+ An ordinary Source blockquote that specifies a complete acting prompt without requiring quoted relay retains the existing rule above: its one leading marker is Source syntax and is not prompt content.
81
+
68
82
  Source statements that assign active-leaf routing, call identity, suspension,
69
83
  or return matching to the host describe execution preconditions rather than
70
84
  behaviors for Captain to perform. text2gears shall use such a statement only as
@@ -139,6 +153,11 @@ A single-outcome producer then declares exactly one bullet naming the
139
153
  property; this consumed-output case is the sole one in which a
140
154
  single-outcome behavior carries a `Results:` label.
141
155
 
156
+ Where a later prompt relays a delegated player's whole final response as quoted context, the producer shall declare that property in the exact annotated form `` `<field>: <verbatim final text>` ``.
157
+ The annotation makes the field runtime-owned: the adjudicator selects the result guard, while the linked runtime carries the player's canonical final text into that field instead of asking a judge to reproduce it.
158
+ A distinct typed field extracted from that response remains judge-authored even when a later prompt quotes its exact value; quoting a field does not turn it into the player's whole final response.
159
+ One property name shall not be annotated as verbatim in one result contract and judge-authored in another; text2gears shall choose distinct properties or report that the Source cannot be represented by the current contract.
160
+
142
161
  Result metadata is compiler control data, not part of the acting agent's
143
162
  prompt.
144
163
  text2gears shall not put guard names, result-property schema, JSON control
@@ -202,11 +221,11 @@ next phase cannot compile.
202
221
  Example:
203
222
 
204
223
  ```markdown
205
- ### DISCUSS-1
224
+ ### DECIDE-1
206
225
 
207
226
  Parallel group: initial-proposals
208
227
 
209
- When Boss gives a topic, Captain shall prompt Host:
228
+ When Boss gives a topic, Captain shall prompt Coder:
210
229
 
211
230
  > Propose your design independently.
212
231
  ```
@@ -306,6 +325,7 @@ Prompts shall carry the specification's normative requirements as instructions t
306
325
 
307
326
  Source snippets may overlap or duplicate.
308
327
  When composing them into a spec item, text2gears shall deduplicate identical prompt lines.
328
+ It shall not deduplicate across distinct authored fragments when doing so would erase a fragment boundary or change the Source-ordered prompt.
309
329
 
310
330
  Each spec item addresses one state behavior and carries its full final prompt (the static part).
311
331
  Cross-item duplication is acceptable: spec items are compiled artifacts; Source is what users maintain.
package/src/runtime.d.ts CHANGED
@@ -7,6 +7,12 @@ export interface PlayerResult {
7
7
  export interface PlayerCallOptions {
8
8
  resume: string | false;
9
9
  }
10
+ export interface PlayerSessionStore {
11
+ select(playerId: string): string | false;
12
+ update(playerId: string, resumeToken?: string): void;
13
+ snapshot(): Readonly<Record<string, string>>;
14
+ restore(tokens: Readonly<Record<string, string>>): void;
15
+ }
10
16
  export interface CaptainCallOptions {
11
17
  visibility: 'visible' | 'hidden';
12
18
  resume: string | false;
@@ -106,9 +112,10 @@ export interface PlaybookSession {
106
112
  parentSessionId?: string;
107
113
  parentCallId?: string;
108
114
  depth: number;
115
+ playerSessions?: PlayerSessionStore;
109
116
  ports: PlaybookPorts;
110
117
  }
111
- export type PlaybookTraceType = 'session.started' | 'boss.input.received' | 'judge.call.started' | 'judge.call.finished' | 'player.call.started' | 'player.call.finished' | 'captain.call.started' | 'captain.call.finished' | 'playbook.call.started' | 'playbook.call.finished' | 'fsm.transition' | 'status.emitted' | 'boss.input.settled' | 'session.disposed';
118
+ export type PlaybookTraceType = 'session.started' | 'boss.input.received' | 'judge.call.started' | 'judge.call.finished' | 'player.call.started' | 'player.call.finished' | 'captain.call.started' | 'captain.call.finished' | 'playbook.call.started' | 'playbook.call.finished' | 'apply.started' | 'apply.finished' | 'fsm.transition' | 'status.emitted' | 'boss.input.settled' | 'session.disposed';
112
119
  export interface PlaybookTraceEvent {
113
120
  schemaVersion: 2;
114
121
  sessionId: string;
@@ -148,10 +155,38 @@ export interface PlaybookRuntimeSnapshot {
148
155
  state: PlaybookState;
149
156
  pendingBossQuestions: readonly PlaybookPendingBossQuestion[];
150
157
  }
158
+ export interface PlaybookControlAction {
159
+ id: string;
160
+ label: string;
161
+ }
162
+ export interface PlaybookControlView {
163
+ state: PlaybookState;
164
+ stateDescription?: string;
165
+ context?: JsonValue;
166
+ pendingQuestions: readonly PlaybookPendingBossQuestion[];
167
+ lastError?: NormalizedError;
168
+ actions: readonly PlaybookControlAction[];
169
+ }
170
+ export type PlaybookControlReceipt = {
171
+ disposition: 'rejected';
172
+ reason: string;
173
+ } | {
174
+ disposition: 'executed';
175
+ run: PlaybookRunResult;
176
+ } | {
177
+ disposition: 'failed';
178
+ error: NormalizedError;
179
+ };
151
180
  export interface PlaybookRuntime {
152
181
  init(session: PlaybookSession): Promise<void>;
153
182
  exportSnapshot?(): PlaybookRuntimeSnapshot | undefined;
154
183
  restore?(session: PlaybookSession, snapshot: PlaybookRuntimeSnapshot): Promise<void>;
184
+ describe?(): PlaybookControlView;
185
+ apply?(input: {
186
+ actionId: string;
187
+ key: string;
188
+ signal: AbortSignal;
189
+ }): Promise<PlaybookControlReceipt>;
155
190
  handleBossInput(turn: {
156
191
  text: string;
157
192
  signal: AbortSignal;
package/src/runtime.ts CHANGED
@@ -19,6 +19,17 @@ export interface PlayerCallOptions {
19
19
  resume: string | false;
20
20
  }
21
21
 
22
+ // DR-030: a composing host may supply one frame-local view of the root
23
+ // engagement's player continuation. The runtime selects through this store
24
+ // before tracing/calling and updates it from the validated result. Hosts that
25
+ // omit it retain the runtime's private per-session store.
26
+ export interface PlayerSessionStore {
27
+ select(playerId: string): string | false;
28
+ update(playerId: string, resumeToken?: string): void;
29
+ snapshot(): Readonly<Record<string, string>>;
30
+ restore(tokens: Readonly<Record<string, string>>): void;
31
+ }
32
+
22
33
  export interface CaptainCallOptions {
23
34
  visibility: 'visible' | 'hidden';
24
35
  resume: string | false;
@@ -143,6 +154,7 @@ export interface PlaybookSession {
143
154
  parentSessionId?: string;
144
155
  parentCallId?: string;
145
156
  depth: number;
157
+ playerSessions?: PlayerSessionStore;
146
158
  ports: PlaybookPorts;
147
159
  }
148
160
 
@@ -157,6 +169,8 @@ export type PlaybookTraceType =
157
169
  | 'captain.call.finished'
158
170
  | 'playbook.call.started'
159
171
  | 'playbook.call.finished'
172
+ | 'apply.started'
173
+ | 'apply.finished'
160
174
  | 'fsm.transition'
161
175
  | 'status.emitted'
162
176
  | 'boss.input.settled'
@@ -206,6 +220,38 @@ export interface PlaybookRuntimeSnapshot {
206
220
  pendingBossQuestions: readonly PlaybookPendingBossQuestion[];
207
221
  }
208
222
 
223
+ // DR-029: one currently valid, runtime-advertised control action. The id
224
+ // is stable within the returned view; the label is runtime-written,
225
+ // Boss-appropriate text derived from source state descriptions.
226
+ export interface PlaybookControlAction {
227
+ id: string;
228
+ label: string;
229
+ }
230
+
231
+ // DR-029: the sanitized control view `describe()` returns — current
232
+ // state and the runtime-written description of what that state means,
233
+ // the authored context projection, pending Boss questions, the last
234
+ // recorded error, and the currently valid actions. `stateDescription` is
235
+ // the Boss-appropriate grounding a host may speak from; the state id is
236
+ // internal and is absent from it whenever the runtime's source declares
237
+ // no description for the state it is in.
238
+ export interface PlaybookControlView {
239
+ state: PlaybookState;
240
+ stateDescription?: string;
241
+ context?: JsonValue;
242
+ pendingQuestions: readonly PlaybookPendingBossQuestion[];
243
+ lastError?: NormalizedError;
244
+ actions: readonly PlaybookControlAction[];
245
+ }
246
+
247
+ // DR-029: the receipt `apply()` returns says which of three things
248
+ // happened — rejected before any effect, executed with the settled run
249
+ // result, or failed after effects may exist.
250
+ export type PlaybookControlReceipt =
251
+ | { disposition: 'rejected'; reason: string }
252
+ | { disposition: 'executed'; run: PlaybookRunResult }
253
+ | { disposition: 'failed'; error: NormalizedError };
254
+
209
255
  export interface PlaybookRuntime {
210
256
  init(session: PlaybookSession): Promise<void>;
211
257
  // DR-014 §1 optional durable-session capability: a runtime implements
@@ -218,6 +264,19 @@ export interface PlaybookRuntime {
218
264
  session: PlaybookSession,
219
265
  snapshot: PlaybookRuntimeSnapshot,
220
266
  ): Promise<void>;
267
+ // DR-029 optional control-surface capability: a runtime implements
268
+ // both members or neither. `describe` is side-effect free and valid at
269
+ // parked quiescence outside an active boundary; `apply` revalidates the
270
+ // named action against the live state, executes it at most once per
271
+ // idempotency key within that runtime instance, and returns a receipt. A
272
+ // runtime lacking the pair advertises no actions; plain text delivery is
273
+ // the only verb against it.
274
+ describe?(): PlaybookControlView;
275
+ apply?(input: {
276
+ actionId: string;
277
+ key: string;
278
+ signal: AbortSignal;
279
+ }): Promise<PlaybookControlReceipt>;
221
280
  handleBossInput(turn: {
222
281
  text: string;
223
282
  signal: AbortSignal;
@@ -48,12 +48,30 @@ export type JudgePurpose = 'boss-input-classification' | 'player-output-adjudica
48
48
  export interface RuntimeBoundaryCalls {
49
49
  callPlayer(input: PlaybookPlayerInput, playerId: string, prompt: string, signal: AbortSignal): Promise<PlayerResult>;
50
50
  callJudge(purpose: JudgePurpose, stateId: string | undefined, prompt: string, signal: AbortSignal): Promise<string>;
51
- callCaptain?(input: PlaybookCaptainInput, prompt: string, signal: AbortSignal): Promise<CaptainResult>;
51
+ callCaptain?(input: PlaybookCaptainInput, prompt: string, signal: AbortSignal, callOptions?: XStateCaptainCallOptions): Promise<CaptainResult>;
52
+ }
53
+ /**
54
+ * Presentation selection for one traced direct-Captain call
55
+ * (slc/link.md §Captain adjudication). `'visible'` (the default) is the
56
+ * workflow form: the port receives `{ visibility: 'visible', resume: false }`
57
+ * and the trace pair carries both members. `'hidden'` is the controller form
58
+ * (DR-029): the port receives `{ visibility: 'hidden', resume: false }`
59
+ * while the host's session-Captain wrapper owns the actual durable-conversation
60
+ * resume selection, so the trace pair carries `visibility: 'hidden'` and no
61
+ * `resume` member — the pinned token never enters runtime telemetry.
62
+ */
63
+ export interface XStateCaptainCallOptions {
64
+ visibility?: 'visible' | 'hidden';
52
65
  }
53
66
  export interface ScheduledStatus {
54
67
  message: string;
55
68
  data?: JsonValue;
56
69
  }
70
+ /** Boss-facing identity for one FSM state whose invoked actor is `player`. */
71
+ export interface XStatePlayerStateStatus {
72
+ player: string;
73
+ label: string;
74
+ }
57
75
  export interface XStateBossEventFieldSpec {
58
76
  /** The judge supplies routing data; the runtime supplies exact Boss text. */
59
77
  source: 'judge' | 'text';
@@ -81,6 +99,46 @@ export interface XStatePlaybookRuntimeCompat {
81
99
  /** The engine ABI the artifact was linked against. */
82
100
  runtimeAbi: number;
83
101
  }
102
+ /**
103
+ * One direct-Captain actor invocation handed to a spec's `captainStrategy`
104
+ * (slc/link.md §Captain adjudication, controller form). The engine owns
105
+ * signal combination, emission draining, trace pairing, the shared
106
+ * Captain/judge lane, and control-plane latching; the strategy owns the
107
+ * playbook-specific call pipeline — e.g. the controller's hidden decision
108
+ * call, `{ action, … }` control-JSON validation with its single corrective
109
+ * re-ask, and controller-port submission.
110
+ */
111
+ export interface XStateCaptainStrategyRun<TOptions> {
112
+ input: PlaybookCaptainInput;
113
+ /** The prompt composed by the spec's Captain composer for `input`. */
114
+ prompt: string;
115
+ /** Combined invocation-lifetime + active-boundary abort signal. */
116
+ signal: AbortSignal;
117
+ /** The immutable validated runtime options. */
118
+ options: TOptions;
119
+ /** The bound immutable playbook session identity. */
120
+ session: PlaybookSession;
121
+ /**
122
+ * One traced Captain call through the shared serialized lane; every call —
123
+ * initial or corrective — emits its own paired `captain.call.started` /
124
+ * `captain.call.finished` boundary. Throws the boundary's authoritative
125
+ * failure for non-`ok` and empty-`ok` results exactly as the default
126
+ * pipeline does.
127
+ */
128
+ callCaptain(prompt: string, callOptions?: XStateCaptainCallOptions): Promise<CaptainResult>;
129
+ /**
130
+ * DR-028: true when `error` is the boundary's re-askable empty-`ok`
131
+ * marker; the strategy may re-issue the same composed call exactly once.
132
+ */
133
+ isEmptyOkRetry(error: unknown): boolean;
134
+ /**
135
+ * Mark `error` as a recoverable FSM-result failure: it travels the invoked
136
+ * actor's XState `onError` path without being latched as a control-plane
137
+ * error, so the machine's authored recovery arms can route it.
138
+ */
139
+ recoverableFailure<E extends Error>(error: E): E;
140
+ }
141
+ export type XStateCaptainStrategy<TOptions> = (run: XStateCaptainStrategyRun<TOptions>) => Promise<PlaybookActorOutput>;
84
142
  export interface XStatePlaybookRuntimeSpec<TOptions> {
85
143
  /** Diagnostic label used in internal invariant errors. Default 'playbook'. */
86
144
  label?: string;
@@ -112,10 +170,22 @@ export interface XStatePlaybookRuntimeSpec<TOptions> {
112
170
  * the XState machine alone.
113
171
  */
114
172
  bossEvents?: readonly XStateBossEventSpec[];
115
- /** Boss-input classifier override; default: generic parked-state classifier. */
116
- classifyBossText?: (text: string, ports: PlaybookPorts, signal: AbortSignal, snapshotOrState: unknown, boundary?: RuntimeBoundaryCalls) => Promise<EventObject | undefined>;
117
- /** Status line emitted after classification names an event. Default: none. */
173
+ /** Boss-input classifier override; default: generic parked-state classifier. Receives the bound validated options last so a fully deterministic controller mapping can consult host-supplied option members (slc/link.md §Boss-event mapping). */
174
+ classifyBossText?: (text: string, ports: PlaybookPorts, signal: AbortSignal, snapshotOrState: unknown, boundary?: RuntimeBoundaryCalls, options?: TOptions) => Promise<EventObject | undefined>;
175
+ /**
176
+ * Direct-Captain actor strategy override (slc/link.md §Captain
177
+ * adjudication, controller form): replaces the default visible-call +
178
+ * hidden-judge pipeline for every `captain` state of this machine. The
179
+ * engine still composes the prompt, combines signals, traces each call as
180
+ * its own pair, and latches control-plane errors; failures the strategy
181
+ * marks with `recoverableFailure` travel the actor's `onError` path as
182
+ * recoverable FSM-result failures instead.
183
+ */
184
+ captainStrategy?: XStateCaptainStrategy<TOptions>;
185
+ /** Status line emitted after classification; canonical metadata defaults to the event type, legacy artifacts to none. */
118
186
  classificationStatus?: (event: EventObject) => string | undefined;
187
+ /** Complete FSM-derived Boss-facing metadata for every `player` state; its presence selects the canonical status profile. */
188
+ playerStates?: Readonly<Record<string, XStatePlayerStateStatus>>;
119
189
  /** Map a player-invoking state's input to the host player id. Default: lowercased player name. */
120
190
  resolvePlayerId?: (input: PlaybookPlayerInput, options: TOptions) => string;
121
191
  /** Compose the player prompt. Default: continuation blocks + `<field>` placeholder substitution. */
@@ -130,9 +200,21 @@ export interface XStatePlaybookRuntimeSpec<TOptions> {
130
200
  extractRequiredFields?: (description: string) => string[];
131
201
  /** Required fields carried verbatim from the player's finalText instead of judge JSON. Default: none. */
132
202
  verbatimPayloadFields?: ReadonlySet<string>;
203
+ /**
204
+ * DR-029 / PBRT-52: the runtime-authored ControlView context
205
+ * projection — the exact FSM context members `describe()` may expose,
206
+ * in the order the view lists them. Only this artifact knows which of
207
+ * its context members are safe and relevant for a controller prompt, so
208
+ * the engine exports what is named here and nothing else: a member the
209
+ * artifact has not named stays private, and a member added to the FSM
210
+ * later stays private until someone names it. Absent or empty: the view
211
+ * carries no context at all. `pendingBossQuestion` and `lastError` are
212
+ * surfaced first-class by the view and shall not be named here.
213
+ */
214
+ controlContextFields?: readonly string[];
133
215
  /** States that may suspend for a Boss reply. Default: targets of the FSM's `awaitBossReply` BOSS_REPLY transitions. */
134
216
  resumableStateIds?: ReadonlySet<string>;
135
- /** Human status lines for a root transition. Default: entry lines with question/failure surfacing. */
217
+ /** Human status lines for a root transition. Default: guard, declared-player, question, and failure lines. */
136
218
  statusesForState?: (state: PlaybookState, context: Record<string, unknown>, event: unknown) => readonly ScheduledStatus[];
137
219
  /** Detached JSON-safe transition-event descriptor. Default: `type` + `transitionEventFields` strings + validated output + normalized error. */
138
220
  normalizeTransitionEvent?: (event: unknown) => JsonValue | undefined;
@@ -215,6 +297,12 @@ export declare function defaultBuildCaptainJudgePrompt(input: {
215
297
  }, finalText: string): string;
216
298
  /** Targets of the FSM's `awaitBossReply` BOSS_REPLY transitions. */
217
299
  export declare function resumableStateIdsFromMachine(machine: AnyStateMachine): ReadonlySet<string>;
300
+ /**
301
+ * Source state descriptions by state key, node id, and `meta.playbook`
302
+ * state id, read from `machine.config`. Control actions are labeled from
303
+ * these descriptions (DR-029); a state without one has no entry.
304
+ */
305
+ export declare function stateDescriptionsFromMachine(machine: AnyStateMachine): ReadonlyMap<string, string>;
218
306
  /**
219
307
  * Build a `PlaybookRuntimeFactory` that interprets the given FSM artifact
220
308
  * under the slc/link.md contract. The factory provides every actor kind the
@@ -222,7 +310,8 @@ export declare function resumableStateIdsFromMachine(machine: AnyStateMachine):
222
310
  * (literal and dynamic) — and implements the full runtime lifecycle including
223
311
  * the optional parked-session snapshot capability (DR-014).
224
312
  *
225
- * Scope: single-region root machines (each snapshot exposes exactly one
226
- * playbook state id). Parallel-region FSMs keep their own linked runtimes.
313
+ * Scope: machines that declare no parallel state (each snapshot exposes
314
+ * exactly one playbook state id). Parallel-region FSMs keep their own linked
315
+ * runtimes.
227
316
  */
228
317
  export declare function createXStatePlaybookRuntime<TOptions>(machine: AnyStateMachine, spec: XStatePlaybookRuntimeSpec<TOptions>): PlaybookRuntimeFactory<TOptions>;