@sublang/playbook 1.3.0 → 3.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 +101 -338
- package/docs/cli.md +102 -0
- package/docs/configuration.md +158 -0
- package/docs/embedding.md +161 -0
- package/package.json +7 -3
- package/reference/sdlc/code.md +105 -0
- package/reference/sdlc/code.playbook/bin/playbook.js +236 -38
- package/reference/sdlc/code.playbook/bin/run.js +27 -2
- package/reference/sdlc/code.playbook/code.fsm.js +38 -36
- package/reference/sdlc/code.playbook/code.fsm.ts +38 -36
- package/reference/sdlc/code.playbook/code.gears.md +30 -26
- package/reference/sdlc/code.playbook/code.playbook.js +4 -0
- package/reference/sdlc/code.playbook/code.playbook.ts +6 -0
- package/reference/sdlc/code.playbook/playbook-captain.js +67 -8
- package/reference/sdlc/code.playbook/playbook-captain.ts +80 -9
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +38 -32
- package/reference/sdlc/discuss.md +93 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.js +5 -4
- package/reference/sdlc/discuss.playbook/discuss.fsm.ts +5 -4
- package/reference/sdlc/discuss.playbook/discuss.gears.md +19 -12
- package/reference/sdlc/discuss.playbook/discuss.playbook.js +3 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.ts +5 -0
- package/slc/link.md +33 -14
- package/src/xstate-playbook-runtime.js +64 -19
- package/src/xstate-playbook-runtime.ts +87 -24
- package/src/xstate-runtime.d.ts +1 -0
- package/src/xstate-runtime.js +19 -0
- package/src/xstate-runtime.ts +20 -0
|
@@ -20,7 +20,10 @@ import type {
|
|
|
20
20
|
PlaybookRuntime,
|
|
21
21
|
PlaybookState,
|
|
22
22
|
} from '@sublang/playbook/runtime';
|
|
23
|
-
import {
|
|
23
|
+
import {
|
|
24
|
+
hiddenControlEnvelope,
|
|
25
|
+
registerPlaybookAbortCleanup,
|
|
26
|
+
} from '../../../src/xstate-runtime.js';
|
|
24
27
|
import createDefaultCaptainRuntime from '../captain.playbook/captain.playbook.js';
|
|
25
28
|
import type { PlaybookSummaryPolicy, RegistryPlayer } from './code.registry.js';
|
|
26
29
|
|
|
@@ -154,6 +157,56 @@ function visibleChatEnvelope(message: string): string {
|
|
|
154
157
|
].join('\n\n');
|
|
155
158
|
}
|
|
156
159
|
|
|
160
|
+
// DR-013 A1: adapters with no provider-enforced tool-restriction surface.
|
|
161
|
+
// Cligent's Codex adapter rejects any `allowedTools` value — including the
|
|
162
|
+
// empty list that expresses tool-free — because the supported Codex SDK
|
|
163
|
+
// cannot enforce one, so requesting it fails every control call before the
|
|
164
|
+
// model is reached. Omitting the option is the only way such an adapter can
|
|
165
|
+
// run a control call at all; its isolation then rests on the authored
|
|
166
|
+
// hidden-judge envelope below rather than on provider enforcement.
|
|
167
|
+
const ADAPTERS_WITHOUT_TOOL_ENFORCEMENT: ReadonlySet<string> = new Set([
|
|
168
|
+
'codex',
|
|
169
|
+
]);
|
|
170
|
+
|
|
171
|
+
// The tool half of a control call's options. An empty allowlist means "no
|
|
172
|
+
// tools available" and is distinct from omission, which grants the adapter's
|
|
173
|
+
// full native tool surface — so omit only where the empty list would be
|
|
174
|
+
// refused, and keep requesting enforcement whenever the adapter is unknown.
|
|
175
|
+
function controlCallToolOptions(
|
|
176
|
+
captainAdapter: string | undefined,
|
|
177
|
+
): { allowedTools?: readonly string[] } {
|
|
178
|
+
if (
|
|
179
|
+
captainAdapter !== undefined &&
|
|
180
|
+
ADAPTERS_WITHOUT_TOOL_ENFORCEMENT.has(captainAdapter)
|
|
181
|
+
) {
|
|
182
|
+
return {};
|
|
183
|
+
}
|
|
184
|
+
return { allowedTools: [] };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// A runtime-requested allowlist forwarded to the captain agent. The empty
|
|
188
|
+
// list is the runtime's way of saying "tool-free", so it is the only value
|
|
189
|
+
// the host substitutes; a non-empty list is a real restriction and stays
|
|
190
|
+
// fail-closed on an adapter that cannot enforce it.
|
|
191
|
+
function forwardedToolOptions(
|
|
192
|
+
requested: readonly string[] | undefined,
|
|
193
|
+
captainAdapter: string | undefined,
|
|
194
|
+
): { allowedTools?: readonly string[] } {
|
|
195
|
+
if (requested === undefined) return {};
|
|
196
|
+
if (requested.length === 0) return controlCallToolOptions(captainAdapter);
|
|
197
|
+
return { allowedTools: requested };
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function readCaptainAdapter(options: unknown): string | undefined {
|
|
201
|
+
if (typeof options !== 'object' || options === null) return undefined;
|
|
202
|
+
const adapter = (options as Record<string, unknown>).captainAdapter;
|
|
203
|
+
return typeof adapter === 'string' && adapter.length > 0
|
|
204
|
+
? adapter
|
|
205
|
+
: undefined;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const hiddenJudgeEnvelope = hiddenControlEnvelope;
|
|
209
|
+
|
|
157
210
|
function visibleTurnSummaryEnvelope(input: {
|
|
158
211
|
playbookId: string;
|
|
159
212
|
submittedText: string;
|
|
@@ -368,6 +421,10 @@ export function createPlaybookCaptainShell(
|
|
|
368
421
|
const createCaptainRuntime: NonNullable<
|
|
369
422
|
PlaybookCaptainDeps['createCaptainRuntime']
|
|
370
423
|
> = deps.createCaptainRuntime ?? createDefaultCaptainRuntime;
|
|
424
|
+
// DR-013 A1: the launcher passes the resolved captain adapter through
|
|
425
|
+
// `captain.options`; a raw `--config` launch leaves it undefined, which
|
|
426
|
+
// keeps the enforced empty allowlist and its fail-closed behavior.
|
|
427
|
+
const captainAdapter = readCaptainAdapter(options);
|
|
371
428
|
let entries: readonly PlaybookCaptainRegistryEntry[] = [];
|
|
372
429
|
let byCommand = new Map<string, PlaybookCaptainRegistryEntry>();
|
|
373
430
|
let byId = new Map<string, PlaybookCaptainRegistryEntry>();
|
|
@@ -650,9 +707,7 @@ export function createPlaybookCaptainShell(
|
|
|
650
707
|
{
|
|
651
708
|
visibility: options.visibility,
|
|
652
709
|
resume: options.resume,
|
|
653
|
-
...(options.allowedTools
|
|
654
|
-
? {}
|
|
655
|
-
: { allowedTools: options.allowedTools }),
|
|
710
|
+
...forwardedToolOptions(options.allowedTools, captainAdapter),
|
|
656
711
|
},
|
|
657
712
|
signal,
|
|
658
713
|
);
|
|
@@ -671,8 +726,12 @@ export function createPlaybookCaptainShell(
|
|
|
671
726
|
const result = await callCaptainQueued(
|
|
672
727
|
frame,
|
|
673
728
|
activeContext,
|
|
674
|
-
prompt,
|
|
675
|
-
{
|
|
729
|
+
hiddenJudgeEnvelope(prompt),
|
|
730
|
+
{
|
|
731
|
+
visibility: 'hidden',
|
|
732
|
+
resume: false,
|
|
733
|
+
...controlCallToolOptions(captainAdapter),
|
|
734
|
+
},
|
|
676
735
|
signal,
|
|
677
736
|
);
|
|
678
737
|
if (result.status !== 'ok') {
|
|
@@ -1495,7 +1554,11 @@ export function createPlaybookCaptainShell(
|
|
|
1495
1554
|
frame,
|
|
1496
1555
|
context,
|
|
1497
1556
|
visibleChatEnvelope(message),
|
|
1498
|
-
{
|
|
1557
|
+
{
|
|
1558
|
+
visibility: 'visible',
|
|
1559
|
+
resume: false,
|
|
1560
|
+
...controlCallToolOptions(captainAdapter),
|
|
1561
|
+
},
|
|
1499
1562
|
context.signal,
|
|
1500
1563
|
);
|
|
1501
1564
|
if (result.status !== 'ok') {
|
|
@@ -1519,7 +1582,11 @@ export function createPlaybookCaptainShell(
|
|
|
1519
1582
|
frame,
|
|
1520
1583
|
context,
|
|
1521
1584
|
visibleTurnSummaryEnvelope(input),
|
|
1522
|
-
{
|
|
1585
|
+
{
|
|
1586
|
+
visibility: 'visible',
|
|
1587
|
+
resume: false,
|
|
1588
|
+
...controlCallToolOptions(captainAdapter),
|
|
1589
|
+
},
|
|
1523
1590
|
context.signal,
|
|
1524
1591
|
);
|
|
1525
1592
|
if (result.status !== 'ok') {
|
|
@@ -1577,7 +1644,11 @@ export function createPlaybookCaptainShell(
|
|
|
1577
1644
|
leaf,
|
|
1578
1645
|
context,
|
|
1579
1646
|
hiddenLifecycleEnvelope(turn.prompt),
|
|
1580
|
-
{
|
|
1647
|
+
{
|
|
1648
|
+
visibility: 'hidden',
|
|
1649
|
+
resume: false,
|
|
1650
|
+
...controlCallToolOptions(captainAdapter),
|
|
1651
|
+
},
|
|
1581
1652
|
context.signal,
|
|
1582
1653
|
);
|
|
1583
1654
|
if (result.status === 'ok' && result.finalText !== undefined) {
|
|
@@ -6,39 +6,25 @@
|
|
|
6
6
|
# The launcher injects captain.from and the namespaced <id>-<role> host
|
|
7
7
|
# players, then launches cligent's tmux-play under the Playbook Captain shell.
|
|
8
8
|
|
|
9
|
-
#
|
|
10
|
-
# (claude, codex)
|
|
11
|
-
#
|
|
12
|
-
#
|
|
13
|
-
# player roles that reference them.
|
|
9
|
+
# Every agent — the Captain and each playbook role — carries its own
|
|
10
|
+
# settings inline: an adapter shorthand (claude, codex) or a block with
|
|
11
|
+
# adapter/model/effort/permissions. Retuning one agent never changes
|
|
12
|
+
# another.
|
|
14
13
|
# Every seeded agent runs in cligent's protected auto mode
|
|
15
14
|
# (permissions.mode: auto): claude maps it to permissionMode auto, codex to
|
|
16
15
|
# on-request + auto_review. Codex roles also grant writablePaths: ['.git']
|
|
17
16
|
# so commit turns can write git metadata under the codex sandbox.
|
|
18
|
-
profiles:
|
|
19
|
-
claude-opus:
|
|
20
|
-
adapter: claude
|
|
21
|
-
model: claude-opus-4-8
|
|
22
|
-
reasoningEffort: high
|
|
23
|
-
permissions:
|
|
24
|
-
mode: auto
|
|
25
|
-
claude-opus-1m:
|
|
26
|
-
adapter: claude
|
|
27
|
-
model: claude-opus-4-8[1m]
|
|
28
|
-
reasoningEffort: xhigh
|
|
29
|
-
permissions:
|
|
30
|
-
mode: auto
|
|
31
|
-
codex-gpt:
|
|
32
|
-
adapter: codex
|
|
33
|
-
model: gpt-5.5
|
|
34
|
-
reasoningEffort: xhigh
|
|
35
|
-
permissions:
|
|
36
|
-
mode: auto
|
|
37
|
-
writablePaths: ['.git']
|
|
38
17
|
|
|
39
|
-
# The Captain/Judge agent
|
|
40
|
-
#
|
|
41
|
-
|
|
18
|
+
# The Captain/Judge agent.
|
|
19
|
+
# Captain routing/adjudication calls run tool-free. Claude enforces that at
|
|
20
|
+
# the provider level; the codex adapter cannot enforce a tool list, so a
|
|
21
|
+
# codex captain degrades to a prompt-level restriction (DR-013 A1).
|
|
22
|
+
captain:
|
|
23
|
+
adapter: claude
|
|
24
|
+
model: claude-opus-4-8
|
|
25
|
+
effort: high
|
|
26
|
+
permissions:
|
|
27
|
+
mode: auto
|
|
42
28
|
|
|
43
29
|
# Host notifications. Omitting turn_aborted resolves it to off.
|
|
44
30
|
notifications:
|
|
@@ -53,8 +39,19 @@ playbooks:
|
|
|
53
39
|
code:
|
|
54
40
|
from: "@sublang/playbook/code/registry"
|
|
55
41
|
players:
|
|
56
|
-
coder:
|
|
57
|
-
|
|
42
|
+
coder:
|
|
43
|
+
adapter: claude
|
|
44
|
+
model: claude-opus-4-8[1m]
|
|
45
|
+
effort: xhigh
|
|
46
|
+
permissions:
|
|
47
|
+
mode: auto
|
|
48
|
+
reviewer:
|
|
49
|
+
adapter: codex
|
|
50
|
+
model: gpt-5.5
|
|
51
|
+
effort: xhigh
|
|
52
|
+
permissions:
|
|
53
|
+
mode: auto
|
|
54
|
+
writablePaths: ['.git']
|
|
58
55
|
committer: coder
|
|
59
56
|
|
|
60
57
|
# The DISCUSS playbook: two agents converge on spec items or decision
|
|
@@ -63,8 +60,17 @@ playbooks:
|
|
|
63
60
|
# discuss:
|
|
64
61
|
# from: "@sublang/playbook/discuss/registry"
|
|
65
62
|
# players:
|
|
66
|
-
# host:
|
|
67
|
-
#
|
|
63
|
+
# host:
|
|
64
|
+
# adapter: claude
|
|
65
|
+
# model: claude-opus-4-8
|
|
66
|
+
# permissions:
|
|
67
|
+
# mode: auto
|
|
68
|
+
# participant:
|
|
69
|
+
# adapter: codex
|
|
70
|
+
# model: gpt-5.5
|
|
71
|
+
# permissions:
|
|
72
|
+
# mode: auto
|
|
73
|
+
# writablePaths: ['.git']
|
|
68
74
|
# committer: host
|
|
69
75
|
|
|
70
76
|
# Non-interactive `playbook run` defaults (optional). Each value is an
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
<!-- SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai> -->
|
|
3
|
+
|
|
4
|
+
# Discuss
|
|
5
|
+
|
|
6
|
+
Players:
|
|
7
|
+
|
|
8
|
+
- Host
|
|
9
|
+
- Participant
|
|
10
|
+
- Committer = Host | Participant
|
|
11
|
+
|
|
12
|
+
When Boss gives a topic, Captain shall relay it to both players concurrently and independently, without waiting for either proposal before asking the other, along with the following prompt:
|
|
13
|
+
|
|
14
|
+
> Assess whether Boss's topic above is better expressed as a few spec items (per @specs/meta.md) or requires one or more DRs added to @specs/decisions/.
|
|
15
|
+
> Consult @specs/map.md, if necessary, to find relevant context.
|
|
16
|
+
> Each DR should be coherent and focused.
|
|
17
|
+
> Propose your design in reply.
|
|
18
|
+
> DRs, if any, need not include full detail here — describe the key points at a high level.
|
|
19
|
+
> Don't change any code.
|
|
20
|
+
|
|
21
|
+
The initial discussion shall go round by round.
|
|
22
|
+
In each round, Captain shall prompt both players concurrently.
|
|
23
|
+
Both players each shall make a new proposal using only the completed proposals from the previous round; neither shall see the other's current-round result before replying.
|
|
24
|
+
Captain shall join both results before beginning the next round, using the following prompt:
|
|
25
|
+
|
|
26
|
+
> Consider the other agent's proposal below.
|
|
27
|
+
> (1) If there are essentially different points (including creation or division of DRs), list them, accept any reasonable ones, and challenge the rest with strong reasoning, solid evidence, and comprehensive thinking — make your argument.
|
|
28
|
+
> (2) Only if your proposal of the previous round is equivalent to the other's, with nothing to reconcile, state the end of initial discussion.
|
|
29
|
+
> Don't change any code.
|
|
30
|
+
|
|
31
|
+
A Boss interrupt into parallel discussion shall restart the whole initial-proposal or reconciliation round so both independent branches receive one coherent prior-round input. An individual branch that asks Boss a question may still resume on its own; branch working states are not Boss-interrupt destinations.
|
|
32
|
+
|
|
33
|
+
When both players state the end of initial discussion, Captain shall ask Host to write spec items or DRs according to the agreement, along with the following prompt:
|
|
34
|
+
|
|
35
|
+
> Update @specs/map.md to reflect your changes (if any) when done.
|
|
36
|
+
|
|
37
|
+
When Committer commits at the end of the initial discussion, or when Host addresses findings with changes, Captain shall ask Participant to review the spec changes in a round, without waiting for Boss.
|
|
38
|
+
In the first step of each round, Participant shall review the latest changes, address any rebuttals, and raise any findings.
|
|
39
|
+
In the second step of each round, Host shall address any findings.
|
|
40
|
+
Rounds continue until Participant raises no findings.
|
|
41
|
+
|
|
42
|
+
Spec item files are the files under @specs/ that hold spec items — @specs/packages/ and @specs/compositions/ in the current layout, or @specs/user/, @specs/dev/, and @specs/test/ in the legacy one; decision and intent records (iteration records in older scaffolds), @specs/map.md, and @specs/meta.md are not spec item files.
|
|
43
|
+
|
|
44
|
+
While any new or updated spec item (in spec item files) is under review, Captain shall include the following prompt for Participant:
|
|
45
|
+
|
|
46
|
+
> Verify any new or updated spec items are:
|
|
47
|
+
>
|
|
48
|
+
> - Complete & coherent: sufficient for you to reimplement code.
|
|
49
|
+
> - Right level: external behavior users rely on or internal system behavior (organized per @specs/meta.md), not implementation specifics; integration/system testing, not unit testing.
|
|
50
|
+
> - Minimal: essential and concise; every item earns its place; also check with other items.
|
|
51
|
+
> - Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
52
|
+
>
|
|
53
|
+
> Flag anything missing, redundant, over-specified, or under-specified.
|
|
54
|
+
|
|
55
|
+
While any new or updated DR is under review, Captain shall include the following prompt for Participant:
|
|
56
|
+
|
|
57
|
+
> Review any new/updated decision following @specs/meta.md (reread if necessary).
|
|
58
|
+
> Flag any issues or propose any design suggestions (numbered; no duplication), with strong reasoning and evidence.
|
|
59
|
+
> Key statements must be backed by references unless they are common sense or widely acknowledged best practices.
|
|
60
|
+
>
|
|
61
|
+
> If the decision is well-thought-out and well-written, don't raise nitpicks.
|
|
62
|
+
> Remember to keep the DR simple and minimal.
|
|
63
|
+
|
|
64
|
+
When Participant begins any review, Captain shall include the following prompt:
|
|
65
|
+
|
|
66
|
+
> Think thoroughly — don't just approve or reject.
|
|
67
|
+
> For context discovery, consult @specs/map.md; @specs/meta.md describes the spec format.
|
|
68
|
+
> Verify @specs/map.md reflects the changes.
|
|
69
|
+
> If the change is ready to commit or push, don't raise nitpicks.
|
|
70
|
+
> Do not edit files or commit; report findings only.
|
|
71
|
+
|
|
72
|
+
When Participant raises any findings, Captain shall relay them to Host along with the following prompt:
|
|
73
|
+
|
|
74
|
+
> For each review item below for the above changes, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.
|
|
75
|
+
> Stage all current changes that belong in the repo before making any edits, and leave your edits unstaged/untracked.
|
|
76
|
+
|
|
77
|
+
When Host raises any rebuttals, Captain shall relay them to Participant along with the following prompt:
|
|
78
|
+
|
|
79
|
+
> For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.
|
|
80
|
+
|
|
81
|
+
When the spec items or DRs are written at the end of the initial discussion, or Participant raises no findings on uncommitted changes, Captain shall ask Committer to commit with the following prompt:
|
|
82
|
+
|
|
83
|
+
> Then make a commit of the changes that belong in the repo, following @specs/packages/git.md (reread if necessary).
|
|
84
|
+
> If that spec is absent, follow the legacy @specs/dev/git.md; if neither exists, follow the repository's existing commit conventions and do not search elsewhere.
|
|
85
|
+
> Write the commit message concisely.
|
|
86
|
+
> Host is \<host-llm\>.
|
|
87
|
+
> Participant is \<participant-llm\>.
|
|
88
|
+
|
|
89
|
+
`<*-llm>` shall be the conventional human form of the substituted ID (e.g., `claude-opus-4-7` → `Claude-Opus-4.7`, `gpt-5.5` → `GPT-5.5`).
|
|
90
|
+
|
|
91
|
+
For the initial-discussion commit outcome, any adjudicated `reviewScope`
|
|
92
|
+
payload shall be exactly `specItems`, `decisionRecords`, or `mixed`; a prose
|
|
93
|
+
summary is not a review scope.
|
|
@@ -51,7 +51,7 @@ const DISCUSS_6_PROMPT = [
|
|
|
51
51
|
'Review the latest spec changes, address any rebuttals, and raise any findings.',
|
|
52
52
|
'Verify any new or updated spec items are:',
|
|
53
53
|
'Complete & coherent: sufficient for you to reimplement code.',
|
|
54
|
-
'Right level:
|
|
54
|
+
'Right level: external behavior users rely on or internal system behavior (organized per @specs/meta.md), not implementation specifics; integration/system testing, not unit testing.',
|
|
55
55
|
'Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
56
56
|
'Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
57
57
|
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
@@ -84,7 +84,7 @@ const DISCUSS_10_PROMPT = [
|
|
|
84
84
|
'Review the latest spec changes, address any rebuttals, and raise any findings.',
|
|
85
85
|
'Verify any new or updated spec items are:',
|
|
86
86
|
'Complete & coherent: sufficient for you to reimplement code.',
|
|
87
|
-
'Right level:
|
|
87
|
+
'Right level: external behavior users rely on or internal system behavior (organized per @specs/meta.md), not implementation specifics; integration/system testing, not unit testing.',
|
|
88
88
|
'Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
89
89
|
'Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
90
90
|
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
@@ -110,7 +110,8 @@ const DISCUSS_13_PROMPT = [
|
|
|
110
110
|
'For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.',
|
|
111
111
|
].join('\n');
|
|
112
112
|
const DISCUSS_14_PROMPT = [
|
|
113
|
-
'Then make a commit of the changes that belong in the repo, following @specs/
|
|
113
|
+
'Then make a commit of the changes that belong in the repo, following @specs/packages/git.md (reread if necessary).',
|
|
114
|
+
"If that spec is absent, follow the legacy @specs/dev/git.md; if neither exists, follow the repository's existing commit conventions and do not search elsewhere.",
|
|
114
115
|
'Write the commit message concisely.',
|
|
115
116
|
'Host is <host-llm>.',
|
|
116
117
|
'Participant is <participant-llm>.',
|
|
@@ -1250,7 +1251,7 @@ export const discussMachine = setup({
|
|
|
1250
1251
|
sourceItem: 'DISCUSS-14',
|
|
1251
1252
|
prompt: DISCUSS_14_PROMPT,
|
|
1252
1253
|
result: withNeedsBossReply({
|
|
1253
|
-
committed: 'Committer made the initial-discussion commit. Output may include `latestChanges
|
|
1254
|
+
committed: 'Committer made the initial-discussion commit. Output may include `latestChanges: <summary>` and `reviewScope: "specItems" | "decisionRecords" | "mixed"`.',
|
|
1254
1255
|
}),
|
|
1255
1256
|
latestChanges: context.latestChanges,
|
|
1256
1257
|
reviewScope: context.reviewScope,
|
|
@@ -220,7 +220,7 @@ const DISCUSS_6_PROMPT = [
|
|
|
220
220
|
'Review the latest spec changes, address any rebuttals, and raise any findings.',
|
|
221
221
|
'Verify any new or updated spec items are:',
|
|
222
222
|
'Complete & coherent: sufficient for you to reimplement code.',
|
|
223
|
-
'Right level:
|
|
223
|
+
'Right level: external behavior users rely on or internal system behavior (organized per @specs/meta.md), not implementation specifics; integration/system testing, not unit testing.',
|
|
224
224
|
'Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
225
225
|
'Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
226
226
|
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
@@ -257,7 +257,7 @@ const DISCUSS_10_PROMPT = [
|
|
|
257
257
|
'Review the latest spec changes, address any rebuttals, and raise any findings.',
|
|
258
258
|
'Verify any new or updated spec items are:',
|
|
259
259
|
'Complete & coherent: sufficient for you to reimplement code.',
|
|
260
|
-
'Right level:
|
|
260
|
+
'Right level: external behavior users rely on or internal system behavior (organized per @specs/meta.md), not implementation specifics; integration/system testing, not unit testing.',
|
|
261
261
|
'Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
262
262
|
'Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
263
263
|
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
@@ -287,7 +287,8 @@ const DISCUSS_13_PROMPT = [
|
|
|
287
287
|
].join('\n');
|
|
288
288
|
|
|
289
289
|
const DISCUSS_14_PROMPT = [
|
|
290
|
-
'Then make a commit of the changes that belong in the repo, following @specs/
|
|
290
|
+
'Then make a commit of the changes that belong in the repo, following @specs/packages/git.md (reread if necessary).',
|
|
291
|
+
"If that spec is absent, follow the legacy @specs/dev/git.md; if neither exists, follow the repository's existing commit conventions and do not search elsewhere.",
|
|
291
292
|
'Write the commit message concisely.',
|
|
292
293
|
'Host is <host-llm>.',
|
|
293
294
|
'Participant is <participant-llm>.',
|
|
@@ -1611,7 +1612,7 @@ export const discussMachine = setup({
|
|
|
1611
1612
|
prompt: DISCUSS_14_PROMPT,
|
|
1612
1613
|
result: withNeedsBossReply({
|
|
1613
1614
|
committed:
|
|
1614
|
-
'Committer made the initial-discussion commit. Output may include `latestChanges
|
|
1615
|
+
'Committer made the initial-discussion commit. Output may include `latestChanges: <summary>` and `reviewScope: "specItems" | "decisionRecords" | "mixed"`.',
|
|
1615
1616
|
}),
|
|
1616
1617
|
latestChanges: context.latestChanges,
|
|
1617
1618
|
reviewScope: context.reviewScope,
|
|
@@ -89,16 +89,18 @@ In the first step of each review round, Participant reviews the latest changes,
|
|
|
89
89
|
In the second step of each review round, Host addresses any findings.
|
|
90
90
|
Rounds continue until Participant raises no findings.
|
|
91
91
|
|
|
92
|
+
Spec item files are the files under @specs/ that hold spec items — @specs/packages/ and @specs/compositions/ in the current layout, or @specs/user/, @specs/dev/, and @specs/test/ in the legacy one; decision and intent records (iteration records in older scaffolds), @specs/map.md, and @specs/meta.md are not spec item files.
|
|
93
|
+
|
|
92
94
|
### DISCUSS-6
|
|
93
95
|
|
|
94
|
-
While new or updated spec items
|
|
96
|
+
While new or updated spec items (in spec item files) are under review and no new or updated DR is under review, when Committer commits at the end of the initial discussion, Captain shall prompt Participant:
|
|
95
97
|
|
|
96
98
|
> Latest changes: <changes>
|
|
97
99
|
> Rebuttals to address, if any: <rebuttals>
|
|
98
100
|
> Review the latest spec changes, address any rebuttals, and raise any findings.
|
|
99
101
|
> Verify any new or updated spec items are:
|
|
100
102
|
> Complete & coherent: sufficient for you to reimplement code.
|
|
101
|
-
> Right level:
|
|
103
|
+
> Right level: external behavior users rely on or internal system behavior (organized per @specs/meta.md), not implementation specifics; integration/system testing, not unit testing.
|
|
102
104
|
> Minimal: essential and concise; every item earns its place; also check with other items.
|
|
103
105
|
> Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
104
106
|
> Flag anything missing, redundant, over-specified, or under-specified.
|
|
@@ -110,14 +112,14 @@ While new or updated spec items under @specs/user, @specs/dev, or @specs/test ar
|
|
|
110
112
|
|
|
111
113
|
### DISCUSS-7
|
|
112
114
|
|
|
113
|
-
While new or updated spec items
|
|
115
|
+
While new or updated spec items (in spec item files) are under review and no new or updated DR is under review, when Host addresses findings with changes, Captain shall prompt Participant:
|
|
114
116
|
|
|
115
117
|
> Latest changes: <changes>
|
|
116
118
|
> Rebuttals to address, if any: <rebuttals>
|
|
117
119
|
> Review the latest spec changes, address any rebuttals, and raise any findings.
|
|
118
120
|
> Verify any new or updated spec items are:
|
|
119
121
|
> Complete & coherent: sufficient for you to reimplement code.
|
|
120
|
-
> Right level:
|
|
122
|
+
> Right level: external behavior users rely on or internal system behavior (organized per @specs/meta.md), not implementation specifics; integration/system testing, not unit testing.
|
|
121
123
|
> Minimal: essential and concise; every item earns its place; also check with other items.
|
|
122
124
|
> Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
123
125
|
> Flag anything missing, redundant, over-specified, or under-specified.
|
|
@@ -129,7 +131,7 @@ While new or updated spec items under @specs/user, @specs/dev, or @specs/test ar
|
|
|
129
131
|
|
|
130
132
|
### DISCUSS-8
|
|
131
133
|
|
|
132
|
-
While new or updated DRs are under review and no new or updated spec item
|
|
134
|
+
While new or updated DRs are under review and no new or updated spec item (in spec item files) is under review, when Committer commits at the end of the initial discussion, Captain shall prompt Participant:
|
|
133
135
|
|
|
134
136
|
> Latest changes: <changes>
|
|
135
137
|
> Rebuttals to address, if any: <rebuttals>
|
|
@@ -147,7 +149,7 @@ While new or updated DRs are under review and no new or updated spec item under
|
|
|
147
149
|
|
|
148
150
|
### DISCUSS-9
|
|
149
151
|
|
|
150
|
-
While new or updated DRs are under review and no new or updated spec item
|
|
152
|
+
While new or updated DRs are under review and no new or updated spec item (in spec item files) is under review, when Host addresses findings with changes, Captain shall prompt Participant:
|
|
151
153
|
|
|
152
154
|
> Latest changes: <changes>
|
|
153
155
|
> Rebuttals to address, if any: <rebuttals>
|
|
@@ -165,14 +167,14 @@ While new or updated DRs are under review and no new or updated spec item under
|
|
|
165
167
|
|
|
166
168
|
### DISCUSS-10
|
|
167
169
|
|
|
168
|
-
While new or updated spec items
|
|
170
|
+
While new or updated spec items (in spec item files) are under review and new or updated DRs are under review, when Committer commits at the end of the initial discussion, Captain shall prompt Participant:
|
|
169
171
|
|
|
170
172
|
> Latest changes: <changes>
|
|
171
173
|
> Rebuttals to address, if any: <rebuttals>
|
|
172
174
|
> Review the latest spec changes, address any rebuttals, and raise any findings.
|
|
173
175
|
> Verify any new or updated spec items are:
|
|
174
176
|
> Complete & coherent: sufficient for you to reimplement code.
|
|
175
|
-
> Right level:
|
|
177
|
+
> Right level: external behavior users rely on or internal system behavior (organized per @specs/meta.md), not implementation specifics; integration/system testing, not unit testing.
|
|
176
178
|
> Minimal: essential and concise; every item earns its place; also check with other items.
|
|
177
179
|
> Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
178
180
|
> Flag anything missing, redundant, over-specified, or under-specified.
|
|
@@ -189,14 +191,14 @@ While new or updated spec items under @specs/user, @specs/dev, or @specs/test ar
|
|
|
189
191
|
|
|
190
192
|
### DISCUSS-11
|
|
191
193
|
|
|
192
|
-
While new or updated spec items
|
|
194
|
+
While new or updated spec items (in spec item files) are under review and new or updated DRs are under review, when Host addresses findings with changes, Captain shall prompt Participant:
|
|
193
195
|
|
|
194
196
|
> Latest changes: <changes>
|
|
195
197
|
> Rebuttals to address, if any: <rebuttals>
|
|
196
198
|
> Review the latest spec changes, address any rebuttals, and raise any findings.
|
|
197
199
|
> Verify any new or updated spec items are:
|
|
198
200
|
> Complete & coherent: sufficient for you to reimplement code.
|
|
199
|
-
> Right level:
|
|
201
|
+
> Right level: external behavior users rely on or internal system behavior (organized per @specs/meta.md), not implementation specifics; integration/system testing, not unit testing.
|
|
200
202
|
> Minimal: essential and concise; every item earns its place; also check with other items.
|
|
201
203
|
> Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
202
204
|
> Flag anything missing, redundant, over-specified, or under-specified.
|
|
@@ -234,17 +236,22 @@ Model ID formatting examples: `claude-opus-4-7` becomes `Claude-Opus-4.7`; `gpt-
|
|
|
234
236
|
|
|
235
237
|
When the spec items or DRs are written at the end of the initial discussion, Captain shall prompt Committer:
|
|
236
238
|
|
|
237
|
-
> Then make a commit of the changes that belong in the repo, following @specs/
|
|
239
|
+
> Then make a commit of the changes that belong in the repo, following @specs/packages/git.md (reread if necessary).
|
|
240
|
+
> If that spec is absent, follow the legacy @specs/dev/git.md; if neither exists, follow the repository's existing commit conventions and do not search elsewhere.
|
|
238
241
|
> Write the commit message concisely.
|
|
239
242
|
> Host is <host-llm>.
|
|
240
243
|
> Participant is <participant-llm>.
|
|
241
244
|
> Format the Host and Participant model IDs as conventional human forms.
|
|
242
245
|
|
|
246
|
+
Results:
|
|
247
|
+
- `committed`: Committer made the initial-discussion commit. Output may include `latestChanges: <summary>` and `reviewScope: "specItems" | "decisionRecords" | "mixed"`.
|
|
248
|
+
|
|
243
249
|
### DISCUSS-15
|
|
244
250
|
|
|
245
251
|
When Participant raises no findings on uncommitted changes, Captain shall prompt Committer:
|
|
246
252
|
|
|
247
|
-
> Then make a commit of the changes that belong in the repo, following @specs/
|
|
253
|
+
> Then make a commit of the changes that belong in the repo, following @specs/packages/git.md (reread if necessary).
|
|
254
|
+
> If that spec is absent, follow the legacy @specs/dev/git.md; if neither exists, follow the repository's existing commit conventions and do not search elsewhere.
|
|
248
255
|
> Write the commit message concisely.
|
|
249
256
|
> Host is <host-llm>.
|
|
250
257
|
> Participant is <participant-llm>.
|
|
@@ -458,6 +458,9 @@ function parseClassification(raw, pendingQuestionIds = []) {
|
|
|
458
458
|
function buildAdjudicatorPrompt(input, playerOutput) {
|
|
459
459
|
const lines = [];
|
|
460
460
|
lines.push('You are the guard adjudicator for a playbook state machine.');
|
|
461
|
+
lines.push('This is hidden control work. Do not call tools, inspect files, or ' +
|
|
462
|
+
'seek external evidence. Decide only from the supplied player output ' +
|
|
463
|
+
'and guard descriptions. Reply with exactly one JSON object and no prose.');
|
|
461
464
|
lines.push(`The player "${input.player}" produced the output below for source item ${input.sourceItem}.`);
|
|
462
465
|
lines.push('Choose exactly one guard whose description matches that output.');
|
|
463
466
|
lines.push('');
|
|
@@ -618,6 +618,11 @@ function buildAdjudicatorPrompt(
|
|
|
618
618
|
): string {
|
|
619
619
|
const lines: string[] = [];
|
|
620
620
|
lines.push('You are the guard adjudicator for a playbook state machine.');
|
|
621
|
+
lines.push(
|
|
622
|
+
'This is hidden control work. Do not call tools, inspect files, or ' +
|
|
623
|
+
'seek external evidence. Decide only from the supplied player output ' +
|
|
624
|
+
'and guard descriptions. Reply with exactly one JSON object and no prose.',
|
|
625
|
+
);
|
|
621
626
|
lines.push(
|
|
622
627
|
`The player "${input.player}" produced the output below for source item ${input.sourceItem}.`,
|
|
623
628
|
);
|
package/slc/link.md
CHANGED
|
@@ -257,15 +257,21 @@ array requests a tool-free call, while omission preserves the host Captain's
|
|
|
257
257
|
configured tools.
|
|
258
258
|
`CaptainResult` carries no resume token or player-continuation selection.
|
|
259
259
|
A non-`ok`
|
|
260
|
-
result, or an `ok` result without `finalText`, shall
|
|
261
|
-
the
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
drive it to quiescence,
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
260
|
+
result, or an `ok` result without non-empty `finalText`, shall record that
|
|
261
|
+
failure on the call's single finish trace and reject the actor through the
|
|
262
|
+
FSM's error path. These structured host-result failures are recoverable
|
|
263
|
+
workflow failures, not control-plane failures: the runtime shall let the actor
|
|
264
|
+
take `onError`, drive it to quiescence, drain ordered emissions, and resolve
|
|
265
|
+
the public method with `{ outcome: 'failed' }` carrying the failure state's
|
|
266
|
+
error. This matches the delegated-player result boundary.
|
|
267
|
+
A non-abort thrown `callCaptain` port, a malformed host result, and a rejecting
|
|
268
|
+
trace sink remain control-plane failures that reject the public method. If the
|
|
269
|
+
required finish sink rejects after a structured host-result failure, the
|
|
270
|
+
actor's error and failure-state evidence shall remain the host-result failure,
|
|
271
|
+
while the public method rejects with the sink failure surfaced by the turn's
|
|
272
|
+
emission drain. Absent such a control-plane failure, if the combined signal
|
|
273
|
+
has aborted, ordinary abort settlement remains authoritative after the actor
|
|
274
|
+
reaches its error path.
|
|
269
275
|
|
|
270
276
|
Every linked runtime owns a map from resolved player id to its latest non-empty `resumeToken`.
|
|
271
277
|
Before reading a resolved direct-Captain or delegated-player result, the
|
|
@@ -716,9 +722,12 @@ Two default adjudication strategies, in selection order:
|
|
|
716
722
|
lists the `result` keys with their descriptions, and demands a JSON
|
|
717
723
|
`{ guard, …structuralPayloadFields }` answer keyed to exactly one of the
|
|
718
724
|
declared guards, excluding the runtime-owned direct-Captain `question` and
|
|
719
|
-
`response` fields above. The
|
|
720
|
-
|
|
721
|
-
the
|
|
725
|
+
`response` fields above. The prompt shall identify hidden control work,
|
|
726
|
+
prohibit tool use, file inspection, and external evidence, direct the judge
|
|
727
|
+
to decide only from the supplied actor output and declared outcomes, and
|
|
728
|
+
require exactly one JSON object with no prose. The judge prompt shall not
|
|
729
|
+
interpret the player's output, paraphrase it, or alter the FSM's `result`
|
|
730
|
+
text — it carries the description verbatim.
|
|
722
731
|
- **Marker-parse** (delegated-player alternative): a deterministic parser that
|
|
723
732
|
scans the player output for a terminal control line such as
|
|
724
733
|
`FSM-RESULT: { "guard": "...", ... }`. Useful when player adapters can
|
|
@@ -753,8 +762,11 @@ Adjudicator failures are control-plane errors.
|
|
|
753
762
|
The runtime shall propagate them by throwing out of `handleBossInput` after attempting cleanup.
|
|
754
763
|
The host adapter surfaces the throw on its control-plane channel (cligent surfaces such throws as `runtime_error` per [TMUX-025](https://github.com/sublang-ai/cligent/blob/main/specs/user/tmux-play.md#tmux-025)).
|
|
755
764
|
The host's player-result channels (`player_finished` and equivalents) are reserved for failures the player itself produced; the host emits them when `callPlayer` resolves with `status !== 'ok'`.
|
|
756
|
-
Captain
|
|
757
|
-
reported as player failures
|
|
765
|
+
Direct-Captain host-result failures stay on the Captain actor boundary and
|
|
766
|
+
shall not be reported as player failures; they follow the recoverable FSM
|
|
767
|
+
failure path specified above. Captain transport, result-shape, trace-sink, and
|
|
768
|
+
adjudication failures remain control-plane errors unless the transport failure
|
|
769
|
+
is causally identical to the active abort signal.
|
|
758
770
|
Because XState still needs the invoked promise to settle, the linked runtime
|
|
759
771
|
shall latch an adjudicator, actor-output JSON-validation, or nested-boundary
|
|
760
772
|
control error outside machine context, allow the invocation's `onError` path to
|
|
@@ -1316,6 +1328,13 @@ The emitted module:
|
|
|
1316
1328
|
weaken, runtime-derived entry text ownership or closed interrupt targets.
|
|
1317
1329
|
A conflicting duplicate field contract is a linker/runtime construction
|
|
1318
1330
|
error.
|
|
1331
|
+
`NO_ACTION` and `BOSS_REPLY` are runtime-owned event types the factory
|
|
1332
|
+
supplies itself — `NO_ACTION` as exactly `{ type: 'NO_ACTION' }`, and
|
|
1333
|
+
`BOSS_REPLY` as an optional judge-selected `questionId` plus the exact-text
|
|
1334
|
+
`answer` the runtime attaches. `bossEvents` shall carry no entry for either
|
|
1335
|
+
type; supplying one is a construction error, so a linker that judges a
|
|
1336
|
+
runtime-owned arm to have lost payload detail under erasure shall report
|
|
1337
|
+
that gap rather than emit the entry.
|
|
1319
1338
|
- Default-exports the factory call as `createPlaybookRuntime`, typed
|
|
1320
1339
|
`PlaybookRuntimeFactory<PlaybookRuntimeOptions>`.
|
|
1321
1340
|
- Exposes, under an `_internal` export, the pure helpers verification
|