@sublang/playbook 15.1.0 → 16.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 (76) hide show
  1. package/docs/embedding.md +2 -2
  2. package/package.json +1 -1
  3. package/reference/sdlc/branch.playbook/branch.fsm.d.ts +63 -33
  4. package/reference/sdlc/branch.playbook/branch.fsm.js +190 -108
  5. package/reference/sdlc/branch.playbook/branch.fsm.ts +269 -147
  6. package/reference/sdlc/branch.playbook/branch.gears.md +7 -17
  7. package/reference/sdlc/branch.playbook/branch.playbook.d.ts +12 -16
  8. package/reference/sdlc/branch.playbook/branch.playbook.js +112 -101
  9. package/reference/sdlc/branch.playbook/branch.playbook.ts +128 -171
  10. package/reference/sdlc/branch.playbook/branch.registry.d.ts +3 -2
  11. package/reference/sdlc/branch.playbook/branch.registry.ts +6 -2
  12. package/reference/sdlc/code.playbook/code.fsm.d.ts +143 -90
  13. package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +8 -8
  14. package/reference/sdlc/code.playbook/code.fsm.introspect.ts +13 -13
  15. package/reference/sdlc/code.playbook/code.fsm.js +609 -649
  16. package/reference/sdlc/code.playbook/code.fsm.ts +890 -821
  17. package/reference/sdlc/code.playbook/code.gears.md +39 -29
  18. package/reference/sdlc/code.playbook/code.playbook.d.ts +13 -16
  19. package/reference/sdlc/code.playbook/code.playbook.js +166 -147
  20. package/reference/sdlc/code.playbook/code.playbook.ts +180 -229
  21. package/reference/sdlc/code.playbook/code.registry.d.ts +3 -2
  22. package/reference/sdlc/code.playbook/code.registry.ts +6 -2
  23. package/reference/sdlc/code.playbook/playbook-captain.d.ts +42 -0
  24. package/reference/sdlc/code.playbook/playbook-captain.js +829 -194
  25. package/reference/sdlc/code.playbook/playbook-captain.ts +1227 -220
  26. package/reference/sdlc/decide.md +1 -0
  27. package/reference/sdlc/decide.playbook/decide.fsm.d.ts +270 -154
  28. package/reference/sdlc/decide.playbook/decide.fsm.js +765 -732
  29. package/reference/sdlc/decide.playbook/decide.fsm.ts +1167 -945
  30. package/reference/sdlc/decide.playbook/decide.gears.md +28 -21
  31. package/reference/sdlc/decide.playbook/decide.playbook.d.ts +11 -59
  32. package/reference/sdlc/decide.playbook/decide.playbook.js +155 -3696
  33. package/reference/sdlc/decide.playbook/decide.playbook.ts +186 -5244
  34. package/reference/sdlc/decide.playbook/decide.registry.d.ts +8 -4
  35. package/reference/sdlc/decide.playbook/decide.registry.js +2 -2
  36. package/reference/sdlc/decide.playbook/decide.registry.ts +13 -6
  37. package/reference/sdlc/dev.playbook/dev.fsm.d.ts +113 -131
  38. package/reference/sdlc/dev.playbook/dev.fsm.js +517 -575
  39. package/reference/sdlc/dev.playbook/dev.fsm.ts +667 -787
  40. package/reference/sdlc/dev.playbook/dev.gears.md +52 -54
  41. package/reference/sdlc/dev.playbook/dev.playbook.d.ts +13 -10
  42. package/reference/sdlc/dev.playbook/dev.playbook.js +128 -120
  43. package/reference/sdlc/dev.playbook/dev.playbook.ts +143 -193
  44. package/reference/sdlc/dev.playbook/dev.registry.d.ts +3 -2
  45. package/reference/sdlc/dev.playbook/dev.registry.ts +6 -2
  46. package/reference/sdlc/pr.playbook/pr.fsm.d.ts +92 -85
  47. package/reference/sdlc/pr.playbook/pr.fsm.js +461 -518
  48. package/reference/sdlc/pr.playbook/pr.fsm.ts +533 -663
  49. package/reference/sdlc/pr.playbook/pr.gears.md +47 -63
  50. package/reference/sdlc/pr.playbook/pr.playbook.d.ts +13 -23
  51. package/reference/sdlc/pr.playbook/pr.playbook.js +118 -112
  52. package/reference/sdlc/pr.playbook/pr.playbook.ts +136 -190
  53. package/reference/sdlc/pr.playbook/pr.registry.d.ts +3 -2
  54. package/reference/sdlc/pr.playbook/pr.registry.ts +4 -2
  55. package/reference/sdlc/review.md +3 -3
  56. package/reference/sdlc/review.playbook/review.fsm.d.ts +150 -116
  57. package/reference/sdlc/review.playbook/review.fsm.js +479 -550
  58. package/reference/sdlc/review.playbook/review.fsm.ts +717 -662
  59. package/reference/sdlc/review.playbook/review.gears.md +32 -29
  60. package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -12
  61. package/reference/sdlc/review.playbook/review.playbook.js +180 -155
  62. package/reference/sdlc/review.playbook/review.playbook.ts +190 -230
  63. package/reference/sdlc/review.playbook/review.registry.d.ts +6 -5
  64. package/reference/sdlc/review.playbook/review.registry.js +3 -3
  65. package/reference/sdlc/review.playbook/review.registry.ts +9 -5
  66. package/slc/gears2fsm.md +72 -3
  67. package/slc/link.md +50 -27
  68. package/slc/materialize-link.mjs +51 -13
  69. package/slc/optimize.md +4 -1
  70. package/slc/prefix-prompts.mjs +29 -28
  71. package/slc/prefix.md +27 -24
  72. package/slc/slc.pin-inputs.json +11 -2
  73. package/slc/text2gears.md +71 -11
  74. package/src/xstate-playbook-runtime.d.ts +54 -15
  75. package/src/xstate-playbook-runtime.js +1154 -248
  76. package/src/xstate-playbook-runtime.ts +1603 -317
@@ -1,245 +1,195 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
3
- //
4
- // Generated by slc/link.md (FSM-to-Runtime linker).
5
- // Source FSM: ./dev.fsm.ts
6
- // Role metadata: Analyst→analyst (canonical local role)
7
- // Boss event: deterministic START_DEV entry; exact Boss text becomes
8
- // developmentRequest; pending Analyst questions retain
9
- // BOSS_REPLY
10
- // Adjudication: LLM judge for the one Analyst state; planningResult is
11
- // carried verbatim
12
- // Nested calls: literal code, decide, branch, and pr targets through the
13
- // shared bridge; branch, revision, commit, and pull-request
14
- // identities enter only from canonical child results
15
- // Compat: artifact schema 3 / runtime ABI 1
16
-
3
+ // Generated by slc/materialize-link.mjs; governed by the complete slc/link.md.
4
+ // FSM: "./dev.fsm.js"; export: devMachine; strategies: shared defaults with labelled string relays and nested actors.
5
+ import { devMachine as machine } from "./dev.fsm.js";
6
+ import type { PlayerInput as SourcePlayerInput } from "./dev.fsm.js";
17
7
  import {
18
- createXStatePlaybookRuntime,
19
- composePlayerContinuation,
20
- snapshotJsonValue,
8
+ createXStatePlaybookRuntime, snapshotJsonValue,
9
+ composePlayerContinuation, type XStatePromptIdentity,
21
10
  type PlaybookPlayerInput,
22
- type XStatePlaybookRuntimeFactory,
23
11
  type XStatePlaybookRuntimeConstruction,
12
+ type XStatePlaybookRuntimeFactory,
24
13
  type XStatePlaybookRuntimeSpecV3,
25
14
  } from '@sublang/playbook/xstate-runtime';
26
- import {
27
- devMachine,
28
- type DevInput,
29
- type PlayerInput,
30
- } from './dev.fsm.js';
31
- import type { PlaybookHostConstructionCapabilities } from '../code.playbook/playbook-captain.js';
32
- import type {
33
- CaptainCallOptions,
34
- CaptainResult,
35
- JsonValue,
36
- NormalizedError,
37
- PlayerCallOptions,
38
- PlaybookCallRequest,
39
- PlaybookCallResult,
40
- PlaybookCallStart,
41
- PlaybookControlReceipt,
42
- PlaybookControlView,
43
- PlaybookPendingCall,
44
- PlaybookPorts,
45
- PlaybookRunResult,
46
- PlaybookRuntime,
47
- PlaybookRuntimeFactory,
48
- PlaybookRuntimeSnapshot,
49
- PlaybookSession,
50
- PlaybookState,
51
- PlaybookStateValue,
52
- PlaybookTraceEvent,
53
- PlaybookTraceType,
15
+ export type {
54
16
  PlayerResult,
17
+ PlayerCallOptions,
55
18
  PlayerSessionStore,
56
- } from '@sublang/playbook/runtime';
57
-
58
- export type {
59
- CaptainCallOptions,
60
19
  CaptainResult,
20
+ CaptainCallOptions,
61
21
  JsonValue,
62
22
  NormalizedError,
63
- PlayerCallOptions,
64
23
  PlaybookCallRequest,
65
24
  PlaybookCallResult,
66
25
  PlaybookCallStart,
67
- PlaybookControlReceipt,
68
- PlaybookControlView,
26
+ PlaybookStateValue,
27
+ PlaybookState,
69
28
  PlaybookPendingCall,
70
- PlaybookPorts,
71
29
  PlaybookRunResult,
72
30
  PlaybookRuntime,
73
31
  PlaybookRuntimeFactory,
74
32
  PlaybookRuntimeSnapshot,
75
33
  PlaybookSession,
76
- PlaybookState,
77
- PlaybookStateValue,
34
+ PlaybookPorts,
78
35
  PlaybookTraceEvent,
79
36
  PlaybookTraceType,
80
- PlayerResult,
81
- PlayerSessionStore,
82
- };
83
-
84
- export type DevPlaybookOptions = DevInput;
85
- export type DevPlaybookHostCapabilities =
86
- PlaybookHostConstructionCapabilities &
87
- XStatePlaybookRuntimeConstruction<DevPlaybookOptions, object>['hostCapabilities'];
37
+ PlaybookControlReceipt,
38
+ PlaybookControlView,
39
+ } from '@sublang/playbook/runtime';
88
40
 
89
- const OPTION_KEYS = new Set(['runResults']);
90
- const PLACEHOLDER = /<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>/g;
41
+ export interface PlaybookRuntimeOptions {
42
+ readonly "runResults"?: string;
43
+ }
44
+ export type PlaybookHostCapabilities = XStatePlaybookRuntimeConstruction<
45
+ PlaybookRuntimeOptions, { readonly authority: object }
46
+ >['hostCapabilities'];
91
47
 
92
- const VERBATIM_PAYLOAD_FIELDS: ReadonlySet<string> = new Set([
93
- 'planningResult',
48
+ const OPTION_SCHEMA = {
49
+ "runResults": {
50
+ "type": "string",
51
+ "required": false
52
+ }
53
+ } as const;
54
+ const INPUT_MAPPING = {
55
+ "runResults": "runResults"
56
+ } as const;
57
+ const RESUMABLE_STATE_IDS: ReadonlySet<string> = new Set([
58
+ "planAnalysis"
94
59
  ]);
95
60
  const UNFINISHED_FINAL_STATE_IDS: ReadonlySet<string> = new Set([
96
- 'reportedChildFailure',
61
+ "reportedChildFailure"
97
62
  ]);
98
-
99
- function snapshotDevOptions(value: unknown): DevPlaybookOptions {
100
- const captured = snapshotJsonValue(value, 'DEV runtime options');
101
- if (
102
- captured === null ||
103
- typeof captured !== 'object' ||
104
- Array.isArray(captured)
105
- ) {
106
- throw new TypeError('DEV runtime options must be an object');
63
+ const VERBATIM_PAYLOAD_FIELDS: ReadonlySet<string> = new Set([
64
+ "planningResult"
65
+ ]);
66
+ export function validateOptions(value: unknown): PlaybookRuntimeOptions {
67
+ const captured = snapshotJsonValue(value === undefined ? {} : value, "DEV runtime options");
68
+ if (captured === null || typeof captured !== 'object' || Array.isArray(captured)) {
69
+ throw new TypeError("DEV runtime options must be an object");
107
70
  }
108
- const record = captured as Readonly<Record<string, JsonValue>>;
109
- for (const [key, option] of Object.entries(record)) {
110
- if (!OPTION_KEYS.has(key)) {
111
- throw new TypeError(`DEV runtime options.${key} is not declared`);
112
- }
113
- if (typeof option !== 'string') {
114
- throw new TypeError(`DEV runtime options.${key} must be a string`);
71
+ const fields = captured as Readonly<Record<string, unknown>>;
72
+ for (const key of Object.keys(captured)) {
73
+ if (!Object.hasOwn(OPTION_SCHEMA, key)) throw new TypeError("DEV runtime options." + key + ' is not declared');
74
+ }
75
+ for (const [key, schema] of Object.entries(OPTION_SCHEMA) as [string, { type: string; required: boolean }][]) {
76
+ if (!Object.hasOwn(captured, key)) {
77
+ if (schema.required) throw new TypeError("DEV runtime options." + key + ' is required');
78
+ } else if (typeof fields[key] !== schema.type || (schema.type === 'number' && !Number.isFinite(fields[key]))) {
79
+ throw new TypeError("DEV runtime options." + key + ' must be a ' + schema.type);
115
80
  }
116
81
  }
117
- return captured as unknown as DevPlaybookOptions;
82
+ return captured as unknown as PlaybookRuntimeOptions;
118
83
  }
119
-
120
- function placeholderField(token: string): string {
121
- if (token === '#') return 'irNumber';
122
- return token.replace(/-([A-Za-z0-9_$])/g, (_match, next: string) =>
123
- next.toUpperCase(),
124
- );
125
- }
126
-
127
- function quotedContinuation(value: string): string {
128
- return value.replaceAll('\n', '\n> ');
129
- }
130
-
131
- /**
132
- * Preserve authored Markdown quote markers around every line of relayed
133
- * runtime text. The generic composer preserves the marker itself; DEV's
134
- * override additionally keeps a multiline value inside that quote and drops
135
- * the optional relays that have no value yet.
136
- */
137
- function composePlayerPrompt(input: PlayerInput, resuming = false): string {
138
- const fields = input as unknown as Record<string, unknown>;
139
- const template = input.prompt
140
- .split('\n')
141
- .filter(
142
- (line) =>
143
- !(
144
- line === '> Prior discussion: <discussion-context>' &&
145
- input.discussionContext.length === 0
146
- ) &&
147
- !(line === '> Run results: <run-results>' && input.runResults.length === 0),
148
- )
149
- .join('\n');
150
- const body = template.replace(
151
- PLACEHOLDER,
152
- (match: string, token: string, offset: number, source: string) => {
153
- const value = fields[placeholderField(token)];
84
+ function renderPlayerPrompt(input: SourcePlayerInput, promptIdentity: XStatePromptIdentity, resuming = false): string {
85
+ const fields = input as unknown as Readonly<Record<string, unknown>>;
86
+ const mapping: Readonly<Record<string, string>> = {};
87
+ const identities: Readonly<Record<string, string>> = {};
88
+ const omitted = new Set<string>(["> Prior discussion: <discussion-context>","> Run results: <run-results>"]);
89
+ const fieldFor = (token: string): string => Object.hasOwn(mapping, token) ? mapping[token]! : (token === '#' ? 'irNumber' : token.replace(/-([A-Za-z0-9_$])/g, (_match: string, next: string) => next.toUpperCase()));
90
+ const parts = input.prompt.split(/(\r?\n)/);
91
+ let body = '';
92
+ for (let index = 0; index < parts.length; index += 2) {
93
+ const line = parts[index]!;
94
+ if (omitted.has(line)) {
95
+ const token = /<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>$/.exec(line)![1]!;
96
+ if (fields[fieldFor(token)] === '') continue;
97
+ }
98
+ body += line.replace(/<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>/g, (match: string, token: string): string => {
99
+ const value = Object.hasOwn(identities, token) ? promptIdentity(identities[token]!) : fields[fieldFor(token)];
154
100
  if (typeof value !== 'string') return match;
155
- const lineStart = source.lastIndexOf('\n', offset - 1) + 1;
156
- const literal = source.slice(lineStart, offset);
157
- return literal.startsWith('> ') ? quotedContinuation(value) : value;
158
- },
159
- );
101
+ return line.startsWith('> ') ? value.replace(/\r?\n/g, (ending: string) => ending + '> ') : value;
102
+ }) + (parts[index + 1] ?? '');
103
+ }
160
104
  return composePlayerContinuation(input, body, resuming);
161
105
  }
162
-
106
+ const composePlayerPrompt = (input: PlaybookPlayerInput, promptIdentity: XStatePromptIdentity, resuming?: boolean): string =>
107
+ renderPlayerPrompt(input as SourcePlayerInput, promptIdentity, resuming);
163
108
  const runtimeSpec = {
164
- label: 'DEV',
165
- // DR-022 / slc/link.md: the declaration carries the value current at link
166
- // time — a literal, never the loading engine's RUNTIME_ABI self-report,
167
- // which would follow whatever engine loads the module and make the
168
- // factory's skew check compare that engine with itself.
169
- compat: { artifactSchema: 3, runtimeAbi: 1 },
170
- snapshotOptions: snapshotDevOptions,
171
- entryEvent: {
172
- type: 'START_DEV',
173
- textField: 'developmentRequest',
174
- // `startDev` copies the entry text here, so the failure-state retry
175
- // reads it back from the persisted machine snapshot and survives a
176
- // continued session (DR-034).
177
- contextField: 'developmentRequest',
109
+ composePlayerPrompt,
110
+ ...{
111
+ "label": "DEV",
112
+ "compat": {
113
+ "artifactSchema": 3,
114
+ "runtimeAbi": 1
178
115
  },
179
- roleStates: {
180
- planAnalysis: {
181
- role: 'analyst',
182
- label: 'Analyst is choosing the development path.',
183
- },
116
+ "entryEvent": {
117
+ "type": "START_DEV",
118
+ "textField": "developmentRequest",
119
+ "contextField": "developmentRequest"
184
120
  },
185
- // DR-044: DEV owns no repository commit — every Analyst outcome is
186
- // governed with the `unchanged` repository disposition, so planning that
187
- // mutates the repository fails authority instead of being adopted.
188
- outcomeAuthority: {
189
- governedPlayerStates: {
190
- planAnalysis: {
191
- discussionComplete: {
192
- fields: {},
193
- repositoryDisposition: 'unchanged',
194
- },
195
- code: {
196
- fields: { planningResult: 'presentation' },
197
- repositoryDisposition: 'unchanged',
121
+ "bossEvents": [],
122
+ "roleStates": {
123
+ "planAnalysis": {
124
+ "role": "analyst",
125
+ "label": "Analyst chooses the development path in a short planning note."
126
+ }
127
+ },
128
+ "outcomeAuthority": {
129
+ "governedPlayerStates": {
130
+ "planAnalysis": {
131
+ "discussionComplete": {
132
+ "fields": {},
133
+ "repositoryDisposition": "unchanged"
198
134
  },
199
- decideThenCode: {
200
- fields: { planningResult: 'presentation' },
201
- repositoryDisposition: 'unchanged',
135
+ "code": {
136
+ "fields": {
137
+ "planningResult": "presentation"
138
+ },
139
+ "repositoryDisposition": "unchanged"
202
140
  },
203
- // DR-050: reading a GitHub issue during planning is not an effect, so
204
- // the two pull-request outcomes stay `unchanged` like the plain ones.
205
- codeViaPullRequest: {
206
- fields: { planningResult: 'presentation' },
207
- repositoryDisposition: 'unchanged',
141
+ "decideThenCode": {
142
+ "fields": {
143
+ "planningResult": "presentation"
144
+ },
145
+ "repositoryDisposition": "unchanged"
208
146
  },
209
- decideThenCodeViaPullRequest: {
210
- fields: { planningResult: 'presentation' },
211
- repositoryDisposition: 'unchanged',
147
+ "codeViaPullRequest": {
148
+ "fields": {
149
+ "planningResult": "presentation"
150
+ },
151
+ "repositoryDisposition": "unchanged"
212
152
  },
213
- needsBossReply: {
214
- fields: { question: 'presentation' },
215
- repositoryDisposition: 'unchanged',
153
+ "decideThenCodeViaPullRequest": {
154
+ "fields": {
155
+ "planningResult": "presentation"
156
+ },
157
+ "repositoryDisposition": "unchanged"
216
158
  },
217
- },
218
- },
159
+ "needsBossReply": {
160
+ "fields": {
161
+ "question": "presentation"
162
+ },
163
+ "repositoryDisposition": "unchanged"
164
+ }
165
+ }
166
+ }
219
167
  },
220
- composePlayerPrompt: (input: PlaybookPlayerInput, _identity, resuming?: boolean) =>
221
- composePlayerPrompt(input as PlayerInput, resuming),
168
+ "placeholderFields": {},
169
+ "transitionEventFields": [
170
+ "developmentRequest",
171
+ "answer",
172
+ "questionId"
173
+ ],
174
+ "controlContextFields": []
175
+ },
176
+ snapshotOptions: validateOptions,
177
+ machineInput: (options: PlaybookRuntimeOptions) => Object.fromEntries(
178
+ Object.entries(INPUT_MAPPING).filter(([, key]) => options[key as keyof PlaybookRuntimeOptions] !== undefined)
179
+ .map(([field, key]) => [field, options[key as keyof PlaybookRuntimeOptions]]),
180
+ ),
222
181
  verbatimPayloadFields: VERBATIM_PAYLOAD_FIELDS,
223
- controlContextFields: [],
182
+ resumableStateIds: RESUMABLE_STATE_IDS,
224
183
  unfinishedFinalStateIds: UNFINISHED_FINAL_STATE_IDS,
225
- transitionEventFields: ['developmentRequest', 'answer', 'questionId'],
226
- } satisfies XStatePlaybookRuntimeSpecV3<DevPlaybookOptions>;
184
+ } satisfies XStatePlaybookRuntimeSpecV3<PlaybookRuntimeOptions>;
227
185
 
228
186
  export const _internal = {
229
- composePlayerPrompt: runtimeSpec.composePlayerPrompt,
230
- VERBATIM_PAYLOAD_FIELDS,
187
+ composePlayerPrompt,
188
+ RESUMABLE_STATE_IDS,
231
189
  UNFINISHED_FINAL_STATE_IDS,
190
+ VERBATIM_PAYLOAD_FIELDS,
232
191
  };
233
-
234
192
  const createPlaybookRuntime: XStatePlaybookRuntimeFactory<
235
- XStatePlaybookRuntimeConstruction<
236
- DevPlaybookOptions,
237
- DevPlaybookHostCapabilities
238
- >,
239
- 3
240
- > = createXStatePlaybookRuntime<
241
- DevPlaybookOptions,
242
- DevPlaybookHostCapabilities
243
- >(devMachine, runtimeSpec);
244
-
193
+ XStatePlaybookRuntimeConstruction<PlaybookRuntimeOptions, PlaybookHostCapabilities>, 3
194
+ > = createXStatePlaybookRuntime<PlaybookRuntimeOptions, PlaybookHostCapabilities>(machine, runtimeSpec);
245
195
  export default createPlaybookRuntime;
@@ -1,4 +1,5 @@
1
- import { type DevPlaybookHostCapabilities, type PlaybookRuntime } from './dev.playbook.js';
1
+ import type { PlaybookHostConstructionCapabilities } from '../code.playbook/playbook-captain.js';
2
+ import { type PlaybookHostCapabilities, type PlaybookRuntime } from './dev.playbook.js';
2
3
  export interface PlaybookSummaryPolicy {
3
4
  stateCountLabels: Readonly<Record<string, string>>;
4
5
  copyPasteGuardNames: readonly string[];
@@ -24,7 +25,7 @@ export interface DevPlaybookRegistryEntry {
24
25
  concurrentRoleSets: readonly [];
25
26
  summaryPolicy: PlaybookSummaryPolicy;
26
27
  validateOptions(optionSlice: unknown): DevOptions;
27
- createRuntime(options: DevOptions, hostCapabilities: DevPlaybookHostCapabilities): PlaybookRuntime;
28
+ createRuntime(options: DevOptions, hostCapabilities: PlaybookHostConstructionCapabilities & PlaybookHostCapabilities): PlaybookRuntime;
28
29
  }
29
30
  export declare const devStateCountLabels: {
30
31
  readonly planAnalysis: "planning round";
@@ -1,8 +1,9 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
3
3
 
4
+ import type { PlaybookHostConstructionCapabilities } from '../code.playbook/playbook-captain.js';
4
5
  import createPlaybookRuntime, {
5
- type DevPlaybookHostCapabilities,
6
+ type PlaybookHostCapabilities,
6
7
  type PlaybookRuntime,
7
8
  } from './dev.playbook.js';
8
9
 
@@ -33,9 +34,12 @@ export interface DevPlaybookRegistryEntry {
33
34
  concurrentRoleSets: readonly [];
34
35
  summaryPolicy: PlaybookSummaryPolicy;
35
36
  validateOptions(optionSlice: unknown): DevOptions;
37
+ // The linked module types live authority as opaque (link-materialization);
38
+ // the Captain entry binds its own construction capabilities here.
36
39
  createRuntime(
37
40
  options: DevOptions,
38
- hostCapabilities: DevPlaybookHostCapabilities,
41
+ hostCapabilities: PlaybookHostConstructionCapabilities &
42
+ PlaybookHostCapabilities,
39
43
  ): PlaybookRuntime;
40
44
  }
41
45