@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
|
@@ -191,29 +191,29 @@ const stateDescriptions = {
|
|
|
191
191
|
summarizeSpecs:
|
|
192
192
|
'CODE-4: Coder summarizes a completed IR into minimal spec items.',
|
|
193
193
|
reviewBossCommitSpecs:
|
|
194
|
-
'CODE-5: Reviewer reviews a Boss-intent commit whose changes are only in
|
|
194
|
+
'CODE-5: Reviewer reviews a Boss-intent commit whose changes are only in spec item files.',
|
|
195
195
|
reviewBossCommitCode:
|
|
196
|
-
'CODE-6: Reviewer reviews a Boss-intent commit whose changes are only outside
|
|
196
|
+
'CODE-6: Reviewer reviews a Boss-intent commit whose changes are only outside spec item files.',
|
|
197
197
|
reviewBossCommitMixed:
|
|
198
|
-
'CODE-7: Reviewer reviews a Boss-intent commit whose changes span both
|
|
198
|
+
'CODE-7: Reviewer reviews a Boss-intent commit whose changes span both spec item files and other files.',
|
|
199
199
|
reviewIrTaskCommitSpecs:
|
|
200
|
-
'CODE-8: Reviewer reviews an IR-task commit whose changes are only in
|
|
200
|
+
'CODE-8: Reviewer reviews an IR-task commit whose changes are only in spec item files.',
|
|
201
201
|
reviewIrTaskCommitCode:
|
|
202
|
-
'CODE-9: Reviewer reviews an IR-task commit whose changes are only outside
|
|
202
|
+
'CODE-9: Reviewer reviews an IR-task commit whose changes are only outside spec item files.',
|
|
203
203
|
reviewIrTaskCommitMixed:
|
|
204
|
-
'CODE-10: Reviewer reviews an IR-task commit whose changes span both
|
|
204
|
+
'CODE-10: Reviewer reviews an IR-task commit whose changes span both spec item files and other files.',
|
|
205
205
|
reviewChangesSpecs:
|
|
206
|
-
'CODE-11: Reviewer reviews uncommitted Coder changes that touch only
|
|
206
|
+
'CODE-11: Reviewer reviews uncommitted Coder changes that touch only spec item files with no accompanying rebuttals.',
|
|
207
207
|
reviewChangesCode:
|
|
208
|
-
'CODE-12: Reviewer reviews uncommitted Coder changes that touch only files outside
|
|
208
|
+
'CODE-12: Reviewer reviews uncommitted Coder changes that touch only files outside spec item files with no accompanying rebuttals.',
|
|
209
209
|
reviewChangesMixed:
|
|
210
|
-
'CODE-13: Reviewer reviews uncommitted Coder changes that touch both
|
|
210
|
+
'CODE-13: Reviewer reviews uncommitted Coder changes that touch both spec item files and other files with no accompanying rebuttals.',
|
|
211
211
|
reviewChangesAndChallengesSpecs:
|
|
212
|
-
'CODE-15: Reviewer reviews uncommitted Coder changes that touch only
|
|
212
|
+
'CODE-15: Reviewer reviews uncommitted Coder changes that touch only spec item files and adjudicates accompanying rebuttals in one round.',
|
|
213
213
|
reviewChangesAndChallengesCode:
|
|
214
|
-
'CODE-16: Reviewer reviews uncommitted Coder changes that touch only files outside
|
|
214
|
+
'CODE-16: Reviewer reviews uncommitted Coder changes that touch only files outside spec item files and adjudicates accompanying rebuttals in one round.',
|
|
215
215
|
reviewChangesAndChallengesMixed:
|
|
216
|
-
'CODE-17: Reviewer reviews uncommitted Coder changes that touch both
|
|
216
|
+
'CODE-17: Reviewer reviews uncommitted Coder changes that touch both spec item files and other files and adjudicates accompanying rebuttals in one round.',
|
|
217
217
|
adjudicateChallenges:
|
|
218
218
|
'CODE-14: Reviewer adjudicates Coder rebuttals against the prior review when Coder produced no code edits this round.',
|
|
219
219
|
commitCoderInitial:
|
|
@@ -354,7 +354,7 @@ const planAndImplementInput: PlayerInputFactory = (context) => ({
|
|
|
354
354
|
...bossReplyInputFields(context),
|
|
355
355
|
prompt: [
|
|
356
356
|
'Assess whether this can be completed in a single commit, following best practices.',
|
|
357
|
-
'If yes, implement and test, updating both code and specs; otherwise, decompose into tasks as a new IR under @specs/iterations and stop without implementing any IR task.',
|
|
357
|
+
'If yes, implement and test, updating both code and specs; otherwise, decompose into tasks as a new IR under @specs/intents (or @specs/iterations in older scaffolds) and stop without implementing any IR task.',
|
|
358
358
|
'For context discovery, @specs/map.md indexes all spec files and @specs/meta.md describes the spec format.',
|
|
359
359
|
'Ensure @specs/map.md reflects the changes.',
|
|
360
360
|
'Do not commit.',
|
|
@@ -396,9 +396,9 @@ const summarizeSpecsInput: PlayerInputFactory = (context) => ({
|
|
|
396
396
|
'Read IR-<#> and corresponding commits.',
|
|
397
397
|
'According to @specs/meta.md, add or update spec items to fully capture:',
|
|
398
398
|
'',
|
|
399
|
-
'- the
|
|
400
|
-
'- the system behavior
|
|
401
|
-
'- the integration/system test cases
|
|
399
|
+
'- the external behavior users rely on,',
|
|
400
|
+
'- the internal system behavior, and',
|
|
401
|
+
'- the integration/system test cases.',
|
|
402
402
|
'',
|
|
403
403
|
'The spec items should be the *minimal* set needed to reimplement code without the IR.',
|
|
404
404
|
'The set should be complete and coherent.',
|
|
@@ -408,7 +408,7 @@ const summarizeSpecsInput: PlayerInputFactory = (context) => ({
|
|
|
408
408
|
].join('\n'),
|
|
409
409
|
result: withNeedsBossReply({
|
|
410
410
|
specsReady: 'Coder produced uncommitted spec updates (Initial Changes).',
|
|
411
|
-
noSpecChanges: 'Existing specs already capture the
|
|
411
|
+
noSpecChanges: 'Existing specs already capture the realized intent.',
|
|
412
412
|
}),
|
|
413
413
|
});
|
|
414
414
|
|
|
@@ -656,17 +656,17 @@ export const codingMachine = setup({
|
|
|
656
656
|
].join('\n'),
|
|
657
657
|
result: {
|
|
658
658
|
changesMadeSpecs:
|
|
659
|
-
'Coder accepted items and produced unstaged/untracked edits in @specs/{user,dev,test}/
|
|
659
|
+
'Coder accepted items and produced unstaged/untracked edits only in spec item files (@specs/packages/, @specs/compositions/, or legacy @specs/{user,dev,test}/), without raising any rebuttals.',
|
|
660
660
|
changesMadeCode:
|
|
661
|
-
'Coder accepted items and produced unstaged/untracked edits outside @specs/
|
|
661
|
+
'Coder accepted items and produced unstaged/untracked edits only outside spec item files (any other files, including @specs/ decision, intent, or legacy iteration records, @specs/map.md, and @specs/meta.md), without raising any rebuttals.',
|
|
662
662
|
changesMadeMixed:
|
|
663
|
-
'Coder accepted items and produced unstaged/untracked edits spanning both
|
|
663
|
+
'Coder accepted items and produced unstaged/untracked edits spanning both spec item files and other files, without raising any rebuttals.',
|
|
664
664
|
changesMadeSpecsAndChallenged:
|
|
665
|
-
'Coder produced unstaged/untracked edits in @specs/{user,dev,test}/
|
|
665
|
+
'Coder produced unstaged/untracked edits only in spec item files (@specs/packages/, @specs/compositions/, or legacy @specs/{user,dev,test}/) AND challenged one or more review items. Output shall include `challenges: <numbered rebuttals, one per challenged item>`.',
|
|
666
666
|
changesMadeCodeAndChallenged:
|
|
667
|
-
'Coder produced unstaged/untracked edits outside
|
|
667
|
+
'Coder produced unstaged/untracked edits only outside spec item files AND challenged one or more review items. Output shall include `challenges: <numbered rebuttals, one per challenged item>`.',
|
|
668
668
|
changesMadeMixedAndChallenged:
|
|
669
|
-
'Coder produced unstaged/untracked edits spanning both
|
|
669
|
+
'Coder produced unstaged/untracked edits spanning both spec item files and other files AND challenged one or more review items. Output shall include `challenges: <numbered rebuttals, one per challenged item>`.',
|
|
670
670
|
challengesRaised:
|
|
671
671
|
'Coder challenged one or more review items without producing any code edits. Output shall include `challenges: <numbered rebuttals, one per challenged item>`.',
|
|
672
672
|
accepted:
|
|
@@ -831,7 +831,7 @@ export const codingMachine = setup({
|
|
|
831
831
|
'Verify any affected spec items are:',
|
|
832
832
|
'',
|
|
833
833
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
834
|
-
'- Right level:
|
|
834
|
+
'- 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.',
|
|
835
835
|
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
836
836
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
837
837
|
'',
|
|
@@ -957,7 +957,7 @@ export const codingMachine = setup({
|
|
|
957
957
|
'Verify any affected spec items are:',
|
|
958
958
|
'',
|
|
959
959
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
960
|
-
'- Right level:
|
|
960
|
+
'- 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.',
|
|
961
961
|
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
962
962
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
963
963
|
'',
|
|
@@ -1023,7 +1023,7 @@ export const codingMachine = setup({
|
|
|
1023
1023
|
'Verify any affected spec items are:',
|
|
1024
1024
|
'',
|
|
1025
1025
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
1026
|
-
'- Right level:
|
|
1026
|
+
'- 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.',
|
|
1027
1027
|
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
1028
1028
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
1029
1029
|
'',
|
|
@@ -1151,7 +1151,7 @@ export const codingMachine = setup({
|
|
|
1151
1151
|
'Verify any affected spec items are:',
|
|
1152
1152
|
'',
|
|
1153
1153
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
1154
|
-
'- Right level:
|
|
1154
|
+
'- 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.',
|
|
1155
1155
|
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
1156
1156
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
1157
1157
|
'',
|
|
@@ -1215,7 +1215,7 @@ export const codingMachine = setup({
|
|
|
1215
1215
|
'Verify any affected spec items are:',
|
|
1216
1216
|
'',
|
|
1217
1217
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
1218
|
-
'- Right level:
|
|
1218
|
+
'- 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.',
|
|
1219
1219
|
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
1220
1220
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
1221
1221
|
'',
|
|
@@ -1321,7 +1321,7 @@ export const codingMachine = setup({
|
|
|
1321
1321
|
'Verify any affected spec items are:',
|
|
1322
1322
|
'',
|
|
1323
1323
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
1324
|
-
'- Right level:
|
|
1324
|
+
'- 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.',
|
|
1325
1325
|
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
1326
1326
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
1327
1327
|
'',
|
|
@@ -1377,7 +1377,7 @@ export const codingMachine = setup({
|
|
|
1377
1377
|
'Verify any affected spec items are:',
|
|
1378
1378
|
'',
|
|
1379
1379
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
1380
|
-
'- Right level:
|
|
1380
|
+
'- 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.',
|
|
1381
1381
|
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
1382
1382
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
1383
1383
|
'',
|
|
@@ -1492,7 +1492,7 @@ export const codingMachine = setup({
|
|
|
1492
1492
|
'Verify any affected spec items are:',
|
|
1493
1493
|
'',
|
|
1494
1494
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
1495
|
-
'- Right level:
|
|
1495
|
+
'- 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.',
|
|
1496
1496
|
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
1497
1497
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
1498
1498
|
'',
|
|
@@ -1621,18 +1621,19 @@ export const codingMachine = setup({
|
|
|
1621
1621
|
coderPlayer: context.coderPlayer,
|
|
1622
1622
|
committerPlayer: context.committerPlayer,
|
|
1623
1623
|
prompt: [
|
|
1624
|
-
'Make a commit of the changes that belong in the repo, following @specs/
|
|
1624
|
+
'Make a commit of the changes that belong in the repo, following @specs/packages/git.md (reread if necessary).',
|
|
1625
|
+
"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.",
|
|
1625
1626
|
'Write the commit message concisely.',
|
|
1626
1627
|
'Coder is <coder-llm>.',
|
|
1627
1628
|
'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`).',
|
|
1628
1629
|
].join('\n'),
|
|
1629
1630
|
result: {
|
|
1630
1631
|
committedSpecs:
|
|
1631
|
-
'Committed changes that touch only @specs/{user,dev,test}
|
|
1632
|
+
'Committed changes that touch only spec item files (@specs/packages/, @specs/compositions/, or legacy @specs/{user,dev,test}/).',
|
|
1632
1633
|
committedCode:
|
|
1633
|
-
'Committed changes that touch only files
|
|
1634
|
+
'Committed changes that touch only files that are not spec item files (any other files, including @specs/ decision, intent, or legacy iteration records, @specs/map.md, and @specs/meta.md).',
|
|
1634
1635
|
committedMixed:
|
|
1635
|
-
'Committed changes that span both
|
|
1636
|
+
'Committed changes that span both spec item files and other files.',
|
|
1636
1637
|
noRelevantChanges: 'There are no relevant changes to commit.',
|
|
1637
1638
|
needsBossInput: 'Committing requires additional Boss input.',
|
|
1638
1639
|
needsBossReply: needsBossReplyDescription,
|
|
@@ -1700,7 +1701,8 @@ export const codingMachine = setup({
|
|
|
1700
1701
|
reviewerPlayer: context.reviewerPlayer,
|
|
1701
1702
|
committerPlayer: context.committerPlayer,
|
|
1702
1703
|
prompt: [
|
|
1703
|
-
'Make a commit of the changes that belong in the repo, following @specs/
|
|
1704
|
+
'Make a commit of the changes that belong in the repo, following @specs/packages/git.md (reread if necessary).',
|
|
1705
|
+
"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.",
|
|
1704
1706
|
'Write the commit message concisely.',
|
|
1705
1707
|
'Coder is <coder-llm>; Reviewer is <reviewer-llm>.',
|
|
1706
1708
|
'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`).',
|
|
@@ -15,7 +15,7 @@ Players:
|
|
|
15
15
|
|
|
16
16
|
When Boss gives a coding intent, Captain shall relay it to Coder along with the following prompt:
|
|
17
17
|
> Assess whether this can be completed in a single commit, following best practices.
|
|
18
|
-
> If yes, implement and test, updating both code and specs; otherwise, decompose into tasks as a new IR under @specs/iterations and stop without implementing any IR task.
|
|
18
|
+
> If yes, implement and test, updating both code and specs; otherwise, decompose into tasks as a new IR under @specs/intents (or @specs/iterations in older scaffolds) and stop without implementing any IR task.
|
|
19
19
|
> For context discovery, @specs/map.md indexes all spec files and @specs/meta.md describes the spec format.
|
|
20
20
|
> Ensure @specs/map.md reflects the changes.
|
|
21
21
|
> Do not commit.
|
|
@@ -42,9 +42,9 @@ When an IR is done, Captain shall prompt Coder:
|
|
|
42
42
|
> Read IR-<#> and corresponding commits.
|
|
43
43
|
> According to @specs/meta.md, add or update spec items to fully capture:
|
|
44
44
|
>
|
|
45
|
-
> - the
|
|
46
|
-
> - the system behavior
|
|
47
|
-
> - the integration/system test cases
|
|
45
|
+
> - the external behavior users rely on,
|
|
46
|
+
> - the internal system behavior, and
|
|
47
|
+
> - the integration/system test cases.
|
|
48
48
|
>
|
|
49
49
|
> The spec items should be the *minimal* set needed to reimplement code without the IR.
|
|
50
50
|
> The set should be complete and coherent.
|
|
@@ -58,15 +58,17 @@ For each finding in a review round, Coder either addresses it with changes or ch
|
|
|
58
58
|
Any code change to address findings starts a new round of review, even if some findings are also rebutted.
|
|
59
59
|
Rounds continue until Reviewer raises no findings.
|
|
60
60
|
|
|
61
|
+
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.
|
|
62
|
+
|
|
61
63
|
### CODE-5
|
|
62
64
|
|
|
63
|
-
When Committer commits Initial Changes from a Boss coding intent involving changes only in
|
|
65
|
+
When Committer commits Initial Changes from a Boss coding intent involving changes only in spec item files, Captain shall relay the Boss's coding intent to Reviewer along with the following prompt:
|
|
64
66
|
> Review the latest commit.
|
|
65
67
|
> Refer to the commit message.
|
|
66
68
|
> Verify any affected spec items are:
|
|
67
69
|
>
|
|
68
70
|
> - Complete & coherent: sufficient for you to reimplement code.
|
|
69
|
-
> - Right level:
|
|
71
|
+
> - 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.
|
|
70
72
|
> - Minimal: essential and concise; every item earns its place; also check with other items.
|
|
71
73
|
> - Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
72
74
|
>
|
|
@@ -78,7 +80,7 @@ When Committer commits Initial Changes from a Boss coding intent involving chang
|
|
|
78
80
|
|
|
79
81
|
### CODE-6
|
|
80
82
|
|
|
81
|
-
When Committer commits Initial Changes from a Boss coding intent involving changes only outside
|
|
83
|
+
When Committer commits Initial Changes from a Boss coding intent involving changes only outside spec item files, Captain shall relay the Boss's coding intent to Reviewer along with the following prompt:
|
|
82
84
|
> Review the latest commit.
|
|
83
85
|
> Refer to the commit message.
|
|
84
86
|
> Flag any issues or improvements (numbered; no duplication).
|
|
@@ -90,7 +92,7 @@ When Committer commits Initial Changes from a Boss coding intent involving chang
|
|
|
90
92
|
|
|
91
93
|
### CODE-7
|
|
92
94
|
|
|
93
|
-
When Committer commits Initial Changes from a Boss coding intent involving changes both in and outside
|
|
95
|
+
When Committer commits Initial Changes from a Boss coding intent involving changes both in and outside spec item files, Captain shall relay the Boss's coding intent to Reviewer along with the following prompt:
|
|
94
96
|
> Review the latest commit.
|
|
95
97
|
> Refer to the commit message.
|
|
96
98
|
> Flag any issues or improvements (numbered; no duplication).
|
|
@@ -98,7 +100,7 @@ When Committer commits Initial Changes from a Boss coding intent involving chang
|
|
|
98
100
|
> Verify any affected spec items are:
|
|
99
101
|
>
|
|
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
|
>
|
|
@@ -110,13 +112,13 @@ When Committer commits Initial Changes from a Boss coding intent involving chang
|
|
|
110
112
|
|
|
111
113
|
### CODE-8
|
|
112
114
|
|
|
113
|
-
When Committer commits Initial Changes from an IR task involving changes only in
|
|
115
|
+
When Committer commits Initial Changes from an IR task involving changes only in spec item files, Captain shall relay the IR's task description to Reviewer along with the following prompt:
|
|
114
116
|
> Review the latest commit.
|
|
115
117
|
> Refer to the commit message.
|
|
116
118
|
> Verify any affected spec items are:
|
|
117
119
|
>
|
|
118
120
|
> - Complete & coherent: sufficient for you to reimplement code.
|
|
119
|
-
> - Right level:
|
|
121
|
+
> - 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.
|
|
120
122
|
> - Minimal: essential and concise; every item earns its place; also check with other items.
|
|
121
123
|
> - Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
122
124
|
>
|
|
@@ -128,7 +130,7 @@ When Committer commits Initial Changes from an IR task involving changes only in
|
|
|
128
130
|
|
|
129
131
|
### CODE-9
|
|
130
132
|
|
|
131
|
-
When Committer commits Initial Changes from an IR task involving changes only outside
|
|
133
|
+
When Committer commits Initial Changes from an IR task involving changes only outside spec item files, Captain shall relay the IR's task description to Reviewer along with the following prompt:
|
|
132
134
|
> Review the latest commit.
|
|
133
135
|
> Refer to the commit message.
|
|
134
136
|
> Flag any issues or improvements (numbered; no duplication).
|
|
@@ -140,7 +142,7 @@ When Committer commits Initial Changes from an IR task involving changes only ou
|
|
|
140
142
|
|
|
141
143
|
### CODE-10
|
|
142
144
|
|
|
143
|
-
When Committer commits Initial Changes from an IR task involving changes both in and outside
|
|
145
|
+
When Committer commits Initial Changes from an IR task involving changes both in and outside spec item files, Captain shall relay the IR's task description to Reviewer along with the following prompt:
|
|
144
146
|
> Review the latest commit.
|
|
145
147
|
> Refer to the commit message.
|
|
146
148
|
> Flag any issues or improvements (numbered; no duplication).
|
|
@@ -148,7 +150,7 @@ When Committer commits Initial Changes from an IR task involving changes both in
|
|
|
148
150
|
> Verify any affected spec items are:
|
|
149
151
|
>
|
|
150
152
|
> - Complete & coherent: sufficient for you to reimplement code.
|
|
151
|
-
> - Right level:
|
|
153
|
+
> - 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.
|
|
152
154
|
> - Minimal: essential and concise; every item earns its place; also check with other items.
|
|
153
155
|
> - Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
154
156
|
>
|
|
@@ -160,13 +162,13 @@ When Committer commits Initial Changes from an IR task involving changes both in
|
|
|
160
162
|
|
|
161
163
|
### CODE-11
|
|
162
164
|
|
|
163
|
-
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes only in
|
|
165
|
+
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes only in spec item files without raising rebuttals, Captain shall prompt Reviewer to begin a review round:
|
|
164
166
|
> Review the unstaged and untracked changes in the context of the staged changes.
|
|
165
167
|
> Understand the intent.
|
|
166
168
|
> Verify any affected spec items are:
|
|
167
169
|
>
|
|
168
170
|
> - Complete & coherent: sufficient for you to reimplement code.
|
|
169
|
-
> - Right level:
|
|
171
|
+
> - 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.
|
|
170
172
|
> - Minimal: essential and concise; every item earns its place; also check with other items.
|
|
171
173
|
> - Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
172
174
|
>
|
|
@@ -178,7 +180,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
|
|
|
178
180
|
|
|
179
181
|
### CODE-12
|
|
180
182
|
|
|
181
|
-
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes only outside
|
|
183
|
+
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes only outside spec item files without raising rebuttals, Captain shall prompt Reviewer to begin a review round:
|
|
182
184
|
> Review the unstaged and untracked changes in the context of the staged changes.
|
|
183
185
|
> Understand the intent.
|
|
184
186
|
> Flag any issues or improvements (numbered; no duplication).
|
|
@@ -190,7 +192,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
|
|
|
190
192
|
|
|
191
193
|
### CODE-13
|
|
192
194
|
|
|
193
|
-
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes both in and outside
|
|
195
|
+
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes both in and outside spec item files without raising rebuttals, Captain shall prompt Reviewer to begin a review round:
|
|
194
196
|
> Review the unstaged and untracked changes in the context of the staged changes.
|
|
195
197
|
> Understand the intent.
|
|
196
198
|
> Flag any issues or improvements (numbered; no duplication).
|
|
@@ -198,7 +200,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
|
|
|
198
200
|
> Verify any affected spec items are:
|
|
199
201
|
>
|
|
200
202
|
> - Complete & coherent: sufficient for you to reimplement code.
|
|
201
|
-
> - Right level:
|
|
203
|
+
> - 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.
|
|
202
204
|
> - Minimal: essential and concise; every item earns its place; also check with other items.
|
|
203
205
|
> - Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
204
206
|
>
|
|
@@ -216,13 +218,13 @@ When Coder raises rebuttals without making code changes, Captain shall relay the
|
|
|
216
218
|
|
|
217
219
|
### CODE-15
|
|
218
220
|
|
|
219
|
-
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes only in
|
|
221
|
+
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes only in spec item files and also raises rebuttals, Captain shall prompt Reviewer to begin a review round and relay the rebuttals along with the following prompt:
|
|
220
222
|
> Review the unstaged and untracked changes in the context of the staged changes.
|
|
221
223
|
> Understand the intent.
|
|
222
224
|
> Verify any affected spec items are:
|
|
223
225
|
>
|
|
224
226
|
> - Complete & coherent: sufficient for you to reimplement code.
|
|
225
|
-
> - Right level:
|
|
227
|
+
> - 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.
|
|
226
228
|
> - Minimal: essential and concise; every item earns its place; also check with other items.
|
|
227
229
|
> - Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
228
230
|
>
|
|
@@ -235,7 +237,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
|
|
|
235
237
|
|
|
236
238
|
### CODE-16
|
|
237
239
|
|
|
238
|
-
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes only outside
|
|
240
|
+
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes only outside spec item files and also raises rebuttals, Captain shall prompt Reviewer to begin a review round and relay the rebuttals along with the following prompt:
|
|
239
241
|
> Review the unstaged and untracked changes in the context of the staged changes.
|
|
240
242
|
> Understand the intent.
|
|
241
243
|
> Flag any issues or improvements (numbered; no duplication).
|
|
@@ -248,7 +250,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
|
|
|
248
250
|
|
|
249
251
|
### CODE-17
|
|
250
252
|
|
|
251
|
-
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes both in and outside
|
|
253
|
+
When Coder makes unreviewed changes (outside of any Initial Changes) involving changes both in and outside spec item files and also raises rebuttals, Captain shall prompt Reviewer to begin a review round and relay the rebuttals along with the following prompt:
|
|
252
254
|
> Review the unstaged and untracked changes in the context of the staged changes.
|
|
253
255
|
> Understand the intent.
|
|
254
256
|
> Flag any issues or improvements (numbered; no duplication).
|
|
@@ -256,7 +258,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
|
|
|
256
258
|
> Verify any affected spec items are:
|
|
257
259
|
>
|
|
258
260
|
> - Complete & coherent: sufficient for you to reimplement code.
|
|
259
|
-
> - Right level:
|
|
261
|
+
> - 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.
|
|
260
262
|
> - Minimal: essential and concise; every item earns its place; also check with other items.
|
|
261
263
|
> - Well organized: spec packages are finely scoped, with high cohesion and low coupling.
|
|
262
264
|
>
|
|
@@ -272,7 +274,8 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
|
|
|
272
274
|
### CODE-18
|
|
273
275
|
|
|
274
276
|
When Coder makes any Initial Changes and Reviewer has not played since the last commit, Captain shall prompt Committer:
|
|
275
|
-
> Make a commit of the changes that belong in the repo, following @specs/
|
|
277
|
+
> Make a commit of the changes that belong in the repo, following @specs/packages/git.md (reread if necessary).
|
|
278
|
+
> 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.
|
|
276
279
|
> Write the commit message concisely.
|
|
277
280
|
> Coder is <coder-llm>.
|
|
278
281
|
> 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`).
|
|
@@ -282,7 +285,8 @@ Result guard: `needsBossInput` — Committing requires additional Boss input or
|
|
|
282
285
|
### CODE-19
|
|
283
286
|
|
|
284
287
|
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:
|
|
285
|
-
> Make a commit of the changes that belong in the repo, following @specs/
|
|
288
|
+
> Make a commit of the changes that belong in the repo, following @specs/packages/git.md (reread if necessary).
|
|
289
|
+
> 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.
|
|
286
290
|
> Write the commit message concisely.
|
|
287
291
|
> Coder is <coder-llm>; Reviewer is <reviewer-llm>.
|
|
288
292
|
> 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`).
|
|
@@ -189,6 +189,10 @@ function extractRequiredFields(description) {
|
|
|
189
189
|
}
|
|
190
190
|
function buildJudgePrompt(input, finalText) {
|
|
191
191
|
const lines = [];
|
|
192
|
+
lines.push('This is hidden control work. Do not call tools, inspect files, or ' +
|
|
193
|
+
'seek external evidence. Decide only from the supplied player output ' +
|
|
194
|
+
'and outcome descriptions. Reply with exactly one JSON object and no prose.');
|
|
195
|
+
lines.push('');
|
|
192
196
|
lines.push(`The ${input.player} just produced this output:`);
|
|
193
197
|
lines.push('');
|
|
194
198
|
lines.push('```');
|
|
@@ -290,6 +290,12 @@ function extractRequiredFields(description: string): string[] {
|
|
|
290
290
|
|
|
291
291
|
function buildJudgePrompt(input: PlayerInput, finalText: string): string {
|
|
292
292
|
const lines: string[] = [];
|
|
293
|
+
lines.push(
|
|
294
|
+
'This is hidden control work. Do not call tools, inspect files, or ' +
|
|
295
|
+
'seek external evidence. Decide only from the supplied player output ' +
|
|
296
|
+
'and outcome descriptions. Reply with exactly one JSON object and no prose.',
|
|
297
|
+
);
|
|
298
|
+
lines.push('');
|
|
293
299
|
lines.push(`The ${input.player} just produced this output:`);
|
|
294
300
|
lines.push('');
|
|
295
301
|
lines.push('```');
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
3
|
import { randomUUID } from 'node:crypto';
|
|
4
4
|
import PQueue from 'p-queue';
|
|
5
|
-
import { registerPlaybookAbortCleanup } from '../../../src/xstate-runtime.js';
|
|
5
|
+
import { hiddenControlEnvelope, registerPlaybookAbortCleanup, } from '../../../src/xstate-runtime.js';
|
|
6
6
|
import createDefaultCaptainRuntime from '../captain.playbook/captain.playbook.js';
|
|
7
7
|
class VisibilityControlError extends Error {
|
|
8
8
|
constructor(cause) {
|
|
@@ -27,6 +27,47 @@ function visibleChatEnvelope(message) {
|
|
|
27
27
|
message,
|
|
28
28
|
].join('\n\n');
|
|
29
29
|
}
|
|
30
|
+
// DR-013 A1: adapters with no provider-enforced tool-restriction surface.
|
|
31
|
+
// Cligent's Codex adapter rejects any `allowedTools` value — including the
|
|
32
|
+
// empty list that expresses tool-free — because the supported Codex SDK
|
|
33
|
+
// cannot enforce one, so requesting it fails every control call before the
|
|
34
|
+
// model is reached. Omitting the option is the only way such an adapter can
|
|
35
|
+
// run a control call at all; its isolation then rests on the authored
|
|
36
|
+
// hidden-judge envelope below rather than on provider enforcement.
|
|
37
|
+
const ADAPTERS_WITHOUT_TOOL_ENFORCEMENT = new Set([
|
|
38
|
+
'codex',
|
|
39
|
+
]);
|
|
40
|
+
// The tool half of a control call's options. An empty allowlist means "no
|
|
41
|
+
// tools available" and is distinct from omission, which grants the adapter's
|
|
42
|
+
// full native tool surface — so omit only where the empty list would be
|
|
43
|
+
// refused, and keep requesting enforcement whenever the adapter is unknown.
|
|
44
|
+
function controlCallToolOptions(captainAdapter) {
|
|
45
|
+
if (captainAdapter !== undefined &&
|
|
46
|
+
ADAPTERS_WITHOUT_TOOL_ENFORCEMENT.has(captainAdapter)) {
|
|
47
|
+
return {};
|
|
48
|
+
}
|
|
49
|
+
return { allowedTools: [] };
|
|
50
|
+
}
|
|
51
|
+
// A runtime-requested allowlist forwarded to the captain agent. The empty
|
|
52
|
+
// list is the runtime's way of saying "tool-free", so it is the only value
|
|
53
|
+
// the host substitutes; a non-empty list is a real restriction and stays
|
|
54
|
+
// fail-closed on an adapter that cannot enforce it.
|
|
55
|
+
function forwardedToolOptions(requested, captainAdapter) {
|
|
56
|
+
if (requested === undefined)
|
|
57
|
+
return {};
|
|
58
|
+
if (requested.length === 0)
|
|
59
|
+
return controlCallToolOptions(captainAdapter);
|
|
60
|
+
return { allowedTools: requested };
|
|
61
|
+
}
|
|
62
|
+
function readCaptainAdapter(options) {
|
|
63
|
+
if (typeof options !== 'object' || options === null)
|
|
64
|
+
return undefined;
|
|
65
|
+
const adapter = options.captainAdapter;
|
|
66
|
+
return typeof adapter === 'string' && adapter.length > 0
|
|
67
|
+
? adapter
|
|
68
|
+
: undefined;
|
|
69
|
+
}
|
|
70
|
+
const hiddenJudgeEnvelope = hiddenControlEnvelope;
|
|
30
71
|
function visibleTurnSummaryEnvelope(input) {
|
|
31
72
|
return [
|
|
32
73
|
'You are the Playbook Captain shell.',
|
|
@@ -176,6 +217,10 @@ export function createPlaybookCaptainShell(options, deps = {}) {
|
|
|
176
217
|
const loadModule = deps.loadModule ?? ((specifier) => import(specifier));
|
|
177
218
|
const createSessionId = deps.createSessionId ?? randomUUID;
|
|
178
219
|
const createCaptainRuntime = deps.createCaptainRuntime ?? createDefaultCaptainRuntime;
|
|
220
|
+
// DR-013 A1: the launcher passes the resolved captain adapter through
|
|
221
|
+
// `captain.options`; a raw `--config` launch leaves it undefined, which
|
|
222
|
+
// keeps the enforced empty allowlist and its fail-closed behavior.
|
|
223
|
+
const captainAdapter = readCaptainAdapter(options);
|
|
179
224
|
let entries = [];
|
|
180
225
|
let byCommand = new Map();
|
|
181
226
|
let byId = new Map();
|
|
@@ -382,9 +427,7 @@ export function createPlaybookCaptainShell(options, deps = {}) {
|
|
|
382
427
|
const result = await callCaptainQueued(frame, activeContext, prompt, {
|
|
383
428
|
visibility: options.visibility,
|
|
384
429
|
resume: options.resume,
|
|
385
|
-
...(options.allowedTools
|
|
386
|
-
? {}
|
|
387
|
-
: { allowedTools: options.allowedTools }),
|
|
430
|
+
...forwardedToolOptions(options.allowedTools, captainAdapter),
|
|
388
431
|
}, signal);
|
|
389
432
|
return {
|
|
390
433
|
status: result.status,
|
|
@@ -398,7 +441,11 @@ export function createPlaybookCaptainShell(options, deps = {}) {
|
|
|
398
441
|
if (!activeContext) {
|
|
399
442
|
throw new Error('callJudge invoked outside a Boss turn');
|
|
400
443
|
}
|
|
401
|
-
const result = await callCaptainQueued(frame, activeContext, prompt, {
|
|
444
|
+
const result = await callCaptainQueued(frame, activeContext, hiddenJudgeEnvelope(prompt), {
|
|
445
|
+
visibility: 'hidden',
|
|
446
|
+
resume: false,
|
|
447
|
+
...controlCallToolOptions(captainAdapter),
|
|
448
|
+
}, signal);
|
|
402
449
|
if (result.status !== 'ok') {
|
|
403
450
|
throw new Error(result.error ?? `callCaptain status "${result.status}"`);
|
|
404
451
|
}
|
|
@@ -1101,13 +1148,21 @@ export function createPlaybookCaptainShell(options, deps = {}) {
|
|
|
1101
1148
|
}
|
|
1102
1149
|
};
|
|
1103
1150
|
const callVisibleChat = async (frame, context, message) => {
|
|
1104
|
-
const result = await callCaptainQueued(frame, context, visibleChatEnvelope(message), {
|
|
1151
|
+
const result = await callCaptainQueued(frame, context, visibleChatEnvelope(message), {
|
|
1152
|
+
visibility: 'visible',
|
|
1153
|
+
resume: false,
|
|
1154
|
+
...controlCallToolOptions(captainAdapter),
|
|
1155
|
+
}, context.signal);
|
|
1105
1156
|
if (result.status !== 'ok') {
|
|
1106
1157
|
throw new Error(result.error ?? `callCaptain status "${result.status}"`);
|
|
1107
1158
|
}
|
|
1108
1159
|
};
|
|
1109
1160
|
const callVisibleTurnSummary = async (frame, context, input) => {
|
|
1110
|
-
const result = await callCaptainQueued(frame, context, visibleTurnSummaryEnvelope(input), {
|
|
1161
|
+
const result = await callCaptainQueued(frame, context, visibleTurnSummaryEnvelope(input), {
|
|
1162
|
+
visibility: 'visible',
|
|
1163
|
+
resume: false,
|
|
1164
|
+
...controlCallToolOptions(captainAdapter),
|
|
1165
|
+
}, context.signal);
|
|
1111
1166
|
if (result.status !== 'ok') {
|
|
1112
1167
|
throw new Error(result.error ?? `callCaptain status "${result.status}"`);
|
|
1113
1168
|
}
|
|
@@ -1151,7 +1206,11 @@ export function createPlaybookCaptainShell(options, deps = {}) {
|
|
|
1151
1206
|
}
|
|
1152
1207
|
let decision;
|
|
1153
1208
|
try {
|
|
1154
|
-
const result = await callCaptainQueued(leaf, context, hiddenLifecycleEnvelope(turn.prompt), {
|
|
1209
|
+
const result = await callCaptainQueued(leaf, context, hiddenLifecycleEnvelope(turn.prompt), {
|
|
1210
|
+
visibility: 'hidden',
|
|
1211
|
+
resume: false,
|
|
1212
|
+
...controlCallToolOptions(captainAdapter),
|
|
1213
|
+
}, context.signal);
|
|
1155
1214
|
if (result.status === 'ok' && result.finalText !== undefined) {
|
|
1156
1215
|
decision = parseLifecycleDecision(result.finalText);
|
|
1157
1216
|
}
|