@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,10 +1,10 @@
1
1
  # SPDX-License-Identifier: Apache-2.0
2
2
  # SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
3
3
 
4
- # Generic `playbook` launcher config.
4
+ # Shared `playbook` and `playbook run` launcher config.
5
5
  # Top-level host fields only — no `config:` wrapper, no top-level `players`.
6
6
  # The launcher injects captain.from and the namespaced <id>-<role> host
7
- # players, then launches cligent's tmux-play under the Playbook Captain shell.
7
+ # players, then hosts the same Playbook Captain shell interactively or headlessly.
8
8
 
9
9
  # Every agent — the Captain and each playbook role — carries its own
10
10
  # settings inline: an adapter shorthand (claude, codex) or a block with
@@ -20,7 +20,7 @@
20
20
  # Every seeded agent runs in cligent's protected auto mode
21
21
  # (permissions.mode: auto): claude maps it to permissionMode auto, codex to
22
22
  # on-request + auto_review. Codex roles also grant writablePaths: ['.git']
23
- # so commit turns can write git metadata under the codex sandbox.
23
+ # so they can inspect and work with repository metadata under the sandbox.
24
24
 
25
25
  # The Captain/Judge agent.
26
26
  # Captain routing/adjudication calls run tool-free. Claude enforces that at
@@ -33,18 +33,33 @@ captain:
33
33
  permissions:
34
34
  mode: auto
35
35
 
36
- # Host notifications. Omitting turn_aborted resolves it to off.
36
+ # Interactive host notifications. Headless runs ignore presentation fields.
37
+ # Omitting turn_aborted resolves it to off.
37
38
  notifications:
38
39
  player_finished: bell
39
40
  turn_finished: desktop
40
41
 
41
42
  # Enabled playbooks. Each is loaded from its explicit `from` module; the
42
43
  # `<id>` key must equal that module's manifest id. `from`, `command`, and
43
- # `players` are launcher-owned; every other key (e.g. CODE's `committer`)
44
- # is that playbook's option slice.
44
+ # `players` are launcher-owned; every other key is that playbook's option
45
+ # slice.
46
+ #
47
+ # Nested calls map roles by exact id. CODE and DECIDE call REVIEW with the
48
+ # same `coder` and `reviewer` ids, so those child roles continue the nearest
49
+ # ancestor sessions. A standalone REVIEW uses its own bindings below.
45
50
  playbooks:
46
51
  code:
47
52
  from: "@sublang/playbook/code/registry"
53
+ players:
54
+ coder:
55
+ adapter: claude
56
+ model: claude-opus-4-8[1m]
57
+ effort: xhigh
58
+ permissions:
59
+ mode: auto
60
+
61
+ review:
62
+ from: "@sublang/playbook/review/registry"
48
63
  players:
49
64
  coder:
50
65
  adapter: claude
@@ -59,34 +74,20 @@ playbooks:
59
74
  permissions:
60
75
  mode: auto
61
76
  writablePaths: ['.git']
62
- committer: coder
63
-
64
- # The DISCUSS playbook: two agents converge on spec items or decision
65
- # records. `committer` picks which player runs Committer commits
66
- # (default: host).
67
- # discuss:
68
- # from: "@sublang/playbook/discuss/registry"
69
- # players:
70
- # host:
71
- # adapter: claude
72
- # model: claude-opus-4-8
73
- # permissions:
74
- # mode: auto
75
- # participant:
76
- # adapter: codex
77
- # model: gpt-5.5
78
- # permissions:
79
- # mode: auto
80
- # writablePaths: ['.git']
81
- # committer: host
82
77
 
83
- # Non-interactive `playbook run` defaults (optional). Each value is an
84
- # agent string <adapter>[:<model>][@<effort>]; `player` is the catch-all
85
- # for any required role without its own `players.<role>` entry, across
86
- # every playbook. Flags override per role (--player / --captain), and
87
- # `playbook run resume` keeps the lineup stored with the parked session.
88
- #run:
89
- # captain: claude:claude-opus-4-8@high
90
- # player: claude:claude-opus-4-8@high
91
- # players:
92
- # coder: claude:claude-opus-4-8[1m]@xhigh
78
+ decide:
79
+ from: "@sublang/playbook/decide/registry"
80
+ players:
81
+ coder:
82
+ adapter: claude
83
+ model: claude-opus-4-8[1m]
84
+ effort: xhigh
85
+ permissions:
86
+ mode: auto
87
+ reviewer:
88
+ adapter: codex
89
+ model: gpt-5.5
90
+ effort: xhigh
91
+ permissions:
92
+ mode: auto
93
+ writablePaths: ['.git']
@@ -0,0 +1,54 @@
1
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
2
+ <!-- SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai> -->
3
+ <!-- AI agents: do not edit this file without human approval. -->
4
+
5
+ # Decide
6
+
7
+ Players:
8
+
9
+ - Coder
10
+ - Reviewer
11
+
12
+ The caller supplies the topic including any specific context.
13
+
14
+ When the caller gives a topic, Captain shall relay the complete topic in quotes (`>`) to Coder and Reviewer concurrently and independently.
15
+ Captain shall not wait for either proposal before requesting the other.
16
+ Captain shall give each player the following instruction:
17
+
18
+ ```markdown
19
+ Assess whether the topic is better expressed as a few spec items under @specs/packages/ or requires one or more DRs under @specs/decisions/.
20
+ Propose your design.
21
+ Keep your proposal coherent, focused, and concise.
22
+ Consult @specs/map.md for relevant context and @specs/meta.md for spec requirements, if needed.
23
+ Do not change any files.
24
+ ```
25
+
26
+ Neither player shall receive the other's proposal until both proposals are complete and Coder has committed Coder's own proposal.
27
+ A Boss interrupt during the parallel proposal pair shall restart the whole pair so both players receive the same new topic and remain independent.
28
+
29
+ When both proposals are complete, Captain shall then give Coder the following instruction:
30
+
31
+ ```markdown
32
+ Turn your proposal into the necessary spec items or DRs.
33
+ Follow @specs/meta.md and update @specs/map.md when needed.
34
+ Do not inspect or incorporate Reviewer's proposal before this commit.
35
+ Do not change code or implement the proposal.
36
+
37
+ Commit the result as one new commit, following @specs/packages/git.md.
38
+ Make the commit message explain concisely what changed and why.
39
+ Report it as exactly one final-response line beginning `Commit: `, followed only by the exact commit identity.
40
+ Coder is <coder-llm>; format the model token in conventional human form.
41
+ ```
42
+
43
+ After Coder commits, Captain shall call playbook `review`:
44
+
45
+ > Review the latest commit as a spec-design change against the initial intent.
46
+ > Compare it with your independent proposal and take the best of both.
47
+ > Make your suggestions.
48
+ >
49
+ > Initial intent: \<caller-topic\>.
50
+ > Coder's independent proposal: \<coder-proposal\>.
51
+
52
+ `decide` is complete when `review` returns the approved latest commit and the fact that no unsettled findings remain.
53
+ When `review` returns an authored abort or failure, or a terminal result that does not prove exact approval, `decide` shall report the failure and the last `decide`-owned commit to its caller.
54
+ When the nested `review` call fails outside that authored result contract, `decide` shall park as failed and retain the control-plane error instead of reporting an authored review outcome.
@@ -0,0 +1,261 @@
1
+ export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
2
+ readonly [key: string]: JsonValue;
3
+ };
4
+ type Player = 'Coder' | 'Reviewer';
5
+ type JumpableStateId = 'independentProposals';
6
+ type ResumableStateId = 'askCoderProposal' | 'askReviewerProposal' | 'commitCoderProposal';
7
+ export interface PendingBossQuestion {
8
+ questionId: ResumableStateId;
9
+ resumeStateId: ResumableStateId;
10
+ sourceItem: string;
11
+ player: Player;
12
+ question: string;
13
+ }
14
+ type PendingBossQuestions = Partial<Record<ResumableStateId, PendingBossQuestion>>;
15
+ type BossReplies = Partial<Record<ResumableStateId, string>>;
16
+ type PendingBossQuestionParams = Omit<PendingBossQuestion, 'questionId'>;
17
+ export interface ReviewSuccessOutput {
18
+ approvedCommit: 'latest';
19
+ noUnsettledFindings: true;
20
+ }
21
+ export interface DecideFailureOutput {
22
+ lastDecideCommit: string;
23
+ noUnsettledFindings: false;
24
+ reviewStatus: 'aborted' | 'error';
25
+ error?: {
26
+ name: string;
27
+ message: string;
28
+ };
29
+ }
30
+ export type DecideOutput = ReviewSuccessOutput | DecideFailureOutput;
31
+ interface ChildFailure {
32
+ status: 'aborted' | 'error';
33
+ playbookId: 'review';
34
+ error?: {
35
+ name: string;
36
+ message: string;
37
+ };
38
+ }
39
+ export interface DecideContext {
40
+ coderLlm: string;
41
+ callerTopic?: string;
42
+ coderProposal?: string;
43
+ reviewerProposal?: string;
44
+ latestCommit?: string;
45
+ reviewResult?: ReviewSuccessOutput;
46
+ reviewFailure?: ChildFailure;
47
+ lastResult?: PlayerOutput;
48
+ lastError?: unknown;
49
+ pendingBossQuestions?: PendingBossQuestions;
50
+ bossReplies?: BossReplies;
51
+ stagedCoderResult?: PlayerOutput;
52
+ stagedReviewerResult?: PlayerOutput;
53
+ }
54
+ export type DecideEvent = {
55
+ type: 'START_DECIDE';
56
+ callerTopic: string;
57
+ } | {
58
+ type: 'BOSS_INTERRUPT';
59
+ targetId: JumpableStateId;
60
+ bossIntent: string;
61
+ } | {
62
+ type: 'BOSS_REPLY';
63
+ questionId?: ResumableStateId;
64
+ answer: string;
65
+ };
66
+ export interface DecideInput {
67
+ coderLlm: string;
68
+ }
69
+ export interface PlayerInput {
70
+ stateId: ResumableStateId;
71
+ sourceItem: string;
72
+ prompt: string;
73
+ result: Record<string, string>;
74
+ player: Player;
75
+ callerTopic?: string;
76
+ coderLlm?: string;
77
+ pendingBossQuestion?: PendingBossQuestion;
78
+ bossReply?: string;
79
+ }
80
+ type AdditionalPlayerFields = {
81
+ coderProposal?: string;
82
+ reviewerProposal?: string;
83
+ coderOutput?: string;
84
+ latestCommit?: string;
85
+ question?: string;
86
+ readonly [key: string]: unknown;
87
+ };
88
+ export type PlayerOutput = ({
89
+ guard: 'proposed';
90
+ coderProposal: string;
91
+ } & AdditionalPlayerFields) | ({
92
+ guard: 'proposed';
93
+ reviewerProposal: string;
94
+ } & AdditionalPlayerFields) | ({
95
+ guard: 'committed';
96
+ coderOutput: string;
97
+ latestCommit: string;
98
+ } & AdditionalPlayerFields) | ({
99
+ guard: 'needsBossReply';
100
+ question: string;
101
+ } & AdditionalPlayerFields);
102
+ export interface PlaybookInput {
103
+ stateId: 'reviewCommit';
104
+ sourceItem: 'DECIDE-4';
105
+ playbookId: 'review';
106
+ text: string;
107
+ }
108
+ export declare const decideMachine: import("xstate").StateMachine<DecideContext, {
109
+ type: "START_DECIDE";
110
+ callerTopic: string;
111
+ } | {
112
+ type: "BOSS_INTERRUPT";
113
+ targetId: JumpableStateId;
114
+ bossIntent: string;
115
+ } | {
116
+ type: "BOSS_REPLY";
117
+ questionId?: ResumableStateId;
118
+ answer: string;
119
+ }, {
120
+ [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;
121
+ }, {
122
+ src: "playbook";
123
+ logic: import("xstate").PromiseActorLogic<JsonValue | undefined, PlaybookInput, import("xstate").EventObject>;
124
+ id: string | undefined;
125
+ } | {
126
+ src: "player";
127
+ logic: import("xstate").PromiseActorLogic<PlayerOutput, PlayerInput, import("xstate").EventObject>;
128
+ id: string | undefined;
129
+ }, {
130
+ type: "rememberActorError";
131
+ params: import("xstate").NonReducibleUnknown;
132
+ } | {
133
+ type: "rememberBossReply";
134
+ params: import("xstate").NonReducibleUnknown;
135
+ } | {
136
+ type: "clearBossReplyContext";
137
+ params: import("xstate").NonReducibleUnknown;
138
+ } | {
139
+ type: "copyInterruptedTopic";
140
+ params: import("xstate").NonReducibleUnknown;
141
+ } | {
142
+ type: "copyStartTopic";
143
+ params: import("xstate").NonReducibleUnknown;
144
+ } | {
145
+ type: "stageCoderProposal";
146
+ params: import("xstate").NonReducibleUnknown;
147
+ } | {
148
+ type: "stageReviewerProposal";
149
+ params: import("xstate").NonReducibleUnknown;
150
+ } | {
151
+ type: "promoteProposals";
152
+ params: import("xstate").NonReducibleUnknown;
153
+ } | {
154
+ type: "rememberCommit";
155
+ params: import("xstate").NonReducibleUnknown;
156
+ } | {
157
+ type: "rememberReviewSuccess";
158
+ params: import("xstate").NonReducibleUnknown;
159
+ } | {
160
+ type: "rememberReviewFailure";
161
+ params: import("xstate").NonReducibleUnknown;
162
+ } | {
163
+ type: "rememberReviewProtocolFailure";
164
+ params: import("xstate").NonReducibleUnknown;
165
+ } | {
166
+ type: "rememberMalformedActorOutput";
167
+ params: import("xstate").NonReducibleUnknown;
168
+ } | {
169
+ type: "rememberMalformedBossReply";
170
+ params: import("xstate").NonReducibleUnknown;
171
+ } | {
172
+ type: "setPendingBossQuestion";
173
+ params: PendingBossQuestionParams;
174
+ } | {
175
+ type: "clearBranchBossReplyContext";
176
+ params: {
177
+ stateId: ResumableStateId;
178
+ };
179
+ } | {
180
+ type: "clearProposalRoundContext";
181
+ params: import("xstate").NonReducibleUnknown;
182
+ }, {
183
+ type: "authoredReviewFailure";
184
+ params: unknown;
185
+ } | {
186
+ type: "committed";
187
+ params: unknown;
188
+ } | {
189
+ type: "coderProposed";
190
+ params: unknown;
191
+ } | {
192
+ type: "reviewerProposed";
193
+ params: unknown;
194
+ } | {
195
+ type: "needsBossReplyWithQuestion";
196
+ params: unknown;
197
+ } | {
198
+ type: "needsBossReplyWithoutQuestion";
199
+ params: unknown;
200
+ } | {
201
+ type: "validReviewSuccess";
202
+ params: unknown;
203
+ }, never, "done" | "failed" | "awaitBossReply" | "ready" | "commitCoderProposal" | "reviewCommit" | "reportedReviewFailure" | {
204
+ independentProposals: {
205
+ coder: "complete" | "working" | "waiting";
206
+ reviewer: "complete" | "working" | "waiting";
207
+ };
208
+ }, string, DecideInput, ReviewSuccessOutput | DecideFailureOutput, import("xstate").EventObject, import("xstate").MetaObject, {
209
+ id: "decide";
210
+ states: {
211
+ readonly ready: {
212
+ id: "ready";
213
+ };
214
+ readonly independentProposals: {
215
+ id: "independentProposals";
216
+ states: {
217
+ readonly coder: {
218
+ states: {
219
+ readonly working: {
220
+ id: "askCoderProposal";
221
+ };
222
+ readonly waiting: {
223
+ id: "waitCoderProposalReply";
224
+ };
225
+ readonly complete: {};
226
+ };
227
+ };
228
+ readonly reviewer: {
229
+ states: {
230
+ readonly working: {
231
+ id: "askReviewerProposal";
232
+ };
233
+ readonly waiting: {
234
+ id: "waitReviewerProposalReply";
235
+ };
236
+ readonly complete: {};
237
+ };
238
+ };
239
+ };
240
+ };
241
+ readonly commitCoderProposal: {
242
+ id: "commitCoderProposal";
243
+ };
244
+ readonly awaitBossReply: {
245
+ id: "awaitBossReply";
246
+ };
247
+ readonly reviewCommit: {
248
+ id: "reviewCommit";
249
+ };
250
+ readonly failed: {
251
+ id: "failed";
252
+ };
253
+ readonly reportedReviewFailure: {
254
+ id: "reportedReviewFailure";
255
+ };
256
+ readonly done: {
257
+ id: "done";
258
+ };
259
+ };
260
+ }>;
261
+ export default decideMachine;