@sublang/playbook 2.0.0 → 3.1.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 (30) hide show
  1. package/README.md +102 -338
  2. package/docs/cli.md +123 -0
  3. package/docs/configuration.md +158 -0
  4. package/docs/embedding.md +161 -0
  5. package/package.json +7 -2
  6. package/reference/sdlc/code.md +105 -0
  7. package/reference/sdlc/code.playbook/bin/playbook.js +237 -38
  8. package/reference/sdlc/code.playbook/bin/provision.js +228 -0
  9. package/reference/sdlc/code.playbook/bin/run.js +76 -3
  10. package/reference/sdlc/code.playbook/code.fsm.js +38 -36
  11. package/reference/sdlc/code.playbook/code.fsm.ts +38 -36
  12. package/reference/sdlc/code.playbook/code.gears.md +30 -26
  13. package/reference/sdlc/code.playbook/code.playbook.js +4 -0
  14. package/reference/sdlc/code.playbook/code.playbook.ts +6 -0
  15. package/reference/sdlc/code.playbook/playbook-captain.js +67 -8
  16. package/reference/sdlc/code.playbook/playbook-captain.ts +80 -9
  17. package/reference/sdlc/code.playbook/playbook.config.template.yaml +38 -32
  18. package/reference/sdlc/discuss.md +93 -0
  19. package/reference/sdlc/discuss.playbook/discuss.fsm.js +5 -4
  20. package/reference/sdlc/discuss.playbook/discuss.fsm.ts +5 -4
  21. package/reference/sdlc/discuss.playbook/discuss.gears.md +19 -12
  22. package/reference/sdlc/discuss.playbook/discuss.playbook.js +3 -0
  23. package/reference/sdlc/discuss.playbook/discuss.playbook.ts +5 -0
  24. package/slc/link.md +20 -3
  25. package/src/xstate-playbook-runtime.d.ts +17 -0
  26. package/src/xstate-playbook-runtime.js +49 -0
  27. package/src/xstate-playbook-runtime.ts +81 -4
  28. package/src/xstate-runtime.d.ts +1 -0
  29. package/src/xstate-runtime.js +19 -0
  30. package/src/xstate-runtime.ts +20 -0
package/README.md CHANGED
@@ -9,282 +9,118 @@
9
9
 
10
10
  _Skills made reliable through state machines and visualization._
11
11
 
12
- playbook is a compiler stack and reference implementation for turning a
13
- natural-language procedure into a runnable, inspectable state-machine
14
- agent a _playbook_ that orchestrates other AI agents per a spec
15
- written in plain prose. Instead of a free-form LLM deciding what to do
16
- next, an explicit finite state machine drives the workflow, every
17
- Captain-, player-, and nested-playbook-invoking state pinned 1:1 to a
18
- human-readable spec item and contract-tested.
19
-
20
- A quick vocabulary, used throughout: the **Boss** is you, the human in
21
- charge; the **Captain** is the agent pane the Boss talks to;
22
- **players** are the coding agents a playbook delegates work to; and a
23
- hidden **judge** classifies free-text Boss input into state-machine
24
- events, so playbooks need no slash commands of their own. Playbooks run
25
- inside a *host* built on
12
+ playbook turns a natural-language procedure into a runnable,
13
+ inspectable state-machine agent a _playbook_ that orchestrates other
14
+ AI agents per a spec written in plain prose. Instead of a free-form LLM
15
+ deciding what to do next, an explicit finite state machine drives the
16
+ workflow, every agent-invoking state pinned 1:1 to a human-readable spec
17
+ item and contract-tested.
18
+
19
+ Vocabulary: the **Boss** is you; the **Captain** is the agent pane you
20
+ talk to; **players** are the coding agents a playbook delegates to; a
21
+ hidden **judge** classifies your free text into state-machine events.
22
+ Playbooks run inside a *host* built on
26
23
  [cligent](https://github.com/sublang-ai/cligent), the sibling SDK that
27
- drives coding-agent CLIs; cligent's `tmux-play` terminal app is the
28
- reference host.
29
-
30
- Three phases take prose to runtime:
31
-
32
- 1. **text → GEARS** ([slc/text2gears.md](slc/text2gears.md)) — GEARS is
33
- the intermediate representation: normative spec items, one per state
34
- behavior, partitioned by trigger and prompt content.
35
- 2. **GEARS → FSM** ([slc/gears2fsm.md](slc/gears2fsm.md)) — an XState v5
36
- finite state machine; each gear maps to one direct-Captain,
37
- delegated-player, or nested-playbook state with a typed actor
38
- contract. The compiled FSM can be visualized and simulated with the
39
- bundled [XState sketch visualizer](views/sketch).
40
- 3. **FSM → runtime** ([slc/link.md](slc/link.md)) — a host-agnostic
41
- module that drives Boss turns through ports the host wires up
42
- (cligent's `tmux-play` is one such host).
43
-
44
- The repository contains end-to-end worked examples. The generic default
45
- Captain is generated from
46
- [`reference/sdlc/captain.md`](reference/sdlc/captain.md), CODE — a
47
- coder / reviewer / committer development loop — from
48
- [`reference/sdlc/code.md`](reference/sdlc/code.md), and DISCUSS — two
49
- agents converging on spec items — from
50
- [`reference/sdlc/discuss.md`](reference/sdlc/discuss.md). Together they
51
- show direct Captain work, sequential nested playbook calls, and
52
- parallel players.
53
-
54
- ## Getting started — the reference CODE playbook
55
-
56
- The reference is the canonical worked example —
57
- [CODE source](reference/sdlc/code.md) →
58
- [gears](reference/sdlc/code.playbook/code.gears.md) →
59
- [FSM](reference/sdlc/code.playbook/code.fsm.ts) → runtime — with
60
- the runtime registered behind the built-in Playbook Captain shell for
61
- cligent's `tmux-play` host out of the box.
62
- The compiled artifacts live under
63
- [`reference/sdlc/code.playbook/`](reference/sdlc/code.playbook),
64
- the [slc](https://github.com/sublang-ai/slc) compiler pipeline's
65
- `<basename>.<pipeline>/` output directory.
66
-
67
- > **Release status:** 1.0.0 is the first release of the composed system: the
68
- > compiled default Captain, CODE and DISCUSS, nested playbook calls, the
69
- > semver-stable six-port runtime contract (see
70
- > [docs/embedding.md](docs/embedding.md)), and non-interactive `playbook run`
71
- > with parked-session resume and per-run agent tuning.
24
+ drives coding-agent CLIs; its `tmux-play` terminal app is the reference
25
+ host.
72
26
 
73
- ### Requirements
27
+ ## Quick start
74
28
 
75
- - Node.js >= 20.6.0.
76
- - `tmux` and [`glow`](https://github.com/charmbracelet/glow#installation)
77
- on `PATH` the `tmux-play` host renders Markdown pane output with
78
- glow and fails fast without it.
79
- - Auth for the seeded agents: a signed-in
80
- [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview)
81
- (`~/.claude`) or `ANTHROPIC_API_KEY`, and a signed-in
82
- [Codex CLI](https://github.com/openai/codex) (`~/.codex`) or
83
- `OPENAI_API_KEY`.
84
-
85
- ### Install (users)
86
-
87
- Install the package globally. `@sublang/cligent`, the Claude and
88
- Codex adapter SDKs, and `xstate` are direct dependencies, so a single
89
- install pulls in the reference CODE playbook and its host:
29
+ Requires Node.js >= 20.6.0, `tmux` and
30
+ [`glow`](https://github.com/charmbracelet/glow#installation) on `PATH`,
31
+ and auth for the seeded agents signed-in
32
+ [Claude Code](https://docs.anthropic.com/en/docs/claude-code/overview)
33
+ or `ANTHROPIC_API_KEY`, and signed-in
34
+ [Codex CLI](https://github.com/openai/codex) or `OPENAI_API_KEY`.
90
35
 
91
36
  ```sh
92
37
  npm install -g @sublang/playbook
93
- ```
94
-
95
- Then launch the reference playbook in a `tmux-play` session:
96
-
97
- ```sh
98
38
  playbook
99
39
  ```
100
40
 
101
- For a one-shot run without a global install, invoke the scoped
102
- package through npx (it runs the package's `playbook` bin):
41
+ The first launch seeds a commented config at
42
+ `${XDG_CONFIG_HOME:-$HOME/.config}/playbook/playbook.config.yaml`,
43
+ composes a `tmux-play` config, checks the declared adapters, and opens
44
+ the session. Then type a task, or `/code <task>` to select the CODE
45
+ playbook directly.
103
46
 
104
- ```sh
105
- npx @sublang/playbook
106
- ```
107
-
108
- On first run, `playbook` creates a commented user config at
109
- `${XDG_CONFIG_HOME:-$HOME/.config}/playbook/playbook.config.yaml`
110
- from the bundled starter, prints that path to stderr, then composes a
111
- `tmux-play` config and checks the declared adapters before launching.
112
- Later runs reuse that file and do not overwrite it.
113
-
114
- Known adapter readiness is intentionally light: `claude` is ready when
115
- local Claude Code auth exists or `ANTHROPIC_API_KEY` is set; `codex` is
116
- ready when local Codex CLI auth exists or `OPENAI_API_KEY` is set. If a
117
- known adapter is not ready, `playbook` prints its own help text with the
118
- config path, auth pointers, and agent-swap recipe, then exits without
119
- launching. You can view the same recovery text at any time:
120
-
121
- ```sh
122
- playbook --help
123
- ```
124
-
125
- `playbook --list` prints the configured playbooks with their slash
126
- commands and intents. Every seeded agent — the Captain and both roles —
127
- runs in cligent's protected auto mode (`permissions.mode: auto`), so
128
- routine in-session approval prompts are suppressed without switching to
129
- bypass permissions. The seeded Codex Reviewer additionally grants
130
- `permissions.writablePaths: [.git]` so git metadata writes stay
131
- available under the Codex sandbox; the Claude agents need no such grant
132
- under their auto mode.
133
-
134
- ### Run a playbook non-interactively
135
-
136
- `playbook run <from> [task]` runs one playbook once, without tmux-play
137
- and without a config entry — point it straight at a registry module:
138
-
139
- ```sh
140
- playbook run @sublang/playbook/code/registry "add a test for parseArgs" \
141
- --player coder=claude --player reviewer=codex --cwd ./my-repo
142
- ```
143
-
144
- `[task]` is read from stdin when omitted — pipe long or multi-line
145
- intents the same way you would to `claude -p` or `codex exec`. Roles
146
- and the captain default to `claude`; bind them with
147
- `--player <role>=<agent>` and `--captain <agent>`, where `<agent>` is
148
- `<adapter>[:<model>][@<effort>]` — say `codex:gpt-5.5@xhigh`, or
149
- `claude@high` for the default model at high reasoning effort; the
150
- model keeps every interior colon (`opencode:ollama/llama3:8b@max`),
151
- and unsupported efforts are rejected up front naming the adapter's
152
- supported values. To stop retyping those flags, set durable defaults
153
- once in the user config's top-level `run:` block — `run.captain`,
154
- `run.players.<role>`, and a `run.player` catch-all for any other
155
- required role, each the same agent string; flags keep winning per
156
- role, and `resume` always keeps the lineup stored with the parked
157
- session ([PBCLI-28](specs/user/playbook-cli.md#pbcli-28),
158
- [DR-017](specs/decisions/017-run-defaults-config.md)). Pass a
159
- playbook option with
160
- `--option <key>=<value>`, and add `--json` to print one JSON envelope
161
- (`outcome`, `sessionId`, and the output or pending questions) instead
162
- of plain text. It exits `0` on a terminal outcome, `2` on failure, `3`
163
- when the playbook needs a Boss reply, and `1` on a bad argument or
164
- module. See [PBCLI-18](specs/user/playbook-cli.md#pbcli-18).
165
-
166
- When the playbook stops to ask the Boss something, the run is parked,
167
- not lost: the question prints to stdout, the session is saved under
168
- `${XDG_STATE_HOME:-$HOME/.local/state}/playbook/sessions/`, and stderr
169
- names the exact command that continues it. Answer with `resume`:
170
-
171
- ```sh
172
- playbook run resume 4f2c…9ab1 "keep the scope small; skip the docs"
173
- playbook run resume --last # most recently parked session; reply on stdin
174
- ```
175
-
176
- A resumed run picks the playbook up exactly where it parked — same
177
- session id, same workflow state, and each agent continues its own
178
- conversation — then prints the final output and exits `0`, or parks
179
- again with the next question and exits `3`. The agent lineup, options,
180
- and working directory are stored with the session, so `resume` takes no
181
- binding flags. In scripts, capture the session id from the `--json`
182
- envelope, like Claude Code's `session_id` or `codex exec resume`. See
183
- [PBCLI-22](specs/user/playbook-cli.md#pbcli-22) and
184
- [DR-014](specs/decisions/014-durable-one-shot-run-sessions.md).
185
-
186
- ### Configure agents
187
-
188
- Edit the seeded user config when you want different coding agents:
189
-
190
- ```sh
191
- $EDITOR "${XDG_CONFIG_HOME:-$HOME/.config}/playbook/playbook.config.yaml"
192
- ```
193
-
194
- To retune a single launch without editing that file, overlay a
195
- fragment in the same format with `--with` (repeatable, later files
196
- win; maps merge recursively, other values replace):
197
-
198
- ```sh
199
- playbook --with fast-lineup.yaml
200
- ```
47
+ Every agent carries its own settings, so retuning one player never
48
+ changes another:
201
49
 
202
50
  ```yaml
203
- # fast-lineup.yaml — swap the Coder for one run; nothing is written back.
204
- profiles:
205
- codex-fast: { adapter: codex, model: gpt-5.5, reasoningEffort: medium }
206
51
  playbooks:
207
52
  code:
53
+ from: '@sublang/playbook/code/registry'
208
54
  players:
209
- coder: codex-fast
55
+ coder: { adapter: claude, model: 'claude-opus-4-8[1m]', effort: xhigh }
56
+ reviewer: { adapter: codex, model: gpt-5.5, effort: xhigh }
210
57
  ```
211
58
 
212
- See [PBCLI-25](specs/user/playbook-cli.md#pbcli-25) and
213
- [DR-015](specs/decisions/015-per-run-agent-tuning.md).
59
+ To run once without tmux — for scripts and CI — point `run` straight at
60
+ a registry module:
214
61
 
215
- The config is top-level (no `config:` wrapper): a `profiles` map of
216
- reusable agent settings, a `captain` agent (it runs both visible
217
- Captain work and hidden judge calls), optional `layout` /
218
- `notifications` / `theme`, and a `playbooks` map of enabled playbooks.
219
- Each `captain` or `players.<role>` value is a profile id or an adapter
220
- shorthand (`claude`, `codex`); other adapter ids are passed through to
221
- `tmux-play` with a warning because `playbook` cannot preflight their
222
- auth. Name profiles by their underlying agent/model (e.g. `claude-opus`,
223
- `codex-gpt`) so the profile ids read distinctly from the player roles
224
- that reference them. Within a `playbooks.<id>` block, `from` (the
225
- registry module), `command` (an optional slash-command override), and
226
- `players` are launcher-owned; every other key is that playbook's option
227
- slice. The launcher injects the rest — you do not write host wiring by
228
- hand.
229
-
230
- For example, the seeded config runs the Coder on Claude Opus 4.8 1m and
231
- the Reviewer on GPT-5.5:
232
-
233
- ```yaml
234
- profiles:
235
- claude-opus:
236
- adapter: claude
237
- model: claude-opus-4-8
238
- reasoningEffort: high
239
- permissions:
240
- mode: auto # protected auto mode for the Claude Captain
241
- claude-opus-1m:
242
- adapter: claude
243
- model: claude-opus-4-8[1m]
244
- reasoningEffort: xhigh
245
- permissions:
246
- mode: auto # protected auto mode for the Claude Coder
247
- codex-gpt:
248
- adapter: codex
249
- model: gpt-5.5
250
- reasoningEffort: xhigh
251
- permissions:
252
- mode: auto
253
- writablePaths:
254
- - .git # allow git metadata writes under Codex auto mode
62
+ ```sh
63
+ playbook run @sublang/playbook/code/registry "add a test for parseArgs" --json
64
+ ```
255
65
 
256
- captain: claude-opus
66
+ - **[docs/cli.md](docs/cli.md)** — both surfaces: Boss turns, flags,
67
+ exit codes, and resuming a parked `run`.
68
+ - **[docs/configuration.md](docs/configuration.md)** — the config file,
69
+ per-launch `--with` overlays, and choosing the Captain agent.
70
+ - **[docs/embedding.md](docs/embedding.md)** — the six-port runtime
71
+ contract for hosts other than `tmux-play`.
72
+
73
+ > **Current release:** 3.1.0. The composed system — the compiled default
74
+ > Captain, CODE and DISCUSS, nested playbook calls, script actors and the
75
+ > GEARS optimize pass, the semver-stable six-port runtime contract, and
76
+ > non-interactive `playbook run` with parked-session resume — landed in
77
+ > 1.0.0. Since then, `playbook run` gained defaults in the user config,
78
+ > 3.0.0 replaced the top-level `profiles` map with inline agent settings
79
+ > (existing configs migrate themselves on the next launch), and 3.1.0
80
+ > added the linked-artifact/engine compatibility check. See the
81
+ > [CHANGELOG](CHANGELOG.md).
82
+
83
+ ## How it compiles
84
+
85
+ Three phases take prose to runtime, plus an optional optimizer:
86
+
87
+ 1. **text → GEARS** ([slc/text2gears.md](slc/text2gears.md)) — normative
88
+ spec items, one per state behavior, partitioned by trigger and prompt
89
+ content.
90
+ 2. **GEARS → FSM** ([slc/gears2fsm.md](slc/gears2fsm.md)) — an XState v5
91
+ machine; each gear maps to one direct-Captain, delegated-player, or
92
+ nested-playbook state with a typed actor contract. The compiled FSM
93
+ can be visualized and simulated with the bundled
94
+ [XState sketch visualizer](views/sketch).
95
+ 3. **FSM → runtime** ([slc/link.md](slc/link.md)) — a host-agnostic
96
+ module that drives Boss turns through ports the host wires up.
257
97
 
258
- playbooks:
259
- code:
260
- from: '@sublang/playbook/code/registry'
261
- players:
262
- coder: claude-opus-1m
263
- reviewer: codex-gpt
264
- committer: coder # which role commits — `coder` or `reviewer`
265
- ```
98
+ Between the first two, [slc/optimize.md](slc/optimize.md) may rewrite a
99
+ deterministic mechanical gear — canonically git repository setup — into a
100
+ *script item* the runtime executes directly, with no agent call.
101
+ Unoptimized compiles are byte-identical, so the pass is opt-in.
266
102
 
267
- `committer` is CODE's one option: an alias naming which role runs the
268
- commit turn (fallback semantics:
269
- [PBRT-8](specs/dev/playbook-runtime.md#pbrt-8)). Each role's per-run
270
- prompt names its pinned `model`, else its `adapter`
271
- ([PBRT-4](specs/user/playbook-runtime.md#pbrt-4)), so commit trailers
272
- can credit the concrete model (e.g. `claude-opus-4-8[1m]`) rather than
273
- the adapter family.
103
+ The repository carries end-to-end worked examples: the generic default
104
+ Captain from [`reference/sdlc/captain.md`](reference/sdlc/captain.md),
105
+ CODE — a coder / reviewer / committer loop — from
106
+ [`reference/sdlc/code.md`](reference/sdlc/code.md), and DISCUSS two
107
+ agents converging on spec items — from
108
+ [`reference/sdlc/discuss.md`](reference/sdlc/discuss.md). Together they
109
+ show direct Captain work, sequential nested playbook calls, and parallel
110
+ players. Compiled artifacts live beside each source in
111
+ `<basename>.playbook/`, the [slc](https://github.com/sublang-ai/slc)
112
+ pipeline's output directory.
274
113
 
275
- If you need a separate config file for a one-off run, pass a raw
276
- `tmux-play` config explicitly; this bypasses the seed, composition, and
277
- readiness gate and forwards the arguments to `tmux-play` verbatim
278
- ([PBCLI-1](specs/user/playbook-cli.md#pbcli-1)):
114
+ ## Contributing
279
115
 
280
- ```sh
281
- playbook --config ./tmux-play.config.yaml
282
- ```
116
+ We welcome contributions of all kinds.
283
117
 
284
- ### Install (contributors / from source)
118
+ - 🌟 Star our repo if you find playbook useful.
119
+ - [Open an issue](https://github.com/sublang-ai/playbook/issues) for bugs or feature requests.
120
+ - [Open a PR](https://github.com/sublang-ai/playbook/pulls) for fixes or improvements.
121
+ - Discuss on [Discord](https://discord.gg/XxTPjNqy9g) for support or new ideas.
285
122
 
286
- The checked-in lockfile resolves every runtime contract required by the
287
- source tree:
123
+ From source:
288
124
 
289
125
  ```sh
290
126
  git clone https://github.com/sublang-ai/playbook.git
@@ -292,95 +128,23 @@ cd playbook
292
128
  pnpm install --frozen-lockfile
293
129
  pnpm build
294
130
  pnpm test
131
+ pnpm playbook # drive a Boss turn against the source tree
295
132
  ```
296
133
 
297
- To co-develop Playbook with an unreleased cligent checkout, clone
298
- cligent beside this repository, build it, and copy
299
- `pnpm-workspace.yaml.example` to the gitignored
300
- `pnpm-workspace.yaml`. That optional override links the sibling checkout
301
- in place of the registry version. Do not commit the local lockfile
302
- rewrite it produces ([RELEASE-11](specs/dev/release.md#release-11)).
303
-
304
- Drive a Boss turn against the source tree with the launcher, which
305
- resolves `tmux-play`, the Playbook Captain shell, and the CODE registry
306
- from the local package:
307
-
308
- ```sh
309
- pnpm playbook
310
- ```
311
-
312
- On first run this seeds the generic config at
313
- `${XDG_CONFIG_HOME:-$HOME/.config}/playbook/playbook.config.yaml`
314
- (see [Configure agents](#configure-agents)) and launches the composed
315
- session, so this works whether or not `@sublang/cligent` is installed
316
- globally.
317
-
318
- ### Running a Boss turn
319
-
320
- The Boss pane starts at the Playbook Captain shell. Use `/code <task>`
321
- to explicitly select the CODE playbook, or use ordinary text and let the
322
- compiled default Captain ask a material routing question or plan one or more
323
- enabled playbook calls. It cannot answer the initial intent directly;
324
- calls run sequentially so Captain can reassess after every child result
325
- and then return a concrete result or actionable conclusion. Once a turn
326
- reaches CODE, the CODE judge classifies it into an FSM event (start a coding
327
- turn, continue or summarize an iteration, interrupt to a named state, or
328
- nothing) per
329
- [PBRT-1](specs/user/playbook-runtime.md#pbrt-1).
330
- When a player surfaces a clarifying question
331
- the FSM parks, the pane shows the question, and your
332
- next turn is normally classified as the reply — or a fresh directive
333
- abandons it ([PBRT-2](specs/user/playbook-runtime.md#pbrt-2)).
334
-
335
- The Captain pane shows `/code` start/stop/finished status with `◇` lines
336
- and streams CODE progress with captain-speech classification/questions
337
- per [PBRT-3](specs/user/playbook-runtime.md#pbrt-3), while player
338
- prompts ride their own panes.
339
-
340
- ### Embedding the runtime in your own host
341
-
342
- The runtime is host-agnostic — the `tmux-play` adapter is one host. The
343
- port and runtime contracts live in the type-only, semver-stable module
344
- [`@sublang/playbook/runtime`](src/runtime.ts): a host satisfies the six
345
- ports once and inherits every playbook. See
346
- [docs/embedding.md](docs/embedding.md) for the contract surface, a
347
- complete ports example, session/trace semantics, and how to read the
348
- published compiler-phase specs from the package.
349
-
350
- ## Workflow
351
-
352
- playbook is itself spec-driven: the compiler phases are specs in `slc/`,
353
- and the reference playbook is regenerated from its prose source. The
354
- loop:
355
-
356
- 1. **Edit source.** The worked examples include
357
- [`reference/sdlc/code.md`](reference/sdlc/code.md) and the generic
358
- [`reference/sdlc/captain.md`](reference/sdlc/captain.md).
359
- 2. **Recompile gears** per [`slc/text2gears.md`](slc/text2gears.md) into
360
- the source's `<name>.playbook/<name>.gears.md`.
361
- 3. **Recompile FSM and runtime** per
362
- [`slc/gears2fsm.md`](slc/gears2fsm.md) and
363
- [`slc/link.md`](slc/link.md) into that playbook artifact directory.
364
- 4. **Sync runtime, tests, and downstream specs** so `pnpm test` stays
365
- green and the introspect contract holds 1:1 between gear items and
366
- FSM direct-Captain, delegated-player, and nested-playbook states.
367
- 5. **Commit** with co-author trailers per
368
- [`specs/dev/git.md`](specs/dev/git.md).
369
-
370
- The behavioral contract between gears and FSM
371
- ([PLAYBOOK-1..6](specs/dev/playbook.md)) and the runtime contract that
372
- ports satisfy ([the PBRT dev items](specs/dev/playbook-runtime.md)) are
373
- pinned in [`specs/dev/`](specs/dev/) and verified by tests under the
374
- reference package.
375
-
376
- ## Contributing
377
-
378
- We welcome contributions of all kinds.
379
-
380
- - 🌟 Star our repo if you find playbook useful.
381
- - [Open an issue](https://github.com/sublang-ai/playbook/issues) for bugs or feature requests.
382
- - [Open a PR](https://github.com/sublang-ai/playbook/pulls) for fixes or improvements.
383
- - Discuss on [Discord](https://discord.gg/XxTPjNqy9g) for support or new ideas.
134
+ To co-develop against an unreleased cligent checkout, clone it beside
135
+ this repository, build it, and copy `pnpm-workspace.yaml.example` to the
136
+ gitignored `pnpm-workspace.yaml`. Do not commit the lockfile rewrite it
137
+ produces ([RELEASE-11](specs/dev/release.md#release-11)).
138
+
139
+ playbook is itself spec-driven: the compiler phases are specs in
140
+ [`slc/`](slc), and the reference playbooks are regenerated from their
141
+ prose sources. Edit a source, recompile gears then FSM and runtime into
142
+ its artifact directory, sync tests and downstream specs until
143
+ `pnpm test` is green, and commit with co-author trailers per
144
+ [`specs/dev/git.md`](specs/dev/git.md). The gears↔FSM contract
145
+ ([the PLAYBOOK dev items](specs/dev/playbook.md)) and the runtime
146
+ contract ([the PBRT dev items](specs/dev/playbook-runtime.md)) are
147
+ pinned in [`specs/dev/`](specs/dev) and verified by the test suite.
384
148
 
385
149
  ## License
386
150
 
package/docs/cli.md ADDED
@@ -0,0 +1,123 @@
1
+ <!-- SPDX-License-Identifier: Apache-2.0 -->
2
+ <!-- SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai> -->
3
+
4
+ # Using the CLI
5
+
6
+ `playbook` has two surfaces: an interactive tmux-play session, and a
7
+ one-shot non-interactive `run`. Agent settings for both come from the
8
+ [config](configuration.md).
9
+
10
+ ## Interactive
11
+
12
+ ```sh
13
+ playbook # launch the configured playbooks in tmux-play
14
+ playbook --list # ids, slash commands, and intents; no launch
15
+ playbook --help # config path, auth pointers, agent-swap recipe
16
+ ```
17
+
18
+ Without a global install, `npx @sublang/playbook` runs the same bin.
19
+
20
+ The command resolves its config (seeding it on first run), composes a
21
+ `tmux-play` config, checks adapter readiness, and launches. It exits
22
+ with tmux-play's status, re-raises a terminating signal on itself, and
23
+ exits `127` when it cannot launch at all
24
+ ([PBCLI-1](../specs/user/playbook-cli.md#pbcli-1),
25
+ [PBCLI-2](../specs/user/playbook-cli.md#pbcli-2)).
26
+
27
+ ### Running a Boss turn
28
+
29
+ The Boss pane starts at the Playbook Captain shell. Use `/code <task>`
30
+ to select the CODE playbook explicitly, or type ordinary text and let
31
+ the compiled default Captain ask a material routing question or plan one
32
+ or more enabled playbook calls. It cannot answer the initial intent
33
+ directly; calls run sequentially so Captain can reassess after every
34
+ child result and then return a concrete result or actionable conclusion.
35
+
36
+ Once a turn reaches CODE, the CODE judge classifies it into an FSM event
37
+ — start a coding turn, continue or summarize an iteration, interrupt to
38
+ a named state, or nothing
39
+ ([PBRT-1](../specs/user/playbook-runtime.md#pbrt-1)). When a player
40
+ surfaces a clarifying question the FSM parks, the pane shows the
41
+ question, and your next turn is normally classified as the reply — a
42
+ fresh directive abandons it
43
+ ([PBRT-2](../specs/user/playbook-runtime.md#pbrt-2)).
44
+
45
+ The Captain pane shows start/stop/finished status with `◇` lines and
46
+ streams progress with captain-speech classification and questions
47
+ ([PBRT-3](../specs/user/playbook-runtime.md#pbrt-3)), while player
48
+ prompts ride their own panes.
49
+
50
+ ## Non-interactive
51
+
52
+ `playbook run <from> [task]` runs one playbook once, without tmux-play
53
+ and without a config entry — point it straight at a registry module:
54
+
55
+ ```sh
56
+ playbook run @sublang/playbook/code/registry "add a test for parseArgs" \
57
+ --player coder=claude --player reviewer=codex --cwd ./my-repo
58
+ ```
59
+
60
+ `[task]` is read from stdin when omitted — pipe long or multi-line
61
+ intents the same way you would to `claude -p` or `codex exec`.
62
+
63
+ | Flag | Meaning |
64
+ | --- | --- |
65
+ | `--player <role>=<agent>` | bind a required role |
66
+ | `--captain <agent>` | set the captain/judge agent |
67
+ | `--option <key>=<value>` | a playbook option (CODE's `committer`) |
68
+ | `--cwd <dir>` | the agents' working directory |
69
+ | `--json` | one envelope: `outcome`, `sessionId`, output or questions |
70
+ | `--no-provision` | never create engine links beside a filesystem `<from>` |
71
+
72
+ `<agent>` is `<adapter>[:<model>][@<effort>]` — `codex:gpt-5.5@xhigh`,
73
+ or `claude@high` for the default model at high reasoning effort. The
74
+ model keeps every interior colon (`opencode:ollama/llama3:8b@max`), and
75
+ an unsupported effort is rejected up front naming the adapter's
76
+ supported values. Roles and the captain default to `claude` unless the
77
+ config supplies [run defaults](configuration.md#defaults-for-playbook-run).
78
+
79
+ Exit codes: `0` terminal, `1` bad argument or module, `2` failure, `3`
80
+ the playbook needs a Boss reply
81
+ ([PBCLI-18](../specs/user/playbook-cli.md#pbcli-18)).
82
+
83
+ ### Engine provisioning
84
+
85
+ A compiled playbook module imports `xstate` and
86
+ `@sublang/playbook/xstate-runtime` from its own directory. When a
87
+ filesystem `<from>` cannot resolve them — typically under a global
88
+ `npm install -g @sublang/playbook` with no project-local packages —
89
+ `playbook run` provisions them automatically before loading: it creates
90
+ `node_modules/xstate` and `node_modules/@sublang/playbook` beside the
91
+ module as symlinks to the running host's own packages and prints one
92
+ line naming what it linked
93
+ ([PBCLI-36](../specs/user/playbook-cli.md#pbcli-36),
94
+ [DR-024](../specs/decisions/024-runtime-engine-provisioning.md)).
95
+ A directory where the imports already resolve is never touched — a
96
+ project-local install always wins — and `--no-provision` disables the
97
+ mechanism entirely.
98
+
99
+ If the module's directory is a git repository, add `node_modules/` to
100
+ its `.gitignore` so the provisioned links never land in commits made by
101
+ player agents working there.
102
+
103
+ ### Resuming a parked run
104
+
105
+ When the playbook stops to ask something, the run is parked, not lost:
106
+ the question prints to stdout, the session is saved under
107
+ `${XDG_STATE_HOME:-$HOME/.local/state}/playbook/sessions/`, and stderr
108
+ names the command that continues it.
109
+
110
+ ```sh
111
+ playbook run resume 4f2c…9ab1 "keep the scope small; skip the docs"
112
+ playbook run resume --last # most recently parked session; reply on stdin
113
+ ```
114
+
115
+ A resumed run picks up exactly where it parked — same session id, same
116
+ workflow state, and each agent continues its own conversation — then
117
+ prints the final output and exits `0`, or parks again and exits `3`. The
118
+ lineup, options, and working directory are stored with the session, so
119
+ `resume` takes no binding flags. In scripts, capture the session id from
120
+ the `--json` envelope, like Claude Code's `session_id` or
121
+ `codex exec resume`
122
+ ([PBCLI-22](../specs/user/playbook-cli.md#pbcli-22),
123
+ [DR-014](../specs/decisions/014-durable-one-shot-run-sessions.md)).