@sublang/playbook 5.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 (65) hide show
  1. package/README.md +11 -7
  2. package/docs/cli.md +38 -35
  3. package/docs/configuration.md +58 -15
  4. package/docs/embedding.md +24 -16
  5. package/package.json +40 -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/code.fsm.d.ts +229 -94
  10. package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +26 -44
  11. package/reference/sdlc/code.playbook/code.fsm.introspect.js +61 -66
  12. package/reference/sdlc/code.playbook/code.fsm.introspect.ts +100 -149
  13. package/reference/sdlc/code.playbook/code.fsm.js +587 -1347
  14. package/reference/sdlc/code.playbook/code.fsm.ts +809 -1650
  15. package/reference/sdlc/code.playbook/code.gears.md +51 -263
  16. package/reference/sdlc/code.playbook/code.playbook.d.ts +8 -47
  17. package/reference/sdlc/code.playbook/code.playbook.js +69 -656
  18. package/reference/sdlc/code.playbook/code.playbook.ts +90 -867
  19. package/reference/sdlc/code.playbook/code.registry.d.ts +9 -25
  20. package/reference/sdlc/code.playbook/code.registry.js +20 -78
  21. package/reference/sdlc/code.playbook/code.registry.ts +58 -122
  22. package/reference/sdlc/code.playbook/playbook-captain.js +93 -15
  23. package/reference/sdlc/code.playbook/playbook-captain.ts +115 -19
  24. package/reference/sdlc/code.playbook/playbook.config.template.yaml +33 -22
  25. package/reference/sdlc/decide.md +54 -0
  26. package/reference/sdlc/decide.playbook/decide.fsm.d.ts +261 -0
  27. package/reference/sdlc/decide.playbook/decide.fsm.js +894 -0
  28. package/reference/sdlc/decide.playbook/decide.fsm.ts +1152 -0
  29. package/reference/sdlc/decide.playbook/decide.gears.md +88 -0
  30. package/reference/sdlc/decide.playbook/decide.playbook.d.ts +67 -0
  31. package/reference/sdlc/{discuss.playbook/discuss.playbook.js → decide.playbook/decide.playbook.js} +471 -362
  32. package/reference/sdlc/{discuss.playbook/discuss.playbook.ts → decide.playbook/decide.playbook.ts} +575 -443
  33. package/reference/sdlc/decide.playbook/decide.registry.d.ts +41 -0
  34. package/reference/sdlc/decide.playbook/decide.registry.js +60 -0
  35. package/reference/sdlc/decide.playbook/decide.registry.ts +125 -0
  36. package/reference/sdlc/review.md +81 -0
  37. package/reference/sdlc/review.playbook/review.fsm.d.ts +183 -0
  38. package/reference/sdlc/review.playbook/review.fsm.js +524 -0
  39. package/reference/sdlc/review.playbook/review.fsm.ts +652 -0
  40. package/reference/sdlc/review.playbook/review.gears.md +112 -0
  41. package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -0
  42. package/reference/sdlc/review.playbook/review.playbook.js +112 -0
  43. package/reference/sdlc/review.playbook/review.playbook.ts +201 -0
  44. package/reference/sdlc/review.playbook/review.registry.d.ts +43 -0
  45. package/reference/sdlc/review.playbook/review.registry.js +73 -0
  46. package/reference/sdlc/review.playbook/review.registry.ts +138 -0
  47. package/slc/gears2fsm.md +13 -4
  48. package/slc/link.md +48 -2
  49. package/slc/text2gears.md +22 -2
  50. package/src/runtime.d.ts +7 -0
  51. package/src/runtime.ts +12 -0
  52. package/src/xstate-playbook-runtime.d.ts +9 -2
  53. package/src/xstate-playbook-runtime.js +255 -21
  54. package/src/xstate-playbook-runtime.ts +333 -28
  55. package/src/xstate-runtime.js +25 -0
  56. package/src/xstate-runtime.ts +51 -0
  57. package/reference/sdlc/discuss.md +0 -93
  58. package/reference/sdlc/discuss.playbook/discuss.fsm.d.ts +0 -396
  59. package/reference/sdlc/discuss.playbook/discuss.fsm.js +0 -2067
  60. package/reference/sdlc/discuss.playbook/discuss.fsm.ts +0 -2465
  61. package/reference/sdlc/discuss.playbook/discuss.gears.md +0 -258
  62. package/reference/sdlc/discuss.playbook/discuss.playbook.d.ts +0 -113
  63. package/reference/sdlc/discuss.playbook/discuss.registry.d.ts +0 -58
  64. package/reference/sdlc/discuss.playbook/discuss.registry.js +0 -97
  65. package/reference/sdlc/discuss.playbook/discuss.registry.ts +0 -153
package/README.md CHANGED
@@ -25,7 +25,8 @@ Run `playbook` for an interactive tmux UI powered by [cligent](https://github.co
25
25
 
26
26
  ## Quick start
27
27
 
28
- Out of the box, Playbook includes **CODE**, a coding-and-review loop, and **DISCUSS**, in which two agents develop, reconcile, and review a specification.
28
+ Out of the box, Playbook includes **CODE** for implementation, **REVIEW** for commit-based review and fixes, and **DECIDE** for independently proposed and reviewed specification decisions.
29
+ CODE and DECIDE call REVIEW as a nested playbook.
29
30
 
30
31
  The interactive starter config uses Claude as both Captain and Coder, and Codex as Reviewer.
31
32
 
@@ -51,17 +52,20 @@ cd /path/to/your/project
51
52
  playbook
52
53
  ```
53
54
 
54
- Type a task, or enter `/code <task>` to select CODE directly.
55
+ Type a task, enter `/code <task>` for implementation, or enter
56
+ `/decide <question>` for an independently proposed and reviewed decision.
55
57
 
56
58
  On first launch, Playbook writes its config to `${XDG_CONFIG_HOME:-$HOME/.config}/playbook/playbook.config.yaml`.
57
59
 
58
60
  One-shot runs use separate defaults instead of the interactive lineup.
59
- Without configured `run` defaults, the Captain and every player use Claude; retain the Codex Reviewer with:
61
+ Without configured `run` defaults, the Captain and every player use Claude; run standalone REVIEW with a Codex Reviewer using:
60
62
 
61
63
  ```sh
62
- playbook run @sublang/playbook/code/registry "add a test for parseArgs" --player reviewer=codex --json
64
+ playbook run @sublang/playbook/review/registry "review the latest commit" --player reviewer=codex --json
63
65
  ```
64
66
 
67
+ CODE and DECIDE require interactive `playbook` because the one-shot host does not drive nested calls.
68
+
65
69
  See [Using the CLI](docs/cli.md) for flags and session resume, [Configuring agents](docs/configuration.md) for lineups, [Embedding](docs/embedding.md) for custom hosts, and the [changelog](CHANGELOG.md) for releases.
66
70
 
67
71
  ## Create your own playbook
@@ -85,7 +89,7 @@ SLC's `playbook` pipeline has three phases:
85
89
  3. **FSM → runtime** ([slc/link.md](slc/link.md)) — links the machine to a host-independent interface for user input, agent calls, status, and telemetry.
86
90
 
87
91
  The default [optimization pass](slc/optimize.md) replaces eligible mechanical steps with local shell scripts; `--no-optimize` skips it.
88
- Inspect the complete [Captain](reference/sdlc/captain.md), [CODE](reference/sdlc/code.md), and [DISCUSS](reference/sdlc/discuss.md) examples.
92
+ Inspect the complete [Captain](reference/sdlc/captain.md), [CODE](reference/sdlc/code.md), [REVIEW](reference/sdlc/review.md), and [DECIDE](reference/sdlc/decide.md) examples.
89
93
 
90
94
  ## Contributing
91
95
 
@@ -108,8 +112,8 @@ pnpm playbook # drive a Boss turn against the source tree
108
112
  ```
109
113
 
110
114
  Playbook is itself spec-driven: the compiler phases are specs in [`slc/`](slc), and the reference playbooks are regenerated from their prose sources.
111
- Edit a source, regenerate its GEARS, FSM, and runtime artifacts, sync the tests and downstream specs until `pnpm test` passes, and commit with co-author trailers per [`specs/dev/git.md`](specs/dev/git.md).
112
- The gears↔FSM contract ([the PLAYBOOK dev items](specs/dev/playbook.md)) and the runtime contract ([the PBRT dev items](specs/dev/playbook-runtime.md)) are pinned in [`specs/dev/`](specs/dev) and verified by the test suite.
115
+ Edit a source, regenerate its GEARS, FSM, and runtime artifacts, sync the tests and downstream specs until `pnpm test` passes, and commit with co-author trailers per [`specs/packages/git.md`](specs/packages/git.md).
116
+ The gears↔FSM contract ([the playbook package](specs/packages/playbook.md)) and runtime contract ([the playbook-runtime package](specs/packages/playbook-runtime.md)) are pinned in [`specs/packages/`](specs/packages) and verified by the test suite.
113
117
 
114
118
  ## License
115
119
 
package/docs/cli.md CHANGED
@@ -50,7 +50,7 @@ runtime is reported as not installed; a stale one with its installed
50
50
  and required versions, never as absent. Either way the remedy printed
51
51
  is cligent's pinned install, `npm install -g <package>@<version>`, so
52
52
  following it cannot install a version the gate refuses again
53
- ([PBCLI-40](../specs/user/playbook-cli.md#pbcli-40)).
53
+ ([[playbook-cli-40](../specs/packages/playbook-cli.md#playbook-cli-40)]).
54
54
 
55
55
  ## Interactive
56
56
 
@@ -81,53 +81,56 @@ The command resolves its config (seeding it on first run), composes a
81
81
  `tmux-play` config, checks adapter readiness, and launches. It exits
82
82
  with tmux-play's status, re-raises a terminating signal on itself, and
83
83
  exits `127` when it cannot launch at all
84
- ([PBCLI-1](../specs/user/playbook-cli.md#pbcli-1),
85
- [PBCLI-2](../specs/user/playbook-cli.md#pbcli-2)).
84
+ ([[playbook-cli-1](../specs/packages/playbook-cli.md#playbook-cli-1)],
85
+ [[playbook-cli-2](../specs/packages/playbook-cli.md#playbook-cli-2)]).
86
86
 
87
87
  ### Running a Boss turn
88
88
 
89
89
  The Boss pane starts at the Playbook Captain shell, where the session
90
- Captain runs for the whole session and sees every turn. Use
91
- `/code <task>` to select the CODE playbook explicitly — a registered
92
- command resolves deterministically, with no model call parsing it: at
93
- idle it starts that playbook, at its own leaf it delivers the rest of
94
- the line, an enabled command absent from the active path switches to it,
95
- and a bare `/code` answers with status or a clarification instead of
96
- restarting anything. Type ordinary text and the session Captain decides
97
- the turn instead: it chats back, starts or switches a playbook, hands
98
- the text to the working playbook, dismisses it, or applies one recovery
99
- action the running playbook currently offers. It never does the
100
- specialized work itself, and a conversational turn — including a
101
- progress or status question — leaves the engagement, its parked state,
102
- and any pending player question untouched
103
- ([CAPTAIN-1](../specs/user/playbook-captain.md#captain-1),
104
- [CAPTAIN-2](../specs/user/playbook-captain.md#captain-2)).
105
-
106
- Once a turn reaches CODE, the CODE judge classifies it into an FSM event
107
- start a coding turn, continue or summarize an iteration, interrupt to
108
- a named state, or nothing
109
- ([PBRT-1](../specs/user/playbook-runtime.md#pbrt-1)). When a player
110
- surfaces a clarifying question the FSM parks, the pane shows the
111
- question, and your next turn is normally classified as the reply — a
112
- fresh directive abandons it
113
- ([PBRT-2](../specs/user/playbook-runtime.md#pbrt-2)).
90
+ Captain runs for the whole session and sees every turn. Use `/code`,
91
+ `/review`, or `/decide` followed by a task to select one of the bundled
92
+ playbooks explicitly. A registered command resolves deterministically,
93
+ with no model call parsing it: at idle it starts that playbook, at its
94
+ own leaf it delivers the rest of the line, an enabled command absent
95
+ from the active path switches to it, and a bare command answers with
96
+ status or a clarification instead of restarting anything. Type ordinary
97
+ text and the session Captain decides the turn instead: it chats back,
98
+ starts or switches a playbook, hands the text to the working playbook,
99
+ dismisses it, or applies one recovery action the running playbook
100
+ currently offers. It never does the specialized work itself, and a
101
+ conversational turn — including a progress or status question — leaves
102
+ the engagement, its parked state, and any pending player question
103
+ untouched
104
+ ([[playbook-captain-1](../specs/packages/playbook-captain.md#playbook-captain-1)],
105
+ [[playbook-captain-2](../specs/packages/playbook-captain.md#playbook-captain-2)]).
106
+
107
+ The current CODE, REVIEW, and DECIDE workflows take their deterministic
108
+ initial event from the selecting Boss turn. CODE and DECIDE then call
109
+ REVIEW as a nested playbook: an exact same-name child role continues the
110
+ ancestor's player pane and backend conversation, while any additional
111
+ role uses REVIEW's configured fallback. When a player surfaces a
112
+ clarifying question the FSM parks, the pane shows the question, and a
113
+ judge classifies your next turn as its reply or a fresh directive that
114
+ abandons it
115
+ ([[playbook-runtime-2](../specs/packages/playbook-runtime.md#playbook-runtime-2)]).
114
116
 
115
117
  The Captain pane shows start/stop/finished status with `◇` lines and
116
118
  streams progress with captain-speech classification and questions
117
- ([PBRT-3](../specs/user/playbook-runtime.md#pbrt-3)), while player
119
+ ([[playbook-runtime-3](../specs/packages/playbook-runtime.md#playbook-runtime-3)]), while player
118
120
  prompts ride their own panes. A turn that actually did something ends
119
121
  with one Captain reply summarizing what changed, composed only from that
120
122
  turn's reported outcome; a turn that changed nothing ends with an
121
123
  ordinary reply and no saved-counts line
122
- ([CAPTAIN-19](../specs/user/playbook-captain.md#captain-19)).
124
+ ([[playbook-captain-19](../specs/packages/playbook-captain.md#playbook-captain-19)]).
123
125
 
124
126
  ## Non-interactive
125
127
 
126
128
  `playbook run <from> [task]` runs one playbook once, without tmux-play
127
- and without a config entry point it straight at a registry module:
129
+ and without an interactive config entry. For example, run REVIEW
130
+ directly against the latest commit:
128
131
 
129
132
  ```sh
130
- playbook run @sublang/playbook/code/registry "add a test for parseArgs" \
133
+ playbook run @sublang/playbook/review/registry "review the latest commit" \
131
134
  --player coder=claude --player reviewer=codex --cwd ./my-repo
132
135
  ```
133
136
 
@@ -138,7 +141,7 @@ intents the same way you would to `claude -p` or `codex exec`.
138
141
  | --- | --- |
139
142
  | `--player <role>=<agent>` | bind a required role |
140
143
  | `--captain <agent>` | set the captain/judge agent |
141
- | `--option <key>=<value>` | a playbook option (CODE's `committer`) |
144
+ | `--option <key>=<value>` | a registry-defined playbook option (none in the current bundled workflows) |
142
145
  | `--cwd <dir>` | the agents' working directory |
143
146
  | `--json` | one envelope: `outcome`, `sessionId`, output or questions |
144
147
  | `--no-provision` | never create engine links beside a filesystem `<from>` |
@@ -152,7 +155,7 @@ config supplies [run defaults](configuration.md#defaults-for-playbook-run).
152
155
 
153
156
  Exit codes: `0` terminal, `1` bad argument or module, `2` failure, `3`
154
157
  the playbook needs a Boss reply
155
- ([PBCLI-18](../specs/user/playbook-cli.md#pbcli-18)).
158
+ ([[playbook-cli-18](../specs/packages/playbook-cli.md#playbook-cli-18)]).
156
159
 
157
160
  ### Engine provisioning
158
161
 
@@ -164,7 +167,7 @@ install with no project-local packages —
164
167
  `node_modules/xstate` and `node_modules/@sublang/playbook` beside the
165
168
  module as symlinks to the running host's own packages and prints one
166
169
  line naming what it linked
167
- ([PBCLI-36](../specs/user/playbook-cli.md#pbcli-36),
170
+ ([[playbook-cli-36](../specs/packages/playbook-cli.md#playbook-cli-36)],
168
171
  [DR-024](../specs/decisions/024-runtime-engine-provisioning.md)).
169
172
  A directory where the imports already resolve is never touched — a
170
173
  project-local install always wins — and `--no-provision` disables the
@@ -193,5 +196,5 @@ lineup, options, and working directory are stored with the session, so
193
196
  `resume` takes no binding flags. In scripts, capture the session id from
194
197
  the `--json` envelope, like Claude Code's `session_id` or
195
198
  `codex exec resume`
196
- ([PBCLI-22](../specs/user/playbook-cli.md#pbcli-22),
199
+ ([[playbook-cli-22](../specs/packages/playbook-cli.md#playbook-cli-22)],
197
200
  [DR-014](../specs/decisions/014-durable-one-shot-run-sessions.md)).
@@ -33,8 +33,8 @@ Within a `playbooks.<id>` block, `from` (the registry module), `command`
33
33
  every other key is that playbook's option slice. The launcher injects
34
34
  the rest — you do not write host wiring by hand.
35
35
 
36
- The seeded config runs the Coder on Claude Opus 4.8 1m and the Reviewer
37
- on GPT-5.5:
36
+ The seeded config runs each Coder on Claude Opus 4.8 1m and each
37
+ Reviewer on GPT-5.5:
38
38
 
39
39
  ```yaml
40
40
  captain:
@@ -54,6 +54,16 @@ playbooks:
54
54
  effort: xhigh
55
55
  permissions:
56
56
  mode: auto # protected auto mode for the Claude Coder
57
+
58
+ review:
59
+ from: '@sublang/playbook/review/registry'
60
+ players:
61
+ coder:
62
+ adapter: claude
63
+ model: claude-opus-4-8[1m]
64
+ effort: xhigh
65
+ permissions:
66
+ mode: auto
57
67
  reviewer:
58
68
  adapter: codex
59
69
  model: gpt-5.5
@@ -62,15 +72,47 @@ playbooks:
62
72
  mode: auto
63
73
  writablePaths:
64
74
  - .git # allow git metadata writes under Codex auto mode
65
- committer: coder # which role commits — `coder` or `reviewer`
75
+
76
+ decide:
77
+ from: '@sublang/playbook/decide/registry'
78
+ players:
79
+ coder:
80
+ adapter: claude
81
+ model: claude-opus-4-8[1m]
82
+ effort: xhigh
83
+ permissions:
84
+ mode: auto
85
+ reviewer:
86
+ adapter: codex
87
+ model: gpt-5.5
88
+ effort: xhigh
89
+ permissions:
90
+ mode: auto
91
+ writablePaths:
92
+ - .git
66
93
  ```
67
94
 
68
- `committer` is CODE's one option: an alias naming which role runs the
69
- commit turn (fallback semantics:
70
- [PBRT-8](../specs/dev/playbook-runtime.md#pbrt-8)). Each role's per-run
71
- prompt names its pinned `model`, else its `adapter`
72
- ([PBRT-4](../specs/user/playbook-runtime.md#pbrt-4)), so commit trailers
73
- credit the concrete model rather than the adapter family.
95
+ The current bundled workflows accept no workflow-specific options.
96
+ Each role's per-run prompt names its pinned `model`, else its `adapter`
97
+ ([[playbook-runtime-4](../specs/packages/playbook-runtime.md#playbook-runtime-4)]),
98
+ so commit trailers credit the concrete model rather than the adapter
99
+ family.
100
+
101
+ ## Nested roles and sessions
102
+
103
+ The launcher creates a namespaced fallback player for every configured
104
+ playbook role, but a nested call maps an exact same-name role to the
105
+ nearest ancestor's effective player and backend conversation. CODE's
106
+ nested REVIEW therefore continues CODE's `coder` and uses REVIEW's
107
+ configured `reviewer`; DECIDE's nested REVIEW continues both of
108
+ DECIDE's roles. A standalone REVIEW starts with REVIEW's own configured
109
+ players, and every new root engagement starts fresh
110
+ ([DR-030](../specs/decisions/030-shared-mapped-player-continuity.md)).
111
+
112
+ The separate fallback entries are still required because tmux creates
113
+ its roster at launch time. The host changes which existing panes are
114
+ visible as the active nested leaf changes; it does not create a new
115
+ host player or backend agent session for a mapped role.
74
116
 
75
117
  ## Choosing the Captain agent
76
118
 
@@ -80,7 +122,7 @@ instead of doing the work itself. Claude enforces
80
122
  that at the provider level. The Codex adapter cannot — it rejects any
81
123
  tool list — so a `captain:` on `codex` falls back to a prompt-level
82
124
  restriction
83
- ([DR-013 A1](../specs/decisions/013-routing-only-captain-control.md#addendum-a1-prompt-level-isolation-for-adapters-without-tool-enforcement)).
125
+ ([DR-013](../specs/decisions/013-routing-only-captain-control.md) A1).
84
126
  Codex remains a good choice for *players*, where full tools are wanted.
85
127
 
86
128
  Adapter readiness is intentionally light: `claude` is ready with local
@@ -109,8 +151,8 @@ playbooks:
109
151
  effort: medium
110
152
  permissions:
111
153
  mode: auto
112
- # The seeded `committer` is `coder`, so this role runs the commit
113
- # turn; a Codex agent needs the `.git` grant to write git metadata.
154
+ # CODE's Coder commits, so Codex needs the `.git` grant to write
155
+ # repository metadata.
114
156
  writablePaths:
115
157
  - .git
116
158
  ```
@@ -122,7 +164,7 @@ role switched to `codex` needs its own `writablePaths` grant, because
122
164
  the base Claude block had no reason to carry one.
123
165
 
124
166
  The global file is never modified, and `--with` is not forwarded to
125
- `tmux-play` ([PBCLI-25](../specs/user/playbook-cli.md#pbcli-25)).
167
+ `tmux-play` ([[playbook-cli-25](../specs/packages/playbook-cli.md#playbook-cli-25)]).
126
168
 
127
169
  ## Defaults for `playbook run`
128
170
 
@@ -131,7 +173,7 @@ lineup so you stop retyping flags — `run.captain`, `run.players.<role>`,
131
173
  and a `run.player` catch-all for any other required role, each an
132
174
  `<adapter>[:<model>][@<effort>]` string. Flags win per role, and
133
175
  `resume` always keeps the lineup stored with the parked session
134
- ([PBCLI-28](../specs/user/playbook-cli.md#pbcli-28),
176
+ ([[playbook-cli-28](../specs/packages/playbook-cli.md#playbook-cli-28)],
135
177
  [DR-017](../specs/decisions/017-run-defaults-config.md)).
136
178
 
137
179
  ```yaml
@@ -139,6 +181,7 @@ run:
139
181
  captain: claude:claude-opus-4-8@high
140
182
  players:
141
183
  coder: claude:claude-opus-4-8[1m]@xhigh
184
+ reviewer: codex:gpt-5.5@xhigh
142
185
  ```
143
186
 
144
187
  ## Migrating from `profiles`
@@ -153,7 +196,7 @@ do by hand.
153
196
 
154
197
  For a one-off, pass a raw `tmux-play` config explicitly. This bypasses
155
198
  the seed, composition, and readiness gate, forwarding arguments to
156
- `tmux-play` verbatim ([PBCLI-1](../specs/user/playbook-cli.md#pbcli-1)):
199
+ `tmux-play` verbatim ([[playbook-cli-1](../specs/packages/playbook-cli.md#playbook-cli-1)]):
157
200
 
158
201
  ```sh
159
202
  playbook --config ./tmux-play.config.yaml
package/docs/embedding.md CHANGED
@@ -8,7 +8,7 @@ one host, and [spex](https://github.com/sublang-ai/spex) (the desktop
8
8
  app) is another. This guide shows how to wire a playbook runtime into
9
9
  your own host.
10
10
 
11
- > **Release note:** this guide targets the semver-stable 1.0 six-port
11
+ > **Release note:** this guide targets the current semver-stable six-port
12
12
  > contract; see the [CHANGELOG](../CHANGELOG.md) for migration details.
13
13
 
14
14
  ## The runtime contract
@@ -17,11 +17,11 @@ The port and runtime contracts live in the type-only module
17
17
  [`@sublang/playbook/runtime`](../src/runtime.ts) — a public,
18
18
  semver-stable surface (`PlayerResult`, `PlaybookPorts`,
19
19
  `PlaybookRuntime`, `PlaybookSession`, `PlayerCallOptions`,
20
- `CaptainCallOptions`, `CaptainResult`, `PlaybookTraceEvent`, and
21
- `PlaybookRuntimeFactory`) that imports no CODE or FSM types, so a host
22
- satisfies it once and inherits every playbook. The CODE runtime
23
- re-exports `PlayerResult`, `PlaybookPorts`, `PlaybookSession`, and
24
- `PlaybookRuntime` from `@sublang/playbook/code/playbook`;
20
+ `PlayerSessionStore`, `CaptainCallOptions`, `CaptainResult`,
21
+ `PlaybookTraceEvent`, and `PlaybookRuntimeFactory`) that imports no CODE
22
+ or FSM types, so a host satisfies it once and inherits every playbook.
23
+ The generated CODE, REVIEW, and DECIDE modules re-export their shared
24
+ runtime contract types from their public `playbook` subpaths;
25
25
  `PlaybookRuntimeFactory` is available from `@sublang/playbook/runtime`.
26
26
 
27
27
  Generated linked runtimes reuse the XState integration engine exposed
@@ -32,7 +32,7 @@ nested-playbook bridge.
32
32
  ## Constructing a runtime against your own ports
33
33
 
34
34
  ```ts
35
- import createPlaybookRuntime from '@sublang/playbook/code/playbook';
35
+ import createPlaybookRuntime from '@sublang/playbook/review/playbook';
36
36
  import type {
37
37
  CaptainCallOptions,
38
38
  CaptainResult,
@@ -104,20 +104,20 @@ const ports: PlaybookPorts = {
104
104
  };
105
105
 
106
106
  const runtime = createPlaybookRuntime({
107
- coderPlayer: 'claude',
108
- reviewerPlayer: 'codex',
107
+ coderLlm: 'claude-opus-4-8[1m]',
108
+ reviewerLlm: 'gpt-5.5',
109
109
  });
110
110
 
111
111
  const playbookSessionId = randomUUID();
112
112
  await runtime.init({
113
113
  sessionId: playbookSessionId,
114
- playbookId: 'code',
114
+ playbookId: 'review',
115
115
  rootSessionId: playbookSessionId,
116
116
  depth: 0,
117
117
  ports,
118
118
  });
119
119
  await runtime.handleBossInput({
120
- text: 'Start fixing the bug',
120
+ text: 'Review the latest commit against the requested intent',
121
121
  signal: new AbortController().signal,
122
122
  });
123
123
  await runtime.dispose();
@@ -129,11 +129,19 @@ Every init-to-dispose lifecycle is one playbook session. Its
129
129
  `playbook.trace` telemetry carries that immutable ID plus a contiguous
130
130
  sequence across exact Boss input, judge/player calls, FSM transitions,
131
131
  visible Captain work, nested playbook calls, status, settlement, and
132
- disposal. Each resolved player starts fresh in a new playbook session
133
- and then resumes only from the latest opaque `resumeToken` its adapter
134
- returned; trace data and tokens never enter Boss-visible status text.
135
- Because trace observers do receive opaque resume tokens, persisted
136
- traces should be protected as sensitive data.
132
+ disposal. Without `PlaybookSession.playerSessions`, a standalone runtime
133
+ starts each player fresh and privately retains the latest opaque
134
+ `resumeToken` its adapter returned.
135
+
136
+ A composing host can instead supply a frame-local `PlayerSessionStore`
137
+ view over one root-owned continuation map. The host maps each local role
138
+ to its effective binding, so a nested exact same-name role selects and
139
+ updates the ancestor conversation while an unmatched child role gets
140
+ its own binding. Child return or disposal does not clear the root's
141
+ token, and a new root engagement starts fresh. Trace data and tokens
142
+ never enter Boss-visible status text. Because trace observers do receive
143
+ opaque resume tokens, persisted traces should be protected as sensitive
144
+ data.
137
145
 
138
146
  See
139
147
  [`code.playbook.test.ts`](../reference/sdlc/code.playbook/code.playbook.test.ts)
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "@sublang/playbook",
3
- "version": "5.0.0",
3
+ "version": "6.0.0",
4
4
  "type": "module",
5
- "description": "Composable XState v5 playbook runtime with compiled Captain, CODE, and DISCUSS workflows driven by GEARS specs.",
5
+ "description": "Composable XState v5 playbook runtime with compiled Captain, CODE, REVIEW, and DECIDE workflows driven by GEARS specs.",
6
6
  "license": "Apache-2.0",
7
7
  "homepage": "https://github.com/sublang-ai/playbook#readme",
8
8
  "repository": {
@@ -40,7 +40,8 @@
40
40
  "slc/optimize.md",
41
41
  "reference/sdlc/captain.md",
42
42
  "reference/sdlc/code.md",
43
- "reference/sdlc/discuss.md",
43
+ "reference/sdlc/review.md",
44
+ "reference/sdlc/decide.md",
44
45
  "reference/sdlc/captain.playbook/captain.gears.md",
45
46
  "reference/sdlc/captain.playbook/captain.fsm.ts",
46
47
  "reference/sdlc/captain.playbook/captain.fsm.js",
@@ -69,16 +70,26 @@
69
70
  "reference/sdlc/code.playbook/bin/run.js",
70
71
  "reference/sdlc/code.playbook/bin/provision.js",
71
72
  "reference/sdlc/code.playbook/bin/adapter-sdk.js",
72
- "reference/sdlc/discuss.playbook/discuss.gears.md",
73
- "reference/sdlc/discuss.playbook/discuss.fsm.ts",
74
- "reference/sdlc/discuss.playbook/discuss.fsm.js",
75
- "reference/sdlc/discuss.playbook/discuss.fsm.d.ts",
76
- "reference/sdlc/discuss.playbook/discuss.playbook.ts",
77
- "reference/sdlc/discuss.playbook/discuss.playbook.js",
78
- "reference/sdlc/discuss.playbook/discuss.playbook.d.ts",
79
- "reference/sdlc/discuss.playbook/discuss.registry.ts",
80
- "reference/sdlc/discuss.playbook/discuss.registry.js",
81
- "reference/sdlc/discuss.playbook/discuss.registry.d.ts",
73
+ "reference/sdlc/review.playbook/review.gears.md",
74
+ "reference/sdlc/review.playbook/review.fsm.ts",
75
+ "reference/sdlc/review.playbook/review.fsm.js",
76
+ "reference/sdlc/review.playbook/review.fsm.d.ts",
77
+ "reference/sdlc/review.playbook/review.playbook.ts",
78
+ "reference/sdlc/review.playbook/review.playbook.js",
79
+ "reference/sdlc/review.playbook/review.playbook.d.ts",
80
+ "reference/sdlc/review.playbook/review.registry.ts",
81
+ "reference/sdlc/review.playbook/review.registry.js",
82
+ "reference/sdlc/review.playbook/review.registry.d.ts",
83
+ "reference/sdlc/decide.playbook/decide.gears.md",
84
+ "reference/sdlc/decide.playbook/decide.fsm.ts",
85
+ "reference/sdlc/decide.playbook/decide.fsm.js",
86
+ "reference/sdlc/decide.playbook/decide.fsm.d.ts",
87
+ "reference/sdlc/decide.playbook/decide.playbook.ts",
88
+ "reference/sdlc/decide.playbook/decide.playbook.js",
89
+ "reference/sdlc/decide.playbook/decide.playbook.d.ts",
90
+ "reference/sdlc/decide.playbook/decide.registry.ts",
91
+ "reference/sdlc/decide.playbook/decide.registry.js",
92
+ "reference/sdlc/decide.playbook/decide.registry.d.ts",
82
93
  "docs"
83
94
  ],
84
95
  "bin": {
@@ -110,18 +121,26 @@
110
121
  "default": "./reference/sdlc/code.playbook/playbook-captain.js"
111
122
  },
112
123
  "./slc/*": "./slc/*",
113
- "./discuss/playbook": {
114
- "types": "./reference/sdlc/discuss.playbook/discuss.playbook.d.ts",
115
- "default": "./reference/sdlc/discuss.playbook/discuss.playbook.js"
124
+ "./review/playbook": {
125
+ "types": "./reference/sdlc/review.playbook/review.playbook.d.ts",
126
+ "default": "./reference/sdlc/review.playbook/review.playbook.js"
116
127
  },
117
- "./discuss/registry": {
118
- "types": "./reference/sdlc/discuss.playbook/discuss.registry.d.ts",
119
- "default": "./reference/sdlc/discuss.playbook/discuss.registry.js"
128
+ "./review/registry": {
129
+ "types": "./reference/sdlc/review.playbook/review.registry.d.ts",
130
+ "default": "./reference/sdlc/review.playbook/review.registry.js"
131
+ },
132
+ "./decide/playbook": {
133
+ "types": "./reference/sdlc/decide.playbook/decide.playbook.d.ts",
134
+ "default": "./reference/sdlc/decide.playbook/decide.playbook.js"
135
+ },
136
+ "./decide/registry": {
137
+ "types": "./reference/sdlc/decide.playbook/decide.registry.d.ts",
138
+ "default": "./reference/sdlc/decide.playbook/decide.registry.js"
120
139
  }
121
140
  },
122
141
  "scripts": {
123
142
  "build": "tsc",
124
- "test": "vitest run",
143
+ "test": "spex lint && vitest run",
125
144
  "test:acceptance": "vitest run --config vitest.acceptance.config.ts",
126
145
  "smoke:release": "node scripts/release-smoke.mjs",
127
146
  "check:links": "node scripts/check-links.mjs",
@@ -133,7 +152,7 @@
133
152
  },
134
153
  "dependencies": {
135
154
  "@sublang/cligent": "^0.19.0",
136
- "@sublang/spex": "^0.3.0",
155
+ "@sublang/spex": "^2.1.1",
137
156
  "p-queue": "^9.3.1",
138
157
  "xstate": "^5.19.4",
139
158
  "yaml": "^2.9.0"
@@ -520,6 +520,8 @@ const runtimeSpec = {
520
520
  snapshotOptions: snapshotCaptainOptions,
521
521
  machineInput: (options) => ({ enabledPlaybooks: options.enabledPlaybooks }),
522
522
  classifyBossText: (text, ports, signal, snapshotOrState, boundary, options) => classifyControllerTurn(text, ports, signal, snapshotOrState, boundary, options),
523
+ playerStates: {},
524
+ classificationStatus: () => undefined,
523
525
  captainStrategy: controllerCaptainStrategy,
524
526
  // CAPPLAY-10 / PBRT-52: the Captain's own ControlView context projection —
525
527
  // the settlement evidence the machine retains for its decision and reply
@@ -810,6 +810,8 @@ const runtimeSpec: XStatePlaybookRuntimeSpec<ValidatedCaptainOptions> = {
810
810
  boundary,
811
811
  options,
812
812
  ) as Promise<import('xstate').EventObject | undefined>,
813
+ playerStates: {},
814
+ classificationStatus: () => undefined,
813
815
  captainStrategy: controllerCaptainStrategy,
814
816
  // CAPPLAY-10 / PBRT-52: the Captain's own ControlView context projection —
815
817
  // the settlement evidence the machine retains for its decision and reply