@sublang/playbook 0.1.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/LICENSE +201 -0
- package/README.md +181 -0
- package/bin/playbook-code.js +40 -0
- package/code.fsm.d.ts +86 -0
- package/code.fsm.introspect.d.ts +30 -0
- package/code.fsm.introspect.js +50 -0
- package/code.fsm.introspect.ts +129 -0
- package/code.fsm.js +1022 -0
- package/code.fsm.ts +1224 -0
- package/code.gears.md +250 -0
- package/code.playbook.d.ts +53 -0
- package/code.playbook.js +598 -0
- package/code.playbook.ts +743 -0
- package/code.tmux-play.d.ts +2 -0
- package/code.tmux-play.js +77 -0
- package/code.tmux-play.ts +110 -0
- package/package.json +77 -0
- package/tmux-play.config.yaml +33 -0
- package/tmux-play.production.config.yaml +21 -0
package/code.fsm.js
ADDED
|
@@ -0,0 +1,1022 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
+
// XState v5's generics do not flow through helpers declared outside the
|
|
4
|
+
// machine (e.g., shared guard/action factories, the `readyEvents` block),
|
|
5
|
+
// so strict checking emits structural-mismatch noise without surfacing real
|
|
6
|
+
// bugs. The runner overrides `captain` via `.provide({ actors: { ... } })`
|
|
7
|
+
// and re-asserts the public surface (`CodingContext`, `CodingEvent`,
|
|
8
|
+
// `CaptainInput`, `CaptainOutput`) at the boundary.
|
|
9
|
+
// @ts-nocheck
|
|
10
|
+
import { assign, fromPromise, setup } from 'xstate';
|
|
11
|
+
const jumpableStateIds = [
|
|
12
|
+
'ready',
|
|
13
|
+
'planAndImplement',
|
|
14
|
+
'respondToReview',
|
|
15
|
+
'continueIr',
|
|
16
|
+
'summarizeSpecs',
|
|
17
|
+
'reviewBossCommitSpecs',
|
|
18
|
+
'reviewBossCommitCode',
|
|
19
|
+
'reviewBossCommitMixed',
|
|
20
|
+
'reviewIrTaskCommitSpecs',
|
|
21
|
+
'reviewIrTaskCommitCode',
|
|
22
|
+
'reviewIrTaskCommitMixed',
|
|
23
|
+
'reviewChangesSpecs',
|
|
24
|
+
'reviewChangesCode',
|
|
25
|
+
'reviewChangesMixed',
|
|
26
|
+
'reviewChangesAndChallengesSpecs',
|
|
27
|
+
'reviewChangesAndChallengesCode',
|
|
28
|
+
'reviewChangesAndChallengesMixed',
|
|
29
|
+
'adjudicateChallenges',
|
|
30
|
+
'commitCoderInitial',
|
|
31
|
+
'commitJoint',
|
|
32
|
+
'failed',
|
|
33
|
+
];
|
|
34
|
+
const outputOf = (event) => event.output;
|
|
35
|
+
const guardIs = (guard) => ({ event }) => outputOf(event)?.guard === guard;
|
|
36
|
+
const guardAndOrigin = (guard, origin) => ({ context, event }) => outputOf(event)?.guard === guard && context.changeOrigin === origin;
|
|
37
|
+
const acceptedAfter = (subject) => ({ context, event }) => outputOf(event)?.guard === 'accepted' && context.reviewSubject === subject;
|
|
38
|
+
const noFindingsAfter = (afterReview) => ({ context, event }) => outputOf(event)?.guard === 'noFindings' && context.afterReview === afterReview;
|
|
39
|
+
const rememberCaptainOutput = assign({
|
|
40
|
+
lastResult: ({ event }) => outputOf(event),
|
|
41
|
+
lastError: () => undefined,
|
|
42
|
+
irNumber: ({ context, event }) => outputOf(event)?.irNumber ?? context.irNumber,
|
|
43
|
+
taskDescription: ({ context, event }) => outputOf(event)?.taskDescription ?? context.taskDescription,
|
|
44
|
+
reviews: ({ context, event }) => outputOf(event)?.reviews ?? context.reviews,
|
|
45
|
+
challenges: ({ context, event }) => outputOf(event)?.challenges ?? context.challenges,
|
|
46
|
+
});
|
|
47
|
+
const rememberCaptainError = assign({
|
|
48
|
+
lastError: ({ event }) => event.error,
|
|
49
|
+
});
|
|
50
|
+
const rememberBossInput = assign({
|
|
51
|
+
intent: ({ context, event }) => event.intent ?? context.intent,
|
|
52
|
+
irNumber: ({ context, event }) => event.irNumber ?? context.irNumber,
|
|
53
|
+
});
|
|
54
|
+
const bossInterrupts = (ids) => ids.map((id) => ({
|
|
55
|
+
target: `#${id}`,
|
|
56
|
+
guard: ({ event }) => event.type === 'BOSS_INTERRUPT' && event.targetId === id,
|
|
57
|
+
reenter: true,
|
|
58
|
+
actions: rememberBossInput,
|
|
59
|
+
}));
|
|
60
|
+
const captainError = {
|
|
61
|
+
target: '#failed',
|
|
62
|
+
actions: rememberCaptainError,
|
|
63
|
+
};
|
|
64
|
+
const readyEvents = {
|
|
65
|
+
START_CODING: {
|
|
66
|
+
target: '#planAndImplement',
|
|
67
|
+
actions: [
|
|
68
|
+
rememberBossInput,
|
|
69
|
+
assign({
|
|
70
|
+
workflow: () => 'singleCommit',
|
|
71
|
+
changeOrigin: () => 'bossIntent',
|
|
72
|
+
afterReview: () => 'done',
|
|
73
|
+
}),
|
|
74
|
+
],
|
|
75
|
+
},
|
|
76
|
+
CONTINUE_IR: {
|
|
77
|
+
target: '#continueIr',
|
|
78
|
+
actions: [
|
|
79
|
+
rememberBossInput,
|
|
80
|
+
assign({
|
|
81
|
+
workflow: () => 'iteration',
|
|
82
|
+
changeOrigin: () => 'irTask',
|
|
83
|
+
afterReview: () => 'continueIr',
|
|
84
|
+
}),
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
SUMMARIZE_IR: {
|
|
88
|
+
target: '#summarizeSpecs',
|
|
89
|
+
actions: [
|
|
90
|
+
rememberBossInput,
|
|
91
|
+
assign({
|
|
92
|
+
workflow: () => 'specSummary',
|
|
93
|
+
changeOrigin: () => 'irTask',
|
|
94
|
+
afterReview: () => 'done',
|
|
95
|
+
}),
|
|
96
|
+
],
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
const captainPlaceholder = fromPromise(async () => {
|
|
100
|
+
throw new Error('captain actor must be provided by the runner');
|
|
101
|
+
});
|
|
102
|
+
export const codingMachine = setup({
|
|
103
|
+
types: {},
|
|
104
|
+
actors: {
|
|
105
|
+
captain: captainPlaceholder,
|
|
106
|
+
},
|
|
107
|
+
}).createMachine({
|
|
108
|
+
id: 'coding',
|
|
109
|
+
context: ({ input }) => ({
|
|
110
|
+
intent: input?.intent,
|
|
111
|
+
irNumber: input?.irNumber,
|
|
112
|
+
coderPlayer: input?.coderPlayer,
|
|
113
|
+
reviewerPlayer: input?.reviewerPlayer,
|
|
114
|
+
committerPlayer: input?.committerPlayer,
|
|
115
|
+
}),
|
|
116
|
+
initial: 'ready',
|
|
117
|
+
on: {
|
|
118
|
+
BOSS_INTERRUPT: bossInterrupts(jumpableStateIds),
|
|
119
|
+
},
|
|
120
|
+
states: {
|
|
121
|
+
ready: {
|
|
122
|
+
id: 'ready',
|
|
123
|
+
description: 'Idle hub: waits for Boss to start or resume a coding sub-procedure.',
|
|
124
|
+
on: readyEvents,
|
|
125
|
+
},
|
|
126
|
+
planAndImplement: {
|
|
127
|
+
id: 'planAndImplement',
|
|
128
|
+
description: 'CODE-1: Coder assesses a Boss intent and either implements a single-commit change or drafts an IR.',
|
|
129
|
+
invoke: {
|
|
130
|
+
src: 'captain',
|
|
131
|
+
input: ({ context }) => ({
|
|
132
|
+
player: 'Coder',
|
|
133
|
+
sourceItem: 'CODE-1',
|
|
134
|
+
intent: context.intent,
|
|
135
|
+
prompt: [
|
|
136
|
+
'Assess whether this can be completed in a single commit, following best practices.',
|
|
137
|
+
'If yes, implement and test, updating both code and specs; otherwise, decompose into tasks as a new IR under @specs/iterations.',
|
|
138
|
+
'Consult @specs/map.md for relevant context if needed; ensure it reflects the changes.',
|
|
139
|
+
'Do not commit.',
|
|
140
|
+
].join('\n'),
|
|
141
|
+
result: {
|
|
142
|
+
singleCommitReady: 'Coder produced uncommitted single-commit changes (Initial Changes).',
|
|
143
|
+
irDrafted: 'Coder decomposed the intent into a new IR and drafted it uncommitted (Initial Changes).',
|
|
144
|
+
needsBossInput: 'Progress requires additional Boss input.',
|
|
145
|
+
},
|
|
146
|
+
}),
|
|
147
|
+
onDone: [
|
|
148
|
+
{
|
|
149
|
+
guard: guardIs('singleCommitReady'),
|
|
150
|
+
target: '#commitCoderInitial',
|
|
151
|
+
actions: [
|
|
152
|
+
rememberCaptainOutput,
|
|
153
|
+
assign({
|
|
154
|
+
workflow: () => 'singleCommit',
|
|
155
|
+
changeOrigin: () => 'bossIntent',
|
|
156
|
+
afterReview: () => 'done',
|
|
157
|
+
}),
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
guard: guardIs('irDrafted'),
|
|
162
|
+
target: '#commitCoderInitial',
|
|
163
|
+
actions: [
|
|
164
|
+
rememberCaptainOutput,
|
|
165
|
+
assign({
|
|
166
|
+
workflow: () => 'iteration',
|
|
167
|
+
changeOrigin: () => 'bossIntent',
|
|
168
|
+
afterReview: () => 'continueIr',
|
|
169
|
+
}),
|
|
170
|
+
],
|
|
171
|
+
},
|
|
172
|
+
{ guard: guardIs('needsBossInput'), target: '#ready', actions: rememberCaptainOutput },
|
|
173
|
+
],
|
|
174
|
+
onError: captainError,
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
respondToReview: {
|
|
178
|
+
id: 'respondToReview',
|
|
179
|
+
description: 'CODE-2: Coder addresses or challenges Reviewer findings.',
|
|
180
|
+
invoke: {
|
|
181
|
+
src: 'captain',
|
|
182
|
+
input: ({ context }) => ({
|
|
183
|
+
player: 'Coder',
|
|
184
|
+
sourceItem: 'CODE-2',
|
|
185
|
+
reviews: context.reviews,
|
|
186
|
+
prompt: [
|
|
187
|
+
'For each review item below for the above changes, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.',
|
|
188
|
+
'Stage all current changes that belong in the repo before making any edits, and leave your edits unstaged/untracked.',
|
|
189
|
+
].join('\n'),
|
|
190
|
+
result: {
|
|
191
|
+
changesMadeSpecs: 'Coder accepted items and produced unstaged/untracked edits in @specs/{user,dev,test}/ only, without raising any rebuttals.',
|
|
192
|
+
changesMadeCode: 'Coder accepted items and produced unstaged/untracked edits outside @specs/{user,dev,test}/ only, without raising any rebuttals.',
|
|
193
|
+
changesMadeMixed: 'Coder accepted items and produced unstaged/untracked edits spanning both @specs/{user,dev,test}/ and other files, without raising any rebuttals.',
|
|
194
|
+
changesMadeSpecsAndChallenged: 'Coder produced unstaged/untracked edits in @specs/{user,dev,test}/ only AND challenged one or more review items. Output shall include `challenges: <numbered rebuttals, one per challenged item>`.',
|
|
195
|
+
changesMadeCodeAndChallenged: 'Coder produced unstaged/untracked edits outside @specs/{user,dev,test}/ only AND challenged one or more review items. Output shall include `challenges: <numbered rebuttals, one per challenged item>`.',
|
|
196
|
+
changesMadeMixedAndChallenged: 'Coder produced unstaged/untracked edits spanning both @specs/{user,dev,test}/ and other files AND challenged one or more review items. Output shall include `challenges: <numbered rebuttals, one per challenged item>`.',
|
|
197
|
+
challengesRaised: 'Coder challenged one or more review items without producing any code edits. Output shall include `challenges: <numbered rebuttals, one per challenged item>`.',
|
|
198
|
+
accepted: 'Coder accepted the review outcome without further edits.',
|
|
199
|
+
},
|
|
200
|
+
}),
|
|
201
|
+
onDone: [
|
|
202
|
+
{
|
|
203
|
+
guard: guardIs('changesMadeSpecs'),
|
|
204
|
+
target: '#reviewChangesSpecs',
|
|
205
|
+
actions: rememberCaptainOutput,
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
guard: guardIs('changesMadeCode'),
|
|
209
|
+
target: '#reviewChangesCode',
|
|
210
|
+
actions: rememberCaptainOutput,
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
guard: guardIs('changesMadeMixed'),
|
|
214
|
+
target: '#reviewChangesMixed',
|
|
215
|
+
actions: rememberCaptainOutput,
|
|
216
|
+
},
|
|
217
|
+
{
|
|
218
|
+
guard: guardIs('changesMadeSpecsAndChallenged'),
|
|
219
|
+
target: '#reviewChangesAndChallengesSpecs',
|
|
220
|
+
actions: rememberCaptainOutput,
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
guard: guardIs('changesMadeCodeAndChallenged'),
|
|
224
|
+
target: '#reviewChangesAndChallengesCode',
|
|
225
|
+
actions: rememberCaptainOutput,
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
guard: guardIs('changesMadeMixedAndChallenged'),
|
|
229
|
+
target: '#reviewChangesAndChallengesMixed',
|
|
230
|
+
actions: rememberCaptainOutput,
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
guard: guardIs('challengesRaised'),
|
|
234
|
+
target: '#adjudicateChallenges',
|
|
235
|
+
actions: rememberCaptainOutput,
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
guard: acceptedAfter('changes'),
|
|
239
|
+
target: '#commitJoint',
|
|
240
|
+
actions: rememberCaptainOutput,
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
guard: ({ context, event }) => outputOf(event)?.guard === 'accepted' &&
|
|
244
|
+
context.reviewSubject === 'commit' &&
|
|
245
|
+
context.afterReview === 'continueIr',
|
|
246
|
+
target: '#continueIr',
|
|
247
|
+
actions: rememberCaptainOutput,
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
guard: ({ context, event }) => outputOf(event)?.guard === 'accepted' &&
|
|
251
|
+
context.reviewSubject === 'commit' &&
|
|
252
|
+
context.afterReview === 'summarizeSpecs',
|
|
253
|
+
target: '#summarizeSpecs',
|
|
254
|
+
actions: rememberCaptainOutput,
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
guard: ({ context, event }) => outputOf(event)?.guard === 'accepted' &&
|
|
258
|
+
context.reviewSubject === 'commit' &&
|
|
259
|
+
context.afterReview === 'done',
|
|
260
|
+
target: '#done',
|
|
261
|
+
actions: rememberCaptainOutput,
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
onError: captainError,
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
continueIr: {
|
|
268
|
+
id: 'continueIr',
|
|
269
|
+
description: 'CODE-3: Coder continues an IR after the previous task or IR draft passed review.',
|
|
270
|
+
invoke: {
|
|
271
|
+
src: 'captain',
|
|
272
|
+
input: ({ context }) => ({
|
|
273
|
+
player: 'Coder',
|
|
274
|
+
sourceItem: 'CODE-3',
|
|
275
|
+
irNumber: context.irNumber,
|
|
276
|
+
prompt: [
|
|
277
|
+
'Continue to implement IR-<#> if not all deliverables and tasks are done.',
|
|
278
|
+
'Implement one task at a time (including corresponding tests if any).',
|
|
279
|
+
'Stop after each task for review — do not commit yet.',
|
|
280
|
+
'If relevant, mark progress in the IR.',
|
|
281
|
+
].join('\n'),
|
|
282
|
+
result: {
|
|
283
|
+
taskReady: 'Coder produced uncommitted changes for the next IR task (Initial Changes). Output shall include `taskDescription: <one-line description of the task just implemented>`.',
|
|
284
|
+
iterationDone: 'All IR deliverables and tasks are done.',
|
|
285
|
+
needsBossInput: 'Progress requires additional Boss input.',
|
|
286
|
+
},
|
|
287
|
+
}),
|
|
288
|
+
onDone: [
|
|
289
|
+
{
|
|
290
|
+
guard: guardIs('taskReady'),
|
|
291
|
+
target: '#commitCoderInitial',
|
|
292
|
+
actions: [
|
|
293
|
+
rememberCaptainOutput,
|
|
294
|
+
assign({
|
|
295
|
+
workflow: () => 'iteration',
|
|
296
|
+
changeOrigin: () => 'irTask',
|
|
297
|
+
afterReview: () => 'continueIr',
|
|
298
|
+
}),
|
|
299
|
+
],
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
guard: guardIs('iterationDone'),
|
|
303
|
+
target: '#summarizeSpecs',
|
|
304
|
+
actions: [
|
|
305
|
+
rememberCaptainOutput,
|
|
306
|
+
assign({
|
|
307
|
+
workflow: () => 'specSummary',
|
|
308
|
+
afterReview: () => 'done',
|
|
309
|
+
}),
|
|
310
|
+
],
|
|
311
|
+
},
|
|
312
|
+
{ guard: guardIs('needsBossInput'), target: '#ready', actions: rememberCaptainOutput },
|
|
313
|
+
],
|
|
314
|
+
onError: captainError,
|
|
315
|
+
},
|
|
316
|
+
},
|
|
317
|
+
summarizeSpecs: {
|
|
318
|
+
id: 'summarizeSpecs',
|
|
319
|
+
description: 'CODE-4: Coder summarizes a completed IR into minimal spec items.',
|
|
320
|
+
invoke: {
|
|
321
|
+
src: 'captain',
|
|
322
|
+
input: ({ context }) => ({
|
|
323
|
+
player: 'Coder',
|
|
324
|
+
sourceItem: 'CODE-4',
|
|
325
|
+
irNumber: context.irNumber,
|
|
326
|
+
prompt: [
|
|
327
|
+
'Read IR-<#> and corresponding commits.',
|
|
328
|
+
'According to @specs/meta.md, add or update spec items to fully capture:',
|
|
329
|
+
'',
|
|
330
|
+
'- the user requirements in @specs/user,',
|
|
331
|
+
'- the system behavior in @specs/dev, and',
|
|
332
|
+
'- the integration/system test cases in @specs/test.',
|
|
333
|
+
'',
|
|
334
|
+
'The spec items should be the *minimal* set needed to reimplement code without the IR.',
|
|
335
|
+
'The set should be complete and coherent.',
|
|
336
|
+
'Avoid implementation specifics.',
|
|
337
|
+
'Avoid redundant spec items.',
|
|
338
|
+
'Consult @specs/map.md for relevant context and update it to reflect your changes.',
|
|
339
|
+
].join('\n'),
|
|
340
|
+
result: {
|
|
341
|
+
specsReady: 'Coder produced uncommitted spec updates (Initial Changes).',
|
|
342
|
+
noSpecChanges: 'Existing specs already capture the iteration.',
|
|
343
|
+
needsBossInput: 'Spec summarization requires additional Boss input.',
|
|
344
|
+
},
|
|
345
|
+
}),
|
|
346
|
+
onDone: [
|
|
347
|
+
{
|
|
348
|
+
guard: guardIs('specsReady'),
|
|
349
|
+
target: '#commitCoderInitial',
|
|
350
|
+
actions: [
|
|
351
|
+
rememberCaptainOutput,
|
|
352
|
+
assign({
|
|
353
|
+
workflow: () => 'specSummary',
|
|
354
|
+
changeOrigin: () => 'irTask',
|
|
355
|
+
afterReview: () => 'done',
|
|
356
|
+
}),
|
|
357
|
+
],
|
|
358
|
+
},
|
|
359
|
+
{ guard: guardIs('noSpecChanges'), target: '#done', actions: rememberCaptainOutput },
|
|
360
|
+
{ guard: guardIs('needsBossInput'), target: '#ready', actions: rememberCaptainOutput },
|
|
361
|
+
],
|
|
362
|
+
onError: captainError,
|
|
363
|
+
},
|
|
364
|
+
},
|
|
365
|
+
reviewBossCommitSpecs: {
|
|
366
|
+
id: 'reviewBossCommitSpecs',
|
|
367
|
+
description: 'CODE-5: Reviewer reviews a Boss-intent commit whose changes are only in @specs/{user,dev,test}/.',
|
|
368
|
+
invoke: {
|
|
369
|
+
src: 'captain',
|
|
370
|
+
input: ({ context }) => ({
|
|
371
|
+
player: 'Reviewer',
|
|
372
|
+
sourceItem: 'CODE-5',
|
|
373
|
+
intent: context.intent,
|
|
374
|
+
prompt: [
|
|
375
|
+
'Review the latest commit.',
|
|
376
|
+
'Refer to the commit message.',
|
|
377
|
+
'Verify any affected spec items are:',
|
|
378
|
+
'',
|
|
379
|
+
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
380
|
+
'- Right level: user requirements (in @specs/user) or behavior (in @specs/dev), not implementation specifics; integration/system testing (in @specs/test), not unit testing.',
|
|
381
|
+
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
382
|
+
'',
|
|
383
|
+
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
384
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
385
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
386
|
+
].join('\n'),
|
|
387
|
+
result: {
|
|
388
|
+
noFindings: 'The spec-only commit has no review findings.',
|
|
389
|
+
hasFindings: 'The review produced findings for Coder. Output shall include `reviews: <numbered list of findings, no duplication>`.',
|
|
390
|
+
},
|
|
391
|
+
}),
|
|
392
|
+
onDone: [
|
|
393
|
+
{ guard: noFindingsAfter('continueIr'), target: '#continueIr', actions: rememberCaptainOutput },
|
|
394
|
+
{ guard: noFindingsAfter('summarizeSpecs'), target: '#summarizeSpecs', actions: rememberCaptainOutput },
|
|
395
|
+
{ guard: noFindingsAfter('done'), target: '#done', actions: rememberCaptainOutput },
|
|
396
|
+
{
|
|
397
|
+
guard: guardIs('hasFindings'),
|
|
398
|
+
target: '#respondToReview',
|
|
399
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'commit' })],
|
|
400
|
+
},
|
|
401
|
+
],
|
|
402
|
+
onError: captainError,
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
reviewBossCommitCode: {
|
|
406
|
+
id: 'reviewBossCommitCode',
|
|
407
|
+
description: 'CODE-6: Reviewer reviews a Boss-intent commit whose changes are only outside @specs/{user,dev,test}/.',
|
|
408
|
+
invoke: {
|
|
409
|
+
src: 'captain',
|
|
410
|
+
input: ({ context }) => ({
|
|
411
|
+
player: 'Reviewer',
|
|
412
|
+
sourceItem: 'CODE-6',
|
|
413
|
+
intent: context.intent,
|
|
414
|
+
prompt: [
|
|
415
|
+
'Review the latest commit.',
|
|
416
|
+
'Refer to the commit message.',
|
|
417
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
418
|
+
"Think thoroughly — don't just approve or reject.",
|
|
419
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
420
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
421
|
+
].join('\n'),
|
|
422
|
+
result: {
|
|
423
|
+
noFindings: 'The code-only commit has no review findings.',
|
|
424
|
+
hasFindings: 'The review produced findings for Coder. Output shall include `reviews: <numbered list of findings, no duplication>`.',
|
|
425
|
+
},
|
|
426
|
+
}),
|
|
427
|
+
onDone: [
|
|
428
|
+
{ guard: noFindingsAfter('continueIr'), target: '#continueIr', actions: rememberCaptainOutput },
|
|
429
|
+
{ guard: noFindingsAfter('summarizeSpecs'), target: '#summarizeSpecs', actions: rememberCaptainOutput },
|
|
430
|
+
{ guard: noFindingsAfter('done'), target: '#done', actions: rememberCaptainOutput },
|
|
431
|
+
{
|
|
432
|
+
guard: guardIs('hasFindings'),
|
|
433
|
+
target: '#respondToReview',
|
|
434
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'commit' })],
|
|
435
|
+
},
|
|
436
|
+
],
|
|
437
|
+
onError: captainError,
|
|
438
|
+
},
|
|
439
|
+
},
|
|
440
|
+
reviewBossCommitMixed: {
|
|
441
|
+
id: 'reviewBossCommitMixed',
|
|
442
|
+
description: 'CODE-7: Reviewer reviews a Boss-intent commit whose changes span both @specs/{user,dev,test}/ and other files.',
|
|
443
|
+
invoke: {
|
|
444
|
+
src: 'captain',
|
|
445
|
+
input: ({ context }) => ({
|
|
446
|
+
player: 'Reviewer',
|
|
447
|
+
sourceItem: 'CODE-7',
|
|
448
|
+
intent: context.intent,
|
|
449
|
+
prompt: [
|
|
450
|
+
'Review the latest commit.',
|
|
451
|
+
'Refer to the commit message.',
|
|
452
|
+
'Verify any affected spec items are:',
|
|
453
|
+
'',
|
|
454
|
+
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
455
|
+
'- Right level: user requirements (in @specs/user) or behavior (in @specs/dev), not implementation specifics; integration/system testing (in @specs/test), not unit testing.',
|
|
456
|
+
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
457
|
+
'',
|
|
458
|
+
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
459
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
460
|
+
"Think thoroughly — don't just approve or reject.",
|
|
461
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
462
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
463
|
+
].join('\n'),
|
|
464
|
+
result: {
|
|
465
|
+
noFindings: 'The mixed commit has no review findings.',
|
|
466
|
+
hasFindings: 'The review produced findings for Coder. Output shall include `reviews: <numbered list of findings, no duplication>`.',
|
|
467
|
+
},
|
|
468
|
+
}),
|
|
469
|
+
onDone: [
|
|
470
|
+
{ guard: noFindingsAfter('continueIr'), target: '#continueIr', actions: rememberCaptainOutput },
|
|
471
|
+
{ guard: noFindingsAfter('summarizeSpecs'), target: '#summarizeSpecs', actions: rememberCaptainOutput },
|
|
472
|
+
{ guard: noFindingsAfter('done'), target: '#done', actions: rememberCaptainOutput },
|
|
473
|
+
{
|
|
474
|
+
guard: guardIs('hasFindings'),
|
|
475
|
+
target: '#respondToReview',
|
|
476
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'commit' })],
|
|
477
|
+
},
|
|
478
|
+
],
|
|
479
|
+
onError: captainError,
|
|
480
|
+
},
|
|
481
|
+
},
|
|
482
|
+
reviewIrTaskCommitSpecs: {
|
|
483
|
+
id: 'reviewIrTaskCommitSpecs',
|
|
484
|
+
description: 'CODE-8: Reviewer reviews an IR-task commit whose changes are only in @specs/{user,dev,test}/.',
|
|
485
|
+
invoke: {
|
|
486
|
+
src: 'captain',
|
|
487
|
+
input: ({ context }) => ({
|
|
488
|
+
player: 'Reviewer',
|
|
489
|
+
sourceItem: 'CODE-8',
|
|
490
|
+
irNumber: context.irNumber,
|
|
491
|
+
taskDescription: context.taskDescription,
|
|
492
|
+
prompt: [
|
|
493
|
+
'Review the latest commit.',
|
|
494
|
+
'Refer to the commit message.',
|
|
495
|
+
'Verify any affected spec items are:',
|
|
496
|
+
'',
|
|
497
|
+
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
498
|
+
'- Right level: user requirements (in @specs/user) or behavior (in @specs/dev), not implementation specifics; integration/system testing (in @specs/test), not unit testing.',
|
|
499
|
+
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
500
|
+
'',
|
|
501
|
+
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
502
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
503
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
504
|
+
].join('\n'),
|
|
505
|
+
result: {
|
|
506
|
+
noFindings: 'The IR-task spec-only commit has no review findings.',
|
|
507
|
+
hasFindings: 'The review produced findings for Coder. Output shall include `reviews: <numbered list of findings, no duplication>`.',
|
|
508
|
+
},
|
|
509
|
+
}),
|
|
510
|
+
onDone: [
|
|
511
|
+
{ guard: noFindingsAfter('continueIr'), target: '#continueIr', actions: rememberCaptainOutput },
|
|
512
|
+
{ guard: noFindingsAfter('summarizeSpecs'), target: '#summarizeSpecs', actions: rememberCaptainOutput },
|
|
513
|
+
{ guard: noFindingsAfter('done'), target: '#done', actions: rememberCaptainOutput },
|
|
514
|
+
{
|
|
515
|
+
guard: guardIs('hasFindings'),
|
|
516
|
+
target: '#respondToReview',
|
|
517
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'commit' })],
|
|
518
|
+
},
|
|
519
|
+
],
|
|
520
|
+
onError: captainError,
|
|
521
|
+
},
|
|
522
|
+
},
|
|
523
|
+
reviewIrTaskCommitCode: {
|
|
524
|
+
id: 'reviewIrTaskCommitCode',
|
|
525
|
+
description: 'CODE-9: Reviewer reviews an IR-task commit whose changes are only outside @specs/{user,dev,test}/.',
|
|
526
|
+
invoke: {
|
|
527
|
+
src: 'captain',
|
|
528
|
+
input: ({ context }) => ({
|
|
529
|
+
player: 'Reviewer',
|
|
530
|
+
sourceItem: 'CODE-9',
|
|
531
|
+
irNumber: context.irNumber,
|
|
532
|
+
taskDescription: context.taskDescription,
|
|
533
|
+
prompt: [
|
|
534
|
+
'Review the latest commit.',
|
|
535
|
+
'Refer to the commit message.',
|
|
536
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
537
|
+
"Think thoroughly — don't just approve or reject.",
|
|
538
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
539
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
540
|
+
].join('\n'),
|
|
541
|
+
result: {
|
|
542
|
+
noFindings: 'The IR-task code-only commit has no review findings.',
|
|
543
|
+
hasFindings: 'The review produced findings for Coder. Output shall include `reviews: <numbered list of findings, no duplication>`.',
|
|
544
|
+
},
|
|
545
|
+
}),
|
|
546
|
+
onDone: [
|
|
547
|
+
{ guard: noFindingsAfter('continueIr'), target: '#continueIr', actions: rememberCaptainOutput },
|
|
548
|
+
{ guard: noFindingsAfter('summarizeSpecs'), target: '#summarizeSpecs', actions: rememberCaptainOutput },
|
|
549
|
+
{ guard: noFindingsAfter('done'), target: '#done', actions: rememberCaptainOutput },
|
|
550
|
+
{
|
|
551
|
+
guard: guardIs('hasFindings'),
|
|
552
|
+
target: '#respondToReview',
|
|
553
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'commit' })],
|
|
554
|
+
},
|
|
555
|
+
],
|
|
556
|
+
onError: captainError,
|
|
557
|
+
},
|
|
558
|
+
},
|
|
559
|
+
reviewIrTaskCommitMixed: {
|
|
560
|
+
id: 'reviewIrTaskCommitMixed',
|
|
561
|
+
description: 'CODE-10: Reviewer reviews an IR-task commit whose changes span both @specs/{user,dev,test}/ and other files.',
|
|
562
|
+
invoke: {
|
|
563
|
+
src: 'captain',
|
|
564
|
+
input: ({ context }) => ({
|
|
565
|
+
player: 'Reviewer',
|
|
566
|
+
sourceItem: 'CODE-10',
|
|
567
|
+
irNumber: context.irNumber,
|
|
568
|
+
taskDescription: context.taskDescription,
|
|
569
|
+
prompt: [
|
|
570
|
+
'Review the latest commit.',
|
|
571
|
+
'Refer to the commit message.',
|
|
572
|
+
'Verify any affected spec items are:',
|
|
573
|
+
'',
|
|
574
|
+
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
575
|
+
'- Right level: user requirements (in @specs/user) or behavior (in @specs/dev), not implementation specifics; integration/system testing (in @specs/test), not unit testing.',
|
|
576
|
+
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
577
|
+
'',
|
|
578
|
+
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
579
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
580
|
+
"Think thoroughly — don't just approve or reject.",
|
|
581
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
582
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
583
|
+
].join('\n'),
|
|
584
|
+
result: {
|
|
585
|
+
noFindings: 'The IR-task mixed commit has no review findings.',
|
|
586
|
+
hasFindings: 'The review produced findings for Coder. Output shall include `reviews: <numbered list of findings, no duplication>`.',
|
|
587
|
+
},
|
|
588
|
+
}),
|
|
589
|
+
onDone: [
|
|
590
|
+
{ guard: noFindingsAfter('continueIr'), target: '#continueIr', actions: rememberCaptainOutput },
|
|
591
|
+
{ guard: noFindingsAfter('summarizeSpecs'), target: '#summarizeSpecs', actions: rememberCaptainOutput },
|
|
592
|
+
{ guard: noFindingsAfter('done'), target: '#done', actions: rememberCaptainOutput },
|
|
593
|
+
{
|
|
594
|
+
guard: guardIs('hasFindings'),
|
|
595
|
+
target: '#respondToReview',
|
|
596
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'commit' })],
|
|
597
|
+
},
|
|
598
|
+
],
|
|
599
|
+
onError: captainError,
|
|
600
|
+
},
|
|
601
|
+
},
|
|
602
|
+
reviewChangesSpecs: {
|
|
603
|
+
id: 'reviewChangesSpecs',
|
|
604
|
+
description: 'CODE-11: Reviewer reviews uncommitted Coder changes that touch only @specs/{user,dev,test}/ with no accompanying rebuttals.',
|
|
605
|
+
invoke: {
|
|
606
|
+
src: 'captain',
|
|
607
|
+
input: () => ({
|
|
608
|
+
player: 'Reviewer',
|
|
609
|
+
sourceItem: 'CODE-11',
|
|
610
|
+
prompt: [
|
|
611
|
+
'Review the unstaged/untracked changes.',
|
|
612
|
+
'Understand the intent.',
|
|
613
|
+
'Verify any affected spec items are:',
|
|
614
|
+
'',
|
|
615
|
+
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
616
|
+
'- Right level: user requirements (in @specs/user) or behavior (in @specs/dev), not implementation specifics; integration/system testing (in @specs/test), not unit testing.',
|
|
617
|
+
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
618
|
+
'',
|
|
619
|
+
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
620
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
621
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
622
|
+
].join('\n'),
|
|
623
|
+
result: {
|
|
624
|
+
noFindings: 'The uncommitted spec-only changes are ready to commit.',
|
|
625
|
+
hasFindings: 'The review produced findings for Coder. Output shall include `reviews: <numbered list of findings, no duplication>`.',
|
|
626
|
+
},
|
|
627
|
+
}),
|
|
628
|
+
onDone: [
|
|
629
|
+
{
|
|
630
|
+
guard: guardIs('noFindings'),
|
|
631
|
+
target: '#commitJoint',
|
|
632
|
+
actions: rememberCaptainOutput,
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
guard: guardIs('hasFindings'),
|
|
636
|
+
target: '#respondToReview',
|
|
637
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'changes' })],
|
|
638
|
+
},
|
|
639
|
+
],
|
|
640
|
+
onError: captainError,
|
|
641
|
+
},
|
|
642
|
+
},
|
|
643
|
+
reviewChangesCode: {
|
|
644
|
+
id: 'reviewChangesCode',
|
|
645
|
+
description: 'CODE-12: Reviewer reviews uncommitted Coder changes that touch only files outside @specs/{user,dev,test}/ with no accompanying rebuttals.',
|
|
646
|
+
invoke: {
|
|
647
|
+
src: 'captain',
|
|
648
|
+
input: () => ({
|
|
649
|
+
player: 'Reviewer',
|
|
650
|
+
sourceItem: 'CODE-12',
|
|
651
|
+
prompt: [
|
|
652
|
+
'Review the unstaged/untracked changes.',
|
|
653
|
+
'Understand the intent.',
|
|
654
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
655
|
+
"Think thoroughly — don't just approve or reject.",
|
|
656
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
657
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
658
|
+
].join('\n'),
|
|
659
|
+
result: {
|
|
660
|
+
noFindings: 'The uncommitted code-only changes are ready to commit.',
|
|
661
|
+
hasFindings: 'The review produced findings for Coder. Output shall include `reviews: <numbered list of findings, no duplication>`.',
|
|
662
|
+
},
|
|
663
|
+
}),
|
|
664
|
+
onDone: [
|
|
665
|
+
{
|
|
666
|
+
guard: guardIs('noFindings'),
|
|
667
|
+
target: '#commitJoint',
|
|
668
|
+
actions: rememberCaptainOutput,
|
|
669
|
+
},
|
|
670
|
+
{
|
|
671
|
+
guard: guardIs('hasFindings'),
|
|
672
|
+
target: '#respondToReview',
|
|
673
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'changes' })],
|
|
674
|
+
},
|
|
675
|
+
],
|
|
676
|
+
onError: captainError,
|
|
677
|
+
},
|
|
678
|
+
},
|
|
679
|
+
reviewChangesMixed: {
|
|
680
|
+
id: 'reviewChangesMixed',
|
|
681
|
+
description: 'CODE-13: Reviewer reviews uncommitted Coder changes that touch both @specs/{user,dev,test}/ and other files with no accompanying rebuttals.',
|
|
682
|
+
invoke: {
|
|
683
|
+
src: 'captain',
|
|
684
|
+
input: () => ({
|
|
685
|
+
player: 'Reviewer',
|
|
686
|
+
sourceItem: 'CODE-13',
|
|
687
|
+
prompt: [
|
|
688
|
+
'Review the unstaged/untracked changes.',
|
|
689
|
+
'Understand the intent.',
|
|
690
|
+
'Verify any affected spec items are:',
|
|
691
|
+
'',
|
|
692
|
+
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
693
|
+
'- Right level: user requirements (in @specs/user) or behavior (in @specs/dev), not implementation specifics; integration/system testing (in @specs/test), not unit testing.',
|
|
694
|
+
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
695
|
+
'',
|
|
696
|
+
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
697
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
698
|
+
"Think thoroughly — don't just approve or reject.",
|
|
699
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
700
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
701
|
+
].join('\n'),
|
|
702
|
+
result: {
|
|
703
|
+
noFindings: 'The uncommitted mixed changes are ready to commit.',
|
|
704
|
+
hasFindings: 'The review produced findings for Coder. Output shall include `reviews: <numbered list of findings, no duplication>`.',
|
|
705
|
+
},
|
|
706
|
+
}),
|
|
707
|
+
onDone: [
|
|
708
|
+
{
|
|
709
|
+
guard: guardIs('noFindings'),
|
|
710
|
+
target: '#commitJoint',
|
|
711
|
+
actions: rememberCaptainOutput,
|
|
712
|
+
},
|
|
713
|
+
{
|
|
714
|
+
guard: guardIs('hasFindings'),
|
|
715
|
+
target: '#respondToReview',
|
|
716
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'changes' })],
|
|
717
|
+
},
|
|
718
|
+
],
|
|
719
|
+
onError: captainError,
|
|
720
|
+
},
|
|
721
|
+
},
|
|
722
|
+
reviewChangesAndChallengesSpecs: {
|
|
723
|
+
id: 'reviewChangesAndChallengesSpecs',
|
|
724
|
+
description: 'CODE-15: Reviewer reviews uncommitted Coder changes that touch only @specs/{user,dev,test}/ and adjudicates accompanying rebuttals in one round.',
|
|
725
|
+
invoke: {
|
|
726
|
+
src: 'captain',
|
|
727
|
+
input: ({ context }) => ({
|
|
728
|
+
player: 'Reviewer',
|
|
729
|
+
sourceItem: 'CODE-15',
|
|
730
|
+
reviews: context.reviews,
|
|
731
|
+
challenges: context.challenges,
|
|
732
|
+
prompt: [
|
|
733
|
+
'Review the unstaged/untracked changes.',
|
|
734
|
+
'Understand the intent.',
|
|
735
|
+
'Verify any affected spec items are:',
|
|
736
|
+
'',
|
|
737
|
+
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
738
|
+
'- Right level: user requirements (in @specs/user) or behavior (in @specs/dev), not implementation specifics; integration/system testing (in @specs/test), not unit testing.',
|
|
739
|
+
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
740
|
+
'',
|
|
741
|
+
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
742
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
743
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
744
|
+
'For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.',
|
|
745
|
+
].join('\n'),
|
|
746
|
+
result: {
|
|
747
|
+
approved: 'The new spec-only changes are ready to commit and every rebuttal was accepted (or no items remained open).',
|
|
748
|
+
needsRevision: 'The combined round needs more work: the review produced findings, one or more rebuttals were rejected, or both. Output shall include `reviews: <numbered list of any new findings or rejected rebuttals to address>`.',
|
|
749
|
+
},
|
|
750
|
+
}),
|
|
751
|
+
onDone: [
|
|
752
|
+
{
|
|
753
|
+
guard: guardIs('approved'),
|
|
754
|
+
target: '#commitJoint',
|
|
755
|
+
actions: rememberCaptainOutput,
|
|
756
|
+
},
|
|
757
|
+
{
|
|
758
|
+
guard: guardIs('needsRevision'),
|
|
759
|
+
target: '#respondToReview',
|
|
760
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'changes' })],
|
|
761
|
+
},
|
|
762
|
+
],
|
|
763
|
+
onError: captainError,
|
|
764
|
+
},
|
|
765
|
+
},
|
|
766
|
+
reviewChangesAndChallengesCode: {
|
|
767
|
+
id: 'reviewChangesAndChallengesCode',
|
|
768
|
+
description: 'CODE-16: Reviewer reviews uncommitted Coder changes that touch only files outside @specs/{user,dev,test}/ and adjudicates accompanying rebuttals in one round.',
|
|
769
|
+
invoke: {
|
|
770
|
+
src: 'captain',
|
|
771
|
+
input: ({ context }) => ({
|
|
772
|
+
player: 'Reviewer',
|
|
773
|
+
sourceItem: 'CODE-16',
|
|
774
|
+
reviews: context.reviews,
|
|
775
|
+
challenges: context.challenges,
|
|
776
|
+
prompt: [
|
|
777
|
+
'Review the unstaged/untracked changes.',
|
|
778
|
+
'Understand the intent.',
|
|
779
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
780
|
+
"Think thoroughly — don't just approve or reject.",
|
|
781
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
782
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
783
|
+
'For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.',
|
|
784
|
+
].join('\n'),
|
|
785
|
+
result: {
|
|
786
|
+
approved: 'The new code-only changes are ready to commit and every rebuttal was accepted (or no items remained open).',
|
|
787
|
+
needsRevision: 'The combined round needs more work: the review produced findings, one or more rebuttals were rejected, or both. Output shall include `reviews: <numbered list of any new findings or rejected rebuttals to address>`.',
|
|
788
|
+
},
|
|
789
|
+
}),
|
|
790
|
+
onDone: [
|
|
791
|
+
{
|
|
792
|
+
guard: guardIs('approved'),
|
|
793
|
+
target: '#commitJoint',
|
|
794
|
+
actions: rememberCaptainOutput,
|
|
795
|
+
},
|
|
796
|
+
{
|
|
797
|
+
guard: guardIs('needsRevision'),
|
|
798
|
+
target: '#respondToReview',
|
|
799
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'changes' })],
|
|
800
|
+
},
|
|
801
|
+
],
|
|
802
|
+
onError: captainError,
|
|
803
|
+
},
|
|
804
|
+
},
|
|
805
|
+
reviewChangesAndChallengesMixed: {
|
|
806
|
+
id: 'reviewChangesAndChallengesMixed',
|
|
807
|
+
description: 'CODE-17: Reviewer reviews uncommitted Coder changes that touch both @specs/{user,dev,test}/ and other files and adjudicates accompanying rebuttals in one round.',
|
|
808
|
+
invoke: {
|
|
809
|
+
src: 'captain',
|
|
810
|
+
input: ({ context }) => ({
|
|
811
|
+
player: 'Reviewer',
|
|
812
|
+
sourceItem: 'CODE-17',
|
|
813
|
+
reviews: context.reviews,
|
|
814
|
+
challenges: context.challenges,
|
|
815
|
+
prompt: [
|
|
816
|
+
'Review the unstaged/untracked changes.',
|
|
817
|
+
'Understand the intent.',
|
|
818
|
+
'Verify any affected spec items are:',
|
|
819
|
+
'',
|
|
820
|
+
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
821
|
+
'- Right level: user requirements (in @specs/user) or behavior (in @specs/dev), not implementation specifics; integration/system testing (in @specs/test), not unit testing.',
|
|
822
|
+
'- Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
823
|
+
'',
|
|
824
|
+
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
825
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
826
|
+
"Think thoroughly — don't just approve or reject.",
|
|
827
|
+
'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
|
|
828
|
+
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
829
|
+
'For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.',
|
|
830
|
+
].join('\n'),
|
|
831
|
+
result: {
|
|
832
|
+
approved: 'The new mixed changes are ready to commit and every rebuttal was accepted (or no items remained open).',
|
|
833
|
+
needsRevision: 'The combined round needs more work: the review produced findings, one or more rebuttals were rejected, or both. Output shall include `reviews: <numbered list of any new findings or rejected rebuttals to address>`.',
|
|
834
|
+
},
|
|
835
|
+
}),
|
|
836
|
+
onDone: [
|
|
837
|
+
{
|
|
838
|
+
guard: guardIs('approved'),
|
|
839
|
+
target: '#commitJoint',
|
|
840
|
+
actions: rememberCaptainOutput,
|
|
841
|
+
},
|
|
842
|
+
{
|
|
843
|
+
guard: guardIs('needsRevision'),
|
|
844
|
+
target: '#respondToReview',
|
|
845
|
+
actions: [rememberCaptainOutput, assign({ reviewSubject: () => 'changes' })],
|
|
846
|
+
},
|
|
847
|
+
],
|
|
848
|
+
onError: captainError,
|
|
849
|
+
},
|
|
850
|
+
},
|
|
851
|
+
adjudicateChallenges: {
|
|
852
|
+
id: 'adjudicateChallenges',
|
|
853
|
+
description: 'CODE-14: Reviewer adjudicates Coder rebuttals against the prior review when Coder produced no code edits this round.',
|
|
854
|
+
invoke: {
|
|
855
|
+
src: 'captain',
|
|
856
|
+
input: ({ context }) => ({
|
|
857
|
+
player: 'Reviewer',
|
|
858
|
+
sourceItem: 'CODE-14',
|
|
859
|
+
reviews: context.reviews,
|
|
860
|
+
challenges: context.challenges,
|
|
861
|
+
prompt: [
|
|
862
|
+
'For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.',
|
|
863
|
+
].join('\n'),
|
|
864
|
+
result: {
|
|
865
|
+
challengeAccepted: 'Reviewer accepted the rebuttal — no further review edits are required.',
|
|
866
|
+
challengeRejected: 'Reviewer rejected the rebuttal — Coder must respond again.',
|
|
867
|
+
noOpenItems: 'No review items remain open.',
|
|
868
|
+
},
|
|
869
|
+
}),
|
|
870
|
+
onDone: [
|
|
871
|
+
{
|
|
872
|
+
guard: ({ context, event }) => (outputOf(event)?.guard === 'challengeAccepted' ||
|
|
873
|
+
outputOf(event)?.guard === 'noOpenItems') &&
|
|
874
|
+
context.reviewSubject === 'changes',
|
|
875
|
+
target: '#commitJoint',
|
|
876
|
+
actions: rememberCaptainOutput,
|
|
877
|
+
},
|
|
878
|
+
{
|
|
879
|
+
guard: ({ context, event }) => (outputOf(event)?.guard === 'challengeAccepted' ||
|
|
880
|
+
outputOf(event)?.guard === 'noOpenItems') &&
|
|
881
|
+
context.reviewSubject === 'commit' &&
|
|
882
|
+
context.afterReview === 'continueIr',
|
|
883
|
+
target: '#continueIr',
|
|
884
|
+
actions: rememberCaptainOutput,
|
|
885
|
+
},
|
|
886
|
+
{
|
|
887
|
+
guard: ({ context, event }) => (outputOf(event)?.guard === 'challengeAccepted' ||
|
|
888
|
+
outputOf(event)?.guard === 'noOpenItems') &&
|
|
889
|
+
context.reviewSubject === 'commit' &&
|
|
890
|
+
context.afterReview === 'summarizeSpecs',
|
|
891
|
+
target: '#summarizeSpecs',
|
|
892
|
+
actions: rememberCaptainOutput,
|
|
893
|
+
},
|
|
894
|
+
{
|
|
895
|
+
guard: ({ context, event }) => (outputOf(event)?.guard === 'challengeAccepted' ||
|
|
896
|
+
outputOf(event)?.guard === 'noOpenItems') &&
|
|
897
|
+
context.reviewSubject === 'commit' &&
|
|
898
|
+
context.afterReview === 'done',
|
|
899
|
+
target: '#done',
|
|
900
|
+
actions: rememberCaptainOutput,
|
|
901
|
+
},
|
|
902
|
+
{
|
|
903
|
+
guard: guardIs('challengeRejected'),
|
|
904
|
+
target: '#respondToReview',
|
|
905
|
+
actions: rememberCaptainOutput,
|
|
906
|
+
},
|
|
907
|
+
],
|
|
908
|
+
onError: captainError,
|
|
909
|
+
},
|
|
910
|
+
},
|
|
911
|
+
commitCoderInitial: {
|
|
912
|
+
id: 'commitCoderInitial',
|
|
913
|
+
description: 'CODE-18: Committer commits Coder Initial Changes when Reviewer has not played since the last commit.',
|
|
914
|
+
invoke: {
|
|
915
|
+
src: 'captain',
|
|
916
|
+
input: ({ context }) => ({
|
|
917
|
+
player: 'Committer',
|
|
918
|
+
sourceItem: 'CODE-18',
|
|
919
|
+
coderPlayer: context.coderPlayer,
|
|
920
|
+
prompt: [
|
|
921
|
+
'Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).',
|
|
922
|
+
'Coder is <coder-llm>.',
|
|
923
|
+
].join('\n'),
|
|
924
|
+
result: {
|
|
925
|
+
committedSpecs: 'Committed changes that touch only @specs/{user,dev,test}/.',
|
|
926
|
+
committedCode: 'Committed changes that touch only files outside @specs/{user,dev,test}/.',
|
|
927
|
+
committedMixed: 'Committed changes that span both @specs/{user,dev,test}/ and other files.',
|
|
928
|
+
noRelevantChanges: 'There are no relevant changes to commit.',
|
|
929
|
+
needsBossInput: 'Committing requires additional Boss input.',
|
|
930
|
+
},
|
|
931
|
+
}),
|
|
932
|
+
onDone: [
|
|
933
|
+
{
|
|
934
|
+
guard: guardAndOrigin('committedSpecs', 'bossIntent'),
|
|
935
|
+
target: '#reviewBossCommitSpecs',
|
|
936
|
+
actions: rememberCaptainOutput,
|
|
937
|
+
},
|
|
938
|
+
{
|
|
939
|
+
guard: guardAndOrigin('committedCode', 'bossIntent'),
|
|
940
|
+
target: '#reviewBossCommitCode',
|
|
941
|
+
actions: rememberCaptainOutput,
|
|
942
|
+
},
|
|
943
|
+
{
|
|
944
|
+
guard: guardAndOrigin('committedMixed', 'bossIntent'),
|
|
945
|
+
target: '#reviewBossCommitMixed',
|
|
946
|
+
actions: rememberCaptainOutput,
|
|
947
|
+
},
|
|
948
|
+
{
|
|
949
|
+
guard: guardAndOrigin('committedSpecs', 'irTask'),
|
|
950
|
+
target: '#reviewIrTaskCommitSpecs',
|
|
951
|
+
actions: rememberCaptainOutput,
|
|
952
|
+
},
|
|
953
|
+
{
|
|
954
|
+
guard: guardAndOrigin('committedCode', 'irTask'),
|
|
955
|
+
target: '#reviewIrTaskCommitCode',
|
|
956
|
+
actions: rememberCaptainOutput,
|
|
957
|
+
},
|
|
958
|
+
{
|
|
959
|
+
guard: guardAndOrigin('committedMixed', 'irTask'),
|
|
960
|
+
target: '#reviewIrTaskCommitMixed',
|
|
961
|
+
actions: rememberCaptainOutput,
|
|
962
|
+
},
|
|
963
|
+
{ guard: guardIs('noRelevantChanges'), target: '#ready', actions: rememberCaptainOutput },
|
|
964
|
+
{ guard: guardIs('needsBossInput'), target: '#ready', actions: rememberCaptainOutput },
|
|
965
|
+
],
|
|
966
|
+
onError: captainError,
|
|
967
|
+
},
|
|
968
|
+
},
|
|
969
|
+
commitJoint: {
|
|
970
|
+
id: 'commitJoint',
|
|
971
|
+
description: 'CODE-19: Committer commits changes when both Coder and Reviewer have played since the last commit.',
|
|
972
|
+
invoke: {
|
|
973
|
+
src: 'captain',
|
|
974
|
+
input: ({ context }) => ({
|
|
975
|
+
player: 'Committer',
|
|
976
|
+
sourceItem: 'CODE-19',
|
|
977
|
+
coderPlayer: context.coderPlayer,
|
|
978
|
+
reviewerPlayer: context.reviewerPlayer,
|
|
979
|
+
prompt: [
|
|
980
|
+
'Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).',
|
|
981
|
+
'Coder is <coder-llm>; Reviewer is <reviewer-llm>.',
|
|
982
|
+
].join('\n'),
|
|
983
|
+
result: {
|
|
984
|
+
committed: 'Relevant changes were committed.',
|
|
985
|
+
noRelevantChanges: 'There are no relevant changes to commit.',
|
|
986
|
+
needsBossInput: 'Committing requires additional Boss input.',
|
|
987
|
+
},
|
|
988
|
+
}),
|
|
989
|
+
onDone: [
|
|
990
|
+
{
|
|
991
|
+
guard: ({ context, event }) => outputOf(event)?.guard === 'committed' && context.afterReview === 'continueIr',
|
|
992
|
+
target: '#continueIr',
|
|
993
|
+
actions: rememberCaptainOutput,
|
|
994
|
+
},
|
|
995
|
+
{
|
|
996
|
+
guard: ({ context, event }) => outputOf(event)?.guard === 'committed' && context.afterReview === 'summarizeSpecs',
|
|
997
|
+
target: '#summarizeSpecs',
|
|
998
|
+
actions: rememberCaptainOutput,
|
|
999
|
+
},
|
|
1000
|
+
{
|
|
1001
|
+
guard: ({ context, event }) => outputOf(event)?.guard === 'committed' && context.afterReview === 'done',
|
|
1002
|
+
target: '#done',
|
|
1003
|
+
actions: rememberCaptainOutput,
|
|
1004
|
+
},
|
|
1005
|
+
{ guard: guardIs('noRelevantChanges'), target: '#done', actions: rememberCaptainOutput },
|
|
1006
|
+
{ guard: guardIs('needsBossInput'), target: '#ready', actions: rememberCaptainOutput },
|
|
1007
|
+
],
|
|
1008
|
+
onError: captainError,
|
|
1009
|
+
},
|
|
1010
|
+
},
|
|
1011
|
+
failed: {
|
|
1012
|
+
id: 'failed',
|
|
1013
|
+
description: 'Captures the last Captain error so the runner can report it. Boss may resume from here.',
|
|
1014
|
+
on: readyEvents,
|
|
1015
|
+
},
|
|
1016
|
+
done: {
|
|
1017
|
+
id: 'done',
|
|
1018
|
+
description: 'The selected coding workflow has completed.',
|
|
1019
|
+
type: 'final',
|
|
1020
|
+
},
|
|
1021
|
+
},
|
|
1022
|
+
});
|