@sublang/playbook 0.4.0 → 0.4.2
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 +27 -7
- package/package.json +2 -2
- package/reference/sdlc/code.playbook/bin/playbook-code.js +3 -1
- package/reference/sdlc/code.playbook/code.fsm.js +2 -0
- package/reference/sdlc/code.playbook/code.fsm.ts +2 -0
- package/reference/sdlc/code.playbook/code.gears.md +2 -0
- package/reference/sdlc/code.playbook/code.tmux-play.js +12 -4
- package/reference/sdlc/code.playbook/code.tmux-play.ts +12 -8
- package/reference/sdlc/code.playbook/playbook-code.config.template.yaml +15 -6
- package/reference/sdlc/code.playbook/tmux-play.config.yaml +11 -3
- package/reference/sdlc/code.playbook/tmux-play.production.config.yaml +6 -1
package/README.md
CHANGED
|
@@ -95,12 +95,14 @@ $EDITOR "${XDG_CONFIG_HOME:-$HOME/.config}/playbook/playbook-code.config.yaml"
|
|
|
95
95
|
Both CODE players can use `claude` or `codex`; other adapter ids are
|
|
96
96
|
passed through to `tmux-play` with a warning because `playbook-code`
|
|
97
97
|
does not know how to preflight their auth. The safe tuning points are
|
|
98
|
-
`captain.adapter`, `captain.model`,
|
|
99
|
-
`captain.from` and the `players[].id` values
|
|
100
|
-
to those host-configuration invariants per
|
|
98
|
+
`captain.adapter`, `captain.model`, each player's `adapter`, and each
|
|
99
|
+
player's `model`. Keep `captain.from` and the `players[].id` values
|
|
100
|
+
fixed; the runtime binds to those host-configuration invariants per
|
|
101
101
|
[PBRT-4](specs/user/playbook-runtime.md#pbrt-4) and derives the
|
|
102
102
|
`<coder-llm>` / `<reviewer-llm>` substitution strings from each
|
|
103
|
-
player entry's `adapter
|
|
103
|
+
player entry's `model` when pinned and `adapter` otherwise — so the
|
|
104
|
+
Committer's commit-message trailers can name the concrete model
|
|
105
|
+
(e.g. `claude-opus-4-7`) rather than the adapter family (`claude`).
|
|
104
106
|
|
|
105
107
|
For example, this swaps the Coder to Codex and the Reviewer to Claude:
|
|
106
108
|
|
|
@@ -108,17 +110,22 @@ For example, this swaps the Coder to Codex and the Reviewer to Claude:
|
|
|
108
110
|
captain:
|
|
109
111
|
from: "@sublang/playbook/code/tmux-play"
|
|
110
112
|
adapter: claude
|
|
111
|
-
model: claude-
|
|
113
|
+
model: claude-sonnet-4-6
|
|
114
|
+
reasoningEffort: high
|
|
112
115
|
permissions:
|
|
113
116
|
mode: auto
|
|
114
117
|
|
|
115
118
|
players:
|
|
116
119
|
- id: coder # must stay `coder` — see PBRT-4
|
|
117
120
|
adapter: codex
|
|
121
|
+
model: gpt-5.5
|
|
122
|
+
reasoningEffort: xhigh
|
|
118
123
|
permissions:
|
|
119
124
|
mode: auto
|
|
120
125
|
- id: reviewer # must stay `reviewer` — see PBRT-4
|
|
121
126
|
adapter: claude
|
|
127
|
+
model: claude-opus-4-7
|
|
128
|
+
reasoningEffort: xhigh
|
|
122
129
|
permissions:
|
|
123
130
|
mode: auto
|
|
124
131
|
```
|
|
@@ -145,8 +152,21 @@ pnpm build
|
|
|
145
152
|
pnpm test
|
|
146
153
|
```
|
|
147
154
|
|
|
148
|
-
`pnpm install`
|
|
149
|
-
|
|
155
|
+
`pnpm install` here installs the `@sublang/cligent` version pinned
|
|
156
|
+
in the checked-in `pnpm-lock.yaml` — the same version CI installs
|
|
157
|
+
via `--frozen-lockfile`, so contributor checkouts and CI agree.
|
|
158
|
+
The published `package.json` declares `@sublang/cligent` as
|
|
159
|
+
`latest`, so an end-user install with no lockfile (e.g., `npm
|
|
160
|
+
install -g @sublang/playbook`) instead resolves whichever cligent
|
|
161
|
+
release currently carries the `latest` dist-tag at install time
|
|
162
|
+
(see [RELEASE-14](specs/dev/release.md#release-14)). To bump the
|
|
163
|
+
contributor pin to today's `latest`, run
|
|
164
|
+
`pnpm update @sublang/cligent` and commit the resulting
|
|
165
|
+
`pnpm-lock.yaml` change — a plain `pnpm install` won't refresh the
|
|
166
|
+
pin, since pnpm sees `specifier: latest` in the lockfile as
|
|
167
|
+
already matching `package.json` and skips re-resolving the tag.
|
|
168
|
+
No local link required for any of this. To point pnpm at a local
|
|
169
|
+
`cligent` checkout
|
|
150
170
|
instead, copy
|
|
151
171
|
[`pnpm-workspace.yaml.example`](pnpm-workspace.yaml.example)
|
|
152
172
|
into place; the override is gitignored so it never leaks into a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sublang/playbook",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Reference CODE playbook — XState v5 FSM, host-agnostic runtime, and tmux-play adapter for a coder/reviewer/committer loop driven by GEARS spec items.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"dependencies": {
|
|
68
68
|
"@anthropic-ai/claude-agent-sdk": "^0.3.143",
|
|
69
69
|
"@openai/codex-sdk": "^0.130.0",
|
|
70
|
-
"@sublang/cligent": "
|
|
70
|
+
"@sublang/cligent": "latest",
|
|
71
71
|
"xstate": "^5.19.4"
|
|
72
72
|
},
|
|
73
73
|
"devDependencies": {
|
|
@@ -175,7 +175,9 @@ function helpText({ userConfigPath, failingAdapters = [] }) {
|
|
|
175
175
|
'',
|
|
176
176
|
'Agent swap recipe:',
|
|
177
177
|
' - change captain.adapter and captain.model for the Captain/Judge',
|
|
178
|
-
' - change each player adapter for the Coder
|
|
178
|
+
' - change each player adapter and (optional) model for the Coder',
|
|
179
|
+
' and Reviewer; model when pinned, else adapter, is substituted',
|
|
180
|
+
' into <coder-llm>/<reviewer-llm> player prompts (PBRT-4)',
|
|
179
181
|
' - keep captain.from and players[].id fixed',
|
|
180
182
|
'',
|
|
181
183
|
].join('\n');
|
|
@@ -1066,6 +1066,7 @@ export const codingMachine = setup({
|
|
|
1066
1066
|
prompt: [
|
|
1067
1067
|
'Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).',
|
|
1068
1068
|
'Coder is <coder-llm>.',
|
|
1069
|
+
'Format the `Co-authored-by` `<model>` token as the conventional human form of the substituted id (e.g., `claude-opus-4-7` → `Claude-Opus-4.7`, `gpt-5.5` → `GPT-5.5`).',
|
|
1069
1070
|
].join('\n'),
|
|
1070
1071
|
result: {
|
|
1071
1072
|
committedSpecs: 'Committed changes that touch only @specs/{user,dev,test}/.',
|
|
@@ -1127,6 +1128,7 @@ export const codingMachine = setup({
|
|
|
1127
1128
|
prompt: [
|
|
1128
1129
|
'Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).',
|
|
1129
1130
|
'Coder is <coder-llm>; Reviewer is <reviewer-llm>.',
|
|
1131
|
+
'Format the `Co-authored-by` `<model>` token as the conventional human form of the substituted id (e.g., `claude-opus-4-7` → `Claude-Opus-4.7`, `gpt-5.5` → `GPT-5.5`).',
|
|
1130
1132
|
].join('\n'),
|
|
1131
1133
|
result: {
|
|
1132
1134
|
committed: 'Relevant changes were committed.',
|
|
@@ -1319,6 +1319,7 @@ export const codingMachine = setup({
|
|
|
1319
1319
|
prompt: [
|
|
1320
1320
|
'Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).',
|
|
1321
1321
|
'Coder is <coder-llm>.',
|
|
1322
|
+
'Format the `Co-authored-by` `<model>` token as the conventional human form of the substituted id (e.g., `claude-opus-4-7` → `Claude-Opus-4.7`, `gpt-5.5` → `GPT-5.5`).',
|
|
1322
1323
|
].join('\n'),
|
|
1323
1324
|
result: {
|
|
1324
1325
|
committedSpecs: 'Committed changes that touch only @specs/{user,dev,test}/.',
|
|
@@ -1382,6 +1383,7 @@ export const codingMachine = setup({
|
|
|
1382
1383
|
prompt: [
|
|
1383
1384
|
'Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).',
|
|
1384
1385
|
'Coder is <coder-llm>; Reviewer is <reviewer-llm>.',
|
|
1386
|
+
'Format the `Co-authored-by` `<model>` token as the conventional human form of the substituted id (e.g., `claude-opus-4-7` → `Claude-Opus-4.7`, `gpt-5.5` → `GPT-5.5`).',
|
|
1385
1387
|
].join('\n'),
|
|
1386
1388
|
result: {
|
|
1387
1389
|
committed: 'Relevant changes were committed.',
|
|
@@ -239,6 +239,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
|
|
|
239
239
|
When Coder makes any Initial Changes and Reviewer has not played since the last commit, Captain shall prompt Committer:
|
|
240
240
|
> Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).
|
|
241
241
|
> Coder is <coder-llm>.
|
|
242
|
+
> Format the `Co-authored-by` `<model>` token as the conventional human form of the substituted id (e.g., `claude-opus-4-7` → `Claude-Opus-4.7`, `gpt-5.5` → `GPT-5.5`).
|
|
242
243
|
|
|
243
244
|
Result guard: `needsBossInput` — Committing requires additional Boss input or rescoping rather than a specific answer to resume this same state.
|
|
244
245
|
|
|
@@ -247,5 +248,6 @@ Result guard: `needsBossInput` — Committing requires additional Boss input or
|
|
|
247
248
|
When Coder makes any Initial Changes and Reviewer has played since the last commit, or Reviewer raises no findings on uncommitted changes and Coder has played since the last commit, Captain shall prompt Committer:
|
|
248
249
|
> Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).
|
|
249
250
|
> Coder is <coder-llm>; Reviewer is <reviewer-llm>.
|
|
251
|
+
> Format the `Co-authored-by` `<model>` token as the conventional human form of the substituted id (e.g., `claude-opus-4-7` → `Claude-Opus-4.7`, `gpt-5.5` → `GPT-5.5`).
|
|
250
252
|
|
|
251
253
|
Result guard: `needsBossInput` — Committing requires additional Boss input or rescoping rather than a specific answer to resume this same state.
|
|
@@ -4,8 +4,12 @@ import createPlaybookRuntime from './code.playbook.js';
|
|
|
4
4
|
// Captain factory per TMUX-014: `(options: unknown) => Captain`.
|
|
5
5
|
// `options` is whatever `captain.options` carries in the YAML config.
|
|
6
6
|
// The per-run player identity strings (`coderPlayer`, `reviewerPlayer`)
|
|
7
|
-
// are derived from `session.players` at init time per PBRT-4
|
|
8
|
-
//
|
|
7
|
+
// are derived from `session.players` at init time per PBRT-4 —
|
|
8
|
+
// preferring each entry's `model` and falling back to `adapter` when
|
|
9
|
+
// no model is pinned — so player prompts and commit-message trailers
|
|
10
|
+
// carry the concrete model identity (e.g. `claude-opus-4-7`) rather
|
|
11
|
+
// than the adapter family name (e.g. `claude`). Any same-named keys
|
|
12
|
+
// in `options` are ignored.
|
|
9
13
|
export default function createCodeTmuxPlayCaptain(options) {
|
|
10
14
|
// CaptainSession is bound at init time and persists across turns;
|
|
11
15
|
// CaptainContext is rebuilt per turn and carries the call
|
|
@@ -17,8 +21,12 @@ export default function createCodeTmuxPlayCaptain(options) {
|
|
|
17
21
|
let activeContext;
|
|
18
22
|
return {
|
|
19
23
|
async init(session) {
|
|
20
|
-
const
|
|
21
|
-
|
|
24
|
+
const playerIdentity = (id) => {
|
|
25
|
+
const entry = session.players.find((p) => p.id === id);
|
|
26
|
+
return entry?.model ?? entry?.adapter;
|
|
27
|
+
};
|
|
28
|
+
const coderPlayer = playerIdentity('coder');
|
|
29
|
+
const reviewerPlayer = playerIdentity('reviewer');
|
|
22
30
|
runtime = createPlaybookRuntime({
|
|
23
31
|
...options,
|
|
24
32
|
coderPlayer,
|
|
@@ -20,8 +20,12 @@ import createPlaybookRuntime, {
|
|
|
20
20
|
// Captain factory per TMUX-014: `(options: unknown) => Captain`.
|
|
21
21
|
// `options` is whatever `captain.options` carries in the YAML config.
|
|
22
22
|
// The per-run player identity strings (`coderPlayer`, `reviewerPlayer`)
|
|
23
|
-
// are derived from `session.players` at init time per PBRT-4
|
|
24
|
-
//
|
|
23
|
+
// are derived from `session.players` at init time per PBRT-4 —
|
|
24
|
+
// preferring each entry's `model` and falling back to `adapter` when
|
|
25
|
+
// no model is pinned — so player prompts and commit-message trailers
|
|
26
|
+
// carry the concrete model identity (e.g. `claude-opus-4-7`) rather
|
|
27
|
+
// than the adapter family name (e.g. `claude`). Any same-named keys
|
|
28
|
+
// in `options` are ignored.
|
|
25
29
|
export default function createCodeTmuxPlayCaptain(
|
|
26
30
|
options: unknown,
|
|
27
31
|
): Captain {
|
|
@@ -36,12 +40,12 @@ export default function createCodeTmuxPlayCaptain(
|
|
|
36
40
|
|
|
37
41
|
return {
|
|
38
42
|
async init(session: CaptainSession): Promise<void> {
|
|
39
|
-
const
|
|
40
|
-
(p) => p.id ===
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
)
|
|
43
|
+
const playerIdentity = (id: string): string | undefined => {
|
|
44
|
+
const entry = session.players.find((p) => p.id === id);
|
|
45
|
+
return entry?.model ?? entry?.adapter;
|
|
46
|
+
};
|
|
47
|
+
const coderPlayer = playerIdentity('coder');
|
|
48
|
+
const reviewerPlayer = playerIdentity('reviewer');
|
|
45
49
|
runtime = createPlaybookRuntime({
|
|
46
50
|
...(options as CodePlaybookOptions),
|
|
47
51
|
coderPlayer,
|
|
@@ -6,22 +6,27 @@
|
|
|
6
6
|
# ${XDG_CONFIG_HOME:-$HOME/.config}/playbook/playbook-code.config.yaml
|
|
7
7
|
#
|
|
8
8
|
# Safe tuning points:
|
|
9
|
-
# - Change captain.adapter / captain.model
|
|
10
|
-
#
|
|
9
|
+
# - Change captain.adapter / captain.model / captain.reasoningEffort to
|
|
10
|
+
# pick the judge/Captain agent and its reasoning tier.
|
|
11
|
+
# - Change each player's adapter, model, and reasoningEffort to pick
|
|
12
|
+
# the Coder and Reviewer agents.
|
|
11
13
|
#
|
|
12
14
|
# PBRT-4 host-configuration invariants:
|
|
13
15
|
# - captain.from must keep pointing at the CODE tmux-play adapter module.
|
|
14
16
|
# - players[].id must remain exactly "coder" and "reviewer"; the runtime routes
|
|
15
17
|
# to those baked ids and does not remap them. The adapter derives the
|
|
16
|
-
# per-run player identity strings (substituted into
|
|
17
|
-
# each entry's
|
|
18
|
+
# per-run player identity strings (substituted into <coder-llm> /
|
|
19
|
+
# <reviewer-llm> in player prompts) from each entry's model when pinned
|
|
20
|
+
# and falls back to its adapter when no model is set, so the Committer's
|
|
21
|
+
# commit-message trailers can name the concrete model.
|
|
18
22
|
|
|
19
23
|
captain:
|
|
20
24
|
# PBRT-4 invariant: keep this adapter module path unchanged.
|
|
21
25
|
from: "@sublang/playbook/code/tmux-play"
|
|
22
|
-
# Tunable: the Captain/Judge adapter and
|
|
26
|
+
# Tunable: the Captain/Judge adapter, model, and reasoning effort.
|
|
23
27
|
adapter: claude
|
|
24
|
-
model: claude-
|
|
28
|
+
model: claude-sonnet-4-6
|
|
29
|
+
reasoningEffort: high
|
|
25
30
|
permissions:
|
|
26
31
|
mode: auto
|
|
27
32
|
|
|
@@ -29,10 +34,14 @@ players:
|
|
|
29
34
|
# PBRT-4 invariant: keep id: coder. Tune adapter/model if desired.
|
|
30
35
|
- id: coder
|
|
31
36
|
adapter: claude
|
|
37
|
+
model: claude-opus-4-7
|
|
38
|
+
reasoningEffort: xhigh
|
|
32
39
|
permissions:
|
|
33
40
|
mode: auto
|
|
34
41
|
# PBRT-4 invariant: keep id: reviewer. Tune adapter/model if desired.
|
|
35
42
|
- id: reviewer
|
|
36
43
|
adapter: codex
|
|
44
|
+
model: gpt-5.5
|
|
45
|
+
reasoningEffort: xhigh
|
|
37
46
|
permissions:
|
|
38
47
|
mode: auto
|
|
@@ -14,7 +14,8 @@ captain:
|
|
|
14
14
|
# options, and the rest of the config are unchanged.
|
|
15
15
|
from: ./code.tmux-play.js
|
|
16
16
|
adapter: claude
|
|
17
|
-
model: claude-
|
|
17
|
+
model: claude-sonnet-4-6
|
|
18
|
+
reasoningEffort: high
|
|
18
19
|
# Agents run in cligent's classifier/reviewer-protected auto mode
|
|
19
20
|
# (cligent DR-005): claude → permissionMode auto, codex → auto_review.
|
|
20
21
|
permissions:
|
|
@@ -24,14 +25,21 @@ captain:
|
|
|
24
25
|
# routes to. The CODE playbook bakes Coder→'coder' and
|
|
25
26
|
# Reviewer→'reviewer' at link time (DR-004 §2); the adapter does
|
|
26
27
|
# not remap, so changing these ids would break callPlayer routing.
|
|
27
|
-
# Each entry's `
|
|
28
|
-
# <reviewer-llm> placeholders in
|
|
28
|
+
# Each entry's `model` (when pinned) or `adapter` (otherwise) is
|
|
29
|
+
# substituted into the <coder-llm> / <reviewer-llm> placeholders in
|
|
30
|
+
# player prompts (DR-004 §6, PBRT-4) — pin a concrete `model:` if
|
|
31
|
+
# you want the Committer's commit-message trailers to name the
|
|
32
|
+
# specific model rather than the adapter family.
|
|
29
33
|
players:
|
|
30
34
|
- id: coder
|
|
31
35
|
adapter: claude
|
|
36
|
+
model: claude-opus-4-7
|
|
37
|
+
reasoningEffort: xhigh
|
|
32
38
|
permissions:
|
|
33
39
|
mode: auto
|
|
34
40
|
- id: reviewer
|
|
35
41
|
adapter: codex
|
|
42
|
+
model: gpt-5.5
|
|
43
|
+
reasoningEffort: xhigh
|
|
36
44
|
permissions:
|
|
37
45
|
mode: auto
|
|
@@ -9,16 +9,21 @@
|
|
|
9
9
|
captain:
|
|
10
10
|
from: "@sublang/playbook/code/tmux-play"
|
|
11
11
|
adapter: claude
|
|
12
|
-
model: claude-
|
|
12
|
+
model: claude-sonnet-4-6
|
|
13
|
+
reasoningEffort: high
|
|
13
14
|
permissions:
|
|
14
15
|
mode: auto
|
|
15
16
|
|
|
16
17
|
players:
|
|
17
18
|
- id: coder
|
|
18
19
|
adapter: claude
|
|
20
|
+
model: claude-opus-4-7
|
|
21
|
+
reasoningEffort: xhigh
|
|
19
22
|
permissions:
|
|
20
23
|
mode: auto
|
|
21
24
|
- id: reviewer
|
|
22
25
|
adapter: codex
|
|
26
|
+
model: gpt-5.5
|
|
27
|
+
reasoningEffort: xhigh
|
|
23
28
|
permissions:
|
|
24
29
|
mode: auto
|