@sublang/playbook 10.0.0 → 12.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 +1 -1
- package/docs/cli.md +67 -19
- package/docs/configuration.md +103 -40
- package/docs/embedding.md +88 -0
- package/package.json +30 -4
- package/reference/sdlc/code.md +35 -15
- package/reference/sdlc/code.playbook/bin/interactive-session.js +58 -6
- package/reference/sdlc/code.playbook/bin/launch-config.js +499 -241
- package/reference/sdlc/code.playbook/bin/playbook.js +236 -187
- package/reference/sdlc/code.playbook/bin/replay-observer.js +221 -0
- package/reference/sdlc/code.playbook/bin/run.js +355 -203
- package/reference/sdlc/code.playbook/bin/session-store.js +1512 -136
- package/reference/sdlc/code.playbook/code.fsm.d.ts +22 -19
- package/reference/sdlc/code.playbook/code.fsm.js +116 -52
- package/reference/sdlc/code.playbook/code.fsm.ts +149 -64
- package/reference/sdlc/code.playbook/code.gears.md +40 -20
- package/reference/sdlc/code.playbook/code.playbook.js +23 -2
- package/reference/sdlc/code.playbook/code.playbook.ts +23 -2
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +4 -1
- package/reference/sdlc/code.playbook/playbook-captain.js +21 -3
- package/reference/sdlc/code.playbook/playbook-captain.ts +42 -6
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +31 -11
- package/reference/sdlc/code.playbook/session-store.d.ts +82 -0
- package/reference/sdlc/code.playbook/session-store.js +113 -0
- package/reference/sdlc/decide.md +24 -15
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +13 -6
- package/reference/sdlc/decide.playbook/decide.fsm.js +54 -27
- package/reference/sdlc/decide.playbook/decide.fsm.ts +68 -29
- package/reference/sdlc/decide.playbook/decide.gears.md +25 -19
- package/reference/sdlc/decide.playbook/decide.playbook.js +11 -3
- package/reference/sdlc/decide.playbook/decide.playbook.ts +11 -3
- package/reference/sdlc/decide.playbook/decide.registry.js +1 -1
- package/reference/sdlc/decide.playbook/decide.registry.ts +1 -1
- package/reference/sdlc/dev.md +52 -0
- package/reference/sdlc/dev.playbook/dev.fsm.d.ts +261 -0
- package/reference/sdlc/dev.playbook/dev.fsm.js +723 -0
- package/reference/sdlc/dev.playbook/dev.fsm.ts +988 -0
- package/reference/sdlc/dev.playbook/dev.gears.md +91 -0
- package/reference/sdlc/dev.playbook/dev.playbook.d.ts +21 -0
- package/reference/sdlc/dev.playbook/dev.playbook.js +143 -0
- package/reference/sdlc/dev.playbook/dev.playbook.ts +246 -0
- package/reference/sdlc/dev.playbook/dev.registry.d.ts +40 -0
- package/reference/sdlc/dev.playbook/dev.registry.js +64 -0
- package/reference/sdlc/dev.playbook/dev.registry.ts +120 -0
- package/reference/sdlc/review.md +36 -18
- package/reference/sdlc/review.playbook/review.fsm.d.ts +15 -2
- package/reference/sdlc/review.playbook/review.fsm.js +77 -27
- package/reference/sdlc/review.playbook/review.fsm.ts +96 -30
- package/reference/sdlc/review.playbook/review.gears.md +52 -26
- package/reference/sdlc/review.playbook/review.playbook.js +17 -7
- package/reference/sdlc/review.playbook/review.playbook.ts +17 -7
- package/reference/sdlc/review.playbook/review.registry.js +1 -1
- package/reference/sdlc/review.playbook/review.registry.ts +1 -1
- package/slc/link.md +12 -5
- package/slc/text2gears.md +3 -0
- package/src/xstate-playbook-runtime.js +5 -2
- package/src/xstate-playbook-runtime.ts +5 -2
- package/src/xstate-runtime.js +13 -1
- package/src/xstate-runtime.ts +13 -1
|
@@ -23,7 +23,6 @@ export type PlayerInput = {
|
|
|
23
23
|
readonly callerInput: string;
|
|
24
24
|
readonly runResults: string;
|
|
25
25
|
readonly irNumber?: string;
|
|
26
|
-
readonly irTask?: string;
|
|
27
26
|
readonly pendingBossQuestion?: PendingBossQuestion;
|
|
28
27
|
readonly bossReply?: string;
|
|
29
28
|
};
|
|
@@ -36,16 +35,18 @@ export type PlayerOutput = {
|
|
|
36
35
|
readonly coderOutput: string;
|
|
37
36
|
readonly latestCommit: string;
|
|
38
37
|
readonly irNumber: string;
|
|
39
|
-
readonly irTask: string;
|
|
40
38
|
} | {
|
|
41
39
|
readonly guard: 'moreTasks';
|
|
42
40
|
readonly coderOutput: string;
|
|
43
41
|
readonly latestCommit: string;
|
|
42
|
+
readonly irNumber: string;
|
|
44
43
|
readonly irTask: string;
|
|
45
44
|
} | {
|
|
46
45
|
readonly guard: 'finalTask';
|
|
47
46
|
readonly coderOutput: string;
|
|
48
47
|
readonly latestCommit: string;
|
|
48
|
+
readonly irNumber: string;
|
|
49
|
+
readonly irTask: string;
|
|
49
50
|
} | {
|
|
50
51
|
readonly guard: 'needsBossReply';
|
|
51
52
|
readonly question: string;
|
|
@@ -57,8 +58,13 @@ export type PlaybookInput = {
|
|
|
57
58
|
readonly text: string;
|
|
58
59
|
};
|
|
59
60
|
export type ReviewOutput = {
|
|
60
|
-
readonly approvedCommit: 'latest';
|
|
61
61
|
readonly noUnsettledFindings: true;
|
|
62
|
+
/**
|
|
63
|
+
* Exact repository revision at which the review scope was evaluated:
|
|
64
|
+
* the last review-fix commit when one landed, otherwise the clean
|
|
65
|
+
* round's receipt-observed HEAD (DR-045). Always present.
|
|
66
|
+
*/
|
|
67
|
+
readonly evaluatedRevision: string;
|
|
62
68
|
};
|
|
63
69
|
export type CompactError = {
|
|
64
70
|
readonly name: string;
|
|
@@ -66,16 +72,16 @@ export type CompactError = {
|
|
|
66
72
|
};
|
|
67
73
|
export type CodePlaybookOutput = {
|
|
68
74
|
readonly status: 'complete';
|
|
69
|
-
/** Exact identity of the
|
|
75
|
+
/** Exact identity of the last CODE-owned commit. */
|
|
70
76
|
readonly lastCodeCommit: string;
|
|
71
|
-
/** Exact
|
|
72
|
-
readonly
|
|
77
|
+
/** Exact repository revision the final passing review evaluated. */
|
|
78
|
+
readonly finalEvaluatedRevision: string;
|
|
79
|
+
/** Every phase's review passed with no unsettled findings. */
|
|
80
|
+
readonly allReviewsPassed: true;
|
|
73
81
|
} | {
|
|
74
82
|
readonly status: 'review-failed';
|
|
75
|
-
/** Exact identity of the
|
|
83
|
+
/** Exact identity of the last CODE-owned commit. */
|
|
76
84
|
readonly lastCodeCommit: string;
|
|
77
|
-
/** Exact Coder final text produced after that commit. */
|
|
78
|
-
readonly lastCodeOutput: string;
|
|
79
85
|
readonly error: CompactError;
|
|
80
86
|
};
|
|
81
87
|
export type CodingInput = {
|
|
@@ -88,7 +94,7 @@ export type CodingContext = {
|
|
|
88
94
|
readonly latestCommit?: string;
|
|
89
95
|
readonly irNumber?: string;
|
|
90
96
|
readonly irTask?: string;
|
|
91
|
-
readonly
|
|
97
|
+
readonly evaluatedRevision?: string;
|
|
92
98
|
readonly phase?: CodePhase;
|
|
93
99
|
readonly completion?: 'complete' | 'review-failed';
|
|
94
100
|
readonly reviewError?: CompactError;
|
|
@@ -146,9 +152,6 @@ export declare const codingMachine: import("xstate").StateMachine<CodingContext,
|
|
|
146
152
|
} | {
|
|
147
153
|
type: "rememberFinalTask";
|
|
148
154
|
params: import("xstate").NonReducibleUnknown;
|
|
149
|
-
} | {
|
|
150
|
-
type: "advanceToNextIrTask";
|
|
151
|
-
params: import("xstate").NonReducibleUnknown;
|
|
152
155
|
} | {
|
|
153
156
|
type: "rememberPendingQuestion";
|
|
154
157
|
params: import("xstate").NonReducibleUnknown;
|
|
@@ -211,16 +214,16 @@ export declare const codingMachine: import("xstate").StateMachine<CodingContext,
|
|
|
211
214
|
params: unknown;
|
|
212
215
|
}, never, "done" | "failed" | "awaitBossReply" | "ready" | "runFirstPhase" | "reviewFirstCommit" | "runIrTask" | "reviewIrTask" | "reportedReviewFailure", string, CodingInput, {
|
|
213
216
|
readonly status: "complete";
|
|
214
|
-
/** Exact identity of the
|
|
217
|
+
/** Exact identity of the last CODE-owned commit. */
|
|
215
218
|
readonly lastCodeCommit: string;
|
|
216
|
-
/** Exact
|
|
217
|
-
readonly
|
|
219
|
+
/** Exact repository revision the final passing review evaluated. */
|
|
220
|
+
readonly finalEvaluatedRevision: string;
|
|
221
|
+
/** Every phase's review passed with no unsettled findings. */
|
|
222
|
+
readonly allReviewsPassed: true;
|
|
218
223
|
} | {
|
|
219
224
|
readonly status: "review-failed";
|
|
220
|
-
/** Exact identity of the
|
|
225
|
+
/** Exact identity of the last CODE-owned commit. */
|
|
221
226
|
readonly lastCodeCommit: string;
|
|
222
|
-
/** Exact Coder final text produced after that commit. */
|
|
223
|
-
readonly lastCodeOutput: string;
|
|
224
227
|
readonly error: CompactError;
|
|
225
228
|
}, import("xstate").EventObject, import("xstate").MetaObject, {
|
|
226
229
|
id: "code";
|
|
@@ -3,56 +3,70 @@
|
|
|
3
3
|
//
|
|
4
4
|
// Generated by slc/gears2fsm.md from ./code.gears.md.
|
|
5
5
|
import { assign, fromPromise, setup } from 'xstate';
|
|
6
|
+
const APPENDED_PHASE_PROMPT = [
|
|
7
|
+
'Keep to the original intent and follow what it asks.',
|
|
8
|
+
'Do not re-run tests or builds whose inputs have not changed since any previous reported run.',
|
|
9
|
+
"Make the phase's minimal changes and then one new commit, following @specs/packages/git.md; never amend an existing commit.",
|
|
10
|
+
'Make the commit message explain concisely what changed and why, including relevant verification.',
|
|
11
|
+
'Identify every new commit you make.',
|
|
12
|
+
'Coder is <coder-llm>.',
|
|
13
|
+
];
|
|
6
14
|
const FIRST_PHASE_PROMPT = [
|
|
7
15
|
'> <caller-input>',
|
|
8
16
|
'> <run-results>',
|
|
9
17
|
'',
|
|
10
|
-
'
|
|
11
|
-
'If
|
|
12
|
-
'
|
|
18
|
+
'First determine whether the coding request starts a new coding intent or continues an existing IR with unfinished work.',
|
|
19
|
+
'If the request may continue an existing IR but does not identify it unambiguously, ask Boss before changing files.',
|
|
20
|
+
'',
|
|
21
|
+
'For a new coding intent, assess whether it can be completed well in one commit.',
|
|
22
|
+
'If it can, implement and test it, update the affected specs, and ensure @specs/map.md remains accurate.',
|
|
23
|
+
'If it cannot, decompose it into tasks sized to exactly one commit each, add a new IR under @specs/intents, and do not implement any IR task in this phase.',
|
|
13
24
|
'Plan affected spec updates before, with, or after their corresponding code changes, either as standalone IR tasks or as explicit work within related tasks.',
|
|
14
25
|
'',
|
|
26
|
+
'For an existing IR, read the identified IR and implement exactly its next unfinished task, including corresponding tests or specs if any.',
|
|
27
|
+
'Do not implement a later task in this phase.',
|
|
28
|
+
"Mark the IR's progress and deliverables when relevant.",
|
|
29
|
+
'If the IR will be finished after this phase, double-check that all acceptance criteria are met.',
|
|
30
|
+
'',
|
|
15
31
|
'Consult @specs/map.md for relevant context and @specs/meta.md for spec requirements, if needed.',
|
|
16
32
|
'',
|
|
17
|
-
|
|
18
|
-
"Make the phase's minimal changes and then one new commit, following @specs/packages/git.md; never amend an existing commit.",
|
|
19
|
-
'Make the commit message explain concisely what changed and why, including relevant verification.',
|
|
20
|
-
'Coder is <coder-llm>; format the model token in conventional human form.',
|
|
33
|
+
...APPENDED_PHASE_PROMPT,
|
|
21
34
|
].join('\n');
|
|
22
35
|
const IR_TASK_PROMPT = [
|
|
23
|
-
'> <
|
|
36
|
+
'> <caller-input>',
|
|
37
|
+
'> <ir-number>',
|
|
24
38
|
'> <run-results>',
|
|
25
39
|
'',
|
|
26
|
-
'Read IR
|
|
40
|
+
'Read the identified IR and implement exactly its next unfinished task, including corresponding tests or specs if any.',
|
|
27
41
|
'Do not implement a later task in this phase.',
|
|
28
42
|
"Mark the IR's progress and deliverables when relevant.",
|
|
29
43
|
'If the IR will be finished after this phase, double-check that all acceptance criteria are met.',
|
|
30
44
|
'',
|
|
31
|
-
|
|
32
|
-
"Make the phase's minimal changes and then one new commit, following @specs/packages/git.md; never amend an existing commit.",
|
|
33
|
-
'Make the commit message explain concisely what changed and why, including relevant verification.',
|
|
34
|
-
'Coder is <coder-llm>; format the model token in conventional human form.',
|
|
45
|
+
...APPENDED_PHASE_PROMPT,
|
|
35
46
|
].join('\n');
|
|
47
|
+
const NEEDS_BOSS_REPLY_RESULT = "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>`.";
|
|
36
48
|
const FIRST_PHASE_RESULTS = {
|
|
37
49
|
directCommit: 'Coder completed and committed the direct implementation phase. Output shall include `coderOutput: <verbatim final text>` and `latestCommit: <commit identity>`.',
|
|
38
|
-
irCommit: 'Coder created and committed a new IR without implementing an IR task. Output shall include `coderOutput: <verbatim final text>`, `latestCommit: <commit identity>`,
|
|
39
|
-
|
|
50
|
+
irCommit: 'Coder created and committed a new IR without implementing an IR task. Output shall include `coderOutput: <verbatim final text>`, `latestCommit: <commit identity>`, and `irNumber` identifying the created IR.',
|
|
51
|
+
moreTasks: 'Coder continued an existing IR, completed and committed exactly its next unfinished task, and at least one task remains. Output shall include `coderOutput: <verbatim final text>`, `latestCommit: <commit identity>`, `irNumber` identifying the continued IR, and `irTask` naming the implemented task.',
|
|
52
|
+
finalTask: 'Coder continued an existing IR and completed and committed its final task. Output shall include `coderOutput: <verbatim final text>`, `latestCommit: <commit identity>`, `irNumber` identifying the continued IR, and `irTask` naming the implemented task.',
|
|
53
|
+
needsBossReply: NEEDS_BOSS_REPLY_RESULT,
|
|
40
54
|
};
|
|
41
55
|
const IR_TASK_RESULTS = {
|
|
42
|
-
moreTasks:
|
|
43
|
-
finalTask:
|
|
44
|
-
needsBossReply:
|
|
56
|
+
moreTasks: "Coder completed and committed exactly the IR's next unfinished task and at least one task remains. Output shall include `coderOutput: <verbatim final text>`, `latestCommit: <commit identity>`, `irNumber` identifying the continued IR, and `irTask` naming the implemented task.",
|
|
57
|
+
finalTask: "Coder completed and committed the IR's final task. Output shall include `coderOutput: <verbatim final text>`, `latestCommit: <commit identity>`, `irNumber` identifying the continued IR, and `irTask` naming the implemented task.",
|
|
58
|
+
needsBossReply: NEEDS_BOSS_REPLY_RESULT,
|
|
45
59
|
};
|
|
46
60
|
const STATE_DESCRIPTIONS = {
|
|
47
61
|
ready: 'Waiting for a coding intent.',
|
|
48
|
-
runFirstPhase: 'Coder is
|
|
49
|
-
reviewFirstCommit: 'The REVIEW playbook is checking the
|
|
62
|
+
runFirstPhase: 'Coder is running the first coding phase: a direct implementation, a new intent record, or an existing intent-record task.',
|
|
63
|
+
reviewFirstCommit: 'The REVIEW playbook is checking the direct or new-IR phase commit.',
|
|
50
64
|
runIrTask: 'Coder is implementing exactly one unfinished intent-record task.',
|
|
51
65
|
reviewIrTask: 'The REVIEW playbook is checking the latest task commit.',
|
|
52
66
|
awaitBossReply: 'Waiting for Boss to answer Coder.',
|
|
53
67
|
failed: 'The coding workflow failed and is waiting for a new coding intent.',
|
|
54
68
|
reportedReviewFailure: 'The coding workflow reported a REVIEW failure and the last code-owned commit.',
|
|
55
|
-
done:
|
|
69
|
+
done: "The coding workflow completed after every phase's REVIEW passed with no unsettled findings.",
|
|
56
70
|
};
|
|
57
71
|
function playbookMeta(stateId, role) {
|
|
58
72
|
return {
|
|
@@ -89,6 +103,11 @@ function hasCommittedOutput(event) {
|
|
|
89
103
|
return (outputString(event, 'coderOutput') !== undefined &&
|
|
90
104
|
outputString(event, 'latestCommit') !== undefined);
|
|
91
105
|
}
|
|
106
|
+
function hasIrTaskOutput(event) {
|
|
107
|
+
return (hasCommittedOutput(event) &&
|
|
108
|
+
outputString(event, 'irNumber') !== undefined &&
|
|
109
|
+
outputString(event, 'irTask') !== undefined);
|
|
110
|
+
}
|
|
92
111
|
function isDirectCommit({ event }) {
|
|
93
112
|
return (outputGuard(event, 'directCommit') &&
|
|
94
113
|
hasCommittedOutput(event));
|
|
@@ -96,17 +115,15 @@ function isDirectCommit({ event }) {
|
|
|
96
115
|
function isIrCommit({ event }) {
|
|
97
116
|
return (outputGuard(event, 'irCommit') &&
|
|
98
117
|
hasCommittedOutput(event) &&
|
|
99
|
-
outputString(event, 'irNumber') !== undefined
|
|
100
|
-
outputString(event, 'irTask') !== undefined);
|
|
118
|
+
outputString(event, 'irNumber') !== undefined);
|
|
101
119
|
}
|
|
102
120
|
function isMoreTasks({ event }) {
|
|
103
121
|
return (outputGuard(event, 'moreTasks') &&
|
|
104
|
-
|
|
105
|
-
outputString(event, 'irTask') !== undefined);
|
|
122
|
+
hasIrTaskOutput(event));
|
|
106
123
|
}
|
|
107
124
|
function isFinalTask({ event }) {
|
|
108
125
|
return (outputGuard(event, 'finalTask') &&
|
|
109
|
-
|
|
126
|
+
hasIrTaskOutput(event));
|
|
110
127
|
}
|
|
111
128
|
function needsBossReply({ event }) {
|
|
112
129
|
return (outputGuard(event, 'needsBossReply') &&
|
|
@@ -116,11 +133,14 @@ function reviewOutput(event) {
|
|
|
116
133
|
return isRecord(event) ? event.output : undefined;
|
|
117
134
|
}
|
|
118
135
|
function isReviewApprovedValue(value) {
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
136
|
+
if (!isRecord(value))
|
|
137
|
+
return false;
|
|
138
|
+
if (Reflect.ownKeys(value).some((key) => typeof key !== 'string' ||
|
|
139
|
+
(key !== 'noUnsettledFindings' && key !== 'evaluatedRevision'))) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
return (value.noUnsettledFindings === true &&
|
|
143
|
+
isNonEmptyString(value.evaluatedRevision));
|
|
124
144
|
}
|
|
125
145
|
function reviewApprovedFor(phase) {
|
|
126
146
|
return ({ context, event }) => context.phase === phase && isReviewApprovedValue(reviewOutput(event));
|
|
@@ -265,16 +285,23 @@ function quoteRelay(label, value) {
|
|
|
265
285
|
const lines = value.split('\n');
|
|
266
286
|
return [`> ${label}: ${lines[0] ?? ''}`, ...lines.slice(1).map((line) => `> ${line}`)].join('\n');
|
|
267
287
|
}
|
|
268
|
-
function
|
|
288
|
+
function reviewScopeLine(context) {
|
|
289
|
+
return (`> Review scope: the commit ${context.latestCommit ?? ''} ` +
|
|
290
|
+
'from this coding phase and its resulting repository state.');
|
|
291
|
+
}
|
|
292
|
+
function newIntentReviewText(context) {
|
|
269
293
|
return [
|
|
270
|
-
quoteRelay('
|
|
294
|
+
quoteRelay('Original intent', context.callerInput ?? ''),
|
|
295
|
+
reviewScopeLine(context),
|
|
271
296
|
quoteRelay('Coder output', context.coderOutput ?? ''),
|
|
272
297
|
].join('\n');
|
|
273
298
|
}
|
|
274
299
|
function irTaskReviewText(context) {
|
|
275
300
|
return [
|
|
276
|
-
quoteRelay('
|
|
301
|
+
quoteRelay('Original intent', context.callerInput ?? ''),
|
|
302
|
+
reviewScopeLine(context),
|
|
277
303
|
quoteRelay('Coder output', context.coderOutput ?? ''),
|
|
304
|
+
quoteRelay('Current IR task', context.irTask ?? ''),
|
|
278
305
|
].join('\n');
|
|
279
306
|
}
|
|
280
307
|
const machineSetup = setup({
|
|
@@ -320,7 +347,7 @@ const machineSetup = setup({
|
|
|
320
347
|
latestCommit: undefined,
|
|
321
348
|
irNumber: undefined,
|
|
322
349
|
irTask: undefined,
|
|
323
|
-
|
|
350
|
+
evaluatedRevision: undefined,
|
|
324
351
|
phase: undefined,
|
|
325
352
|
completion: undefined,
|
|
326
353
|
reviewError: undefined,
|
|
@@ -340,8 +367,7 @@ const machineSetup = setup({
|
|
|
340
367
|
coderOutput: outputString(event, 'coderOutput'),
|
|
341
368
|
latestCommit: outputString(event, 'latestCommit'),
|
|
342
369
|
irNumber: outputString(event, 'irNumber'),
|
|
343
|
-
irTask:
|
|
344
|
-
nextIrTask: undefined,
|
|
370
|
+
irTask: undefined,
|
|
345
371
|
phase: 'ir-created',
|
|
346
372
|
pendingBossQuestion: undefined,
|
|
347
373
|
bossReply: undefined,
|
|
@@ -349,7 +375,8 @@ const machineSetup = setup({
|
|
|
349
375
|
rememberMoreTasks: assign(({ event }) => ({
|
|
350
376
|
coderOutput: outputString(event, 'coderOutput'),
|
|
351
377
|
latestCommit: outputString(event, 'latestCommit'),
|
|
352
|
-
|
|
378
|
+
irNumber: outputString(event, 'irNumber'),
|
|
379
|
+
irTask: outputString(event, 'irTask'),
|
|
353
380
|
phase: 'ir-task-more',
|
|
354
381
|
pendingBossQuestion: undefined,
|
|
355
382
|
bossReply: undefined,
|
|
@@ -357,15 +384,12 @@ const machineSetup = setup({
|
|
|
357
384
|
rememberFinalTask: assign(({ event }) => ({
|
|
358
385
|
coderOutput: outputString(event, 'coderOutput'),
|
|
359
386
|
latestCommit: outputString(event, 'latestCommit'),
|
|
360
|
-
|
|
387
|
+
irNumber: outputString(event, 'irNumber'),
|
|
388
|
+
irTask: outputString(event, 'irTask'),
|
|
361
389
|
phase: 'ir-task-final',
|
|
362
390
|
pendingBossQuestion: undefined,
|
|
363
391
|
bossReply: undefined,
|
|
364
392
|
})),
|
|
365
|
-
advanceToNextIrTask: assign(({ context }) => ({
|
|
366
|
-
irTask: context.nextIrTask,
|
|
367
|
-
nextIrTask: undefined,
|
|
368
|
-
})),
|
|
369
393
|
rememberPendingQuestion: assign(({ context, event }) => {
|
|
370
394
|
const question = outputString(event, 'question');
|
|
371
395
|
const output = playerOutput(event);
|
|
@@ -390,9 +414,14 @@ const machineSetup = setup({
|
|
|
390
414
|
pendingBossQuestion: undefined,
|
|
391
415
|
bossReply: undefined,
|
|
392
416
|
}),
|
|
393
|
-
completeSuccessfully: assign({
|
|
394
|
-
|
|
395
|
-
|
|
417
|
+
completeSuccessfully: assign(({ event }) => {
|
|
418
|
+
const output = reviewOutput(event);
|
|
419
|
+
const approved = isReviewApprovedValue(output) ? output : undefined;
|
|
420
|
+
return {
|
|
421
|
+
completion: 'complete',
|
|
422
|
+
evaluatedRevision: approved?.evaluatedRevision,
|
|
423
|
+
reviewError: undefined,
|
|
424
|
+
};
|
|
396
425
|
}),
|
|
397
426
|
completeWithReviewFailure: assign(({ event }) => ({
|
|
398
427
|
completion: 'review-failed',
|
|
@@ -426,19 +455,26 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
426
455
|
if (!isNonEmptyString(lastCodeCommit)) {
|
|
427
456
|
throw new Error('CODE reached a final state without a commit identity');
|
|
428
457
|
}
|
|
429
|
-
const lastCodeOutput = context.coderOutput ?? '';
|
|
430
458
|
if (context.completion === 'review-failed') {
|
|
431
459
|
return {
|
|
432
460
|
status: 'review-failed',
|
|
433
461
|
lastCodeCommit,
|
|
434
|
-
lastCodeOutput,
|
|
435
462
|
error: context.reviewError ?? {
|
|
436
463
|
name: 'Error',
|
|
437
464
|
message: 'REVIEW failed without error detail.',
|
|
438
465
|
},
|
|
439
466
|
};
|
|
440
467
|
}
|
|
441
|
-
|
|
468
|
+
const finalEvaluatedRevision = context.evaluatedRevision;
|
|
469
|
+
if (!isNonEmptyString(finalEvaluatedRevision)) {
|
|
470
|
+
throw new Error('CODE completed without an evaluated repository revision');
|
|
471
|
+
}
|
|
472
|
+
return {
|
|
473
|
+
status: 'complete',
|
|
474
|
+
lastCodeCommit,
|
|
475
|
+
finalEvaluatedRevision,
|
|
476
|
+
allReviewsPassed: true,
|
|
477
|
+
};
|
|
442
478
|
},
|
|
443
479
|
states: {
|
|
444
480
|
ready: {
|
|
@@ -503,6 +539,36 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
503
539
|
'rememberIrCommit',
|
|
504
540
|
],
|
|
505
541
|
},
|
|
542
|
+
{
|
|
543
|
+
guard: 'isMoreTasks',
|
|
544
|
+
target: 'reviewIrTask',
|
|
545
|
+
actions: [
|
|
546
|
+
{
|
|
547
|
+
type: 'playbook.acceptedOutcome',
|
|
548
|
+
params: {
|
|
549
|
+
source: 'runFirstPhase',
|
|
550
|
+
target: 'reviewIrTask',
|
|
551
|
+
acceptedOutcome: 'moreTasks',
|
|
552
|
+
},
|
|
553
|
+
},
|
|
554
|
+
'rememberMoreTasks',
|
|
555
|
+
],
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
guard: 'isFinalTask',
|
|
559
|
+
target: 'reviewIrTask',
|
|
560
|
+
actions: [
|
|
561
|
+
{
|
|
562
|
+
type: 'playbook.acceptedOutcome',
|
|
563
|
+
params: {
|
|
564
|
+
source: 'runFirstPhase',
|
|
565
|
+
target: 'reviewIrTask',
|
|
566
|
+
acceptedOutcome: 'finalTask',
|
|
567
|
+
},
|
|
568
|
+
},
|
|
569
|
+
'rememberFinalTask',
|
|
570
|
+
],
|
|
571
|
+
},
|
|
506
572
|
{
|
|
507
573
|
guard: 'needsBossReply',
|
|
508
574
|
target: 'awaitBossReply',
|
|
@@ -537,7 +603,7 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
537
603
|
stateId: 'reviewFirstCommit',
|
|
538
604
|
sourceItem: 'CODE-2',
|
|
539
605
|
playbookId: 'review',
|
|
540
|
-
text:
|
|
606
|
+
text: newIntentReviewText(context),
|
|
541
607
|
}),
|
|
542
608
|
onDone: [
|
|
543
609
|
{
|
|
@@ -582,7 +648,6 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
582
648
|
...(context.irNumber === undefined
|
|
583
649
|
? {}
|
|
584
650
|
: { irNumber: context.irNumber }),
|
|
585
|
-
...(context.irTask === undefined ? {} : { irTask: context.irTask }),
|
|
586
651
|
...(context.pendingBossQuestion === undefined
|
|
587
652
|
? {}
|
|
588
653
|
: { pendingBossQuestion: context.pendingBossQuestion }),
|
|
@@ -661,7 +726,6 @@ export const codingMachine = machineSetup.createMachine({
|
|
|
661
726
|
{
|
|
662
727
|
guard: 'reviewApprovedMoreTasks',
|
|
663
728
|
target: 'runIrTask',
|
|
664
|
-
actions: 'advanceToNextIrTask',
|
|
665
729
|
},
|
|
666
730
|
{
|
|
667
731
|
guard: 'reviewApprovedFinalTask',
|