@sublang/playbook 0.9.0 → 1.3.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.
- package/README.md +190 -151
- package/package.json +50 -6
- package/reference/sdlc/captain.md +102 -0
- package/reference/sdlc/captain.playbook/captain.fsm.d.ts +227 -0
- package/reference/sdlc/captain.playbook/captain.fsm.js +628 -0
- package/reference/sdlc/captain.playbook/captain.fsm.ts +851 -0
- package/reference/sdlc/captain.playbook/captain.gears.md +60 -0
- package/reference/sdlc/captain.playbook/captain.playbook.d.ts +23 -0
- package/reference/sdlc/captain.playbook/captain.playbook.js +1053 -0
- package/reference/sdlc/captain.playbook/captain.playbook.ts +1144 -0
- package/reference/sdlc/code.playbook/bin/playbook.js +158 -12
- package/reference/sdlc/code.playbook/bin/run.js +999 -0
- package/reference/sdlc/code.playbook/code.fsm.d.ts +11 -4
- package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +2 -2
- package/reference/sdlc/code.playbook/code.fsm.introspect.js +1 -1
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +6 -6
- package/reference/sdlc/code.playbook/code.fsm.js +334 -102
- package/reference/sdlc/code.playbook/code.fsm.ts +467 -180
- package/reference/sdlc/code.playbook/code.gears.md +11 -10
- package/reference/sdlc/code.playbook/code.playbook.d.ts +16 -19
- package/reference/sdlc/code.playbook/code.playbook.js +199 -488
- package/reference/sdlc/code.playbook/code.playbook.ts +327 -566
- package/reference/sdlc/code.playbook/code.registry.d.ts +0 -3
- package/reference/sdlc/code.playbook/code.registry.js +0 -3
- package/reference/sdlc/code.playbook/code.registry.ts +0 -6
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +9 -4
- package/reference/sdlc/code.playbook/playbook-captain.js +889 -210
- package/reference/sdlc/code.playbook/playbook-captain.ts +1136 -257
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +21 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.d.ts +396 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.js +2066 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.ts +2464 -0
- package/reference/sdlc/discuss.playbook/discuss.gears.md +251 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.d.ts +113 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.js +1514 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.ts +1926 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.d.ts +58 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.js +97 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.ts +153 -0
- package/slc/gears2fsm.md +557 -57
- package/slc/link.md +1165 -89
- package/slc/optimize.md +92 -0
- package/slc/text2gears.md +255 -7
- package/src/runtime.d.ts +146 -3
- package/src/runtime.ts +201 -2
- package/src/xstate-playbook-runtime.d.ts +201 -0
- package/src/xstate-playbook-runtime.js +2058 -0
- package/src/xstate-playbook-runtime.ts +2792 -0
- package/src/xstate-runtime.d.ts +95 -0
- package/src/xstate-runtime.js +1258 -0
- package/src/xstate-runtime.ts +1816 -0
package/README.md
CHANGED
|
@@ -7,28 +7,49 @@
|
|
|
7
7
|
[](https://nodejs.org/)
|
|
8
8
|
[](https://github.com/sublang-ai/playbook/actions/workflows/ci.yml)
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
_Skills made reliable through state machines and visualization._
|
|
11
11
|
|
|
12
12
|
playbook is a compiler stack and reference implementation for turning a
|
|
13
13
|
natural-language procedure into a runnable, inspectable state-machine
|
|
14
|
-
agent — a
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
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
|
|
26
|
+
[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.
|
|
20
35
|
2. **GEARS → FSM** ([slc/gears2fsm.md](slc/gears2fsm.md)) — an XState v5
|
|
21
|
-
finite state machine; each gear maps to one
|
|
22
|
-
with a typed
|
|
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).
|
|
23
40
|
3. **FSM → runtime** ([slc/link.md](slc/link.md)) — a host-agnostic
|
|
24
41
|
module that drives Boss turns through ports the host wires up
|
|
25
42
|
(cligent's `tmux-play` is one such host).
|
|
26
43
|
|
|
27
|
-
The repository
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
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.
|
|
32
53
|
|
|
33
54
|
## Getting started — the reference CODE playbook
|
|
34
55
|
|
|
@@ -40,7 +61,26 @@ the runtime registered behind the built-in Playbook Captain shell for
|
|
|
40
61
|
cligent's `tmux-play` host out of the box.
|
|
41
62
|
The compiled artifacts live under
|
|
42
63
|
[`reference/sdlc/code.playbook/`](reference/sdlc/code.playbook),
|
|
43
|
-
the slc pipeline's
|
|
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.
|
|
72
|
+
|
|
73
|
+
### Requirements
|
|
74
|
+
|
|
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`.
|
|
44
84
|
|
|
45
85
|
### Install (users)
|
|
46
86
|
|
|
@@ -91,6 +131,58 @@ bypass permissions. The seeded Codex Reviewer additionally grants
|
|
|
91
131
|
available under the Codex sandbox; the Claude agents need no such grant
|
|
92
132
|
under their auto mode.
|
|
93
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
|
+
|
|
94
186
|
### Configure agents
|
|
95
187
|
|
|
96
188
|
Edit the seeded user config when you want different coding agents:
|
|
@@ -99,33 +191,44 @@ Edit the seeded user config when you want different coding agents:
|
|
|
99
191
|
$EDITOR "${XDG_CONFIG_HOME:-$HOME/.config}/playbook/playbook.config.yaml"
|
|
100
192
|
```
|
|
101
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
|
+
```
|
|
201
|
+
|
|
202
|
+
```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
|
+
playbooks:
|
|
207
|
+
code:
|
|
208
|
+
players:
|
|
209
|
+
coder: codex-fast
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
See [PBCLI-25](specs/user/playbook-cli.md#pbcli-25) and
|
|
213
|
+
[DR-015](specs/decisions/015-per-run-agent-tuning.md).
|
|
214
|
+
|
|
102
215
|
The config is top-level (no `config:` wrapper): a `profiles` map of
|
|
103
|
-
reusable agent settings, a `captain`
|
|
104
|
-
|
|
105
|
-
`
|
|
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
|
|
106
220
|
shorthand (`claude`, `codex`); other adapter ids are passed through to
|
|
107
221
|
`tmux-play` with a warning because `playbook` cannot preflight their
|
|
108
222
|
auth. Name profiles by their underlying agent/model (e.g. `claude-opus`,
|
|
109
|
-
`codex-gpt`) so the profile ids read distinctly from the
|
|
110
|
-
|
|
111
|
-
`command` (an optional slash-command override), and
|
|
112
|
-
launcher-owned; every other key
|
|
113
|
-
|
|
114
|
-
namespaced `<id>-<role>` host players, so you do not write those by
|
|
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
|
|
115
228
|
hand.
|
|
116
229
|
|
|
117
|
-
CODE's per-run `<coder-llm>` / `<reviewer-llm>` prompt strings come from
|
|
118
|
-
each role's pinned `model`, else its `adapter`
|
|
119
|
-
([PBRT-4](specs/user/playbook-runtime.md#pbrt-4)) — so the Committer's
|
|
120
|
-
commit-message trailers can name the concrete model
|
|
121
|
-
(e.g. `claude-opus-4-8[1m]`) rather than the adapter family (`claude`).
|
|
122
|
-
`committer` is an optional CODE alias naming which role — `coder` or
|
|
123
|
-
`reviewer` — runs the commit turn; the seeded config points it at the
|
|
124
|
-
Coder, and absent the alias the Committer falls back to the Coder
|
|
125
|
-
([PBRT-8](specs/user/playbook-runtime.md#pbrt-8)).
|
|
126
|
-
|
|
127
230
|
For example, the seeded config runs the Coder on Claude Opus 4.8 1m and
|
|
128
|
-
the Reviewer on GPT-5.5
|
|
231
|
+
the Reviewer on GPT-5.5:
|
|
129
232
|
|
|
130
233
|
```yaml
|
|
131
234
|
profiles:
|
|
@@ -134,13 +237,13 @@ profiles:
|
|
|
134
237
|
model: claude-opus-4-8
|
|
135
238
|
reasoningEffort: high
|
|
136
239
|
permissions:
|
|
137
|
-
mode: auto
|
|
240
|
+
mode: auto # protected auto mode for the Claude Captain
|
|
138
241
|
claude-opus-1m:
|
|
139
242
|
adapter: claude
|
|
140
243
|
model: claude-opus-4-8[1m]
|
|
141
244
|
reasoningEffort: xhigh
|
|
142
245
|
permissions:
|
|
143
|
-
mode: auto
|
|
246
|
+
mode: auto # protected auto mode for the Claude Coder
|
|
144
247
|
codex-gpt:
|
|
145
248
|
adapter: codex
|
|
146
249
|
model: gpt-5.5
|
|
@@ -148,19 +251,27 @@ profiles:
|
|
|
148
251
|
permissions:
|
|
149
252
|
mode: auto
|
|
150
253
|
writablePaths:
|
|
151
|
-
- .git
|
|
254
|
+
- .git # allow git metadata writes under Codex auto mode
|
|
152
255
|
|
|
153
256
|
captain: claude-opus
|
|
154
257
|
|
|
155
258
|
playbooks:
|
|
156
259
|
code:
|
|
157
|
-
from:
|
|
260
|
+
from: '@sublang/playbook/code/registry'
|
|
158
261
|
players:
|
|
159
262
|
coder: claude-opus-1m
|
|
160
263
|
reviewer: codex-gpt
|
|
161
|
-
committer: coder
|
|
264
|
+
committer: coder # which role commits — `coder` or `reviewer`
|
|
162
265
|
```
|
|
163
266
|
|
|
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.
|
|
274
|
+
|
|
164
275
|
If you need a separate config file for a one-off run, pass a raw
|
|
165
276
|
`tmux-play` config explicitly; this bypasses the seed, composition, and
|
|
166
277
|
readiness gate and forwards the arguments to `tmux-play` verbatim
|
|
@@ -172,33 +283,23 @@ playbook --config ./tmux-play.config.yaml
|
|
|
172
283
|
|
|
173
284
|
### Install (contributors / from source)
|
|
174
285
|
|
|
175
|
-
|
|
286
|
+
The checked-in lockfile resolves every runtime contract required by the
|
|
287
|
+
source tree:
|
|
176
288
|
|
|
177
289
|
```sh
|
|
178
290
|
git clone https://github.com/sublang-ai/playbook.git
|
|
179
291
|
cd playbook
|
|
180
|
-
pnpm install
|
|
292
|
+
pnpm install --frozen-lockfile
|
|
181
293
|
pnpm build
|
|
182
294
|
pnpm test
|
|
183
295
|
```
|
|
184
296
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
release (see [RELEASE-14](specs/dev/release.md#release-14)). To
|
|
192
|
-
refresh the contributor pin within that range, run
|
|
193
|
-
`pnpm update @sublang/cligent` and commit the resulting
|
|
194
|
-
`pnpm-lock.yaml` change. To adopt a later cligent minor, update the
|
|
195
|
-
`package.json` specifier and lockfile together.
|
|
196
|
-
No local link required for any of this. To point pnpm at a local
|
|
197
|
-
`cligent` checkout
|
|
198
|
-
instead, copy
|
|
199
|
-
[`pnpm-workspace.yaml.example`](pnpm-workspace.yaml.example)
|
|
200
|
-
into place; the override is gitignored so it never leaks into a
|
|
201
|
-
production install.
|
|
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)).
|
|
202
303
|
|
|
203
304
|
Drive a Boss turn against the source tree with the launcher, which
|
|
204
305
|
resolves `tmux-play`, the Playbook Captain shell, and the CODE registry
|
|
@@ -218,87 +319,33 @@ globally.
|
|
|
218
319
|
|
|
219
320
|
The Boss pane starts at the Playbook Captain shell. Use `/code <task>`
|
|
220
321
|
to explicitly select the CODE playbook, or use ordinary text and let the
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
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
|
|
224
329
|
[PBRT-1](specs/user/playbook-runtime.md#pbrt-1).
|
|
225
330
|
When a player surfaces a clarifying question
|
|
226
|
-
the FSM parks
|
|
227
|
-
next turn is normally classified as the reply
|
|
331
|
+
the FSM parks, the pane shows the question, and your
|
|
332
|
+
next turn is normally classified as the reply — or a fresh directive
|
|
228
333
|
abandons it ([PBRT-2](specs/user/playbook-runtime.md#pbrt-2)).
|
|
229
334
|
|
|
230
335
|
The Captain pane shows `/code` start/stop/finished status with `◇` lines
|
|
231
|
-
and streams
|
|
232
|
-
[PBRT-3](specs/user/playbook-runtime.md#pbrt-3), while player
|
|
233
|
-
ride their own panes.
|
|
234
|
-
|
|
235
|
-
Published configs import the shell adapter from
|
|
236
|
-
`@sublang/playbook/playbook-captain` and enable CODE through a
|
|
237
|
-
`captain.options.playbooks.code` block whose `from` is
|
|
238
|
-
`@sublang/playbook/code/registry`. The generic `playbook` launcher
|
|
239
|
-
composes this for you from the top-level `profiles` / `playbooks`
|
|
240
|
-
config above.
|
|
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.
|
|
241
339
|
|
|
242
340
|
### Embedding the runtime in your own host
|
|
243
341
|
|
|
244
|
-
The runtime is host-agnostic
|
|
245
|
-
|
|
246
|
-
[`@sublang/playbook/runtime`](src/runtime.ts)
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
`@sublang/playbook/code/playbook`; `PlaybookRuntimeFactory` is available
|
|
252
|
-
from `@sublang/playbook/runtime`.
|
|
253
|
-
Construct the runtime against your own ports:
|
|
254
|
-
|
|
255
|
-
```ts
|
|
256
|
-
import createPlaybookRuntime from '@sublang/playbook/code/playbook';
|
|
257
|
-
import type { PlaybookPorts } from '@sublang/playbook/runtime';
|
|
258
|
-
|
|
259
|
-
const ports: PlaybookPorts = {
|
|
260
|
-
callPlayer: async (playerId, prompt, signal) => { /* … */ },
|
|
261
|
-
callJudge: async (prompt, signal) => { /* … */ },
|
|
262
|
-
emitStatus: async (message, data) => { /* … */ },
|
|
263
|
-
emitTelemetry: async ({ topic, payload }) => { /* … */ },
|
|
264
|
-
};
|
|
265
|
-
|
|
266
|
-
const runtime = createPlaybookRuntime({
|
|
267
|
-
coderPlayer: 'claude',
|
|
268
|
-
reviewerPlayer: 'codex',
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
await runtime.init(ports);
|
|
272
|
-
await runtime.handleBossInput({
|
|
273
|
-
text: 'Start fixing the bug',
|
|
274
|
-
signal: new AbortController().signal,
|
|
275
|
-
});
|
|
276
|
-
await runtime.dispose();
|
|
277
|
-
```
|
|
278
|
-
|
|
279
|
-
See
|
|
280
|
-
[`code.playbook.test.ts`](reference/sdlc/code.playbook/code.playbook.test.ts)
|
|
281
|
-
for the full range of port shapes (classifier, judge, abort, interrupt,
|
|
282
|
-
status/telemetry) the runtime is contract-tested against.
|
|
283
|
-
|
|
284
|
-
### Reading the published spec contracts
|
|
285
|
-
|
|
286
|
-
The authored compiler-phase specs ship in the package and are exposed
|
|
287
|
-
as a public, semver-stable surface under `@sublang/playbook/slc/*`.
|
|
288
|
-
Resolve and read one with `import.meta.resolve` plus `fs`:
|
|
289
|
-
|
|
290
|
-
```ts
|
|
291
|
-
import { readFile } from 'node:fs/promises';
|
|
292
|
-
import { fileURLToPath } from 'node:url';
|
|
293
|
-
|
|
294
|
-
const url = import.meta.resolve('@sublang/playbook/slc/link.md');
|
|
295
|
-
const link = await readFile(fileURLToPath(url), 'utf8');
|
|
296
|
-
```
|
|
297
|
-
|
|
298
|
-
The three specs are [`slc/text2gears.md`](slc/text2gears.md),
|
|
299
|
-
[`slc/gears2fsm.md`](slc/gears2fsm.md), and [`slc/link.md`](slc/link.md)
|
|
300
|
-
— the FSM-to-runtime contract that `@sublang/playbook/runtime` projects
|
|
301
|
-
into TypeScript.
|
|
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.
|
|
302
349
|
|
|
303
350
|
## Workflow
|
|
304
351
|
|
|
@@ -306,33 +353,25 @@ playbook is itself spec-driven: the compiler phases are specs in `slc/`,
|
|
|
306
353
|
and the reference playbook is regenerated from its prose source. The
|
|
307
354
|
loop:
|
|
308
355
|
|
|
309
|
-
1. **Edit source.**
|
|
310
|
-
[`reference/sdlc/code.md`](reference/sdlc/code.md)
|
|
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).
|
|
311
359
|
2. **Recompile gears** per [`slc/text2gears.md`](slc/text2gears.md) into
|
|
312
|
-
the
|
|
313
|
-
3. **Recompile FSM** per
|
|
314
|
-
|
|
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.
|
|
315
364
|
4. **Sync runtime, tests, and downstream specs** so `pnpm test` stays
|
|
316
365
|
green and the introspect contract holds 1:1 between gear items and
|
|
317
|
-
FSM
|
|
366
|
+
FSM direct-Captain, delegated-player, and nested-playbook states.
|
|
318
367
|
5. **Commit** with co-author trailers per
|
|
319
368
|
[`specs/dev/git.md`](specs/dev/git.md).
|
|
320
369
|
|
|
321
370
|
The behavioral contract between gears and FSM
|
|
322
371
|
([PLAYBOOK-1..6](specs/dev/playbook.md)) and the runtime contract that
|
|
323
|
-
ports satisfy ([PBRT
|
|
324
|
-
in [`specs/dev/`](specs/dev/) and verified by tests under the
|
|
325
|
-
package.
|
|
326
|
-
|
|
327
|
-
## Requirements
|
|
328
|
-
|
|
329
|
-
- Node.js ≥ 20.6.0 (the `playbook` launcher uses
|
|
330
|
-
`import.meta.resolve`, unflagged since this release)
|
|
331
|
-
- pnpm 9 (for the reference package)
|
|
332
|
-
- A configured `tmux-play` host (for live Boss turns) — requires
|
|
333
|
-
`tmux` and [`glow`](https://github.com/charmbracelet/glow#installation)
|
|
334
|
-
on `PATH`; cligent 0.4+ uses `glow` to render Markdown pane
|
|
335
|
-
output and fails fast without it
|
|
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.
|
|
336
375
|
|
|
337
376
|
## Contributing
|
|
338
377
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sublang/playbook",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"type": "module",
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Composable XState v5 playbook runtime with compiled Captain, CODE, and DISCUSS workflows driven by GEARS specs.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"homepage": "https://github.com/sublang-ai/playbook#readme",
|
|
8
8
|
"repository": {
|
|
@@ -28,9 +28,24 @@
|
|
|
28
28
|
"src/runtime.ts",
|
|
29
29
|
"src/runtime.js",
|
|
30
30
|
"src/runtime.d.ts",
|
|
31
|
+
"src/xstate-runtime.ts",
|
|
32
|
+
"src/xstate-runtime.js",
|
|
33
|
+
"src/xstate-runtime.d.ts",
|
|
34
|
+
"src/xstate-playbook-runtime.ts",
|
|
35
|
+
"src/xstate-playbook-runtime.js",
|
|
36
|
+
"src/xstate-playbook-runtime.d.ts",
|
|
31
37
|
"slc/link.md",
|
|
32
38
|
"slc/gears2fsm.md",
|
|
33
39
|
"slc/text2gears.md",
|
|
40
|
+
"slc/optimize.md",
|
|
41
|
+
"reference/sdlc/captain.md",
|
|
42
|
+
"reference/sdlc/captain.playbook/captain.gears.md",
|
|
43
|
+
"reference/sdlc/captain.playbook/captain.fsm.ts",
|
|
44
|
+
"reference/sdlc/captain.playbook/captain.fsm.js",
|
|
45
|
+
"reference/sdlc/captain.playbook/captain.fsm.d.ts",
|
|
46
|
+
"reference/sdlc/captain.playbook/captain.playbook.ts",
|
|
47
|
+
"reference/sdlc/captain.playbook/captain.playbook.js",
|
|
48
|
+
"reference/sdlc/captain.playbook/captain.playbook.d.ts",
|
|
34
49
|
"reference/sdlc/code.playbook/code.fsm.ts",
|
|
35
50
|
"reference/sdlc/code.playbook/code.fsm.js",
|
|
36
51
|
"reference/sdlc/code.playbook/code.fsm.d.ts",
|
|
@@ -48,7 +63,18 @@
|
|
|
48
63
|
"reference/sdlc/code.playbook/playbook-captain.d.ts",
|
|
49
64
|
"reference/sdlc/code.playbook/code.gears.md",
|
|
50
65
|
"reference/sdlc/code.playbook/playbook.config.template.yaml",
|
|
51
|
-
"reference/sdlc/code.playbook/bin/playbook.js"
|
|
66
|
+
"reference/sdlc/code.playbook/bin/playbook.js",
|
|
67
|
+
"reference/sdlc/code.playbook/bin/run.js",
|
|
68
|
+
"reference/sdlc/discuss.playbook/discuss.gears.md",
|
|
69
|
+
"reference/sdlc/discuss.playbook/discuss.fsm.ts",
|
|
70
|
+
"reference/sdlc/discuss.playbook/discuss.fsm.js",
|
|
71
|
+
"reference/sdlc/discuss.playbook/discuss.fsm.d.ts",
|
|
72
|
+
"reference/sdlc/discuss.playbook/discuss.playbook.ts",
|
|
73
|
+
"reference/sdlc/discuss.playbook/discuss.playbook.js",
|
|
74
|
+
"reference/sdlc/discuss.playbook/discuss.playbook.d.ts",
|
|
75
|
+
"reference/sdlc/discuss.playbook/discuss.registry.ts",
|
|
76
|
+
"reference/sdlc/discuss.playbook/discuss.registry.js",
|
|
77
|
+
"reference/sdlc/discuss.playbook/discuss.registry.d.ts"
|
|
52
78
|
],
|
|
53
79
|
"bin": {
|
|
54
80
|
"playbook": "reference/sdlc/code.playbook/bin/playbook.js"
|
|
@@ -58,6 +84,14 @@
|
|
|
58
84
|
"types": "./src/runtime.d.ts",
|
|
59
85
|
"default": "./src/runtime.js"
|
|
60
86
|
},
|
|
87
|
+
"./xstate-runtime": {
|
|
88
|
+
"types": "./src/xstate-runtime.d.ts",
|
|
89
|
+
"default": "./src/xstate-runtime.js"
|
|
90
|
+
},
|
|
91
|
+
"./captain/playbook": {
|
|
92
|
+
"types": "./reference/sdlc/captain.playbook/captain.playbook.d.ts",
|
|
93
|
+
"default": "./reference/sdlc/captain.playbook/captain.playbook.js"
|
|
94
|
+
},
|
|
61
95
|
"./code/playbook": {
|
|
62
96
|
"types": "./reference/sdlc/code.playbook/code.playbook.d.ts",
|
|
63
97
|
"default": "./reference/sdlc/code.playbook/code.playbook.js"
|
|
@@ -70,7 +104,15 @@
|
|
|
70
104
|
"types": "./reference/sdlc/code.playbook/playbook-captain.d.ts",
|
|
71
105
|
"default": "./reference/sdlc/code.playbook/playbook-captain.js"
|
|
72
106
|
},
|
|
73
|
-
"./slc/*": "./slc/*"
|
|
107
|
+
"./slc/*": "./slc/*",
|
|
108
|
+
"./discuss/playbook": {
|
|
109
|
+
"types": "./reference/sdlc/discuss.playbook/discuss.playbook.d.ts",
|
|
110
|
+
"default": "./reference/sdlc/discuss.playbook/discuss.playbook.js"
|
|
111
|
+
},
|
|
112
|
+
"./discuss/registry": {
|
|
113
|
+
"types": "./reference/sdlc/discuss.playbook/discuss.registry.d.ts",
|
|
114
|
+
"default": "./reference/sdlc/discuss.playbook/discuss.registry.js"
|
|
115
|
+
}
|
|
74
116
|
},
|
|
75
117
|
"scripts": {
|
|
76
118
|
"build": "tsc",
|
|
@@ -82,9 +124,11 @@
|
|
|
82
124
|
"provenance": true
|
|
83
125
|
},
|
|
84
126
|
"dependencies": {
|
|
85
|
-
"@anthropic-ai/claude-agent-sdk": "^0.3.
|
|
127
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.154",
|
|
86
128
|
"@openai/codex-sdk": "^0.139.0",
|
|
87
|
-
"@sublang/cligent": "^0.
|
|
129
|
+
"@sublang/cligent": "^0.15.0",
|
|
130
|
+
"@sublang/spex": "^0.3.0",
|
|
131
|
+
"p-queue": "^9.3.1",
|
|
88
132
|
"xstate": "^5.19.4",
|
|
89
133
|
"yaml": "^2.9.0"
|
|
90
134
|
},
|