@sublang/playbook 0.9.0 → 1.3.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 +190 -151
- package/package.json +50 -6
- package/reference/sdlc/captain.md +102 -0
- package/reference/sdlc/captain.playbook/captain.fsm.d.ts +227 -0
- package/reference/sdlc/captain.playbook/captain.fsm.js +628 -0
- package/reference/sdlc/captain.playbook/captain.fsm.ts +851 -0
- package/reference/sdlc/captain.playbook/captain.gears.md +60 -0
- package/reference/sdlc/captain.playbook/captain.playbook.d.ts +23 -0
- package/reference/sdlc/captain.playbook/captain.playbook.js +1053 -0
- package/reference/sdlc/captain.playbook/captain.playbook.ts +1144 -0
- package/reference/sdlc/code.playbook/bin/playbook.js +158 -12
- package/reference/sdlc/code.playbook/bin/run.js +999 -0
- package/reference/sdlc/code.playbook/code.fsm.d.ts +11 -4
- package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +2 -2
- package/reference/sdlc/code.playbook/code.fsm.introspect.js +1 -1
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +6 -6
- package/reference/sdlc/code.playbook/code.fsm.js +334 -102
- package/reference/sdlc/code.playbook/code.fsm.ts +467 -180
- package/reference/sdlc/code.playbook/code.gears.md +11 -10
- package/reference/sdlc/code.playbook/code.playbook.d.ts +16 -19
- package/reference/sdlc/code.playbook/code.playbook.js +199 -488
- package/reference/sdlc/code.playbook/code.playbook.ts +327 -566
- package/reference/sdlc/code.playbook/code.registry.d.ts +0 -3
- package/reference/sdlc/code.playbook/code.registry.js +0 -3
- package/reference/sdlc/code.playbook/code.registry.ts +0 -6
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +9 -4
- package/reference/sdlc/code.playbook/playbook-captain.js +889 -210
- package/reference/sdlc/code.playbook/playbook-captain.ts +1136 -257
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +21 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.d.ts +396 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.js +2066 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.ts +2464 -0
- package/reference/sdlc/discuss.playbook/discuss.gears.md +251 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.d.ts +113 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.js +1514 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.ts +1926 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.d.ts +58 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.js +97 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.ts +153 -0
- package/slc/gears2fsm.md +557 -57
- package/slc/link.md +1165 -89
- package/slc/optimize.md +92 -0
- package/slc/text2gears.md +255 -7
- package/src/runtime.d.ts +146 -3
- package/src/runtime.ts +201 -2
- package/src/xstate-playbook-runtime.d.ts +201 -0
- package/src/xstate-playbook-runtime.js +2058 -0
- package/src/xstate-playbook-runtime.ts +2792 -0
- package/src/xstate-runtime.d.ts +95 -0
- package/src/xstate-runtime.js +1258 -0
- package/src/xstate-runtime.ts +1816 -0
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
// XState v5's generics do not flow through helpers declared outside the
|
|
5
5
|
// machine (e.g., shared guard/action factories, the `readyEvents` block),
|
|
6
6
|
// so strict checking emits structural-mismatch noise without surfacing real
|
|
7
|
-
// bugs. The runner overrides `
|
|
7
|
+
// bugs. The runner overrides `player` via `.provide({ actors: { ... } })`
|
|
8
8
|
// and re-asserts the public surface (`CodingContext`, `CodingEvent`,
|
|
9
|
-
// `
|
|
9
|
+
// `PlayerInput`, `PlayerOutput`) at the boundary.
|
|
10
10
|
// @ts-nocheck
|
|
11
11
|
|
|
12
12
|
import { assign, fromPromise, setup } from 'xstate';
|
|
@@ -43,6 +43,7 @@ type AfterReview = 'continueIr' | 'summarizeSpecs' | 'done';
|
|
|
43
43
|
type ResumableStateId = Exclude<JumpableStateId, 'ready' | 'failed'>;
|
|
44
44
|
|
|
45
45
|
type PendingBossQuestion = {
|
|
46
|
+
questionId: ResumableStateId;
|
|
46
47
|
resumeStateId: ResumableStateId;
|
|
47
48
|
sourceItem: string;
|
|
48
49
|
player: Player;
|
|
@@ -50,7 +51,7 @@ type PendingBossQuestion = {
|
|
|
50
51
|
};
|
|
51
52
|
|
|
52
53
|
export type CaptainInput = {
|
|
53
|
-
|
|
54
|
+
stateId: ResumableStateId;
|
|
54
55
|
sourceItem: string;
|
|
55
56
|
prompt: string;
|
|
56
57
|
result: Record<string, string>;
|
|
@@ -78,6 +79,10 @@ export type CaptainInput = {
|
|
|
78
79
|
bossReply?: string;
|
|
79
80
|
};
|
|
80
81
|
|
|
82
|
+
export type PlayerInput = CaptainInput & {
|
|
83
|
+
player: Player;
|
|
84
|
+
};
|
|
85
|
+
|
|
81
86
|
export type CaptainOutput = {
|
|
82
87
|
guard: string;
|
|
83
88
|
irNumber?: string;
|
|
@@ -89,6 +94,8 @@ export type CaptainOutput = {
|
|
|
89
94
|
[k: string]: unknown;
|
|
90
95
|
};
|
|
91
96
|
|
|
97
|
+
export type PlayerOutput = CaptainOutput;
|
|
98
|
+
|
|
92
99
|
export type CodingInput = {
|
|
93
100
|
intent?: string;
|
|
94
101
|
irNumber?: string;
|
|
@@ -121,7 +128,11 @@ export type CodingEvent =
|
|
|
121
128
|
intent?: string;
|
|
122
129
|
irNumber?: string;
|
|
123
130
|
}
|
|
124
|
-
| {
|
|
131
|
+
| {
|
|
132
|
+
type: 'BOSS_REPLY';
|
|
133
|
+
answer: string;
|
|
134
|
+
questionId?: ResumableStateId;
|
|
135
|
+
};
|
|
125
136
|
|
|
126
137
|
const jumpableStateIds = [
|
|
127
138
|
'ready',
|
|
@@ -169,39 +180,113 @@ const resumableStateIds = [
|
|
|
169
180
|
'commitJoint',
|
|
170
181
|
] as const satisfies readonly ResumableStateId[];
|
|
171
182
|
|
|
183
|
+
const stateDescriptions = {
|
|
184
|
+
ready: 'Idle hub: waits for Boss to start or resume a coding sub-procedure.',
|
|
185
|
+
awaitBossReply: 'Waiting for Boss to answer a player question.',
|
|
186
|
+
planAndImplement:
|
|
187
|
+
'CODE-1: Coder assesses a Boss intent and either implements a single-commit change or drafts an IR.',
|
|
188
|
+
respondToReview: 'CODE-2: Coder addresses or challenges Reviewer findings.',
|
|
189
|
+
continueIr:
|
|
190
|
+
'CODE-3: Coder continues an IR after the previous task or IR draft passed review.',
|
|
191
|
+
summarizeSpecs:
|
|
192
|
+
'CODE-4: Coder summarizes a completed IR into minimal spec items.',
|
|
193
|
+
reviewBossCommitSpecs:
|
|
194
|
+
'CODE-5: Reviewer reviews a Boss-intent commit whose changes are only in @specs/{user,dev,test}/.',
|
|
195
|
+
reviewBossCommitCode:
|
|
196
|
+
'CODE-6: Reviewer reviews a Boss-intent commit whose changes are only outside @specs/{user,dev,test}/.',
|
|
197
|
+
reviewBossCommitMixed:
|
|
198
|
+
'CODE-7: Reviewer reviews a Boss-intent commit whose changes span both @specs/{user,dev,test}/ and other files.',
|
|
199
|
+
reviewIrTaskCommitSpecs:
|
|
200
|
+
'CODE-8: Reviewer reviews an IR-task commit whose changes are only in @specs/{user,dev,test}/.',
|
|
201
|
+
reviewIrTaskCommitCode:
|
|
202
|
+
'CODE-9: Reviewer reviews an IR-task commit whose changes are only outside @specs/{user,dev,test}/.',
|
|
203
|
+
reviewIrTaskCommitMixed:
|
|
204
|
+
'CODE-10: Reviewer reviews an IR-task commit whose changes span both @specs/{user,dev,test}/ and other files.',
|
|
205
|
+
reviewChangesSpecs:
|
|
206
|
+
'CODE-11: Reviewer reviews uncommitted Coder changes that touch only @specs/{user,dev,test}/ with no accompanying rebuttals.',
|
|
207
|
+
reviewChangesCode:
|
|
208
|
+
'CODE-12: Reviewer reviews uncommitted Coder changes that touch only files outside @specs/{user,dev,test}/ with no accompanying rebuttals.',
|
|
209
|
+
reviewChangesMixed:
|
|
210
|
+
'CODE-13: Reviewer reviews uncommitted Coder changes that touch both @specs/{user,dev,test}/ and other files with no accompanying rebuttals.',
|
|
211
|
+
reviewChangesAndChallengesSpecs:
|
|
212
|
+
'CODE-15: Reviewer reviews uncommitted Coder changes that touch only @specs/{user,dev,test}/ and adjudicates accompanying rebuttals in one round.',
|
|
213
|
+
reviewChangesAndChallengesCode:
|
|
214
|
+
'CODE-16: Reviewer reviews uncommitted Coder changes that touch only files outside @specs/{user,dev,test}/ and adjudicates accompanying rebuttals in one round.',
|
|
215
|
+
reviewChangesAndChallengesMixed:
|
|
216
|
+
'CODE-17: Reviewer reviews uncommitted Coder changes that touch both @specs/{user,dev,test}/ and other files and adjudicates accompanying rebuttals in one round.',
|
|
217
|
+
adjudicateChallenges:
|
|
218
|
+
'CODE-14: Reviewer adjudicates Coder rebuttals against the prior review when Coder produced no code edits this round.',
|
|
219
|
+
commitCoderInitial:
|
|
220
|
+
'CODE-18: Committer commits Coder Initial Changes when Reviewer has not played since the last commit.',
|
|
221
|
+
commitJoint:
|
|
222
|
+
'CODE-19: Committer commits changes when both Coder and Reviewer have played since the last commit.',
|
|
223
|
+
failed:
|
|
224
|
+
'Captures the last Captain error so the runner can report it. Boss may resume from here.',
|
|
225
|
+
done: 'The selected coding workflow has completed.',
|
|
226
|
+
} as const satisfies Record<
|
|
227
|
+
JumpableStateId | 'awaitBossReply' | 'done',
|
|
228
|
+
string
|
|
229
|
+
>;
|
|
230
|
+
|
|
231
|
+
const playbookMeta = <StateId extends keyof typeof stateDescriptions>(
|
|
232
|
+
stateId: StateId,
|
|
233
|
+
) => ({
|
|
234
|
+
playbook: {
|
|
235
|
+
stateId,
|
|
236
|
+
description: stateDescriptions[stateId],
|
|
237
|
+
},
|
|
238
|
+
});
|
|
239
|
+
|
|
172
240
|
const outputOf = (event: unknown): CaptainOutput | undefined =>
|
|
173
241
|
(event as { output?: CaptainOutput }).output;
|
|
174
242
|
|
|
175
|
-
const guardIs =
|
|
176
|
-
(
|
|
243
|
+
const guardIs =
|
|
244
|
+
(guard: string) =>
|
|
245
|
+
({ event }: { event: unknown }) =>
|
|
246
|
+
outputOf(event)?.guard === guard;
|
|
177
247
|
|
|
178
|
-
const guardAndOrigin =
|
|
248
|
+
const guardAndOrigin =
|
|
249
|
+
(guard: string, origin: ChangeOrigin) =>
|
|
179
250
|
({ context, event }: { context: CodingContext; event: unknown }) =>
|
|
180
251
|
outputOf(event)?.guard === guard && context.changeOrigin === origin;
|
|
181
252
|
|
|
182
|
-
const acceptedAfter =
|
|
253
|
+
const acceptedAfter =
|
|
254
|
+
(subject: ReviewSubject) =>
|
|
183
255
|
({ context, event }: { context: CodingContext; event: unknown }) =>
|
|
184
256
|
outputOf(event)?.guard === 'accepted' && context.reviewSubject === subject;
|
|
185
257
|
|
|
186
|
-
const noFindingsAfter =
|
|
258
|
+
const noFindingsAfter =
|
|
259
|
+
(afterReview: AfterReview) =>
|
|
187
260
|
({ context, event }: { context: CodingContext; event: unknown }) =>
|
|
188
|
-
outputOf(event)?.guard === 'noFindings' &&
|
|
261
|
+
outputOf(event)?.guard === 'noFindings' &&
|
|
262
|
+
context.afterReview === afterReview;
|
|
189
263
|
|
|
190
264
|
const rememberCaptainOutput = assign({
|
|
191
265
|
lastResult: ({ event }: { event: unknown }) => outputOf(event),
|
|
192
266
|
lastError: () => undefined,
|
|
193
267
|
irNumber: ({ context, event }: { context: CodingContext; event: unknown }) =>
|
|
194
268
|
outputOf(event)?.irNumber ?? context.irNumber,
|
|
195
|
-
taskDescription: ({
|
|
196
|
-
|
|
269
|
+
taskDescription: ({
|
|
270
|
+
context,
|
|
271
|
+
event,
|
|
272
|
+
}: {
|
|
273
|
+
context: CodingContext;
|
|
274
|
+
event: unknown;
|
|
275
|
+
}) => outputOf(event)?.taskDescription ?? context.taskDescription,
|
|
197
276
|
reviews: ({ context, event }: { context: CodingContext; event: unknown }) =>
|
|
198
277
|
outputOf(event)?.reviews ?? context.reviews,
|
|
199
|
-
challenges: ({
|
|
200
|
-
|
|
278
|
+
challenges: ({
|
|
279
|
+
context,
|
|
280
|
+
event,
|
|
281
|
+
}: {
|
|
282
|
+
context: CodingContext;
|
|
283
|
+
event: unknown;
|
|
284
|
+
}) => outputOf(event)?.challenges ?? context.challenges,
|
|
201
285
|
});
|
|
202
286
|
|
|
203
287
|
const rememberCaptainError = assign({
|
|
204
|
-
lastError: ({ event }: { event: unknown }) =>
|
|
288
|
+
lastError: ({ event }: { event: unknown }) =>
|
|
289
|
+
(event as { error?: unknown }).error,
|
|
205
290
|
});
|
|
206
291
|
|
|
207
292
|
const rememberEmptyBossReplyError = assign({
|
|
@@ -215,10 +300,10 @@ const rememberBossInput = assign({
|
|
|
215
300
|
(event as { irNumber?: string }).irNumber ?? context.irNumber,
|
|
216
301
|
});
|
|
217
302
|
|
|
218
|
-
type
|
|
303
|
+
type PlayerInputFactory = (context: Partial<CodingContext>) => PlayerInput;
|
|
219
304
|
|
|
220
305
|
const needsBossReplyDescription =
|
|
221
|
-
"The
|
|
306
|
+
"The acting agent's prose surfaces a clarifying question for Boss that the agent cannot answer alone. Output shall include `question: <verbatim question text from the acting agent's prose>`.";
|
|
222
307
|
|
|
223
308
|
const bossReplyInputFields = (context: Partial<CodingContext>) => ({
|
|
224
309
|
pendingBossQuestion: context.pendingBossQuestion,
|
|
@@ -244,9 +329,15 @@ const captainStateMetadata = {
|
|
|
244
329
|
reviewChangesSpecs: { sourceItem: 'CODE-11', player: 'Reviewer' },
|
|
245
330
|
reviewChangesCode: { sourceItem: 'CODE-12', player: 'Reviewer' },
|
|
246
331
|
reviewChangesMixed: { sourceItem: 'CODE-13', player: 'Reviewer' },
|
|
247
|
-
reviewChangesAndChallengesSpecs: {
|
|
332
|
+
reviewChangesAndChallengesSpecs: {
|
|
333
|
+
sourceItem: 'CODE-15',
|
|
334
|
+
player: 'Reviewer',
|
|
335
|
+
},
|
|
248
336
|
reviewChangesAndChallengesCode: { sourceItem: 'CODE-16', player: 'Reviewer' },
|
|
249
|
-
reviewChangesAndChallengesMixed: {
|
|
337
|
+
reviewChangesAndChallengesMixed: {
|
|
338
|
+
sourceItem: 'CODE-17',
|
|
339
|
+
player: 'Reviewer',
|
|
340
|
+
},
|
|
250
341
|
adjudicateChallenges: { sourceItem: 'CODE-14', player: 'Reviewer' },
|
|
251
342
|
commitCoderInitial: { sourceItem: 'CODE-18', player: 'Committer' },
|
|
252
343
|
commitJoint: { sourceItem: 'CODE-19', player: 'Committer' },
|
|
@@ -255,7 +346,8 @@ const captainStateMetadata = {
|
|
|
255
346
|
{ sourceItem: string; player: Player }
|
|
256
347
|
>;
|
|
257
348
|
|
|
258
|
-
const planAndImplementInput:
|
|
349
|
+
const planAndImplementInput: PlayerInputFactory = (context) => ({
|
|
350
|
+
stateId: 'planAndImplement',
|
|
259
351
|
player: 'Coder',
|
|
260
352
|
sourceItem: 'CODE-1',
|
|
261
353
|
intent: context.intent,
|
|
@@ -275,7 +367,8 @@ const planAndImplementInput: CaptainInputFactory = (context) => ({
|
|
|
275
367
|
}),
|
|
276
368
|
});
|
|
277
369
|
|
|
278
|
-
const continueIrInput:
|
|
370
|
+
const continueIrInput: PlayerInputFactory = (context) => ({
|
|
371
|
+
stateId: 'continueIr',
|
|
279
372
|
player: 'Coder',
|
|
280
373
|
sourceItem: 'CODE-3',
|
|
281
374
|
irNumber: context.irNumber,
|
|
@@ -293,7 +386,8 @@ const continueIrInput: CaptainInputFactory = (context) => ({
|
|
|
293
386
|
}),
|
|
294
387
|
});
|
|
295
388
|
|
|
296
|
-
const summarizeSpecsInput:
|
|
389
|
+
const summarizeSpecsInput: PlayerInputFactory = (context) => ({
|
|
390
|
+
stateId: 'summarizeSpecs',
|
|
297
391
|
player: 'Coder',
|
|
298
392
|
sourceItem: 'CODE-4',
|
|
299
393
|
irNumber: context.irNumber,
|
|
@@ -329,6 +423,7 @@ const setPendingBossQuestion = (resumeStateId: ResumableStateId) =>
|
|
|
329
423
|
}) => {
|
|
330
424
|
const input = captainStateMetadata[resumeStateId];
|
|
331
425
|
return {
|
|
426
|
+
questionId: resumeStateId,
|
|
332
427
|
resumeStateId,
|
|
333
428
|
sourceItem: input.sourceItem,
|
|
334
429
|
player: input.player,
|
|
@@ -351,7 +446,9 @@ const clearBossReplyContext = assign({
|
|
|
351
446
|
const actionsArray = (actions: unknown) =>
|
|
352
447
|
actions === undefined ? [] : Array.isArray(actions) ? actions : [actions];
|
|
353
448
|
|
|
354
|
-
const withClearBossReplyContext = <T extends { actions?: unknown }>(
|
|
449
|
+
const withClearBossReplyContext = <T extends { actions?: unknown }>(
|
|
450
|
+
transition: T,
|
|
451
|
+
): T => ({
|
|
355
452
|
...transition,
|
|
356
453
|
actions: [clearBossReplyContext, ...actionsArray(transition.actions)],
|
|
357
454
|
});
|
|
@@ -371,9 +468,17 @@ const bossInterrupts = (
|
|
|
371
468
|
const resumableStates = (ids: readonly ResumableStateId[]) =>
|
|
372
469
|
ids.map((id) => ({
|
|
373
470
|
target: `#${id}` as const,
|
|
374
|
-
guard: ({
|
|
471
|
+
guard: ({
|
|
472
|
+
context,
|
|
473
|
+
event,
|
|
474
|
+
}: {
|
|
475
|
+
context: CodingContext;
|
|
476
|
+
event: CodingEvent;
|
|
477
|
+
}) =>
|
|
375
478
|
event.type === 'BOSS_REPLY' &&
|
|
376
|
-
context.pendingBossQuestion?.resumeStateId === id
|
|
479
|
+
context.pendingBossQuestion?.resumeStateId === id &&
|
|
480
|
+
(event.questionId === undefined ||
|
|
481
|
+
event.questionId === context.pendingBossQuestion.questionId),
|
|
377
482
|
reenter: true,
|
|
378
483
|
actions: rememberBossReply,
|
|
379
484
|
}));
|
|
@@ -451,8 +556,8 @@ const awaitBossReplyEvents = {
|
|
|
451
556
|
],
|
|
452
557
|
};
|
|
453
558
|
|
|
454
|
-
const
|
|
455
|
-
throw new Error('
|
|
559
|
+
const playerPlaceholder = fromPromise<PlayerOutput, PlayerInput>(async () => {
|
|
560
|
+
throw new Error('player actor must be provided by the runner');
|
|
456
561
|
});
|
|
457
562
|
|
|
458
563
|
export const codingMachine = setup({
|
|
@@ -462,7 +567,7 @@ export const codingMachine = setup({
|
|
|
462
567
|
input: CodingInput | undefined;
|
|
463
568
|
},
|
|
464
569
|
actors: {
|
|
465
|
-
|
|
570
|
+
player: playerPlaceholder,
|
|
466
571
|
},
|
|
467
572
|
}).createMachine({
|
|
468
573
|
id: 'coding',
|
|
@@ -480,23 +585,28 @@ export const codingMachine = setup({
|
|
|
480
585
|
states: {
|
|
481
586
|
ready: {
|
|
482
587
|
id: 'ready',
|
|
483
|
-
description:
|
|
588
|
+
description: stateDescriptions.ready,
|
|
589
|
+
meta: playbookMeta('ready'),
|
|
590
|
+
tags: ['playbook.parked'],
|
|
484
591
|
on: readyEvents,
|
|
485
592
|
},
|
|
486
593
|
|
|
487
594
|
awaitBossReply: {
|
|
488
595
|
id: 'awaitBossReply',
|
|
489
|
-
description:
|
|
596
|
+
description: stateDescriptions.awaitBossReply,
|
|
597
|
+
meta: playbookMeta('awaitBossReply'),
|
|
598
|
+
tags: ['playbook.parked'],
|
|
490
599
|
on: awaitBossReplyEvents,
|
|
491
600
|
},
|
|
492
601
|
|
|
493
602
|
planAndImplement: {
|
|
494
603
|
id: 'planAndImplement',
|
|
495
|
-
description:
|
|
496
|
-
|
|
604
|
+
description: stateDescriptions.planAndImplement,
|
|
605
|
+
meta: playbookMeta('planAndImplement'),
|
|
606
|
+
tags: ['playbook.busy'],
|
|
497
607
|
invoke: {
|
|
498
|
-
src: '
|
|
499
|
-
input: ({ context }):
|
|
608
|
+
src: 'player',
|
|
609
|
+
input: ({ context }): PlayerInput => planAndImplementInput(context),
|
|
500
610
|
onDone: withNeedsBossReplyTransition('planAndImplement', [
|
|
501
611
|
{
|
|
502
612
|
guard: guardIs('singleCommitReady'),
|
|
@@ -529,10 +639,13 @@ export const codingMachine = setup({
|
|
|
529
639
|
|
|
530
640
|
respondToReview: {
|
|
531
641
|
id: 'respondToReview',
|
|
532
|
-
description:
|
|
642
|
+
description: stateDescriptions.respondToReview,
|
|
643
|
+
meta: playbookMeta('respondToReview'),
|
|
644
|
+
tags: ['playbook.busy'],
|
|
533
645
|
invoke: {
|
|
534
|
-
src: '
|
|
535
|
-
input: ({ context }):
|
|
646
|
+
src: 'player',
|
|
647
|
+
input: ({ context }): PlayerInput => ({
|
|
648
|
+
stateId: 'respondToReview',
|
|
536
649
|
player: 'Coder',
|
|
537
650
|
sourceItem: 'CODE-2',
|
|
538
651
|
...bossReplyInputFields(context),
|
|
@@ -633,11 +746,12 @@ export const codingMachine = setup({
|
|
|
633
746
|
|
|
634
747
|
continueIr: {
|
|
635
748
|
id: 'continueIr',
|
|
636
|
-
description:
|
|
637
|
-
|
|
749
|
+
description: stateDescriptions.continueIr,
|
|
750
|
+
meta: playbookMeta('continueIr'),
|
|
751
|
+
tags: ['playbook.busy'],
|
|
638
752
|
invoke: {
|
|
639
|
-
src: '
|
|
640
|
-
input: ({ context }):
|
|
753
|
+
src: 'player',
|
|
754
|
+
input: ({ context }): PlayerInput => continueIrInput(context),
|
|
641
755
|
onDone: withNeedsBossReplyTransition('continueIr', [
|
|
642
756
|
{
|
|
643
757
|
guard: guardIs('taskReady'),
|
|
@@ -669,10 +783,12 @@ export const codingMachine = setup({
|
|
|
669
783
|
|
|
670
784
|
summarizeSpecs: {
|
|
671
785
|
id: 'summarizeSpecs',
|
|
672
|
-
description:
|
|
786
|
+
description: stateDescriptions.summarizeSpecs,
|
|
787
|
+
meta: playbookMeta('summarizeSpecs'),
|
|
788
|
+
tags: ['playbook.busy'],
|
|
673
789
|
invoke: {
|
|
674
|
-
src: '
|
|
675
|
-
input: ({ context }):
|
|
790
|
+
src: 'player',
|
|
791
|
+
input: ({ context }): PlayerInput => summarizeSpecsInput(context),
|
|
676
792
|
onDone: withNeedsBossReplyTransition('summarizeSpecs', [
|
|
677
793
|
{
|
|
678
794
|
guard: guardIs('specsReady'),
|
|
@@ -698,11 +814,13 @@ export const codingMachine = setup({
|
|
|
698
814
|
|
|
699
815
|
reviewBossCommitSpecs: {
|
|
700
816
|
id: 'reviewBossCommitSpecs',
|
|
701
|
-
description:
|
|
702
|
-
|
|
817
|
+
description: stateDescriptions.reviewBossCommitSpecs,
|
|
818
|
+
meta: playbookMeta('reviewBossCommitSpecs'),
|
|
819
|
+
tags: ['playbook.busy'],
|
|
703
820
|
invoke: {
|
|
704
|
-
src: '
|
|
705
|
-
input: ({ context }):
|
|
821
|
+
src: 'player',
|
|
822
|
+
input: ({ context }): PlayerInput => ({
|
|
823
|
+
stateId: 'reviewBossCommitSpecs',
|
|
706
824
|
player: 'Reviewer',
|
|
707
825
|
sourceItem: 'CODE-5',
|
|
708
826
|
...bossReplyInputFields(context),
|
|
@@ -731,13 +849,28 @@ export const codingMachine = setup({
|
|
|
731
849
|
},
|
|
732
850
|
}),
|
|
733
851
|
onDone: withNeedsBossReplyTransition('reviewBossCommitSpecs', [
|
|
734
|
-
{
|
|
735
|
-
|
|
736
|
-
|
|
852
|
+
{
|
|
853
|
+
guard: noFindingsAfter('continueIr'),
|
|
854
|
+
target: '#continueIr',
|
|
855
|
+
actions: rememberCaptainOutput,
|
|
856
|
+
},
|
|
857
|
+
{
|
|
858
|
+
guard: noFindingsAfter('summarizeSpecs'),
|
|
859
|
+
target: '#summarizeSpecs',
|
|
860
|
+
actions: rememberCaptainOutput,
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
guard: noFindingsAfter('done'),
|
|
864
|
+
target: '#done',
|
|
865
|
+
actions: rememberCaptainOutput,
|
|
866
|
+
},
|
|
737
867
|
{
|
|
738
868
|
guard: guardIs('hasFindings'),
|
|
739
869
|
target: '#respondToReview',
|
|
740
|
-
actions: [
|
|
870
|
+
actions: [
|
|
871
|
+
rememberCaptainOutput,
|
|
872
|
+
assign({ reviewSubject: () => 'commit' as const }),
|
|
873
|
+
],
|
|
741
874
|
},
|
|
742
875
|
]),
|
|
743
876
|
onError: captainError,
|
|
@@ -746,11 +879,13 @@ export const codingMachine = setup({
|
|
|
746
879
|
|
|
747
880
|
reviewBossCommitCode: {
|
|
748
881
|
id: 'reviewBossCommitCode',
|
|
749
|
-
description:
|
|
750
|
-
|
|
882
|
+
description: stateDescriptions.reviewBossCommitCode,
|
|
883
|
+
meta: playbookMeta('reviewBossCommitCode'),
|
|
884
|
+
tags: ['playbook.busy'],
|
|
751
885
|
invoke: {
|
|
752
|
-
src: '
|
|
753
|
-
input: ({ context }):
|
|
886
|
+
src: 'player',
|
|
887
|
+
input: ({ context }): PlayerInput => ({
|
|
888
|
+
stateId: 'reviewBossCommitCode',
|
|
754
889
|
player: 'Reviewer',
|
|
755
890
|
sourceItem: 'CODE-6',
|
|
756
891
|
...bossReplyInputFields(context),
|
|
@@ -773,13 +908,28 @@ export const codingMachine = setup({
|
|
|
773
908
|
},
|
|
774
909
|
}),
|
|
775
910
|
onDone: withNeedsBossReplyTransition('reviewBossCommitCode', [
|
|
776
|
-
{
|
|
777
|
-
|
|
778
|
-
|
|
911
|
+
{
|
|
912
|
+
guard: noFindingsAfter('continueIr'),
|
|
913
|
+
target: '#continueIr',
|
|
914
|
+
actions: rememberCaptainOutput,
|
|
915
|
+
},
|
|
916
|
+
{
|
|
917
|
+
guard: noFindingsAfter('summarizeSpecs'),
|
|
918
|
+
target: '#summarizeSpecs',
|
|
919
|
+
actions: rememberCaptainOutput,
|
|
920
|
+
},
|
|
921
|
+
{
|
|
922
|
+
guard: noFindingsAfter('done'),
|
|
923
|
+
target: '#done',
|
|
924
|
+
actions: rememberCaptainOutput,
|
|
925
|
+
},
|
|
779
926
|
{
|
|
780
927
|
guard: guardIs('hasFindings'),
|
|
781
928
|
target: '#respondToReview',
|
|
782
|
-
actions: [
|
|
929
|
+
actions: [
|
|
930
|
+
rememberCaptainOutput,
|
|
931
|
+
assign({ reviewSubject: () => 'commit' as const }),
|
|
932
|
+
],
|
|
783
933
|
},
|
|
784
934
|
]),
|
|
785
935
|
onError: captainError,
|
|
@@ -788,11 +938,13 @@ export const codingMachine = setup({
|
|
|
788
938
|
|
|
789
939
|
reviewBossCommitMixed: {
|
|
790
940
|
id: 'reviewBossCommitMixed',
|
|
791
|
-
description:
|
|
792
|
-
|
|
941
|
+
description: stateDescriptions.reviewBossCommitMixed,
|
|
942
|
+
meta: playbookMeta('reviewBossCommitMixed'),
|
|
943
|
+
tags: ['playbook.busy'],
|
|
793
944
|
invoke: {
|
|
794
|
-
src: '
|
|
795
|
-
input: ({ context }):
|
|
945
|
+
src: 'player',
|
|
946
|
+
input: ({ context }): PlayerInput => ({
|
|
947
|
+
stateId: 'reviewBossCommitMixed',
|
|
796
948
|
player: 'Reviewer',
|
|
797
949
|
sourceItem: 'CODE-7',
|
|
798
950
|
...bossReplyInputFields(context),
|
|
@@ -800,6 +952,8 @@ export const codingMachine = setup({
|
|
|
800
952
|
prompt: [
|
|
801
953
|
'Review the latest commit.',
|
|
802
954
|
'Refer to the commit message.',
|
|
955
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
956
|
+
"Think thoroughly — don't just approve or reject.",
|
|
803
957
|
'Verify any affected spec items are:',
|
|
804
958
|
'',
|
|
805
959
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
@@ -808,8 +962,6 @@ export const codingMachine = setup({
|
|
|
808
962
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
809
963
|
'',
|
|
810
964
|
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
811
|
-
'Flag any issues or improvements (numbered; no duplication).',
|
|
812
|
-
"Think thoroughly — don't just approve or reject.",
|
|
813
965
|
'For context discovery, @specs/map.md indexes all spec files and @specs/meta.md describes the spec format.',
|
|
814
966
|
'Verify @specs/map.md reflects the changes.',
|
|
815
967
|
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
@@ -823,13 +975,28 @@ export const codingMachine = setup({
|
|
|
823
975
|
},
|
|
824
976
|
}),
|
|
825
977
|
onDone: withNeedsBossReplyTransition('reviewBossCommitMixed', [
|
|
826
|
-
{
|
|
827
|
-
|
|
828
|
-
|
|
978
|
+
{
|
|
979
|
+
guard: noFindingsAfter('continueIr'),
|
|
980
|
+
target: '#continueIr',
|
|
981
|
+
actions: rememberCaptainOutput,
|
|
982
|
+
},
|
|
983
|
+
{
|
|
984
|
+
guard: noFindingsAfter('summarizeSpecs'),
|
|
985
|
+
target: '#summarizeSpecs',
|
|
986
|
+
actions: rememberCaptainOutput,
|
|
987
|
+
},
|
|
988
|
+
{
|
|
989
|
+
guard: noFindingsAfter('done'),
|
|
990
|
+
target: '#done',
|
|
991
|
+
actions: rememberCaptainOutput,
|
|
992
|
+
},
|
|
829
993
|
{
|
|
830
994
|
guard: guardIs('hasFindings'),
|
|
831
995
|
target: '#respondToReview',
|
|
832
|
-
actions: [
|
|
996
|
+
actions: [
|
|
997
|
+
rememberCaptainOutput,
|
|
998
|
+
assign({ reviewSubject: () => 'commit' as const }),
|
|
999
|
+
],
|
|
833
1000
|
},
|
|
834
1001
|
]),
|
|
835
1002
|
onError: captainError,
|
|
@@ -838,11 +1005,13 @@ export const codingMachine = setup({
|
|
|
838
1005
|
|
|
839
1006
|
reviewIrTaskCommitSpecs: {
|
|
840
1007
|
id: 'reviewIrTaskCommitSpecs',
|
|
841
|
-
description:
|
|
842
|
-
|
|
1008
|
+
description: stateDescriptions.reviewIrTaskCommitSpecs,
|
|
1009
|
+
meta: playbookMeta('reviewIrTaskCommitSpecs'),
|
|
1010
|
+
tags: ['playbook.busy'],
|
|
843
1011
|
invoke: {
|
|
844
|
-
src: '
|
|
845
|
-
input: ({ context }):
|
|
1012
|
+
src: 'player',
|
|
1013
|
+
input: ({ context }): PlayerInput => ({
|
|
1014
|
+
stateId: 'reviewIrTaskCommitSpecs',
|
|
846
1015
|
player: 'Reviewer',
|
|
847
1016
|
sourceItem: 'CODE-8',
|
|
848
1017
|
...bossReplyInputFields(context),
|
|
@@ -872,13 +1041,28 @@ export const codingMachine = setup({
|
|
|
872
1041
|
},
|
|
873
1042
|
}),
|
|
874
1043
|
onDone: withNeedsBossReplyTransition('reviewIrTaskCommitSpecs', [
|
|
875
|
-
{
|
|
876
|
-
|
|
877
|
-
|
|
1044
|
+
{
|
|
1045
|
+
guard: noFindingsAfter('continueIr'),
|
|
1046
|
+
target: '#continueIr',
|
|
1047
|
+
actions: rememberCaptainOutput,
|
|
1048
|
+
},
|
|
1049
|
+
{
|
|
1050
|
+
guard: noFindingsAfter('summarizeSpecs'),
|
|
1051
|
+
target: '#summarizeSpecs',
|
|
1052
|
+
actions: rememberCaptainOutput,
|
|
1053
|
+
},
|
|
1054
|
+
{
|
|
1055
|
+
guard: noFindingsAfter('done'),
|
|
1056
|
+
target: '#done',
|
|
1057
|
+
actions: rememberCaptainOutput,
|
|
1058
|
+
},
|
|
878
1059
|
{
|
|
879
1060
|
guard: guardIs('hasFindings'),
|
|
880
1061
|
target: '#respondToReview',
|
|
881
|
-
actions: [
|
|
1062
|
+
actions: [
|
|
1063
|
+
rememberCaptainOutput,
|
|
1064
|
+
assign({ reviewSubject: () => 'commit' as const }),
|
|
1065
|
+
],
|
|
882
1066
|
},
|
|
883
1067
|
]),
|
|
884
1068
|
onError: captainError,
|
|
@@ -887,11 +1071,13 @@ export const codingMachine = setup({
|
|
|
887
1071
|
|
|
888
1072
|
reviewIrTaskCommitCode: {
|
|
889
1073
|
id: 'reviewIrTaskCommitCode',
|
|
890
|
-
description:
|
|
891
|
-
|
|
1074
|
+
description: stateDescriptions.reviewIrTaskCommitCode,
|
|
1075
|
+
meta: playbookMeta('reviewIrTaskCommitCode'),
|
|
1076
|
+
tags: ['playbook.busy'],
|
|
892
1077
|
invoke: {
|
|
893
|
-
src: '
|
|
894
|
-
input: ({ context }):
|
|
1078
|
+
src: 'player',
|
|
1079
|
+
input: ({ context }): PlayerInput => ({
|
|
1080
|
+
stateId: 'reviewIrTaskCommitCode',
|
|
895
1081
|
player: 'Reviewer',
|
|
896
1082
|
sourceItem: 'CODE-9',
|
|
897
1083
|
...bossReplyInputFields(context),
|
|
@@ -915,13 +1101,28 @@ export const codingMachine = setup({
|
|
|
915
1101
|
},
|
|
916
1102
|
}),
|
|
917
1103
|
onDone: withNeedsBossReplyTransition('reviewIrTaskCommitCode', [
|
|
918
|
-
{
|
|
919
|
-
|
|
920
|
-
|
|
1104
|
+
{
|
|
1105
|
+
guard: noFindingsAfter('continueIr'),
|
|
1106
|
+
target: '#continueIr',
|
|
1107
|
+
actions: rememberCaptainOutput,
|
|
1108
|
+
},
|
|
1109
|
+
{
|
|
1110
|
+
guard: noFindingsAfter('summarizeSpecs'),
|
|
1111
|
+
target: '#summarizeSpecs',
|
|
1112
|
+
actions: rememberCaptainOutput,
|
|
1113
|
+
},
|
|
1114
|
+
{
|
|
1115
|
+
guard: noFindingsAfter('done'),
|
|
1116
|
+
target: '#done',
|
|
1117
|
+
actions: rememberCaptainOutput,
|
|
1118
|
+
},
|
|
921
1119
|
{
|
|
922
1120
|
guard: guardIs('hasFindings'),
|
|
923
1121
|
target: '#respondToReview',
|
|
924
|
-
actions: [
|
|
1122
|
+
actions: [
|
|
1123
|
+
rememberCaptainOutput,
|
|
1124
|
+
assign({ reviewSubject: () => 'commit' as const }),
|
|
1125
|
+
],
|
|
925
1126
|
},
|
|
926
1127
|
]),
|
|
927
1128
|
onError: captainError,
|
|
@@ -930,11 +1131,13 @@ export const codingMachine = setup({
|
|
|
930
1131
|
|
|
931
1132
|
reviewIrTaskCommitMixed: {
|
|
932
1133
|
id: 'reviewIrTaskCommitMixed',
|
|
933
|
-
description:
|
|
934
|
-
|
|
1134
|
+
description: stateDescriptions.reviewIrTaskCommitMixed,
|
|
1135
|
+
meta: playbookMeta('reviewIrTaskCommitMixed'),
|
|
1136
|
+
tags: ['playbook.busy'],
|
|
935
1137
|
invoke: {
|
|
936
|
-
src: '
|
|
937
|
-
input: ({ context }):
|
|
1138
|
+
src: 'player',
|
|
1139
|
+
input: ({ context }): PlayerInput => ({
|
|
1140
|
+
stateId: 'reviewIrTaskCommitMixed',
|
|
938
1141
|
player: 'Reviewer',
|
|
939
1142
|
sourceItem: 'CODE-10',
|
|
940
1143
|
...bossReplyInputFields(context),
|
|
@@ -943,6 +1146,8 @@ export const codingMachine = setup({
|
|
|
943
1146
|
prompt: [
|
|
944
1147
|
'Review the latest commit.',
|
|
945
1148
|
'Refer to the commit message.',
|
|
1149
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
1150
|
+
"Think thoroughly — don't just approve or reject.",
|
|
946
1151
|
'Verify any affected spec items are:',
|
|
947
1152
|
'',
|
|
948
1153
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
@@ -951,8 +1156,6 @@ export const codingMachine = setup({
|
|
|
951
1156
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
952
1157
|
'',
|
|
953
1158
|
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
954
|
-
'Flag any issues or improvements (numbered; no duplication).',
|
|
955
|
-
"Think thoroughly — don't just approve or reject.",
|
|
956
1159
|
'For context discovery, @specs/map.md indexes all spec files and @specs/meta.md describes the spec format.',
|
|
957
1160
|
'Verify @specs/map.md reflects the changes.',
|
|
958
1161
|
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
@@ -966,13 +1169,28 @@ export const codingMachine = setup({
|
|
|
966
1169
|
},
|
|
967
1170
|
}),
|
|
968
1171
|
onDone: withNeedsBossReplyTransition('reviewIrTaskCommitMixed', [
|
|
969
|
-
{
|
|
970
|
-
|
|
971
|
-
|
|
1172
|
+
{
|
|
1173
|
+
guard: noFindingsAfter('continueIr'),
|
|
1174
|
+
target: '#continueIr',
|
|
1175
|
+
actions: rememberCaptainOutput,
|
|
1176
|
+
},
|
|
1177
|
+
{
|
|
1178
|
+
guard: noFindingsAfter('summarizeSpecs'),
|
|
1179
|
+
target: '#summarizeSpecs',
|
|
1180
|
+
actions: rememberCaptainOutput,
|
|
1181
|
+
},
|
|
1182
|
+
{
|
|
1183
|
+
guard: noFindingsAfter('done'),
|
|
1184
|
+
target: '#done',
|
|
1185
|
+
actions: rememberCaptainOutput,
|
|
1186
|
+
},
|
|
972
1187
|
{
|
|
973
1188
|
guard: guardIs('hasFindings'),
|
|
974
1189
|
target: '#respondToReview',
|
|
975
|
-
actions: [
|
|
1190
|
+
actions: [
|
|
1191
|
+
rememberCaptainOutput,
|
|
1192
|
+
assign({ reviewSubject: () => 'commit' as const }),
|
|
1193
|
+
],
|
|
976
1194
|
},
|
|
977
1195
|
]),
|
|
978
1196
|
onError: captainError,
|
|
@@ -981,11 +1199,13 @@ export const codingMachine = setup({
|
|
|
981
1199
|
|
|
982
1200
|
reviewChangesSpecs: {
|
|
983
1201
|
id: 'reviewChangesSpecs',
|
|
984
|
-
description:
|
|
985
|
-
|
|
1202
|
+
description: stateDescriptions.reviewChangesSpecs,
|
|
1203
|
+
meta: playbookMeta('reviewChangesSpecs'),
|
|
1204
|
+
tags: ['playbook.busy'],
|
|
986
1205
|
invoke: {
|
|
987
|
-
src: '
|
|
988
|
-
input: ({ context }):
|
|
1206
|
+
src: 'player',
|
|
1207
|
+
input: ({ context }): PlayerInput => ({
|
|
1208
|
+
stateId: 'reviewChangesSpecs',
|
|
989
1209
|
player: 'Reviewer',
|
|
990
1210
|
sourceItem: 'CODE-11',
|
|
991
1211
|
...bossReplyInputFields(context),
|
|
@@ -1006,7 +1226,8 @@ export const codingMachine = setup({
|
|
|
1006
1226
|
'Do not edit files or commit; report findings only.',
|
|
1007
1227
|
].join('\n'),
|
|
1008
1228
|
result: {
|
|
1009
|
-
noFindings:
|
|
1229
|
+
noFindings:
|
|
1230
|
+
'The uncommitted spec-only changes are ready to commit.',
|
|
1010
1231
|
hasFindings:
|
|
1011
1232
|
'The review produced findings for Coder. Output shall include `reviews: <numbered list of findings, no duplication>`.',
|
|
1012
1233
|
needsBossReply: needsBossReplyDescription,
|
|
@@ -1021,7 +1242,10 @@ export const codingMachine = setup({
|
|
|
1021
1242
|
{
|
|
1022
1243
|
guard: guardIs('hasFindings'),
|
|
1023
1244
|
target: '#respondToReview',
|
|
1024
|
-
actions: [
|
|
1245
|
+
actions: [
|
|
1246
|
+
rememberCaptainOutput,
|
|
1247
|
+
assign({ reviewSubject: () => 'changes' as const }),
|
|
1248
|
+
],
|
|
1025
1249
|
},
|
|
1026
1250
|
]),
|
|
1027
1251
|
onError: captainError,
|
|
@@ -1030,11 +1254,13 @@ export const codingMachine = setup({
|
|
|
1030
1254
|
|
|
1031
1255
|
reviewChangesCode: {
|
|
1032
1256
|
id: 'reviewChangesCode',
|
|
1033
|
-
description:
|
|
1034
|
-
|
|
1257
|
+
description: stateDescriptions.reviewChangesCode,
|
|
1258
|
+
meta: playbookMeta('reviewChangesCode'),
|
|
1259
|
+
tags: ['playbook.busy'],
|
|
1035
1260
|
invoke: {
|
|
1036
|
-
src: '
|
|
1037
|
-
input: ({ context }):
|
|
1261
|
+
src: 'player',
|
|
1262
|
+
input: ({ context }): PlayerInput => ({
|
|
1263
|
+
stateId: 'reviewChangesCode',
|
|
1038
1264
|
player: 'Reviewer',
|
|
1039
1265
|
sourceItem: 'CODE-12',
|
|
1040
1266
|
...bossReplyInputFields(context),
|
|
@@ -1049,7 +1275,8 @@ export const codingMachine = setup({
|
|
|
1049
1275
|
'Do not edit files or commit; report findings only.',
|
|
1050
1276
|
].join('\n'),
|
|
1051
1277
|
result: {
|
|
1052
|
-
noFindings:
|
|
1278
|
+
noFindings:
|
|
1279
|
+
'The uncommitted code-only changes are ready to commit.',
|
|
1053
1280
|
hasFindings:
|
|
1054
1281
|
'The review produced findings for Coder. Output shall include `reviews: <numbered list of findings, no duplication>`.',
|
|
1055
1282
|
needsBossReply: needsBossReplyDescription,
|
|
@@ -1064,7 +1291,10 @@ export const codingMachine = setup({
|
|
|
1064
1291
|
{
|
|
1065
1292
|
guard: guardIs('hasFindings'),
|
|
1066
1293
|
target: '#respondToReview',
|
|
1067
|
-
actions: [
|
|
1294
|
+
actions: [
|
|
1295
|
+
rememberCaptainOutput,
|
|
1296
|
+
assign({ reviewSubject: () => 'changes' as const }),
|
|
1297
|
+
],
|
|
1068
1298
|
},
|
|
1069
1299
|
]),
|
|
1070
1300
|
onError: captainError,
|
|
@@ -1073,17 +1303,21 @@ export const codingMachine = setup({
|
|
|
1073
1303
|
|
|
1074
1304
|
reviewChangesMixed: {
|
|
1075
1305
|
id: 'reviewChangesMixed',
|
|
1076
|
-
description:
|
|
1077
|
-
|
|
1306
|
+
description: stateDescriptions.reviewChangesMixed,
|
|
1307
|
+
meta: playbookMeta('reviewChangesMixed'),
|
|
1308
|
+
tags: ['playbook.busy'],
|
|
1078
1309
|
invoke: {
|
|
1079
|
-
src: '
|
|
1080
|
-
input: ({ context }):
|
|
1310
|
+
src: 'player',
|
|
1311
|
+
input: ({ context }): PlayerInput => ({
|
|
1312
|
+
stateId: 'reviewChangesMixed',
|
|
1081
1313
|
player: 'Reviewer',
|
|
1082
1314
|
sourceItem: 'CODE-13',
|
|
1083
1315
|
...bossReplyInputFields(context),
|
|
1084
1316
|
prompt: [
|
|
1085
1317
|
'Review the unstaged and untracked changes in the context of the staged changes.',
|
|
1086
1318
|
'Understand the intent.',
|
|
1319
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
1320
|
+
"Think thoroughly — don't just approve or reject.",
|
|
1087
1321
|
'Verify any affected spec items are:',
|
|
1088
1322
|
'',
|
|
1089
1323
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
@@ -1092,8 +1326,6 @@ export const codingMachine = setup({
|
|
|
1092
1326
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
1093
1327
|
'',
|
|
1094
1328
|
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
1095
|
-
'Flag any issues or improvements (numbered; no duplication).',
|
|
1096
|
-
"Think thoroughly — don't just approve or reject.",
|
|
1097
1329
|
'For context discovery, @specs/map.md indexes all spec files and @specs/meta.md describes the spec format.',
|
|
1098
1330
|
'Verify @specs/map.md reflects the changes.',
|
|
1099
1331
|
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
@@ -1115,7 +1347,10 @@ export const codingMachine = setup({
|
|
|
1115
1347
|
{
|
|
1116
1348
|
guard: guardIs('hasFindings'),
|
|
1117
1349
|
target: '#respondToReview',
|
|
1118
|
-
actions: [
|
|
1350
|
+
actions: [
|
|
1351
|
+
rememberCaptainOutput,
|
|
1352
|
+
assign({ reviewSubject: () => 'changes' as const }),
|
|
1353
|
+
],
|
|
1119
1354
|
},
|
|
1120
1355
|
]),
|
|
1121
1356
|
onError: captainError,
|
|
@@ -1124,11 +1359,13 @@ export const codingMachine = setup({
|
|
|
1124
1359
|
|
|
1125
1360
|
reviewChangesAndChallengesSpecs: {
|
|
1126
1361
|
id: 'reviewChangesAndChallengesSpecs',
|
|
1127
|
-
description:
|
|
1128
|
-
|
|
1362
|
+
description: stateDescriptions.reviewChangesAndChallengesSpecs,
|
|
1363
|
+
meta: playbookMeta('reviewChangesAndChallengesSpecs'),
|
|
1364
|
+
tags: ['playbook.busy'],
|
|
1129
1365
|
invoke: {
|
|
1130
|
-
src: '
|
|
1131
|
-
input: ({ context }):
|
|
1366
|
+
src: 'player',
|
|
1367
|
+
input: ({ context }): PlayerInput => ({
|
|
1368
|
+
stateId: 'reviewChangesAndChallengesSpecs',
|
|
1132
1369
|
player: 'Reviewer',
|
|
1133
1370
|
sourceItem: 'CODE-15',
|
|
1134
1371
|
...bossReplyInputFields(context),
|
|
@@ -1159,29 +1396,37 @@ export const codingMachine = setup({
|
|
|
1159
1396
|
needsBossReply: needsBossReplyDescription,
|
|
1160
1397
|
},
|
|
1161
1398
|
}),
|
|
1162
|
-
onDone: withNeedsBossReplyTransition(
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1399
|
+
onDone: withNeedsBossReplyTransition(
|
|
1400
|
+
'reviewChangesAndChallengesSpecs',
|
|
1401
|
+
[
|
|
1402
|
+
{
|
|
1403
|
+
guard: guardIs('approved'),
|
|
1404
|
+
target: '#commitJoint',
|
|
1405
|
+
actions: rememberCaptainOutput,
|
|
1406
|
+
},
|
|
1407
|
+
{
|
|
1408
|
+
guard: guardIs('needsRevision'),
|
|
1409
|
+
target: '#respondToReview',
|
|
1410
|
+
actions: [
|
|
1411
|
+
rememberCaptainOutput,
|
|
1412
|
+
assign({ reviewSubject: () => 'changes' as const }),
|
|
1413
|
+
],
|
|
1414
|
+
},
|
|
1415
|
+
],
|
|
1416
|
+
),
|
|
1174
1417
|
onError: captainError,
|
|
1175
1418
|
},
|
|
1176
1419
|
},
|
|
1177
1420
|
|
|
1178
1421
|
reviewChangesAndChallengesCode: {
|
|
1179
1422
|
id: 'reviewChangesAndChallengesCode',
|
|
1180
|
-
description:
|
|
1181
|
-
|
|
1423
|
+
description: stateDescriptions.reviewChangesAndChallengesCode,
|
|
1424
|
+
meta: playbookMeta('reviewChangesAndChallengesCode'),
|
|
1425
|
+
tags: ['playbook.busy'],
|
|
1182
1426
|
invoke: {
|
|
1183
|
-
src: '
|
|
1184
|
-
input: ({ context }):
|
|
1427
|
+
src: 'player',
|
|
1428
|
+
input: ({ context }): PlayerInput => ({
|
|
1429
|
+
stateId: 'reviewChangesAndChallengesCode',
|
|
1185
1430
|
player: 'Reviewer',
|
|
1186
1431
|
sourceItem: 'CODE-16',
|
|
1187
1432
|
...bossReplyInputFields(context),
|
|
@@ -1215,7 +1460,10 @@ export const codingMachine = setup({
|
|
|
1215
1460
|
{
|
|
1216
1461
|
guard: guardIs('needsRevision'),
|
|
1217
1462
|
target: '#respondToReview',
|
|
1218
|
-
actions: [
|
|
1463
|
+
actions: [
|
|
1464
|
+
rememberCaptainOutput,
|
|
1465
|
+
assign({ reviewSubject: () => 'changes' as const }),
|
|
1466
|
+
],
|
|
1219
1467
|
},
|
|
1220
1468
|
]),
|
|
1221
1469
|
onError: captainError,
|
|
@@ -1224,11 +1472,13 @@ export const codingMachine = setup({
|
|
|
1224
1472
|
|
|
1225
1473
|
reviewChangesAndChallengesMixed: {
|
|
1226
1474
|
id: 'reviewChangesAndChallengesMixed',
|
|
1227
|
-
description:
|
|
1228
|
-
|
|
1475
|
+
description: stateDescriptions.reviewChangesAndChallengesMixed,
|
|
1476
|
+
meta: playbookMeta('reviewChangesAndChallengesMixed'),
|
|
1477
|
+
tags: ['playbook.busy'],
|
|
1229
1478
|
invoke: {
|
|
1230
|
-
src: '
|
|
1231
|
-
input: ({ context }):
|
|
1479
|
+
src: 'player',
|
|
1480
|
+
input: ({ context }): PlayerInput => ({
|
|
1481
|
+
stateId: 'reviewChangesAndChallengesMixed',
|
|
1232
1482
|
player: 'Reviewer',
|
|
1233
1483
|
sourceItem: 'CODE-17',
|
|
1234
1484
|
...bossReplyInputFields(context),
|
|
@@ -1237,6 +1487,8 @@ export const codingMachine = setup({
|
|
|
1237
1487
|
prompt: [
|
|
1238
1488
|
'Review the unstaged and untracked changes in the context of the staged changes.',
|
|
1239
1489
|
'Understand the intent.',
|
|
1490
|
+
'Flag any issues or improvements (numbered; no duplication).',
|
|
1491
|
+
"Think thoroughly — don't just approve or reject.",
|
|
1240
1492
|
'Verify any affected spec items are:',
|
|
1241
1493
|
'',
|
|
1242
1494
|
'- Complete & coherent: sufficient for you to reimplement code.',
|
|
@@ -1245,8 +1497,6 @@ export const codingMachine = setup({
|
|
|
1245
1497
|
'- Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
1246
1498
|
'',
|
|
1247
1499
|
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
1248
|
-
'Flag any issues or improvements (numbered; no duplication).',
|
|
1249
|
-
"Think thoroughly — don't just approve or reject.",
|
|
1250
1500
|
'For context discovery, @specs/map.md indexes all spec files and @specs/meta.md describes the spec format.',
|
|
1251
1501
|
'Verify @specs/map.md reflects the changes.',
|
|
1252
1502
|
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
@@ -1261,28 +1511,37 @@ export const codingMachine = setup({
|
|
|
1261
1511
|
needsBossReply: needsBossReplyDescription,
|
|
1262
1512
|
},
|
|
1263
1513
|
}),
|
|
1264
|
-
onDone: withNeedsBossReplyTransition(
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1514
|
+
onDone: withNeedsBossReplyTransition(
|
|
1515
|
+
'reviewChangesAndChallengesMixed',
|
|
1516
|
+
[
|
|
1517
|
+
{
|
|
1518
|
+
guard: guardIs('approved'),
|
|
1519
|
+
target: '#commitJoint',
|
|
1520
|
+
actions: rememberCaptainOutput,
|
|
1521
|
+
},
|
|
1522
|
+
{
|
|
1523
|
+
guard: guardIs('needsRevision'),
|
|
1524
|
+
target: '#respondToReview',
|
|
1525
|
+
actions: [
|
|
1526
|
+
rememberCaptainOutput,
|
|
1527
|
+
assign({ reviewSubject: () => 'changes' as const }),
|
|
1528
|
+
],
|
|
1529
|
+
},
|
|
1530
|
+
],
|
|
1531
|
+
),
|
|
1276
1532
|
onError: captainError,
|
|
1277
1533
|
},
|
|
1278
1534
|
},
|
|
1279
1535
|
|
|
1280
1536
|
adjudicateChallenges: {
|
|
1281
1537
|
id: 'adjudicateChallenges',
|
|
1282
|
-
description:
|
|
1538
|
+
description: stateDescriptions.adjudicateChallenges,
|
|
1539
|
+
meta: playbookMeta('adjudicateChallenges'),
|
|
1540
|
+
tags: ['playbook.busy'],
|
|
1283
1541
|
invoke: {
|
|
1284
|
-
src: '
|
|
1285
|
-
input: ({ context }):
|
|
1542
|
+
src: 'player',
|
|
1543
|
+
input: ({ context }): PlayerInput => ({
|
|
1544
|
+
stateId: 'adjudicateChallenges',
|
|
1286
1545
|
player: 'Reviewer',
|
|
1287
1546
|
sourceItem: 'CODE-14',
|
|
1288
1547
|
...bossReplyInputFields(context),
|
|
@@ -1349,11 +1608,13 @@ export const codingMachine = setup({
|
|
|
1349
1608
|
|
|
1350
1609
|
commitCoderInitial: {
|
|
1351
1610
|
id: 'commitCoderInitial',
|
|
1352
|
-
description:
|
|
1353
|
-
|
|
1611
|
+
description: stateDescriptions.commitCoderInitial,
|
|
1612
|
+
meta: playbookMeta('commitCoderInitial'),
|
|
1613
|
+
tags: ['playbook.busy'],
|
|
1354
1614
|
invoke: {
|
|
1355
|
-
src: '
|
|
1356
|
-
input: ({ context }):
|
|
1615
|
+
src: 'player',
|
|
1616
|
+
input: ({ context }): PlayerInput => ({
|
|
1617
|
+
stateId: 'commitCoderInitial',
|
|
1357
1618
|
player: 'Committer',
|
|
1358
1619
|
sourceItem: 'CODE-18',
|
|
1359
1620
|
...bossReplyInputFields(context),
|
|
@@ -1361,14 +1622,17 @@ export const codingMachine = setup({
|
|
|
1361
1622
|
committerPlayer: context.committerPlayer,
|
|
1362
1623
|
prompt: [
|
|
1363
1624
|
'Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).',
|
|
1364
|
-
'Write concisely.',
|
|
1625
|
+
'Write the commit message concisely.',
|
|
1365
1626
|
'Coder is <coder-llm>.',
|
|
1366
1627
|
'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`).',
|
|
1367
1628
|
].join('\n'),
|
|
1368
1629
|
result: {
|
|
1369
|
-
committedSpecs:
|
|
1370
|
-
|
|
1371
|
-
|
|
1630
|
+
committedSpecs:
|
|
1631
|
+
'Committed changes that touch only @specs/{user,dev,test}/.',
|
|
1632
|
+
committedCode:
|
|
1633
|
+
'Committed changes that touch only files outside @specs/{user,dev,test}/.',
|
|
1634
|
+
committedMixed:
|
|
1635
|
+
'Committed changes that span both @specs/{user,dev,test}/ and other files.',
|
|
1372
1636
|
noRelevantChanges: 'There are no relevant changes to commit.',
|
|
1373
1637
|
needsBossInput: 'Committing requires additional Boss input.',
|
|
1374
1638
|
needsBossReply: needsBossReplyDescription,
|
|
@@ -1405,8 +1669,16 @@ export const codingMachine = setup({
|
|
|
1405
1669
|
target: '#reviewIrTaskCommitMixed',
|
|
1406
1670
|
actions: rememberCaptainOutput,
|
|
1407
1671
|
},
|
|
1408
|
-
{
|
|
1409
|
-
|
|
1672
|
+
{
|
|
1673
|
+
guard: guardIs('noRelevantChanges'),
|
|
1674
|
+
target: '#ready',
|
|
1675
|
+
actions: rememberCaptainOutput,
|
|
1676
|
+
},
|
|
1677
|
+
{
|
|
1678
|
+
guard: guardIs('needsBossInput'),
|
|
1679
|
+
target: '#ready',
|
|
1680
|
+
actions: rememberCaptainOutput,
|
|
1681
|
+
},
|
|
1410
1682
|
]),
|
|
1411
1683
|
onError: captainError,
|
|
1412
1684
|
},
|
|
@@ -1414,11 +1686,13 @@ export const codingMachine = setup({
|
|
|
1414
1686
|
|
|
1415
1687
|
commitJoint: {
|
|
1416
1688
|
id: 'commitJoint',
|
|
1417
|
-
description:
|
|
1418
|
-
|
|
1689
|
+
description: stateDescriptions.commitJoint,
|
|
1690
|
+
meta: playbookMeta('commitJoint'),
|
|
1691
|
+
tags: ['playbook.busy'],
|
|
1419
1692
|
invoke: {
|
|
1420
|
-
src: '
|
|
1421
|
-
input: ({ context }):
|
|
1693
|
+
src: 'player',
|
|
1694
|
+
input: ({ context }): PlayerInput => ({
|
|
1695
|
+
stateId: 'commitJoint',
|
|
1422
1696
|
player: 'Committer',
|
|
1423
1697
|
sourceItem: 'CODE-19',
|
|
1424
1698
|
...bossReplyInputFields(context),
|
|
@@ -1427,7 +1701,7 @@ export const codingMachine = setup({
|
|
|
1427
1701
|
committerPlayer: context.committerPlayer,
|
|
1428
1702
|
prompt: [
|
|
1429
1703
|
'Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).',
|
|
1430
|
-
'Write concisely.',
|
|
1704
|
+
'Write the commit message concisely.',
|
|
1431
1705
|
'Coder is <coder-llm>; Reviewer is <reviewer-llm>.',
|
|
1432
1706
|
'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`).',
|
|
1433
1707
|
].join('\n'),
|
|
@@ -1441,24 +1715,35 @@ export const codingMachine = setup({
|
|
|
1441
1715
|
onDone: withNeedsBossReplyTransition('commitJoint', [
|
|
1442
1716
|
{
|
|
1443
1717
|
guard: ({ context, event }) =>
|
|
1444
|
-
outputOf(event)?.guard === 'committed' &&
|
|
1718
|
+
outputOf(event)?.guard === 'committed' &&
|
|
1719
|
+
context.afterReview === 'continueIr',
|
|
1445
1720
|
target: '#continueIr',
|
|
1446
1721
|
actions: rememberCaptainOutput,
|
|
1447
1722
|
},
|
|
1448
1723
|
{
|
|
1449
1724
|
guard: ({ context, event }) =>
|
|
1450
|
-
outputOf(event)?.guard === 'committed' &&
|
|
1725
|
+
outputOf(event)?.guard === 'committed' &&
|
|
1726
|
+
context.afterReview === 'summarizeSpecs',
|
|
1451
1727
|
target: '#summarizeSpecs',
|
|
1452
1728
|
actions: rememberCaptainOutput,
|
|
1453
1729
|
},
|
|
1454
1730
|
{
|
|
1455
1731
|
guard: ({ context, event }) =>
|
|
1456
|
-
outputOf(event)?.guard === 'committed' &&
|
|
1732
|
+
outputOf(event)?.guard === 'committed' &&
|
|
1733
|
+
context.afterReview === 'done',
|
|
1734
|
+
target: '#done',
|
|
1735
|
+
actions: rememberCaptainOutput,
|
|
1736
|
+
},
|
|
1737
|
+
{
|
|
1738
|
+
guard: guardIs('noRelevantChanges'),
|
|
1457
1739
|
target: '#done',
|
|
1458
1740
|
actions: rememberCaptainOutput,
|
|
1459
1741
|
},
|
|
1460
|
-
{
|
|
1461
|
-
|
|
1742
|
+
{
|
|
1743
|
+
guard: guardIs('needsBossInput'),
|
|
1744
|
+
target: '#ready',
|
|
1745
|
+
actions: rememberCaptainOutput,
|
|
1746
|
+
},
|
|
1462
1747
|
]),
|
|
1463
1748
|
onError: captainError,
|
|
1464
1749
|
},
|
|
@@ -1466,14 +1751,16 @@ export const codingMachine = setup({
|
|
|
1466
1751
|
|
|
1467
1752
|
failed: {
|
|
1468
1753
|
id: 'failed',
|
|
1469
|
-
description:
|
|
1470
|
-
|
|
1754
|
+
description: stateDescriptions.failed,
|
|
1755
|
+
meta: playbookMeta('failed'),
|
|
1756
|
+
tags: ['playbook.parked'],
|
|
1471
1757
|
on: readyEvents,
|
|
1472
1758
|
},
|
|
1473
1759
|
|
|
1474
1760
|
done: {
|
|
1475
1761
|
id: 'done',
|
|
1476
|
-
description:
|
|
1762
|
+
description: stateDescriptions.done,
|
|
1763
|
+
meta: playbookMeta('done'),
|
|
1477
1764
|
type: 'final',
|
|
1478
1765
|
},
|
|
1479
1766
|
},
|