@sublang/playbook 7.0.0 → 8.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.
- package/README.md +17 -4
- package/docs/cli.md +74 -29
- package/docs/configuration.md +209 -112
- package/docs/embedding.md +71 -25
- package/package.json +4 -3
- package/reference/sdlc/captain.playbook/captain.playbook.js +3 -3
- package/reference/sdlc/captain.playbook/captain.playbook.ts +3 -3
- package/reference/sdlc/code.md +1 -1
- package/reference/sdlc/code.playbook/bin/interactive-session.js +816 -0
- package/reference/sdlc/code.playbook/bin/launch-config.js +1078 -116
- package/reference/sdlc/code.playbook/bin/playbook.js +489 -34
- package/reference/sdlc/code.playbook/bin/run.js +283 -298
- package/reference/sdlc/code.playbook/bin/session-store.js +818 -26
- package/reference/sdlc/code.playbook/code.fsm.d.ts +5 -5
- package/reference/sdlc/code.playbook/code.fsm.introspect.js +2 -2
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +2 -2
- package/reference/sdlc/code.playbook/code.fsm.js +7 -11
- package/reference/sdlc/code.playbook/code.fsm.ts +9 -17
- package/reference/sdlc/code.playbook/code.gears.md +1 -1
- package/reference/sdlc/code.playbook/code.playbook.d.ts +2 -1
- package/reference/sdlc/code.playbook/code.playbook.js +12 -13
- package/reference/sdlc/code.playbook/code.playbook.ts +22 -15
- package/reference/sdlc/code.playbook/code.registry.d.ts +5 -13
- package/reference/sdlc/code.playbook/code.registry.js +3 -10
- package/reference/sdlc/code.playbook/code.registry.ts +7 -32
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +39 -14
- package/reference/sdlc/code.playbook/playbook-captain.js +970 -289
- package/reference/sdlc/code.playbook/playbook-captain.ts +1403 -396
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +41 -49
- package/reference/sdlc/decide.md +4 -4
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +9 -9
- package/reference/sdlc/decide.playbook/decide.fsm.js +21 -14
- package/reference/sdlc/decide.playbook/decide.fsm.ts +27 -23
- package/reference/sdlc/decide.playbook/decide.gears.md +3 -5
- package/reference/sdlc/decide.playbook/decide.playbook.d.ts +9 -13
- package/reference/sdlc/decide.playbook/decide.playbook.js +171 -134
- package/reference/sdlc/decide.playbook/decide.playbook.ts +238 -162
- package/reference/sdlc/decide.playbook/decide.registry.d.ts +5 -13
- package/reference/sdlc/decide.playbook/decide.registry.js +3 -9
- package/reference/sdlc/decide.playbook/decide.registry.ts +7 -31
- package/reference/sdlc/review.md +4 -5
- package/reference/sdlc/review.playbook/review.fsm.d.ts +9 -11
- package/reference/sdlc/review.playbook/review.fsm.js +30 -24
- package/reference/sdlc/review.playbook/review.fsm.ts +39 -35
- package/reference/sdlc/review.playbook/review.gears.md +6 -5
- package/reference/sdlc/review.playbook/review.playbook.d.ts +2 -1
- package/reference/sdlc/review.playbook/review.playbook.js +16 -21
- package/reference/sdlc/review.playbook/review.playbook.ts +26 -26
- package/reference/sdlc/review.playbook/review.registry.d.ts +5 -13
- package/reference/sdlc/review.playbook/review.registry.js +3 -16
- package/reference/sdlc/review.playbook/review.registry.ts +7 -38
- package/slc/gears2fsm.md +27 -23
- package/slc/link.md +113 -93
- package/slc/text2gears.md +19 -18
- package/src/runtime.d.ts +20 -16
- package/src/runtime.ts +19 -23
- package/src/xstate-playbook-runtime.d.ts +21 -17
- package/src/xstate-playbook-runtime.js +241 -149
- package/src/xstate-playbook-runtime.ts +331 -178
- package/src/xstate-runtime.js +63 -24
- package/src/xstate-runtime.ts +96 -28
package/docs/embedding.md
CHANGED
|
@@ -16,8 +16,8 @@ your own host.
|
|
|
16
16
|
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
|
-
`PlaybookRuntime`, `PlaybookSession`, `
|
|
20
|
-
`PlayerSessionStore`, `CaptainCallOptions`, `CaptainResult`,
|
|
19
|
+
`PlaybookRuntime`, `PlaybookSession`, `PlaybookRoleBinding`,
|
|
20
|
+
`PlayerCallOptions`, `PlayerSessionStore`, `CaptainCallOptions`, `CaptainResult`,
|
|
21
21
|
`PlaybookTraceEvent`, and `PlaybookRuntimeFactory`) that imports no CODE
|
|
22
22
|
or FSM types, so a host satisfies it once and inherits every playbook.
|
|
23
23
|
The generated CODE, REVIEW, and DECIDE modules re-export their shared
|
|
@@ -37,6 +37,9 @@ import type {
|
|
|
37
37
|
CaptainCallOptions,
|
|
38
38
|
CaptainResult,
|
|
39
39
|
PlaybookPorts,
|
|
40
|
+
PlaybookRoleBinding,
|
|
41
|
+
PlayerResult,
|
|
42
|
+
PlayerSessionStore,
|
|
40
43
|
} from '@sublang/playbook/runtime';
|
|
41
44
|
import { randomUUID } from 'node:crypto';
|
|
42
45
|
import PQueue from 'p-queue';
|
|
@@ -53,6 +56,33 @@ declare const captainAdapter: {
|
|
|
53
56
|
): Promise<CaptainResult>;
|
|
54
57
|
};
|
|
55
58
|
|
|
59
|
+
declare const playerAdapter: {
|
|
60
|
+
run(
|
|
61
|
+
playerId: string,
|
|
62
|
+
prompt: string,
|
|
63
|
+
options: { signal: AbortSignal; resume: string | false },
|
|
64
|
+
): Promise<PlayerResult>;
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// Roles are local workflow identities. Players are stable provider
|
|
68
|
+
// conversations owned by the logical Captain session. `promptIdentity` is
|
|
69
|
+
// the current model name, or the player's adapter when provider-default is
|
|
70
|
+
// selected; rebuild it from current compatible tuning on restore.
|
|
71
|
+
const roleBindings = {
|
|
72
|
+
coder: {
|
|
73
|
+
playerId: 'team.coder',
|
|
74
|
+
promptIdentity: 'claude-opus-4-8[1m]',
|
|
75
|
+
},
|
|
76
|
+
reviewer: {
|
|
77
|
+
playerId: 'team.reviewer',
|
|
78
|
+
promptIdentity: 'gpt-5.5',
|
|
79
|
+
},
|
|
80
|
+
} satisfies Readonly<Record<string, PlaybookRoleBinding>>;
|
|
81
|
+
|
|
82
|
+
// Supply a frame-local role view over your session-wide player ledger.
|
|
83
|
+
// Equal player IDs must select/update the same token; distinct IDs must not.
|
|
84
|
+
declare const playerSessions: PlayerSessionStore;
|
|
85
|
+
|
|
56
86
|
// Construct one host-wide lane and reuse it for every runtime. Passing each
|
|
57
87
|
// call's signal to both the lane and adapter cancels queued and active work.
|
|
58
88
|
const captainLane = new PQueue({ concurrency: 1 });
|
|
@@ -69,10 +99,16 @@ async function runCaptain(
|
|
|
69
99
|
}
|
|
70
100
|
|
|
71
101
|
const ports: PlaybookPorts = {
|
|
72
|
-
callPlayer: async (
|
|
102
|
+
callPlayer: async (roleId, prompt, signal, { resume }) => {
|
|
103
|
+
const binding = roleBindings[roleId as keyof typeof roleBindings];
|
|
104
|
+
if (binding === undefined) throw new Error(`Unknown role: ${roleId}`);
|
|
73
105
|
// `resume === false` starts fresh; a string selects that player's
|
|
74
|
-
// prior backend conversation. Return the adapter's next token
|
|
75
|
-
|
|
106
|
+
// prior backend conversation. Return the adapter's next token; the
|
|
107
|
+
// runtime updates `playerSessions` only after validating this result.
|
|
108
|
+
return await playerAdapter.run(binding.playerId, prompt, {
|
|
109
|
+
signal,
|
|
110
|
+
resume,
|
|
111
|
+
});
|
|
76
112
|
},
|
|
77
113
|
callCaptain: async (prompt, signal, options) => {
|
|
78
114
|
// Forward every option exactly: omission preserves configured tools, while
|
|
@@ -103,10 +139,7 @@ const ports: PlaybookPorts = {
|
|
|
103
139
|
},
|
|
104
140
|
};
|
|
105
141
|
|
|
106
|
-
const runtime = createPlaybookRuntime({
|
|
107
|
-
coderLlm: 'claude-opus-4-8[1m]',
|
|
108
|
-
reviewerLlm: 'gpt-5.5',
|
|
109
|
-
});
|
|
142
|
+
const runtime = createPlaybookRuntime({});
|
|
110
143
|
|
|
111
144
|
const playbookSessionId = randomUUID();
|
|
112
145
|
await runtime.init({
|
|
@@ -114,6 +147,8 @@ await runtime.init({
|
|
|
114
147
|
playbookId: 'review',
|
|
115
148
|
rootSessionId: playbookSessionId,
|
|
116
149
|
depth: 0,
|
|
150
|
+
roleBindings,
|
|
151
|
+
playerSessions,
|
|
117
152
|
ports,
|
|
118
153
|
});
|
|
119
154
|
await runtime.handleBossInput({
|
|
@@ -125,23 +160,34 @@ await runtime.dispose();
|
|
|
125
160
|
|
|
126
161
|
## Sessions and traces
|
|
127
162
|
|
|
128
|
-
Every init-to-dispose lifecycle is one playbook session.
|
|
163
|
+
Every init-to-dispose lifecycle is one playbook session. Schema-3
|
|
129
164
|
`playbook.trace` telemetry carries that immutable ID plus a contiguous
|
|
130
|
-
sequence across exact Boss input, judge/player calls, FSM transitions,
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
165
|
+
sequence across exact Boss input, judge/player calls, FSM transitions, visible
|
|
166
|
+
Captain work, nested playbook calls, status, settlement, and disposal. A
|
|
167
|
+
shell-hosted player boundary keeps both identities: `roleId` says which local
|
|
168
|
+
workflow job made the call, while `playerId` says which stable session
|
|
169
|
+
conversation owned it. A standalone runtime retains the role without
|
|
170
|
+
inventing host player identity.
|
|
171
|
+
|
|
172
|
+
Without `PlaybookSession.playerSessions`, a standalone runtime starts each
|
|
173
|
+
local role fresh and privately retains the latest opaque `resumeToken` its
|
|
174
|
+
adapter returned. A composing host instead supplies a frame-local
|
|
175
|
+
`PlayerSessionStore` view over one Captain-session ledger and explicit
|
|
176
|
+
`roleBindings`. The store's methods receive local role IDs; the view resolves
|
|
177
|
+
them to the configured stable player IDs. Equal IDs share one token and
|
|
178
|
+
sequential call lane across every frame that names them, while distinct IDs
|
|
179
|
+
remain isolated. Child return, frame disposal, and a later root engagement do
|
|
180
|
+
not clear the session ledger.
|
|
181
|
+
|
|
182
|
+
Runtime snapshots are schema 3. Their `roleResumeTokens` projection remains
|
|
183
|
+
role-local, while the composing shell's own schema-3 snapshot persists the
|
|
184
|
+
stable player ledger and every frame's exact role bindings. Do not restore
|
|
185
|
+
schema 1 or 2 by guessing identity. On a compatible restore, rebuild
|
|
186
|
+
`promptIdentity` from the current model selection (or adapter for an explicit
|
|
187
|
+
provider-default selection) so the next prompt and trace describe the current
|
|
188
|
+
invocation rather than stale machine state. Trace data and tokens never enter
|
|
189
|
+
Boss-visible status text. Because trace observers do receive opaque resume
|
|
190
|
+
tokens, persisted traces should be protected as sensitive data.
|
|
145
191
|
|
|
146
192
|
See
|
|
147
193
|
[`code.playbook.test.ts`](../reference/sdlc/code.playbook/code.playbook.test.ts)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sublang/playbook",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"type": "module",
|
|
5
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",
|
|
@@ -69,6 +69,7 @@
|
|
|
69
69
|
"reference/sdlc/code.playbook/bin/playbook.js",
|
|
70
70
|
"reference/sdlc/code.playbook/bin/launch-config.js",
|
|
71
71
|
"reference/sdlc/code.playbook/bin/run.js",
|
|
72
|
+
"reference/sdlc/code.playbook/bin/interactive-session.js",
|
|
72
73
|
"reference/sdlc/code.playbook/bin/session-store.js",
|
|
73
74
|
"reference/sdlc/code.playbook/bin/provision.js",
|
|
74
75
|
"reference/sdlc/code.playbook/bin/adapter-sdk.js",
|
|
@@ -142,7 +143,7 @@
|
|
|
142
143
|
},
|
|
143
144
|
"scripts": {
|
|
144
145
|
"build": "tsc",
|
|
145
|
-
"test": "spex lint && vitest run",
|
|
146
|
+
"test": "spex lint && vitest run --exclude src/cligent-release-capabilities.test.ts && vitest run src/cligent-release-capabilities.test.ts",
|
|
146
147
|
"test:acceptance": "vitest run --config vitest.acceptance.config.ts",
|
|
147
148
|
"smoke:release": "node scripts/release-smoke.mjs",
|
|
148
149
|
"check:links": "node scripts/check-links.mjs",
|
|
@@ -153,7 +154,7 @@
|
|
|
153
154
|
"provenance": true
|
|
154
155
|
},
|
|
155
156
|
"dependencies": {
|
|
156
|
-
"@sublang/cligent": "^0.
|
|
157
|
+
"@sublang/cligent": "^0.22.0",
|
|
157
158
|
"@sublang/spex": "^2.1.1",
|
|
158
159
|
"p-queue": "^9.3.1",
|
|
159
160
|
"xstate": "^5.19.4",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
// deterministic entry mapping, the controller captain-call
|
|
32
32
|
// strategy with its single corrective re-ask (CAPPLAY-18),
|
|
33
33
|
// controller-port submission, and status formatting.
|
|
34
|
-
// Compat: spec.compat = { artifactSchema:
|
|
34
|
+
// Compat: spec.compat = { artifactSchema: 2, runtimeAbi: 1 }
|
|
35
35
|
// (DR-022; checked at construction by the loading engine).
|
|
36
36
|
import { createXStatePlaybookRuntime, defaultComposeCaptainPrompt, normalizeError, normalizeErrorCompact, parseJudgeJson, snapshotJsonValue, RUNTIME_ABI, } from '../../../src/xstate-runtime.js';
|
|
37
37
|
import { captainMachine, } from './captain.fsm.js';
|
|
@@ -516,11 +516,11 @@ export const _internal = {
|
|
|
516
516
|
// describe/apply control surface — lives in @sublang/playbook/xstate-runtime.
|
|
517
517
|
const runtimeSpec = {
|
|
518
518
|
label: 'CAPTAIN',
|
|
519
|
-
compat: { artifactSchema:
|
|
519
|
+
compat: { artifactSchema: 2, runtimeAbi: RUNTIME_ABI },
|
|
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
|
-
|
|
523
|
+
roleStates: {},
|
|
524
524
|
classificationStatus: () => undefined,
|
|
525
525
|
captainStrategy: controllerCaptainStrategy,
|
|
526
526
|
// CAPPLAY-10 / PBRT-52: the Captain's own ControlView context projection —
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
// deterministic entry mapping, the controller captain-call
|
|
32
32
|
// strategy with its single corrective re-ask (CAPPLAY-18),
|
|
33
33
|
// controller-port submission, and status formatting.
|
|
34
|
-
// Compat: spec.compat = { artifactSchema:
|
|
34
|
+
// Compat: spec.compat = { artifactSchema: 2, runtimeAbi: 1 }
|
|
35
35
|
// (DR-022; checked at construction by the loading engine).
|
|
36
36
|
|
|
37
37
|
import {
|
|
@@ -798,7 +798,7 @@ export const _internal = {
|
|
|
798
798
|
// describe/apply control surface — lives in @sublang/playbook/xstate-runtime.
|
|
799
799
|
const runtimeSpec: XStatePlaybookRuntimeSpec<ValidatedCaptainOptions> = {
|
|
800
800
|
label: 'CAPTAIN',
|
|
801
|
-
compat: { artifactSchema:
|
|
801
|
+
compat: { artifactSchema: 2, runtimeAbi: RUNTIME_ABI },
|
|
802
802
|
snapshotOptions: snapshotCaptainOptions,
|
|
803
803
|
machineInput: (options) => ({ enabledPlaybooks: options.enabledPlaybooks }),
|
|
804
804
|
classifyBossText: (text, ports, signal, snapshotOrState, boundary, options) =>
|
|
@@ -810,7 +810,7 @@ const runtimeSpec: XStatePlaybookRuntimeSpec<ValidatedCaptainOptions> = {
|
|
|
810
810
|
boundary,
|
|
811
811
|
options,
|
|
812
812
|
) as Promise<import('xstate').EventObject | undefined>,
|
|
813
|
-
|
|
813
|
+
roleStates: {},
|
|
814
814
|
classificationStatus: () => undefined,
|
|
815
815
|
captainStrategy: controllerCaptainStrategy,
|
|
816
816
|
// CAPPLAY-10 / PBRT-52: the Captain's own ControlView context projection —
|