@sublang/playbook 7.0.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -7
- package/docs/cli.md +88 -43
- package/docs/configuration.md +221 -119
- package/docs/embedding.md +78 -27
- package/package.json +4 -3
- package/reference/sdlc/captain.playbook/captain.playbook.js +16 -5
- package/reference/sdlc/captain.playbook/captain.playbook.ts +20 -6
- package/reference/sdlc/code.md +1 -1
- package/reference/sdlc/code.playbook/bin/interactive-session.js +816 -0
- package/reference/sdlc/code.playbook/bin/launch-config.js +1078 -116
- package/reference/sdlc/code.playbook/bin/playbook.js +489 -34
- package/reference/sdlc/code.playbook/bin/run.js +283 -298
- package/reference/sdlc/code.playbook/bin/session-store.js +818 -26
- package/reference/sdlc/code.playbook/code.fsm.d.ts +9 -6
- package/reference/sdlc/code.playbook/code.fsm.introspect.js +2 -2
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +2 -2
- package/reference/sdlc/code.playbook/code.fsm.js +18 -15
- package/reference/sdlc/code.playbook/code.fsm.ts +21 -21
- package/reference/sdlc/code.playbook/code.gears.md +1 -1
- package/reference/sdlc/code.playbook/code.playbook.d.ts +2 -1
- package/reference/sdlc/code.playbook/code.playbook.js +25 -15
- package/reference/sdlc/code.playbook/code.playbook.ts +34 -17
- package/reference/sdlc/code.playbook/code.registry.d.ts +5 -13
- package/reference/sdlc/code.playbook/code.registry.js +3 -10
- package/reference/sdlc/code.playbook/code.registry.ts +7 -32
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +39 -14
- package/reference/sdlc/code.playbook/playbook-captain.js +1014 -299
- package/reference/sdlc/code.playbook/playbook-captain.ts +1450 -406
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +41 -49
- package/reference/sdlc/decide.md +4 -4
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +10 -10
- package/reference/sdlc/decide.playbook/decide.fsm.js +21 -14
- package/reference/sdlc/decide.playbook/decide.fsm.ts +27 -23
- package/reference/sdlc/decide.playbook/decide.gears.md +3 -5
- package/reference/sdlc/decide.playbook/decide.playbook.d.ts +11 -13
- package/reference/sdlc/decide.playbook/decide.playbook.js +465 -246
- package/reference/sdlc/decide.playbook/decide.playbook.ts +623 -283
- package/reference/sdlc/decide.playbook/decide.registry.d.ts +5 -13
- package/reference/sdlc/decide.playbook/decide.registry.js +3 -9
- package/reference/sdlc/decide.playbook/decide.registry.ts +7 -31
- package/reference/sdlc/review.md +4 -5
- package/reference/sdlc/review.playbook/review.fsm.d.ts +9 -11
- package/reference/sdlc/review.playbook/review.fsm.js +30 -24
- package/reference/sdlc/review.playbook/review.fsm.ts +39 -35
- package/reference/sdlc/review.playbook/review.gears.md +6 -5
- package/reference/sdlc/review.playbook/review.playbook.d.ts +2 -1
- package/reference/sdlc/review.playbook/review.playbook.js +29 -23
- package/reference/sdlc/review.playbook/review.playbook.ts +38 -28
- package/reference/sdlc/review.playbook/review.registry.d.ts +5 -13
- package/reference/sdlc/review.playbook/review.registry.js +3 -16
- package/reference/sdlc/review.playbook/review.registry.ts +7 -38
- package/slc/gears2fsm.md +45 -24
- package/slc/link.md +297 -135
- package/slc/text2gears.md +19 -18
- package/src/runtime.d.ts +21 -16
- package/src/runtime.ts +20 -23
- package/src/xstate-playbook-runtime.d.ts +34 -20
- package/src/xstate-playbook-runtime.js +973 -400
- package/src/xstate-playbook-runtime.ts +1203 -457
- package/src/xstate-runtime.d.ts +17 -7
- package/src/xstate-runtime.js +198 -81
- package/src/xstate-runtime.ts +339 -112
|
@@ -8,18 +8,20 @@ export type PendingBossQuestion = {
|
|
|
8
8
|
readonly questionId: 'runFirstPhase' | 'runIrTask';
|
|
9
9
|
readonly resumeStateId: 'runFirstPhase' | 'runIrTask';
|
|
10
10
|
readonly sourceItem: 'CODE-1' | 'CODE-3';
|
|
11
|
-
readonly
|
|
11
|
+
readonly asker: {
|
|
12
|
+
readonly kind: 'role';
|
|
13
|
+
readonly roleId: 'coder';
|
|
14
|
+
};
|
|
12
15
|
readonly question: string;
|
|
13
16
|
};
|
|
14
17
|
export type PlayerInput = {
|
|
15
18
|
readonly stateId: 'runFirstPhase' | 'runIrTask';
|
|
16
|
-
readonly
|
|
19
|
+
readonly role: 'coder';
|
|
17
20
|
readonly sourceItem: 'CODE-1' | 'CODE-3';
|
|
18
21
|
readonly prompt: string;
|
|
19
22
|
readonly result: Readonly<Record<string, string>>;
|
|
20
23
|
readonly callerInput: string;
|
|
21
24
|
readonly runResults: string;
|
|
22
|
-
readonly coderPlayer: string;
|
|
23
25
|
readonly irNumber?: string;
|
|
24
26
|
readonly irTask?: string;
|
|
25
27
|
readonly pendingBossQuestion?: PendingBossQuestion;
|
|
@@ -77,11 +79,9 @@ export type CodePlaybookOutput = {
|
|
|
77
79
|
readonly error: CompactError;
|
|
78
80
|
};
|
|
79
81
|
export type CodingInput = {
|
|
80
|
-
readonly coderPlayer?: string;
|
|
81
82
|
readonly runResults?: string;
|
|
82
83
|
};
|
|
83
84
|
export type CodingContext = {
|
|
84
|
-
readonly coderPlayer: string;
|
|
85
85
|
readonly runResults: string;
|
|
86
86
|
readonly callerInput?: string;
|
|
87
87
|
readonly coderOutput?: string;
|
|
@@ -202,7 +202,7 @@ export declare const codingMachine: import("xstate").StateMachine<CodingContext,
|
|
|
202
202
|
} | {
|
|
203
203
|
type: "resumesIrTask";
|
|
204
204
|
params: unknown;
|
|
205
|
-
}, never, "done" | "failed" | "awaitBossReply" | "ready" | "runFirstPhase" | "reviewFirstCommit" | "runIrTask" | "reviewIrTask", string, CodingInput, {
|
|
205
|
+
}, never, "done" | "failed" | "awaitBossReply" | "ready" | "runFirstPhase" | "reviewFirstCommit" | "runIrTask" | "reviewIrTask" | "reportedReviewFailure", string, CodingInput, {
|
|
206
206
|
readonly status: "complete";
|
|
207
207
|
/** Exact identity of the latest CODE-owned commit. */
|
|
208
208
|
readonly lastCodeCommit: string;
|
|
@@ -239,6 +239,9 @@ export declare const codingMachine: import("xstate").StateMachine<CodingContext,
|
|
|
239
239
|
readonly failed: {
|
|
240
240
|
id: "failed";
|
|
241
241
|
};
|
|
242
|
+
readonly reportedReviewFailure: {
|
|
243
|
+
id: "reportedReviewFailure";
|
|
244
|
+
};
|
|
242
245
|
readonly done: {
|
|
243
246
|
id: "done";
|
|
244
247
|
};
|
|
@@ -27,7 +27,7 @@ export function enumeratePlayerStates(machine) {
|
|
|
27
27
|
if (invoke?.src !== 'player' || invoke.input === undefined)
|
|
28
28
|
return [];
|
|
29
29
|
const getInput = (context) => invoke.input?.({ context });
|
|
30
|
-
const input = getInput({
|
|
30
|
+
const input = getInput({ runResults: '' });
|
|
31
31
|
return [
|
|
32
32
|
{
|
|
33
33
|
stateId,
|
|
@@ -47,7 +47,7 @@ export function enumerateNestedPlaybookStates(machine) {
|
|
|
47
47
|
if (invoke?.src !== 'playbook' || invoke.input === undefined)
|
|
48
48
|
return [];
|
|
49
49
|
const getInput = (context) => invoke.input?.({ context });
|
|
50
|
-
const input = getInput({
|
|
50
|
+
const input = getInput({ runResults: '' });
|
|
51
51
|
return [
|
|
52
52
|
{
|
|
53
53
|
stateId,
|
|
@@ -92,7 +92,7 @@ export function enumeratePlayerStates(
|
|
|
92
92
|
if (invoke?.src !== 'player' || invoke.input === undefined) return [];
|
|
93
93
|
const getInput = (context: CodingContext): PlayerInput =>
|
|
94
94
|
invoke.input?.({ context }) as PlayerInput;
|
|
95
|
-
const input = getInput({
|
|
95
|
+
const input = getInput({ runResults: '' });
|
|
96
96
|
return [
|
|
97
97
|
{
|
|
98
98
|
stateId,
|
|
@@ -116,7 +116,7 @@ export function enumerateNestedPlaybookStates(
|
|
|
116
116
|
if (invoke?.src !== 'playbook' || invoke.input === undefined) return [];
|
|
117
117
|
const getInput = (context: CodingContext): PlaybookInput =>
|
|
118
118
|
invoke.input?.({ context }) as PlaybookInput;
|
|
119
|
-
const input = getInput({
|
|
119
|
+
const input = getInput({ runResults: '' });
|
|
120
120
|
return [
|
|
121
121
|
{
|
|
122
122
|
stateId,
|
|
@@ -53,14 +53,15 @@ const STATE_DESCRIPTIONS = {
|
|
|
53
53
|
reviewIrTask: 'The REVIEW playbook is checking the latest task commit.',
|
|
54
54
|
awaitBossReply: 'Waiting for Boss to answer Coder.',
|
|
55
55
|
failed: 'The coding workflow failed and is waiting for a new coding intent.',
|
|
56
|
+
reportedReviewFailure: 'The coding workflow reported a REVIEW failure and the last code-owned commit.',
|
|
56
57
|
done: 'The coding workflow completed after REVIEW found no unsettled findings.',
|
|
57
58
|
};
|
|
58
|
-
function playbookMeta(stateId,
|
|
59
|
+
function playbookMeta(stateId, role) {
|
|
59
60
|
return {
|
|
60
61
|
playbook: {
|
|
61
62
|
stateId,
|
|
62
63
|
description: STATE_DESCRIPTIONS[stateId],
|
|
63
|
-
...(
|
|
64
|
+
...(role === undefined ? {} : { role }),
|
|
64
65
|
},
|
|
65
66
|
};
|
|
66
67
|
}
|
|
@@ -324,7 +325,6 @@ const machineSetup = setup({
|
|
|
324
325
|
if (event.type !== 'START_CODE')
|
|
325
326
|
return {};
|
|
326
327
|
return {
|
|
327
|
-
coderPlayer: context.coderPlayer,
|
|
328
328
|
runResults: context.runResults,
|
|
329
329
|
callerInput: event.callerInput,
|
|
330
330
|
coderOutput: undefined,
|
|
@@ -389,7 +389,7 @@ const machineSetup = setup({
|
|
|
389
389
|
questionId: stateId,
|
|
390
390
|
resumeStateId: stateId,
|
|
391
391
|
sourceItem: stateId === 'runFirstPhase' ? 'CODE-1' : 'CODE-3',
|
|
392
|
-
|
|
392
|
+
asker: { kind: 'role', roleId: 'coder' },
|
|
393
393
|
question,
|
|
394
394
|
},
|
|
395
395
|
bossReply: undefined,
|
|
@@ -430,7 +430,6 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
430
430
|
id: 'code',
|
|
431
431
|
initial: 'ready',
|
|
432
432
|
context: ({ input }) => ({
|
|
433
|
-
coderPlayer: isNonEmptyString(input.coderPlayer) ? input.coderPlayer : 'Coder',
|
|
434
433
|
runResults: typeof input.runResults === 'string' ? input.runResults : '',
|
|
435
434
|
}),
|
|
436
435
|
output: ({ context }) => {
|
|
@@ -465,19 +464,18 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
465
464
|
runFirstPhase: {
|
|
466
465
|
id: 'runFirstPhase',
|
|
467
466
|
description: STATE_DESCRIPTIONS.runFirstPhase,
|
|
468
|
-
meta: playbookMeta('runFirstPhase', '
|
|
467
|
+
meta: playbookMeta('runFirstPhase', 'coder'),
|
|
469
468
|
tags: ['playbook.busy'],
|
|
470
469
|
invoke: {
|
|
471
470
|
src: 'player',
|
|
472
471
|
input: ({ context }) => ({
|
|
473
472
|
stateId: 'runFirstPhase',
|
|
474
|
-
|
|
473
|
+
role: 'coder',
|
|
475
474
|
sourceItem: 'CODE-1',
|
|
476
475
|
prompt: FIRST_PHASE_PROMPT,
|
|
477
476
|
result: FIRST_PHASE_RESULTS,
|
|
478
477
|
callerInput: context.callerInput ?? '',
|
|
479
478
|
runResults: context.runResults,
|
|
480
|
-
coderPlayer: context.coderPlayer,
|
|
481
479
|
...(context.pendingBossQuestion === undefined
|
|
482
480
|
? {}
|
|
483
481
|
: { pendingBossQuestion: context.pendingBossQuestion }),
|
|
@@ -533,14 +531,14 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
533
531
|
target: 'runIrTask',
|
|
534
532
|
},
|
|
535
533
|
{
|
|
536
|
-
target: '
|
|
534
|
+
target: 'reportedReviewFailure',
|
|
537
535
|
actions: 'completeWithInvalidReviewOutput',
|
|
538
536
|
},
|
|
539
537
|
],
|
|
540
538
|
onError: [
|
|
541
539
|
{
|
|
542
540
|
guard: 'authoredReviewFailure',
|
|
543
|
-
target: '
|
|
541
|
+
target: 'reportedReviewFailure',
|
|
544
542
|
actions: 'completeWithReviewFailure',
|
|
545
543
|
},
|
|
546
544
|
{ target: 'failed', actions: 'rememberActorError' },
|
|
@@ -550,19 +548,18 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
550
548
|
runIrTask: {
|
|
551
549
|
id: 'runIrTask',
|
|
552
550
|
description: STATE_DESCRIPTIONS.runIrTask,
|
|
553
|
-
meta: playbookMeta('runIrTask', '
|
|
551
|
+
meta: playbookMeta('runIrTask', 'coder'),
|
|
554
552
|
tags: ['playbook.busy'],
|
|
555
553
|
invoke: {
|
|
556
554
|
src: 'player',
|
|
557
555
|
input: ({ context }) => ({
|
|
558
556
|
stateId: 'runIrTask',
|
|
559
|
-
|
|
557
|
+
role: 'coder',
|
|
560
558
|
sourceItem: 'CODE-3',
|
|
561
559
|
prompt: IR_TASK_PROMPT,
|
|
562
560
|
result: IR_TASK_RESULTS,
|
|
563
561
|
callerInput: context.callerInput ?? '',
|
|
564
562
|
runResults: context.runResults,
|
|
565
|
-
coderPlayer: context.coderPlayer,
|
|
566
563
|
...(context.irNumber === undefined
|
|
567
564
|
? {}
|
|
568
565
|
: { irNumber: context.irNumber }),
|
|
@@ -623,14 +620,14 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
623
620
|
actions: 'completeSuccessfully',
|
|
624
621
|
},
|
|
625
622
|
{
|
|
626
|
-
target: '
|
|
623
|
+
target: 'reportedReviewFailure',
|
|
627
624
|
actions: 'completeWithInvalidReviewOutput',
|
|
628
625
|
},
|
|
629
626
|
],
|
|
630
627
|
onError: [
|
|
631
628
|
{
|
|
632
629
|
guard: 'authoredReviewFailure',
|
|
633
|
-
target: '
|
|
630
|
+
target: 'reportedReviewFailure',
|
|
634
631
|
actions: 'completeWithReviewFailure',
|
|
635
632
|
},
|
|
636
633
|
{ target: 'failed', actions: 'rememberActorError' },
|
|
@@ -674,6 +671,12 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
674
671
|
START_CODE: { target: 'runFirstPhase', actions: 'startCoding' },
|
|
675
672
|
},
|
|
676
673
|
},
|
|
674
|
+
reportedReviewFailure: {
|
|
675
|
+
id: 'reportedReviewFailure',
|
|
676
|
+
description: STATE_DESCRIPTIONS.reportedReviewFailure,
|
|
677
|
+
meta: playbookMeta('reportedReviewFailure'),
|
|
678
|
+
type: 'final',
|
|
679
|
+
},
|
|
677
680
|
done: {
|
|
678
681
|
id: 'done',
|
|
679
682
|
description: STATE_DESCRIPTIONS.done,
|
|
@@ -31,19 +31,18 @@ export type PendingBossQuestion = {
|
|
|
31
31
|
readonly questionId: 'runFirstPhase' | 'runIrTask';
|
|
32
32
|
readonly resumeStateId: 'runFirstPhase' | 'runIrTask';
|
|
33
33
|
readonly sourceItem: 'CODE-1' | 'CODE-3';
|
|
34
|
-
readonly
|
|
34
|
+
readonly asker: { readonly kind: 'role'; readonly roleId: 'coder' };
|
|
35
35
|
readonly question: string;
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
export type PlayerInput = {
|
|
39
39
|
readonly stateId: 'runFirstPhase' | 'runIrTask';
|
|
40
|
-
readonly
|
|
40
|
+
readonly role: 'coder';
|
|
41
41
|
readonly sourceItem: 'CODE-1' | 'CODE-3';
|
|
42
42
|
readonly prompt: string;
|
|
43
43
|
readonly result: Readonly<Record<string, string>>;
|
|
44
44
|
readonly callerInput: string;
|
|
45
45
|
readonly runResults: string;
|
|
46
|
-
readonly coderPlayer: string;
|
|
47
46
|
readonly irNumber?: string;
|
|
48
47
|
readonly irTask?: string;
|
|
49
48
|
readonly pendingBossQuestion?: PendingBossQuestion;
|
|
@@ -114,12 +113,10 @@ export type CodePlaybookOutput =
|
|
|
114
113
|
};
|
|
115
114
|
|
|
116
115
|
export type CodingInput = {
|
|
117
|
-
readonly coderPlayer?: string;
|
|
118
116
|
readonly runResults?: string;
|
|
119
117
|
};
|
|
120
118
|
|
|
121
119
|
export type CodingContext = {
|
|
122
|
-
readonly coderPlayer: string;
|
|
123
120
|
readonly runResults: string;
|
|
124
121
|
readonly callerInput?: string;
|
|
125
122
|
readonly coderOutput?: string;
|
|
@@ -205,18 +202,20 @@ const STATE_DESCRIPTIONS = {
|
|
|
205
202
|
reviewIrTask: 'The REVIEW playbook is checking the latest task commit.',
|
|
206
203
|
awaitBossReply: 'Waiting for Boss to answer Coder.',
|
|
207
204
|
failed: 'The coding workflow failed and is waiting for a new coding intent.',
|
|
205
|
+
reportedReviewFailure:
|
|
206
|
+
'The coding workflow reported a REVIEW failure and the last code-owned commit.',
|
|
208
207
|
done: 'The coding workflow completed after REVIEW found no unsettled findings.',
|
|
209
208
|
} as const;
|
|
210
209
|
|
|
211
210
|
function playbookMeta<StateId extends keyof typeof STATE_DESCRIPTIONS>(
|
|
212
211
|
stateId: StateId,
|
|
213
|
-
|
|
212
|
+
role?: 'coder',
|
|
214
213
|
) {
|
|
215
214
|
return {
|
|
216
215
|
playbook: {
|
|
217
216
|
stateId,
|
|
218
217
|
description: STATE_DESCRIPTIONS[stateId],
|
|
219
|
-
...(
|
|
218
|
+
...(role === undefined ? {} : { role }),
|
|
220
219
|
},
|
|
221
220
|
};
|
|
222
221
|
}
|
|
@@ -557,7 +556,6 @@ const machineSetup = setup({
|
|
|
557
556
|
startCoding: assign(({ context, event }) => {
|
|
558
557
|
if (event.type !== 'START_CODE') return {};
|
|
559
558
|
return {
|
|
560
|
-
coderPlayer: context.coderPlayer,
|
|
561
559
|
runResults: context.runResults,
|
|
562
560
|
callerInput: event.callerInput,
|
|
563
561
|
coderOutput: undefined,
|
|
@@ -623,7 +621,7 @@ const machineSetup = setup({
|
|
|
623
621
|
questionId: stateId,
|
|
624
622
|
resumeStateId: stateId,
|
|
625
623
|
sourceItem: stateId === 'runFirstPhase' ? 'CODE-1' : 'CODE-3',
|
|
626
|
-
|
|
624
|
+
asker: { kind: 'role', roleId: 'coder' },
|
|
627
625
|
question,
|
|
628
626
|
},
|
|
629
627
|
bossReply: undefined,
|
|
@@ -670,8 +668,6 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
670
668
|
id: 'code',
|
|
671
669
|
initial: 'ready',
|
|
672
670
|
context: ({ input }) => ({
|
|
673
|
-
coderPlayer:
|
|
674
|
-
isNonEmptyString(input.coderPlayer) ? input.coderPlayer : 'Coder',
|
|
675
671
|
runResults: typeof input.runResults === 'string' ? input.runResults : '',
|
|
676
672
|
}),
|
|
677
673
|
output: ({ context }): CodePlaybookOutput => {
|
|
@@ -707,19 +703,18 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
707
703
|
runFirstPhase: {
|
|
708
704
|
id: 'runFirstPhase',
|
|
709
705
|
description: STATE_DESCRIPTIONS.runFirstPhase,
|
|
710
|
-
meta: playbookMeta('runFirstPhase', '
|
|
706
|
+
meta: playbookMeta('runFirstPhase', 'coder'),
|
|
711
707
|
tags: ['playbook.busy'],
|
|
712
708
|
invoke: {
|
|
713
709
|
src: 'player',
|
|
714
710
|
input: ({ context }): PlayerInput => ({
|
|
715
711
|
stateId: 'runFirstPhase',
|
|
716
|
-
|
|
712
|
+
role: 'coder',
|
|
717
713
|
sourceItem: 'CODE-1',
|
|
718
714
|
prompt: FIRST_PHASE_PROMPT,
|
|
719
715
|
result: FIRST_PHASE_RESULTS,
|
|
720
716
|
callerInput: context.callerInput ?? '',
|
|
721
717
|
runResults: context.runResults,
|
|
722
|
-
coderPlayer: context.coderPlayer,
|
|
723
718
|
...(context.pendingBossQuestion === undefined
|
|
724
719
|
? {}
|
|
725
720
|
: { pendingBossQuestion: context.pendingBossQuestion }),
|
|
@@ -775,14 +770,14 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
775
770
|
target: 'runIrTask',
|
|
776
771
|
},
|
|
777
772
|
{
|
|
778
|
-
target: '
|
|
773
|
+
target: 'reportedReviewFailure',
|
|
779
774
|
actions: 'completeWithInvalidReviewOutput',
|
|
780
775
|
},
|
|
781
776
|
],
|
|
782
777
|
onError: [
|
|
783
778
|
{
|
|
784
779
|
guard: 'authoredReviewFailure',
|
|
785
|
-
target: '
|
|
780
|
+
target: 'reportedReviewFailure',
|
|
786
781
|
actions: 'completeWithReviewFailure',
|
|
787
782
|
},
|
|
788
783
|
{ target: 'failed', actions: 'rememberActorError' },
|
|
@@ -792,19 +787,18 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
792
787
|
runIrTask: {
|
|
793
788
|
id: 'runIrTask',
|
|
794
789
|
description: STATE_DESCRIPTIONS.runIrTask,
|
|
795
|
-
meta: playbookMeta('runIrTask', '
|
|
790
|
+
meta: playbookMeta('runIrTask', 'coder'),
|
|
796
791
|
tags: ['playbook.busy'],
|
|
797
792
|
invoke: {
|
|
798
793
|
src: 'player',
|
|
799
794
|
input: ({ context }): PlayerInput => ({
|
|
800
795
|
stateId: 'runIrTask',
|
|
801
|
-
|
|
796
|
+
role: 'coder',
|
|
802
797
|
sourceItem: 'CODE-3',
|
|
803
798
|
prompt: IR_TASK_PROMPT,
|
|
804
799
|
result: IR_TASK_RESULTS,
|
|
805
800
|
callerInput: context.callerInput ?? '',
|
|
806
801
|
runResults: context.runResults,
|
|
807
|
-
coderPlayer: context.coderPlayer,
|
|
808
802
|
...(context.irNumber === undefined
|
|
809
803
|
? {}
|
|
810
804
|
: { irNumber: context.irNumber }),
|
|
@@ -865,14 +859,14 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
865
859
|
actions: 'completeSuccessfully',
|
|
866
860
|
},
|
|
867
861
|
{
|
|
868
|
-
target: '
|
|
862
|
+
target: 'reportedReviewFailure',
|
|
869
863
|
actions: 'completeWithInvalidReviewOutput',
|
|
870
864
|
},
|
|
871
865
|
],
|
|
872
866
|
onError: [
|
|
873
867
|
{
|
|
874
868
|
guard: 'authoredReviewFailure',
|
|
875
|
-
target: '
|
|
869
|
+
target: 'reportedReviewFailure',
|
|
876
870
|
actions: 'completeWithReviewFailure',
|
|
877
871
|
},
|
|
878
872
|
{ target: 'failed', actions: 'rememberActorError' },
|
|
@@ -916,6 +910,12 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
916
910
|
START_CODE: { target: 'runFirstPhase', actions: 'startCoding' },
|
|
917
911
|
},
|
|
918
912
|
},
|
|
913
|
+
reportedReviewFailure: {
|
|
914
|
+
id: 'reportedReviewFailure',
|
|
915
|
+
description: STATE_DESCRIPTIONS.reportedReviewFailure,
|
|
916
|
+
meta: playbookMeta('reportedReviewFailure'),
|
|
917
|
+
type: 'final',
|
|
918
|
+
},
|
|
919
919
|
done: {
|
|
920
920
|
id: 'done',
|
|
921
921
|
description: STATE_DESCRIPTIONS.done,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type XStatePromptIdentity } from '@sublang/playbook/xstate-runtime';
|
|
1
2
|
import { type CodingInput, type PlayerInput } from './code.fsm.js';
|
|
2
3
|
import type { CaptainCallOptions, CaptainResult, JsonValue, NormalizedError, PlayerCallOptions, PlaybookCallRequest, PlaybookCallResult, PlaybookCallStart, PlaybookControlReceipt, PlaybookControlView, PlaybookPendingCall, PlaybookPorts, PlaybookRunResult, PlaybookRuntime, PlaybookRuntimeFactory, PlaybookRuntimeSnapshot, PlaybookSession, PlaybookState, PlaybookStateValue, PlaybookTraceEvent, PlaybookTraceType, PlayerResult, PlayerSessionStore } from '@sublang/playbook/runtime';
|
|
3
4
|
export type { CaptainCallOptions, CaptainResult, JsonValue, NormalizedError, PlayerCallOptions, PlaybookCallRequest, PlaybookCallResult, PlaybookCallStart, PlaybookControlReceipt, PlaybookControlView, PlaybookPendingCall, PlaybookPorts, PlaybookRunResult, PlaybookRuntime, PlaybookRuntimeFactory, PlaybookRuntimeSnapshot, PlaybookSession, PlaybookState, PlaybookStateValue, PlaybookTraceEvent, PlaybookTraceType, PlayerResult, PlayerSessionStore, };
|
|
@@ -7,7 +8,7 @@ export type CodePlaybookOptions = CodingInput;
|
|
|
7
8
|
* runtime text. The generic composer preserves the marker itself; CODE's
|
|
8
9
|
* override additionally keeps a multiline value inside that quote.
|
|
9
10
|
*/
|
|
10
|
-
declare function composePlayerPrompt(input: PlayerInput): string;
|
|
11
|
+
declare function composePlayerPrompt(input: PlayerInput, promptIdentity: XStatePromptIdentity): string;
|
|
11
12
|
export declare const _internal: {
|
|
12
13
|
composePlayerPrompt: typeof composePlayerPrompt;
|
|
13
14
|
VERBATIM_PAYLOAD_FIELDS: ReadonlySet<string>;
|
|
@@ -3,15 +3,15 @@
|
|
|
3
3
|
//
|
|
4
4
|
// Generated by slc/link.md (FSM-to-Runtime linker).
|
|
5
5
|
// Source FSM: ./code.fsm.ts
|
|
6
|
-
//
|
|
6
|
+
// Role metadata: Coder→coder (canonical local role)
|
|
7
7
|
// Boss event: deterministic START_CODE entry; exact Boss text becomes
|
|
8
8
|
// callerInput; pending Coder questions retain BOSS_REPLY
|
|
9
9
|
// Adjudication: LLM judge per player state; coderOutput is carried verbatim
|
|
10
10
|
// Nested call: literal review target through the shared bridge
|
|
11
|
-
// Compat: artifact schema
|
|
12
|
-
import {
|
|
11
|
+
// Compat: artifact schema 2 / runtime ABI 1
|
|
12
|
+
import { createXStatePlaybookRuntime, snapshotJsonValue, } from '@sublang/playbook/xstate-runtime';
|
|
13
13
|
import { codingMachine, } from './code.fsm.js';
|
|
14
|
-
const OPTION_KEYS = new Set(['
|
|
14
|
+
const OPTION_KEYS = new Set(['runResults']);
|
|
15
15
|
const PLACEHOLDER = /<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>/g;
|
|
16
16
|
const CONTINUATION_PREAMBLE = 'You previously paused this task to ask Boss a question; Boss has now replied. Continue the same task using the reply below.';
|
|
17
17
|
const VERBATIM_PAYLOAD_FIELDS = new Set([
|
|
@@ -38,8 +38,6 @@ function snapshotCodeOptions(value) {
|
|
|
38
38
|
function placeholderField(token) {
|
|
39
39
|
if (token === '#')
|
|
40
40
|
return 'irNumber';
|
|
41
|
-
if (token === 'coder-llm')
|
|
42
|
-
return 'coderPlayer';
|
|
43
41
|
return token.replace(/-([A-Za-z0-9_$])/g, (_match, next) => next.toUpperCase());
|
|
44
42
|
}
|
|
45
43
|
function quoteContinuation(value) {
|
|
@@ -50,14 +48,16 @@ function quoteContinuation(value) {
|
|
|
50
48
|
* runtime text. The generic composer preserves the marker itself; CODE's
|
|
51
49
|
* override additionally keeps a multiline value inside that quote.
|
|
52
50
|
*/
|
|
53
|
-
function composePlayerPrompt(input) {
|
|
51
|
+
function composePlayerPrompt(input, promptIdentity) {
|
|
54
52
|
const fields = input;
|
|
55
53
|
const template = input.prompt
|
|
56
54
|
.split('\n')
|
|
57
55
|
.filter((line) => !(line === '> <run-results>' && input.runResults.length === 0))
|
|
58
56
|
.join('\n');
|
|
59
57
|
const body = template.replace(PLACEHOLDER, (match, token, offset, source) => {
|
|
60
|
-
const value =
|
|
58
|
+
const value = token === 'coder-llm'
|
|
59
|
+
? promptIdentity('coder')
|
|
60
|
+
: fields[placeholderField(token)];
|
|
61
61
|
if (typeof value !== 'string')
|
|
62
62
|
return match;
|
|
63
63
|
const lineStart = source.lastIndexOf('\n', offset - 1) + 1;
|
|
@@ -81,21 +81,31 @@ export const _internal = {
|
|
|
81
81
|
};
|
|
82
82
|
const runtimeSpec = {
|
|
83
83
|
label: 'CODE',
|
|
84
|
-
|
|
84
|
+
// DR-022 / slc/link.md: the declaration carries the value current at link
|
|
85
|
+
// time — a literal, never the loading engine's RUNTIME_ABI self-report,
|
|
86
|
+
// which would follow whatever engine loads the module and make the
|
|
87
|
+
// factory's skew check compare that engine with itself.
|
|
88
|
+
compat: { artifactSchema: 2, runtimeAbi: 1 },
|
|
85
89
|
snapshotOptions: snapshotCodeOptions,
|
|
86
|
-
entryEvent: {
|
|
87
|
-
|
|
90
|
+
entryEvent: {
|
|
91
|
+
type: 'START_CODE',
|
|
92
|
+
textField: 'callerInput',
|
|
93
|
+
// `startCoding` copies the entry text here, so the failure-state retry
|
|
94
|
+
// reads it back from the persisted machine snapshot and survives a
|
|
95
|
+
// continued session (DR-034).
|
|
96
|
+
contextField: 'callerInput',
|
|
97
|
+
},
|
|
98
|
+
roleStates: {
|
|
88
99
|
runFirstPhase: {
|
|
89
|
-
|
|
100
|
+
role: 'coder',
|
|
90
101
|
label: 'Coder is implementing one direct phase or committing a new intent record.',
|
|
91
102
|
},
|
|
92
103
|
runIrTask: {
|
|
93
|
-
|
|
104
|
+
role: 'coder',
|
|
94
105
|
label: 'Coder is implementing exactly one unfinished intent-record task.',
|
|
95
106
|
},
|
|
96
107
|
},
|
|
97
|
-
|
|
98
|
-
composePlayerPrompt: (input) => composePlayerPrompt(input),
|
|
108
|
+
composePlayerPrompt: (input, promptIdentity) => composePlayerPrompt(input, promptIdentity),
|
|
99
109
|
verbatimPayloadFields: VERBATIM_PAYLOAD_FIELDS,
|
|
100
110
|
controlContextFields: ['phase'],
|
|
101
111
|
transitionEventFields: ['callerInput', 'answer', 'questionId'],
|
|
@@ -3,18 +3,18 @@
|
|
|
3
3
|
//
|
|
4
4
|
// Generated by slc/link.md (FSM-to-Runtime linker).
|
|
5
5
|
// Source FSM: ./code.fsm.ts
|
|
6
|
-
//
|
|
6
|
+
// Role metadata: Coder→coder (canonical local role)
|
|
7
7
|
// Boss event: deterministic START_CODE entry; exact Boss text becomes
|
|
8
8
|
// callerInput; pending Coder questions retain BOSS_REPLY
|
|
9
9
|
// Adjudication: LLM judge per player state; coderOutput is carried verbatim
|
|
10
10
|
// Nested call: literal review target through the shared bridge
|
|
11
|
-
// Compat: artifact schema
|
|
11
|
+
// Compat: artifact schema 2 / runtime ABI 1
|
|
12
12
|
|
|
13
13
|
import {
|
|
14
|
-
RUNTIME_ABI,
|
|
15
14
|
createXStatePlaybookRuntime,
|
|
16
15
|
snapshotJsonValue,
|
|
17
16
|
type PlaybookPlayerInput,
|
|
17
|
+
type XStatePromptIdentity,
|
|
18
18
|
type XStatePlaybookRuntimeSpec,
|
|
19
19
|
} from '@sublang/playbook/xstate-runtime';
|
|
20
20
|
import {
|
|
@@ -76,7 +76,7 @@ export type {
|
|
|
76
76
|
|
|
77
77
|
export type CodePlaybookOptions = CodingInput;
|
|
78
78
|
|
|
79
|
-
const OPTION_KEYS = new Set(['
|
|
79
|
+
const OPTION_KEYS = new Set(['runResults']);
|
|
80
80
|
const PLACEHOLDER = /<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>/g;
|
|
81
81
|
const CONTINUATION_PREAMBLE =
|
|
82
82
|
'You previously paused this task to ask Boss a question; Boss has now replied. Continue the same task using the reply below.';
|
|
@@ -108,7 +108,6 @@ function snapshotCodeOptions(value: unknown): CodePlaybookOptions {
|
|
|
108
108
|
|
|
109
109
|
function placeholderField(token: string): string {
|
|
110
110
|
if (token === '#') return 'irNumber';
|
|
111
|
-
if (token === 'coder-llm') return 'coderPlayer';
|
|
112
111
|
return token.replace(/-([A-Za-z0-9_$])/g, (_match, next: string) =>
|
|
113
112
|
next.toUpperCase(),
|
|
114
113
|
);
|
|
@@ -123,7 +122,10 @@ function quoteContinuation(value: string): string {
|
|
|
123
122
|
* runtime text. The generic composer preserves the marker itself; CODE's
|
|
124
123
|
* override additionally keeps a multiline value inside that quote.
|
|
125
124
|
*/
|
|
126
|
-
function composePlayerPrompt(
|
|
125
|
+
function composePlayerPrompt(
|
|
126
|
+
input: PlayerInput,
|
|
127
|
+
promptIdentity: XStatePromptIdentity,
|
|
128
|
+
): string {
|
|
127
129
|
const fields = input as unknown as Record<string, unknown>;
|
|
128
130
|
const template = input.prompt
|
|
129
131
|
.split('\n')
|
|
@@ -134,7 +136,10 @@ function composePlayerPrompt(input: PlayerInput): string {
|
|
|
134
136
|
const body = template.replace(
|
|
135
137
|
PLACEHOLDER,
|
|
136
138
|
(match: string, token: string, offset: number, source: string) => {
|
|
137
|
-
const value =
|
|
139
|
+
const value =
|
|
140
|
+
token === 'coder-llm'
|
|
141
|
+
? promptIdentity('coder')
|
|
142
|
+
: fields[placeholderField(token)];
|
|
138
143
|
if (typeof value !== 'string') return match;
|
|
139
144
|
const lineStart = source.lastIndexOf('\n', offset - 1) + 1;
|
|
140
145
|
const literal = source.slice(lineStart, offset);
|
|
@@ -160,29 +165,41 @@ export const _internal = {
|
|
|
160
165
|
VERBATIM_PAYLOAD_FIELDS,
|
|
161
166
|
};
|
|
162
167
|
|
|
163
|
-
const runtimeSpec
|
|
168
|
+
const runtimeSpec = {
|
|
164
169
|
label: 'CODE',
|
|
165
|
-
|
|
170
|
+
// DR-022 / slc/link.md: the declaration carries the value current at link
|
|
171
|
+
// time — a literal, never the loading engine's RUNTIME_ABI self-report,
|
|
172
|
+
// which would follow whatever engine loads the module and make the
|
|
173
|
+
// factory's skew check compare that engine with itself.
|
|
174
|
+
compat: { artifactSchema: 2, runtimeAbi: 1 },
|
|
166
175
|
snapshotOptions: snapshotCodeOptions,
|
|
167
|
-
entryEvent: {
|
|
168
|
-
|
|
176
|
+
entryEvent: {
|
|
177
|
+
type: 'START_CODE',
|
|
178
|
+
textField: 'callerInput',
|
|
179
|
+
// `startCoding` copies the entry text here, so the failure-state retry
|
|
180
|
+
// reads it back from the persisted machine snapshot and survives a
|
|
181
|
+
// continued session (DR-034).
|
|
182
|
+
contextField: 'callerInput',
|
|
183
|
+
},
|
|
184
|
+
roleStates: {
|
|
169
185
|
runFirstPhase: {
|
|
170
|
-
|
|
186
|
+
role: 'coder',
|
|
171
187
|
label:
|
|
172
188
|
'Coder is implementing one direct phase or committing a new intent record.',
|
|
173
189
|
},
|
|
174
190
|
runIrTask: {
|
|
175
|
-
|
|
191
|
+
role: 'coder',
|
|
176
192
|
label: 'Coder is implementing exactly one unfinished intent-record task.',
|
|
177
193
|
},
|
|
178
194
|
},
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
195
|
+
composePlayerPrompt: (
|
|
196
|
+
input: PlaybookPlayerInput,
|
|
197
|
+
promptIdentity: XStatePromptIdentity,
|
|
198
|
+
) => composePlayerPrompt(input as PlayerInput, promptIdentity),
|
|
182
199
|
verbatimPayloadFields: VERBATIM_PAYLOAD_FIELDS,
|
|
183
200
|
controlContextFields: ['phase'],
|
|
184
201
|
transitionEventFields: ['callerInput', 'answer', 'questionId'],
|
|
185
|
-
}
|
|
202
|
+
} satisfies XStatePlaybookRuntimeSpec<CodePlaybookOptions>;
|
|
186
203
|
|
|
187
204
|
const createPlaybookRuntime: PlaybookRuntimeFactory<CodePlaybookOptions> =
|
|
188
205
|
createXStatePlaybookRuntime(codingMachine, runtimeSpec);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type PlaybookRuntime } from './code.playbook.js';
|
|
2
2
|
export interface PlaybookSummaryPolicy {
|
|
3
3
|
stateCountLabels: Readonly<Record<string, string>>;
|
|
4
4
|
copyPasteGuardNames: readonly string[];
|
|
@@ -7,24 +7,17 @@ export interface PlaybookSummaryPolicy {
|
|
|
7
7
|
copyPastes: number;
|
|
8
8
|
}, rounds: number): string;
|
|
9
9
|
}
|
|
10
|
-
export interface RegistryPlayer {
|
|
11
|
-
id: string;
|
|
12
|
-
adapter?: string;
|
|
13
|
-
model?: string;
|
|
14
|
-
}
|
|
15
|
-
export interface CreateCodeRuntimeOptions {
|
|
16
|
-
captainOptions: unknown;
|
|
17
|
-
players: readonly RegistryPlayer[];
|
|
18
|
-
}
|
|
19
10
|
export type CodeOptions = Readonly<Record<string, never>>;
|
|
20
11
|
export interface CodePlaybookRegistryEntry {
|
|
21
12
|
id: 'code';
|
|
22
13
|
command: 'code';
|
|
23
14
|
intent: string;
|
|
15
|
+
artifactSchema: 2;
|
|
24
16
|
requiredRoleIds: readonly ['coder'];
|
|
17
|
+
concurrentRoleSets: readonly [];
|
|
25
18
|
summaryPolicy: PlaybookSummaryPolicy;
|
|
26
|
-
validateOptions(
|
|
27
|
-
createRuntime(options:
|
|
19
|
+
validateOptions(optionSlice: unknown): CodeOptions;
|
|
20
|
+
createRuntime(options: CodeOptions): PlaybookRuntime;
|
|
28
21
|
}
|
|
29
22
|
export declare const codeStateCountLabels: {};
|
|
30
23
|
export declare const codeCopyPasteGuardNames: readonly ["directCommit", "irCommit", "moreTasks", "finalTask"];
|
|
@@ -34,6 +27,5 @@ export declare function codeSavedCountsLine(counts: {
|
|
|
34
27
|
}, rounds: number): string;
|
|
35
28
|
export declare const codeSummaryPolicy: PlaybookSummaryPolicy;
|
|
36
29
|
export declare function validateCodeOptions(optionSlice: unknown): CodeOptions;
|
|
37
|
-
export declare function createCodeRuntimeOptions({ captainOptions, players, }: CreateCodeRuntimeOptions): CodePlaybookOptions;
|
|
38
30
|
export declare const codePlaybookRegistryEntry: CodePlaybookRegistryEntry;
|
|
39
31
|
export default codePlaybookRegistryEntry;
|