@sublang/playbook 5.0.0 → 7.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 (72) hide show
  1. package/README.md +22 -14
  2. package/docs/cli.md +138 -90
  3. package/docs/configuration.md +113 -29
  4. package/docs/embedding.md +24 -16
  5. package/package.json +42 -21
  6. package/reference/sdlc/captain.playbook/captain.playbook.js +2 -0
  7. package/reference/sdlc/captain.playbook/captain.playbook.ts +2 -0
  8. package/reference/sdlc/code.md +55 -97
  9. package/reference/sdlc/code.playbook/bin/launch-config.js +938 -0
  10. package/reference/sdlc/code.playbook/bin/playbook.js +145 -562
  11. package/reference/sdlc/code.playbook/bin/provision.js +84 -38
  12. package/reference/sdlc/code.playbook/bin/run.js +1171 -983
  13. package/reference/sdlc/code.playbook/bin/session-store.js +1169 -0
  14. package/reference/sdlc/code.playbook/code.fsm.d.ts +229 -94
  15. package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +26 -44
  16. package/reference/sdlc/code.playbook/code.fsm.introspect.js +61 -66
  17. package/reference/sdlc/code.playbook/code.fsm.introspect.ts +100 -149
  18. package/reference/sdlc/code.playbook/code.fsm.js +587 -1347
  19. package/reference/sdlc/code.playbook/code.fsm.ts +809 -1650
  20. package/reference/sdlc/code.playbook/code.gears.md +51 -263
  21. package/reference/sdlc/code.playbook/code.playbook.d.ts +8 -47
  22. package/reference/sdlc/code.playbook/code.playbook.js +69 -656
  23. package/reference/sdlc/code.playbook/code.playbook.ts +90 -867
  24. package/reference/sdlc/code.playbook/code.registry.d.ts +9 -25
  25. package/reference/sdlc/code.playbook/code.registry.js +20 -78
  26. package/reference/sdlc/code.playbook/code.registry.ts +58 -122
  27. package/reference/sdlc/code.playbook/playbook-captain.d.ts +70 -3
  28. package/reference/sdlc/code.playbook/playbook-captain.js +954 -80
  29. package/reference/sdlc/code.playbook/playbook-captain.ts +1408 -80
  30. package/reference/sdlc/code.playbook/playbook.config.template.yaml +37 -36
  31. package/reference/sdlc/decide.md +54 -0
  32. package/reference/sdlc/decide.playbook/decide.fsm.d.ts +261 -0
  33. package/reference/sdlc/decide.playbook/decide.fsm.js +894 -0
  34. package/reference/sdlc/decide.playbook/decide.fsm.ts +1152 -0
  35. package/reference/sdlc/decide.playbook/decide.gears.md +88 -0
  36. package/reference/sdlc/decide.playbook/decide.playbook.d.ts +67 -0
  37. package/reference/sdlc/{discuss.playbook/discuss.playbook.js → decide.playbook/decide.playbook.js} +545 -372
  38. package/reference/sdlc/{discuss.playbook/discuss.playbook.ts → decide.playbook/decide.playbook.ts} +665 -454
  39. package/reference/sdlc/decide.playbook/decide.registry.d.ts +41 -0
  40. package/reference/sdlc/decide.playbook/decide.registry.js +60 -0
  41. package/reference/sdlc/decide.playbook/decide.registry.ts +125 -0
  42. package/reference/sdlc/review.md +81 -0
  43. package/reference/sdlc/review.playbook/review.fsm.d.ts +183 -0
  44. package/reference/sdlc/review.playbook/review.fsm.js +524 -0
  45. package/reference/sdlc/review.playbook/review.fsm.ts +652 -0
  46. package/reference/sdlc/review.playbook/review.gears.md +112 -0
  47. package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -0
  48. package/reference/sdlc/review.playbook/review.playbook.js +112 -0
  49. package/reference/sdlc/review.playbook/review.playbook.ts +201 -0
  50. package/reference/sdlc/review.playbook/review.registry.d.ts +43 -0
  51. package/reference/sdlc/review.playbook/review.registry.js +73 -0
  52. package/reference/sdlc/review.playbook/review.registry.ts +138 -0
  53. package/slc/gears2fsm.md +13 -4
  54. package/slc/link.md +83 -14
  55. package/slc/text2gears.md +22 -2
  56. package/src/runtime.d.ts +21 -2
  57. package/src/runtime.ts +38 -6
  58. package/src/xstate-playbook-runtime.d.ts +9 -2
  59. package/src/xstate-playbook-runtime.js +319 -35
  60. package/src/xstate-playbook-runtime.ts +412 -41
  61. package/src/xstate-runtime.d.ts +19 -2
  62. package/src/xstate-runtime.js +384 -57
  63. package/src/xstate-runtime.ts +542 -71
  64. package/reference/sdlc/discuss.md +0 -93
  65. package/reference/sdlc/discuss.playbook/discuss.fsm.d.ts +0 -396
  66. package/reference/sdlc/discuss.playbook/discuss.fsm.js +0 -2067
  67. package/reference/sdlc/discuss.playbook/discuss.fsm.ts +0 -2465
  68. package/reference/sdlc/discuss.playbook/discuss.gears.md +0 -258
  69. package/reference/sdlc/discuss.playbook/discuss.playbook.d.ts +0 -113
  70. package/reference/sdlc/discuss.playbook/discuss.registry.d.ts +0 -58
  71. package/reference/sdlc/discuss.playbook/discuss.registry.js +0 -97
  72. package/reference/sdlc/discuss.playbook/discuss.registry.ts +0 -153
@@ -1,112 +1,247 @@
1
- type Player = 'Coder' | 'Reviewer' | 'Committer';
2
- type JumpableStateId = 'ready' | 'planAndImplement' | 'respondToReview' | 'continueIr' | 'summarizeSpecs' | 'reviewBossCommitSpecs' | 'reviewBossCommitCode' | 'reviewBossCommitMixed' | 'reviewIrTaskCommitSpecs' | 'reviewIrTaskCommitCode' | 'reviewIrTaskCommitMixed' | 'reviewChangesSpecs' | 'reviewChangesCode' | 'reviewChangesMixed' | 'reviewChangesAndChallengesSpecs' | 'reviewChangesAndChallengesCode' | 'reviewChangesAndChallengesMixed' | 'adjudicateChallenges' | 'commitCoderInitial' | 'commitJoint' | 'failed';
3
- type WorkflowKind = 'singleCommit' | 'iteration' | 'specSummary';
4
- type ChangeOrigin = 'bossIntent' | 'irTask';
5
- type ReviewSubject = 'commit' | 'changes';
6
- type AfterReview = 'continueIr' | 'summarizeSpecs' | 'done';
7
- type ResumableStateId = Exclude<JumpableStateId, 'ready' | 'failed'>;
8
- type PendingBossQuestion = {
9
- questionId: ResumableStateId;
10
- resumeStateId: ResumableStateId;
11
- sourceItem: string;
12
- player: Player;
13
- question: string;
1
+ export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
2
+ readonly [key: string]: JsonValue;
14
3
  };
15
- export type CaptainInput = {
16
- stateId: ResumableStateId;
17
- sourceItem: string;
18
- prompt: string;
19
- result: Record<string, string>;
20
- intent?: string;
21
- irNumber?: string;
22
- taskDescription?: string;
23
- reviews?: string;
24
- challenges?: string;
25
- coderPlayer?: string;
26
- reviewerPlayer?: string;
27
- committerPlayer?: string;
28
- pendingBossQuestion?: PendingBossQuestion;
29
- bossReply?: string;
4
+ export type CodeStateId = 'runFirstPhase' | 'reviewFirstCommit' | 'runIrTask' | 'reviewIrTask';
5
+ export type CodeSourceItem = 'CODE-1' | 'CODE-2' | 'CODE-3' | 'CODE-4';
6
+ export type CodePhase = 'direct' | 'ir-created' | 'ir-task-more' | 'ir-task-final';
7
+ export type PendingBossQuestion = {
8
+ readonly questionId: 'runFirstPhase' | 'runIrTask';
9
+ readonly resumeStateId: 'runFirstPhase' | 'runIrTask';
10
+ readonly sourceItem: 'CODE-1' | 'CODE-3';
11
+ readonly player: 'Coder';
12
+ readonly question: string;
30
13
  };
31
- export type PlayerInput = CaptainInput & {
32
- player: Player;
14
+ export type PlayerInput = {
15
+ readonly stateId: 'runFirstPhase' | 'runIrTask';
16
+ readonly player: 'Coder';
17
+ readonly sourceItem: 'CODE-1' | 'CODE-3';
18
+ readonly prompt: string;
19
+ readonly result: Readonly<Record<string, string>>;
20
+ readonly callerInput: string;
21
+ readonly runResults: string;
22
+ readonly coderPlayer: string;
23
+ readonly irNumber?: string;
24
+ readonly irTask?: string;
25
+ readonly pendingBossQuestion?: PendingBossQuestion;
26
+ readonly bossReply?: string;
33
27
  };
34
- export type CaptainOutput = {
35
- guard: string;
36
- irNumber?: string;
37
- taskDescription?: string;
38
- reviews?: string;
39
- challenges?: string;
40
- summary?: string;
41
- question?: string;
42
- [k: string]: unknown;
28
+ export type PlayerOutput = {
29
+ readonly guard: 'directCommit';
30
+ readonly coderOutput: string;
31
+ readonly latestCommit: string;
32
+ } | {
33
+ readonly guard: 'irCommit';
34
+ readonly coderOutput: string;
35
+ readonly latestCommit: string;
36
+ readonly irNumber: string;
37
+ readonly irTask: string;
38
+ } | {
39
+ readonly guard: 'moreTasks';
40
+ readonly coderOutput: string;
41
+ readonly latestCommit: string;
42
+ readonly irTask: string;
43
+ } | {
44
+ readonly guard: 'finalTask';
45
+ readonly coderOutput: string;
46
+ readonly latestCommit: string;
47
+ } | {
48
+ readonly guard: 'needsBossReply';
49
+ readonly question: string;
50
+ };
51
+ export type PlaybookInput = {
52
+ readonly stateId: 'reviewFirstCommit' | 'reviewIrTask';
53
+ readonly sourceItem: 'CODE-2' | 'CODE-4';
54
+ readonly playbookId: 'review';
55
+ readonly text: string;
56
+ };
57
+ export type ReviewOutput = {
58
+ readonly approvedCommit: 'latest';
59
+ readonly noUnsettledFindings: true;
60
+ };
61
+ export type CompactError = {
62
+ readonly name: string;
63
+ readonly message: string;
64
+ };
65
+ export type CodePlaybookOutput = {
66
+ readonly status: 'complete';
67
+ /** Exact identity of the latest CODE-owned commit. */
68
+ readonly lastCodeCommit: string;
69
+ /** Exact Coder final text produced after that commit. */
70
+ readonly lastCodeOutput: string;
71
+ } | {
72
+ readonly status: 'review-failed';
73
+ /** Exact identity of the latest CODE-owned commit. */
74
+ readonly lastCodeCommit: string;
75
+ /** Exact Coder final text produced after that commit. */
76
+ readonly lastCodeOutput: string;
77
+ readonly error: CompactError;
43
78
  };
44
- export type PlayerOutput = CaptainOutput;
45
79
  export type CodingInput = {
46
- intent?: string;
47
- irNumber?: string;
48
- coderPlayer?: string;
49
- reviewerPlayer?: string;
50
- committerPlayer?: string;
80
+ readonly coderPlayer?: string;
81
+ readonly runResults?: string;
51
82
  };
52
- export type CodingContext = CodingInput & {
53
- workflow?: WorkflowKind;
54
- changeOrigin?: ChangeOrigin;
55
- reviewSubject?: ReviewSubject;
56
- afterReview?: AfterReview;
57
- taskDescription?: string;
58
- reviews?: string;
59
- challenges?: string;
60
- lastResult?: CaptainOutput;
61
- lastError?: unknown;
62
- pendingBossQuestion?: PendingBossQuestion;
63
- bossReply?: string;
83
+ export type CodingContext = {
84
+ readonly coderPlayer: string;
85
+ readonly runResults: string;
86
+ readonly callerInput?: string;
87
+ readonly coderOutput?: string;
88
+ readonly latestCommit?: string;
89
+ readonly irNumber?: string;
90
+ readonly irTask?: string;
91
+ readonly nextIrTask?: string;
92
+ readonly phase?: CodePhase;
93
+ readonly completion?: 'complete' | 'review-failed';
94
+ readonly reviewError?: CompactError;
95
+ readonly lastError?: unknown;
96
+ readonly pendingBossQuestion?: PendingBossQuestion;
97
+ readonly bossReply?: string;
64
98
  };
65
99
  export type CodingEvent = {
66
- type: 'START_CODING';
67
- intent: string;
100
+ readonly type: 'START_CODE';
101
+ readonly callerInput: string;
102
+ } | {
103
+ readonly type: 'BOSS_REPLY';
104
+ readonly answer: string;
105
+ readonly questionId?: 'runFirstPhase' | 'runIrTask';
106
+ };
107
+ export declare const codingMachine: import("xstate").StateMachine<CodingContext, {
108
+ readonly type: "START_CODE";
109
+ readonly callerInput: string;
68
110
  } | {
69
- type: 'CONTINUE_IR';
70
- irNumber: string;
111
+ readonly type: "BOSS_REPLY";
112
+ readonly answer: string;
113
+ readonly questionId?: "runFirstPhase" | "runIrTask";
114
+ }, {
115
+ [x: string]: import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<JsonValue | undefined, PlaybookInput, import("xstate").EventObject>> | import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<PlayerOutput, PlayerInput, import("xstate").EventObject>> | undefined;
116
+ }, {
117
+ src: "playbook";
118
+ logic: import("xstate").PromiseActorLogic<JsonValue | undefined, PlaybookInput, import("xstate").EventObject>;
119
+ id: string | undefined;
71
120
  } | {
72
- type: 'SUMMARIZE_IR';
73
- irNumber: string;
121
+ src: "player";
122
+ logic: import("xstate").PromiseActorLogic<PlayerOutput, PlayerInput, import("xstate").EventObject>;
123
+ id: string | undefined;
124
+ }, {
125
+ type: "rememberActorError";
126
+ params: import("xstate").NonReducibleUnknown;
74
127
  } | {
75
- type: 'BOSS_INTERRUPT';
76
- targetId: JumpableStateId;
77
- intent?: string;
78
- irNumber?: string;
128
+ type: "startCoding";
129
+ params: import("xstate").NonReducibleUnknown;
79
130
  } | {
80
- type: 'BOSS_REPLY';
81
- answer: string;
82
- questionId?: ResumableStateId;
83
- };
84
- export declare const codingMachine: import("xstate").StateMachine<CodingContext, {
85
- type: "START_CODING";
86
- intent: string;
131
+ type: "rememberDirectCommit";
132
+ params: import("xstate").NonReducibleUnknown;
87
133
  } | {
88
- type: "CONTINUE_IR";
89
- irNumber: string;
134
+ type: "rememberIrCommit";
135
+ params: import("xstate").NonReducibleUnknown;
90
136
  } | {
91
- type: "SUMMARIZE_IR";
92
- irNumber: string;
137
+ type: "rememberMoreTasks";
138
+ params: import("xstate").NonReducibleUnknown;
93
139
  } | {
94
- type: "BOSS_INTERRUPT";
95
- targetId: JumpableStateId;
96
- intent?: string;
97
- irNumber?: string;
140
+ type: "rememberFinalTask";
141
+ params: import("xstate").NonReducibleUnknown;
98
142
  } | {
99
- type: "BOSS_REPLY";
100
- answer: string;
101
- questionId?: ResumableStateId;
102
- }, {
103
- [x: string]: import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<CaptainOutput, PlayerInput, import("xstate").EventObject>> | undefined;
143
+ type: "advanceToNextIrTask";
144
+ params: import("xstate").NonReducibleUnknown;
145
+ } | {
146
+ type: "rememberPendingQuestion";
147
+ params: import("xstate").NonReducibleUnknown;
148
+ } | {
149
+ type: "rememberBossReply";
150
+ params: import("xstate").NonReducibleUnknown;
151
+ } | {
152
+ type: "rememberEmptyBossReplyError";
153
+ params: import("xstate").NonReducibleUnknown;
154
+ } | {
155
+ type: "completeSuccessfully";
156
+ params: import("xstate").NonReducibleUnknown;
157
+ } | {
158
+ type: "completeWithReviewFailure";
159
+ params: import("xstate").NonReducibleUnknown;
160
+ } | {
161
+ type: "completeWithInvalidReviewOutput";
162
+ params: import("xstate").NonReducibleUnknown;
163
+ } | {
164
+ type: "rememberMalformedPlayerOutput";
165
+ params: import("xstate").NonReducibleUnknown;
104
166
  }, {
105
- src: "player";
106
- logic: import("xstate").PromiseActorLogic<CaptainOutput, PlayerInput, import("xstate").EventObject>;
107
- id: string | undefined;
108
- }, never, never, never, {}, string, CodingInput, import("xstate").NonReducibleUnknown, import("xstate").EventObject, import("xstate").MetaObject, {
109
- states?: {} | undefined;
110
- id?: string | undefined | undefined;
167
+ type: "needsBossReply";
168
+ params: unknown;
169
+ } | {
170
+ type: "isDirectCommit";
171
+ params: unknown;
172
+ } | {
173
+ type: "isIrCommit";
174
+ params: unknown;
175
+ } | {
176
+ type: "isMoreTasks";
177
+ params: unknown;
178
+ } | {
179
+ type: "isFinalTask";
180
+ params: unknown;
181
+ } | {
182
+ type: "authoredReviewFailure";
183
+ params: unknown;
184
+ } | {
185
+ type: "reviewApprovedDirect";
186
+ params: unknown;
187
+ } | {
188
+ type: "reviewApprovedIrCreated";
189
+ params: unknown;
190
+ } | {
191
+ type: "reviewApprovedMoreTasks";
192
+ params: unknown;
193
+ } | {
194
+ type: "reviewApprovedFinalTask";
195
+ params: unknown;
196
+ } | {
197
+ type: "emptyBossReply";
198
+ params: unknown;
199
+ } | {
200
+ type: "resumesFirstPhase";
201
+ params: unknown;
202
+ } | {
203
+ type: "resumesIrTask";
204
+ params: unknown;
205
+ }, never, "done" | "failed" | "awaitBossReply" | "ready" | "runFirstPhase" | "reviewFirstCommit" | "runIrTask" | "reviewIrTask", string, CodingInput, {
206
+ readonly status: "complete";
207
+ /** Exact identity of the latest CODE-owned commit. */
208
+ readonly lastCodeCommit: string;
209
+ /** Exact Coder final text produced after that commit. */
210
+ readonly lastCodeOutput: string;
211
+ } | {
212
+ readonly status: "review-failed";
213
+ /** Exact identity of the latest CODE-owned commit. */
214
+ readonly lastCodeCommit: string;
215
+ /** Exact Coder final text produced after that commit. */
216
+ readonly lastCodeOutput: string;
217
+ readonly error: CompactError;
218
+ }, import("xstate").EventObject, import("xstate").MetaObject, {
219
+ id: "code";
220
+ states: {
221
+ readonly ready: {
222
+ id: "ready";
223
+ };
224
+ readonly runFirstPhase: {
225
+ id: "runFirstPhase";
226
+ };
227
+ readonly reviewFirstCommit: {
228
+ id: "reviewFirstCommit";
229
+ };
230
+ readonly runIrTask: {
231
+ id: "runIrTask";
232
+ };
233
+ readonly reviewIrTask: {
234
+ id: "reviewIrTask";
235
+ };
236
+ readonly awaitBossReply: {
237
+ id: "awaitBossReply";
238
+ };
239
+ readonly failed: {
240
+ id: "failed";
241
+ };
242
+ readonly done: {
243
+ id: "done";
244
+ };
245
+ };
111
246
  }>;
112
- export {};
247
+ export default codingMachine;
@@ -1,54 +1,36 @@
1
- import type { CodingContext, PlayerInput, codingMachine } from './code.fsm.js';
2
- export interface CaptainStateInfo {
3
- readonly stateId: string;
4
- readonly sourceItem: string;
5
- readonly getInput: (context: Partial<CodingContext>) => PlayerInput;
6
- readonly transitions: ReadonlyArray<CaptainTransition>;
7
- }
8
- export interface CaptainTransition {
1
+ import type { CodingContext, PlaybookInput, PlayerInput, codingMachine } from './code.fsm.js';
2
+ export type TransitionGuard = (args: {
3
+ context: CodingContext;
4
+ event: unknown;
5
+ }) => boolean;
6
+ export interface InvokingTransition {
9
7
  readonly index: number;
10
8
  readonly target: string;
11
- readonly guard: TransitionGuard;
9
+ readonly guard?: TransitionGuard;
12
10
  readonly actions: unknown;
13
11
  }
14
- export interface AwaitBossReplyInfo {
12
+ export interface PlayerStateInfo {
15
13
  readonly stateId: string;
16
- readonly bossReplyTransitions: ReadonlyArray<BossReplyTransition>;
17
- readonly transitions: ReadonlyArray<AwaitBossReplyTransition>;
14
+ readonly sourceItem: string;
15
+ readonly getInput: (context: CodingContext) => PlayerInput;
16
+ readonly transitions: readonly InvokingTransition[];
18
17
  }
19
- export interface BossReplyTransition {
20
- readonly index: number;
21
- readonly target: string;
22
- readonly guard: TransitionGuard;
23
- readonly actions: unknown;
18
+ export interface NestedPlaybookStateInfo {
19
+ readonly stateId: string;
20
+ readonly sourceItem: string;
21
+ readonly getInput: (context: CodingContext) => PlaybookInput;
22
+ readonly transitions: readonly InvokingTransition[];
24
23
  }
25
- export interface AwaitBossReplyTransition {
26
- readonly eventType: string;
27
- readonly index: number;
28
- readonly target: string;
29
- readonly guard: TransitionGuard;
30
- readonly actions: unknown;
24
+ export interface AwaitBossReplyInfo {
25
+ readonly stateId: 'awaitBossReply';
26
+ readonly bossReplyTransitions: readonly InvokingTransition[];
31
27
  }
32
- export type TransitionGuard = (args: {
33
- context: CodingContext;
34
- event: unknown;
35
- }) => boolean;
36
- export interface RootEventTable {
37
- readonly startCoding: {
38
- readonly target: string;
39
- };
40
- readonly continueIr: {
41
- readonly target: string;
42
- };
43
- readonly summarizeIr: {
28
+ export declare function enumeratePlayerStates(machine: typeof codingMachine): readonly PlayerStateInfo[];
29
+ export declare const enumerateCaptainStates: typeof enumeratePlayerStates;
30
+ export declare function enumerateNestedPlaybookStates(machine: typeof codingMachine): readonly NestedPlaybookStateInfo[];
31
+ export declare function enumerateAwaitBossReply(machine: typeof codingMachine): AwaitBossReplyInfo;
32
+ export declare function enumerateRootEvents(machine: typeof codingMachine): {
33
+ readonly startCode: {
44
34
  readonly target: string;
45
35
  };
46
- readonly bossInterruptTargets: ReadonlyArray<string>;
47
- readonly bossInterruptTargetDescriptions: ReadonlyArray<{
48
- readonly stateId: string;
49
- readonly description: string;
50
- }>;
51
- }
52
- export declare function enumerateCaptainStates(machine: typeof codingMachine): readonly CaptainStateInfo[];
53
- export declare function enumerateRootEvents(machine: typeof codingMachine): RootEventTable;
54
- export declare function enumerateAwaitBossReply(machine: typeof codingMachine): AwaitBossReplyInfo;
36
+ };
@@ -1,77 +1,72 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
3
- export function enumerateCaptainStates(machine) {
4
- const states = getRawConfig(machine).states ?? {};
5
- const out = [];
6
- for (const [stateId, def] of Object.entries(states)) {
7
- const invoke = def.invoke;
8
- if (!invoke || invoke.src !== 'player' || typeof invoke.input !== 'function') {
9
- continue;
10
- }
11
- const inputFn = invoke.input;
12
- const getInput = (context) => inputFn({ context });
13
- const probe = getInput({});
14
- const transitions = toArmArray(invoke.onDone).map((arm, index) => ({
15
- index,
16
- target: stripIdPrefix(String(arm.target ?? '')),
17
- guard: arm.guard ?? alwaysTrue,
18
- actions: arm.actions,
19
- }));
20
- out.push({
21
- stateId,
22
- sourceItem: probe.sourceItem,
23
- getInput,
24
- transitions,
25
- });
26
- }
27
- return out;
3
+ function rawConfig(machine) {
4
+ return machine.config;
28
5
  }
29
- export function enumerateRootEvents(machine) {
30
- const cfg = getRawConfig(machine);
31
- const readyOn = (cfg.states?.ready?.on ?? {});
32
- const rootOn = (cfg.on ?? {});
33
- const bossInterruptTargets = toArmArray(rootOn.BOSS_INTERRUPT).map((arm) => stripIdPrefix(String(arm.target ?? '')));
34
- return {
35
- startCoding: { target: stripIdPrefix(String(readyOn.START_CODING?.target ?? '')) },
36
- continueIr: { target: stripIdPrefix(String(readyOn.CONTINUE_IR?.target ?? '')) },
37
- summarizeIr: { target: stripIdPrefix(String(readyOn.SUMMARIZE_IR?.target ?? '')) },
38
- bossInterruptTargets,
39
- bossInterruptTargetDescriptions: bossInterruptTargets.map((stateId) => {
40
- const description = cfg.states?.[stateId]?.description;
41
- return {
42
- stateId,
43
- description: typeof description === 'string' ? description : '',
44
- };
45
- }),
46
- };
6
+ function arms(value) {
7
+ if (value === undefined || value === null)
8
+ return [];
9
+ return (Array.isArray(value) ? value : [value]);
47
10
  }
48
- export function enumerateAwaitBossReply(machine) {
49
- const stateId = 'awaitBossReply';
50
- const awaitOn = getRawConfig(machine).states?.[stateId]?.on ?? {};
51
- const transitions = Object.entries(awaitOn).flatMap(([eventType, value]) => toArmArray(value).map((arm, index) => ({
52
- eventType,
53
- index,
54
- target: stripIdPrefix(String(arm.target ?? '')),
55
- guard: arm.guard ?? alwaysTrue,
56
- actions: arm.actions,
57
- })));
58
- const bossReplyTransitions = toArmArray(awaitOn.BOSS_REPLY).map((arm, index) => ({
11
+ function targetName(target) {
12
+ const value = String(target ?? '');
13
+ return value.startsWith('#') ? value.slice(1) : value;
14
+ }
15
+ function transitions(value) {
16
+ return arms(value).map((arm, index) => ({
59
17
  index,
60
- target: stripIdPrefix(String(arm.target ?? '')),
61
- guard: arm.guard ?? alwaysTrue,
18
+ target: targetName(arm.target),
19
+ ...(arm.guard === undefined ? {} : { guard: arm.guard }),
62
20
  actions: arm.actions,
63
21
  }));
64
- return { stateId, bossReplyTransitions, transitions };
65
22
  }
66
- function getRawConfig(machine) {
67
- return machine.config;
23
+ export function enumeratePlayerStates(machine) {
24
+ const states = rawConfig(machine).states ?? {};
25
+ return Object.entries(states).flatMap(([stateId, state]) => {
26
+ const invoke = state.invoke;
27
+ if (invoke?.src !== 'player' || invoke.input === undefined)
28
+ return [];
29
+ const getInput = (context) => invoke.input?.({ context });
30
+ const input = getInput({ coderPlayer: 'Coder', runResults: '' });
31
+ return [
32
+ {
33
+ stateId,
34
+ sourceItem: input.sourceItem,
35
+ getInput,
36
+ transitions: transitions(invoke.onDone),
37
+ },
38
+ ];
39
+ });
68
40
  }
69
- function toArmArray(value) {
70
- if (value === undefined || value === null)
71
- return [];
72
- return (Array.isArray(value) ? value : [value]);
41
+ // Backward-compatible internal name retained for repository conformance tools.
42
+ export const enumerateCaptainStates = enumeratePlayerStates;
43
+ export function enumerateNestedPlaybookStates(machine) {
44
+ const states = rawConfig(machine).states ?? {};
45
+ return Object.entries(states).flatMap(([stateId, state]) => {
46
+ const invoke = state.invoke;
47
+ if (invoke?.src !== 'playbook' || invoke.input === undefined)
48
+ return [];
49
+ const getInput = (context) => invoke.input?.({ context });
50
+ const input = getInput({ coderPlayer: 'Coder', runResults: '' });
51
+ return [
52
+ {
53
+ stateId,
54
+ sourceItem: input.sourceItem,
55
+ getInput,
56
+ transitions: transitions(invoke.onDone),
57
+ },
58
+ ];
59
+ });
73
60
  }
74
- function stripIdPrefix(target) {
75
- return target.startsWith('#') ? target.slice(1) : target;
61
+ export function enumerateAwaitBossReply(machine) {
62
+ const on = rawConfig(machine).states?.awaitBossReply?.on ?? {};
63
+ return {
64
+ stateId: 'awaitBossReply',
65
+ bossReplyTransitions: transitions(on.BOSS_REPLY),
66
+ };
67
+ }
68
+ export function enumerateRootEvents(machine) {
69
+ const on = rawConfig(machine).states?.ready?.on ?? {};
70
+ const start = arms(on.START_CODE)[0];
71
+ return { startCode: { target: targetName(start?.target) } };
76
72
  }
77
- const alwaysTrue = () => true;