@sublang/playbook 13.0.0 → 13.2.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 +7 -5
- package/docs/cli.md +28 -9
- package/docs/configuration.md +21 -5
- package/docs/embedding.md +1 -1
- package/package.json +41 -3
- package/reference/sdlc/branch.md +37 -0
- package/reference/sdlc/branch.playbook/branch.fsm.d.ts +169 -0
- package/reference/sdlc/branch.playbook/branch.fsm.js +325 -0
- package/reference/sdlc/branch.playbook/branch.fsm.ts +458 -0
- package/reference/sdlc/branch.playbook/branch.gears.md +44 -0
- package/reference/sdlc/branch.playbook/branch.playbook.d.ts +20 -0
- package/reference/sdlc/branch.playbook/branch.playbook.js +121 -0
- package/reference/sdlc/branch.playbook/branch.playbook.ts +217 -0
- package/reference/sdlc/branch.playbook/branch.registry.d.ts +40 -0
- package/reference/sdlc/branch.playbook/branch.registry.js +63 -0
- package/reference/sdlc/branch.playbook/branch.registry.ts +121 -0
- package/reference/sdlc/code.md +7 -0
- package/reference/sdlc/code.playbook/code.fsm.js +5 -5
- package/reference/sdlc/code.playbook/code.fsm.ts +5 -5
- package/reference/sdlc/code.playbook/code.gears.md +5 -5
- package/reference/sdlc/code.playbook/code.playbook.d.ts +1 -1
- package/reference/sdlc/code.playbook/code.playbook.js +6 -16
- package/reference/sdlc/code.playbook/code.playbook.ts +7 -17
- package/reference/sdlc/code.playbook/playbook-captain.js +4 -1
- package/reference/sdlc/code.playbook/playbook-captain.ts +4 -1
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +16 -2
- package/reference/sdlc/decide.md +2 -0
- package/reference/sdlc/decide.playbook/decide.fsm.js +1 -1
- package/reference/sdlc/decide.playbook/decide.fsm.ts +1 -1
- package/reference/sdlc/decide.playbook/decide.gears.md +2 -2
- package/reference/sdlc/decide.playbook/decide.playbook.d.ts +1 -2
- package/reference/sdlc/decide.playbook/decide.playbook.js +8 -22
- package/reference/sdlc/decide.playbook/decide.playbook.ts +8 -25
- package/reference/sdlc/dev.md +45 -4
- package/reference/sdlc/dev.playbook/dev.fsm.d.ts +100 -9
- package/reference/sdlc/dev.playbook/dev.fsm.js +245 -28
- package/reference/sdlc/dev.playbook/dev.fsm.ts +381 -37
- package/reference/sdlc/dev.playbook/dev.gears.md +60 -22
- package/reference/sdlc/dev.playbook/dev.playbook.d.ts +1 -1
- package/reference/sdlc/dev.playbook/dev.playbook.js +20 -18
- package/reference/sdlc/dev.playbook/dev.playbook.ts +21 -21
- package/reference/sdlc/dev.playbook/dev.registry.d.ts +1 -1
- package/reference/sdlc/dev.playbook/dev.registry.js +7 -2
- package/reference/sdlc/dev.playbook/dev.registry.ts +7 -2
- package/reference/sdlc/pr.md +108 -0
- package/reference/sdlc/pr.playbook/pr.fsm.d.ts +352 -0
- package/reference/sdlc/pr.playbook/pr.fsm.js +902 -0
- package/reference/sdlc/pr.playbook/pr.fsm.ts +1251 -0
- package/reference/sdlc/pr.playbook/pr.gears.md +155 -0
- package/reference/sdlc/pr.playbook/pr.playbook.d.ts +27 -0
- package/reference/sdlc/pr.playbook/pr.playbook.js +133 -0
- package/reference/sdlc/pr.playbook/pr.playbook.ts +235 -0
- package/reference/sdlc/pr.playbook/pr.registry.d.ts +40 -0
- package/reference/sdlc/pr.playbook/pr.registry.js +68 -0
- package/reference/sdlc/pr.playbook/pr.registry.ts +124 -0
- package/reference/sdlc/review.md +18 -0
- package/reference/sdlc/review.playbook/review.fsm.js +8 -8
- package/reference/sdlc/review.playbook/review.fsm.ts +8 -8
- package/reference/sdlc/review.playbook/review.gears.md +8 -8
- package/reference/sdlc/review.playbook/review.playbook.d.ts +1 -1
- package/reference/sdlc/review.playbook/review.playbook.js +5 -15
- package/reference/sdlc/review.playbook/review.playbook.ts +6 -16
- package/slc/link.md +12 -24
- package/src/runtime.d.ts +2 -0
- package/src/runtime.ts +2 -0
- package/src/xstate-playbook-runtime.d.ts +4 -2
- package/src/xstate-playbook-runtime.js +18 -13
- package/src/xstate-playbook-runtime.ts +26 -14
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
// Generated by slc/gears2fsm.md from ./dev.gears.md.
|
|
5
5
|
import { assign, fromPromise, setup } from 'xstate';
|
|
6
6
|
const PLAN_ANALYSIS_PROMPT = [
|
|
7
|
-
'> <development-request>',
|
|
8
|
-
'> <discussion-context>',
|
|
9
|
-
'> <run-results>',
|
|
7
|
+
'> Original request: <development-request>',
|
|
8
|
+
'> Prior discussion: <discussion-context>',
|
|
9
|
+
'> Run results: <run-results>',
|
|
10
10
|
'',
|
|
11
11
|
'Inspect the request and the relevant repository and specs only as needed to determine the smallest sound next step.',
|
|
12
12
|
'Do not change files or commit while planning or discussing the request.',
|
|
@@ -15,6 +15,7 @@ const PLAN_ANALYSIS_PROMPT = [
|
|
|
15
15
|
'- If the discussion has concluded after a Boss reply and no repository work should follow, choose `discussion complete`.',
|
|
16
16
|
'- If implementation can proceed under the existing decisions, choose `code`.',
|
|
17
17
|
'- If implementation first requires a new or amended durable decision that the existing specs do not settle, choose `decide then code`.',
|
|
18
|
+
'- If the request names a GitHub issue (number or URL) or explicitly asks for pull-request delivery, read the issue and its comments as part of the analysis (`gh issue view --comments` with the issue number) and choose `code via pull request` or `decide then code via pull request` in place of `code` or `decide then code`.',
|
|
18
19
|
'',
|
|
19
20
|
'A question or exploratory discussion is not by itself authorization to create a durable decision or implement changes.',
|
|
20
21
|
'Do not choose `decide then code` merely because the work is large.',
|
|
@@ -24,14 +25,18 @@ const PLAN_ANALYSIS_RESULTS = {
|
|
|
24
25
|
discussionComplete: 'Analyst concluded the discussion after a Boss reply, with no repository work to follow.',
|
|
25
26
|
code: 'Analyst determined implementation can proceed under the existing decisions. Output shall include `planningResult: <verbatim final text>`.',
|
|
26
27
|
decideThenCode: 'Analyst determined implementation first requires a new or amended durable decision that the existing specs do not settle. Output shall include `planningResult: <verbatim final text>`.',
|
|
28
|
+
codeViaPullRequest: 'Analyst determined implementation can proceed under the existing decisions and the request names a GitHub issue or explicitly asks for pull-request delivery. Output shall include `planningResult: <verbatim final text>`.',
|
|
29
|
+
decideThenCodeViaPullRequest: 'Analyst determined implementation first requires a new or amended durable decision that the existing specs do not settle and the request names a GitHub issue or explicitly asks for pull-request delivery. Output shall include `planningResult: <verbatim final text>`.',
|
|
27
30
|
needsBossReply: "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>`.",
|
|
28
31
|
};
|
|
29
32
|
const STATE_DESCRIPTIONS = {
|
|
30
33
|
ready: 'Waiting for a development request.',
|
|
31
34
|
planAnalysis: 'Analyst is analyzing the development request to choose the smallest sound next step.',
|
|
35
|
+
createBranch: 'The BRANCH playbook is preparing the pull-request branch for the planned development path.',
|
|
32
36
|
callCode: 'The CODE playbook is implementing the planned development path.',
|
|
33
37
|
callDecide: 'The DECIDE playbook is settling the durable decision the planned path requires.',
|
|
34
38
|
callCodeAfterDecide: 'The CODE playbook is implementing the decided development path.',
|
|
39
|
+
openPullRequest: 'The PR playbook is delivering the implemented branch through a pull request.',
|
|
35
40
|
awaitBossReply: 'Waiting for Boss to answer Analyst.',
|
|
36
41
|
failed: 'The development planning workflow failed and is waiting for a new development request.',
|
|
37
42
|
discussionComplete: 'The planning discussion concluded after a Boss reply with no repository work to follow.',
|
|
@@ -89,6 +94,16 @@ function isDecideThenCode({ event }) {
|
|
|
89
94
|
return (outputGuard(event, 'decideThenCode') &&
|
|
90
95
|
outputString(event, 'planningResult') !== undefined);
|
|
91
96
|
}
|
|
97
|
+
// DR-050: the two pull-request outcomes select the same development paths
|
|
98
|
+
// as `code` and `decide then code`, entered through `branch` first.
|
|
99
|
+
function isCodeViaPullRequest({ event }) {
|
|
100
|
+
return (outputGuard(event, 'codeViaPullRequest') &&
|
|
101
|
+
outputString(event, 'planningResult') !== undefined);
|
|
102
|
+
}
|
|
103
|
+
function isDecideThenCodeViaPullRequest({ event, }) {
|
|
104
|
+
return (outputGuard(event, 'decideThenCodeViaPullRequest') &&
|
|
105
|
+
outputString(event, 'planningResult') !== undefined);
|
|
106
|
+
}
|
|
92
107
|
// Discussion complete is available only after a Boss reply: the round that
|
|
93
108
|
// produced it must itself have been resumed with Boss's answer.
|
|
94
109
|
function isDiscussionComplete({ context, event, }) {
|
|
@@ -111,6 +126,24 @@ function isDecideSuccessValue(value) {
|
|
|
111
126
|
function isDecideSuccess({ event }) {
|
|
112
127
|
return isDecideSuccessValue(childOutputOf(event));
|
|
113
128
|
}
|
|
129
|
+
// BRANCH's canonical successful terminal output carries the exact name of
|
|
130
|
+
// the new checked-out branch, the exact receipt-owned base revision, and the
|
|
131
|
+
// issue summary; DEV consumes exactly those three by name and never defaults
|
|
132
|
+
// a missing one.
|
|
133
|
+
function isBranchSuccessValue(value) {
|
|
134
|
+
return (isRecord(value) &&
|
|
135
|
+
isNonEmptyString(value.branch) &&
|
|
136
|
+
isNonEmptyString(value.baseRevision) &&
|
|
137
|
+
isNonEmptyString(value.issueSummary));
|
|
138
|
+
}
|
|
139
|
+
function isBranchSuccessForCode({ context, event, }) {
|
|
140
|
+
return (context.pullRequestPath === 'code' &&
|
|
141
|
+
isBranchSuccessValue(childOutputOf(event)));
|
|
142
|
+
}
|
|
143
|
+
function isBranchSuccessForDecide({ context, event, }) {
|
|
144
|
+
return (context.pullRequestPath === 'decide-then-code' &&
|
|
145
|
+
isBranchSuccessValue(childOutputOf(event)));
|
|
146
|
+
}
|
|
114
147
|
// CODE's canonical successful terminal output discriminates completion with
|
|
115
148
|
// `status: 'complete'`, carries the exact last CODE-owned commit, and
|
|
116
149
|
// affirms that every phase's review passed.
|
|
@@ -120,8 +153,22 @@ function isCodeSuccessValue(value) {
|
|
|
120
153
|
isNonEmptyString(value.lastCodeCommit) &&
|
|
121
154
|
value.allReviewsPassed === true);
|
|
122
155
|
}
|
|
123
|
-
|
|
124
|
-
|
|
156
|
+
// A plain path completes DEV on that proof alone, exactly as before DR-050.
|
|
157
|
+
function isPlainCodeSuccess({ context, event, }) {
|
|
158
|
+
return (context.deliveryViaPullRequest !== true &&
|
|
159
|
+
isCodeSuccessValue(childOutputOf(event)));
|
|
160
|
+
}
|
|
161
|
+
// A pull-request path additionally consumes the exact final evaluated
|
|
162
|
+
// repository revision for the `pr` call, so a CODE result lacking it does not
|
|
163
|
+
// prove the success that path requires.
|
|
164
|
+
function isCodeSuccessValueForPullRequest(value) {
|
|
165
|
+
return (isCodeSuccessValue(value) &&
|
|
166
|
+
isRecord(value) &&
|
|
167
|
+
isNonEmptyString(value.finalEvaluatedRevision));
|
|
168
|
+
}
|
|
169
|
+
function isCodeSuccessViaPullRequest({ context, event, }) {
|
|
170
|
+
return (context.deliveryViaPullRequest === true &&
|
|
171
|
+
isCodeSuccessValueForPullRequest(childOutputOf(event)));
|
|
125
172
|
}
|
|
126
173
|
function isStateValue(value, ancestors = new Set()) {
|
|
127
174
|
if (typeof value === 'string')
|
|
@@ -334,8 +381,8 @@ function archivedExchanges(context) {
|
|
|
334
381
|
}
|
|
335
382
|
function quotedRelay(values) {
|
|
336
383
|
return values
|
|
337
|
-
.filter((value) => value.length > 0)
|
|
338
|
-
.map((value) => value
|
|
384
|
+
.filter(([, value]) => value.length > 0)
|
|
385
|
+
.map(([label, value]) => `${label}: ${value}`
|
|
339
386
|
.split('\n')
|
|
340
387
|
.map((line) => `> ${line}`)
|
|
341
388
|
.join('\n'))
|
|
@@ -343,9 +390,9 @@ function quotedRelay(values) {
|
|
|
343
390
|
}
|
|
344
391
|
function planningRelayValues(context) {
|
|
345
392
|
return [
|
|
346
|
-
context.developmentRequest ?? '',
|
|
347
|
-
renderDiscussionContext(context.discussionExchanges),
|
|
348
|
-
context.planningResult ?? '',
|
|
393
|
+
['Original request', context.developmentRequest ?? ''],
|
|
394
|
+
['Prior discussion', renderDiscussionContext(context.discussionExchanges)],
|
|
395
|
+
['Planning result', context.planningResult ?? ''],
|
|
349
396
|
];
|
|
350
397
|
}
|
|
351
398
|
function codeCallText(context) {
|
|
@@ -357,10 +404,35 @@ function decideCallText(context) {
|
|
|
357
404
|
function codeAfterDecideCallText(context) {
|
|
358
405
|
return quotedRelay([
|
|
359
406
|
...planningRelayValues(context),
|
|
360
|
-
context.decideCommit ?? '',
|
|
361
|
-
context.evaluatedRevision ?? '',
|
|
407
|
+
['DECIDE commit', context.decideCommit ?? ''],
|
|
408
|
+
['Evaluated revision', context.evaluatedRevision ?? ''],
|
|
409
|
+
]);
|
|
410
|
+
}
|
|
411
|
+
function branchCallText(context) {
|
|
412
|
+
return quotedRelay(planningRelayValues(context));
|
|
413
|
+
}
|
|
414
|
+
// DEV-6: every placeholder is substituted from typed context that only a
|
|
415
|
+
// child's canonical structured result populated — never from player prose.
|
|
416
|
+
function pullRequestCallText(context) {
|
|
417
|
+
return quotedRelay([
|
|
418
|
+
['Original request', context.developmentRequest ?? ''],
|
|
419
|
+
['Issue summary', context.issueSummary ?? ''],
|
|
420
|
+
['Branch', context.branch ?? ''],
|
|
421
|
+
['Base revision', context.baseRevision ?? ''],
|
|
422
|
+
['CODE commit', context.lastCodeCommit ?? ''],
|
|
423
|
+
['Evaluated revision', context.finalEvaluatedRevision ?? ''],
|
|
362
424
|
]);
|
|
363
425
|
}
|
|
426
|
+
function acceptedPlanningPath(context, event, pullRequestPath) {
|
|
427
|
+
return {
|
|
428
|
+
planningResult: outputString(event, 'planningResult'),
|
|
429
|
+
discussionExchanges: archivedExchanges(context),
|
|
430
|
+
deliveryViaPullRequest: pullRequestPath !== undefined,
|
|
431
|
+
pullRequestPath,
|
|
432
|
+
pendingBossQuestion: undefined,
|
|
433
|
+
bossReply: undefined,
|
|
434
|
+
};
|
|
435
|
+
}
|
|
364
436
|
const machineSetup = setup({
|
|
365
437
|
types: {},
|
|
366
438
|
actors: {
|
|
@@ -375,11 +447,18 @@ const machineSetup = setup({
|
|
|
375
447
|
isDiscussionComplete,
|
|
376
448
|
isCodePath,
|
|
377
449
|
isDecideThenCode,
|
|
450
|
+
isCodeViaPullRequest,
|
|
451
|
+
isDecideThenCodeViaPullRequest,
|
|
378
452
|
needsBossReply,
|
|
379
|
-
|
|
453
|
+
isBranchSuccessForCode,
|
|
454
|
+
isBranchSuccessForDecide,
|
|
455
|
+
isCodeSuccessViaPullRequest,
|
|
456
|
+
isPlainCodeSuccess,
|
|
380
457
|
isDecideSuccess,
|
|
458
|
+
authoredBranchFailure: authoredChildFailureGuard('branch'),
|
|
381
459
|
authoredCodeFailure: authoredChildFailureGuard('code'),
|
|
382
460
|
authoredDecideFailure: authoredChildFailureGuard('decide'),
|
|
461
|
+
authoredPrFailure: authoredChildFailureGuard('pr'),
|
|
383
462
|
emptyBossReply: ({ event }) => event.type === 'BOSS_REPLY' && event.answer.trim().length === 0,
|
|
384
463
|
resumesPlanAnalysis: ({ context, event }) => event.type === 'BOSS_REPLY' &&
|
|
385
464
|
event.answer.trim().length > 0 &&
|
|
@@ -398,6 +477,13 @@ const machineSetup = setup({
|
|
|
398
477
|
planningResult: undefined,
|
|
399
478
|
decideCommit: undefined,
|
|
400
479
|
evaluatedRevision: undefined,
|
|
480
|
+
deliveryViaPullRequest: false,
|
|
481
|
+
pullRequestPath: undefined,
|
|
482
|
+
branch: undefined,
|
|
483
|
+
baseRevision: undefined,
|
|
484
|
+
issueSummary: undefined,
|
|
485
|
+
lastCodeCommit: undefined,
|
|
486
|
+
finalEvaluatedRevision: undefined,
|
|
401
487
|
completion: undefined,
|
|
402
488
|
childOutput: undefined,
|
|
403
489
|
childFailure: undefined,
|
|
@@ -412,18 +498,10 @@ const machineSetup = setup({
|
|
|
412
498
|
pendingBossQuestion: undefined,
|
|
413
499
|
bossReply: undefined,
|
|
414
500
|
})),
|
|
415
|
-
rememberCodePath: assign(({ context, event }) => (
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
bossReply: undefined,
|
|
420
|
-
})),
|
|
421
|
-
rememberDecidePath: assign(({ context, event }) => ({
|
|
422
|
-
planningResult: outputString(event, 'planningResult'),
|
|
423
|
-
discussionExchanges: archivedExchanges(context),
|
|
424
|
-
pendingBossQuestion: undefined,
|
|
425
|
-
bossReply: undefined,
|
|
426
|
-
})),
|
|
501
|
+
rememberCodePath: assign(({ context, event }) => acceptedPlanningPath(context, event)),
|
|
502
|
+
rememberDecidePath: assign(({ context, event }) => acceptedPlanningPath(context, event)),
|
|
503
|
+
rememberCodeViaPullRequestPath: assign(({ context, event }) => acceptedPlanningPath(context, event, 'code')),
|
|
504
|
+
rememberDecideThenCodeViaPullRequestPath: assign(({ context, event }) => acceptedPlanningPath(context, event, 'decide-then-code')),
|
|
427
505
|
rememberPendingQuestion: assign(({ context, event }) => {
|
|
428
506
|
const question = outputString(event, 'question');
|
|
429
507
|
if (question === undefined || !outputGuard(event, 'needsBossReply')) {
|
|
@@ -447,6 +525,16 @@ const machineSetup = setup({
|
|
|
447
525
|
pendingBossQuestion: undefined,
|
|
448
526
|
bossReply: undefined,
|
|
449
527
|
}),
|
|
528
|
+
rememberBranchResult: assign(({ event }) => {
|
|
529
|
+
const output = childOutputOf(event);
|
|
530
|
+
if (!isBranchSuccessValue(output))
|
|
531
|
+
return {};
|
|
532
|
+
return {
|
|
533
|
+
branch: output.branch,
|
|
534
|
+
baseRevision: output.baseRevision,
|
|
535
|
+
issueSummary: output.issueSummary,
|
|
536
|
+
};
|
|
537
|
+
}),
|
|
450
538
|
rememberDecideResult: assign(({ event }) => {
|
|
451
539
|
const output = childOutputOf(event);
|
|
452
540
|
if (!isDecideSuccessValue(output))
|
|
@@ -456,6 +544,15 @@ const machineSetup = setup({
|
|
|
456
544
|
evaluatedRevision: output.evaluatedRevision,
|
|
457
545
|
};
|
|
458
546
|
}),
|
|
547
|
+
rememberCodeResult: assign(({ event }) => {
|
|
548
|
+
const output = childOutputOf(event);
|
|
549
|
+
if (!isCodeSuccessValueForPullRequest(output))
|
|
550
|
+
return {};
|
|
551
|
+
return {
|
|
552
|
+
lastCodeCommit: output.lastCodeCommit,
|
|
553
|
+
finalEvaluatedRevision: output.finalEvaluatedRevision,
|
|
554
|
+
};
|
|
555
|
+
}),
|
|
459
556
|
completeWithChildSuccess: assign(({ event }) => {
|
|
460
557
|
const output = childOutputOf(event);
|
|
461
558
|
return {
|
|
@@ -463,6 +560,10 @@ const machineSetup = setup({
|
|
|
463
560
|
...(output === undefined ? {} : { childOutput: output }),
|
|
464
561
|
};
|
|
465
562
|
}),
|
|
563
|
+
completeWithInsufficientBranchResult: assign(({ event }) => ({
|
|
564
|
+
completion: 'child-failed',
|
|
565
|
+
childFailure: insufficientChildResult(event, 'branch'),
|
|
566
|
+
})),
|
|
466
567
|
completeWithInsufficientCodeResult: assign(({ event }) => ({
|
|
467
568
|
completion: 'child-failed',
|
|
468
569
|
childFailure: insufficientChildResult(event, 'code'),
|
|
@@ -471,6 +572,10 @@ const machineSetup = setup({
|
|
|
471
572
|
completion: 'child-failed',
|
|
472
573
|
childFailure: insufficientChildResult(event, 'decide'),
|
|
473
574
|
})),
|
|
575
|
+
completeWithBranchFailure: assign(({ event }) => ({
|
|
576
|
+
completion: 'child-failed',
|
|
577
|
+
childFailure: relayedChildFailure(event, 'branch'),
|
|
578
|
+
})),
|
|
474
579
|
completeWithCodeFailure: assign(({ event }) => ({
|
|
475
580
|
completion: 'child-failed',
|
|
476
581
|
childFailure: relayedChildFailure(event, 'code'),
|
|
@@ -479,6 +584,10 @@ const machineSetup = setup({
|
|
|
479
584
|
completion: 'child-failed',
|
|
480
585
|
childFailure: relayedChildFailure(event, 'decide'),
|
|
481
586
|
})),
|
|
587
|
+
completeWithPrFailure: assign(({ event }) => ({
|
|
588
|
+
completion: 'child-failed',
|
|
589
|
+
childFailure: relayedChildFailure(event, 'pr'),
|
|
590
|
+
})),
|
|
482
591
|
rememberActorError: assign(({ event }) => ({
|
|
483
592
|
lastError: event.error,
|
|
484
593
|
})),
|
|
@@ -493,6 +602,7 @@ export const devMachine = machineSetup.createMachine({
|
|
|
493
602
|
context: ({ input }) => ({
|
|
494
603
|
runResults: typeof input.runResults === 'string' ? input.runResults : '',
|
|
495
604
|
discussionExchanges: [],
|
|
605
|
+
deliveryViaPullRequest: false,
|
|
496
606
|
}),
|
|
497
607
|
output: ({ context }) => {
|
|
498
608
|
if (context.completion === 'discussion-complete') {
|
|
@@ -501,7 +611,9 @@ export const devMachine = machineSetup.createMachine({
|
|
|
501
611
|
if (context.completion === 'complete') {
|
|
502
612
|
return {
|
|
503
613
|
status: 'complete',
|
|
504
|
-
|
|
614
|
+
// `done` is entered by `pr` on a pull-request path and by `code` on a
|
|
615
|
+
// plain path; no other arm completes the workflow.
|
|
616
|
+
childPlaybookId: context.deliveryViaPullRequest ? 'pr' : 'code',
|
|
505
617
|
...(context.childOutput === undefined
|
|
506
618
|
? {}
|
|
507
619
|
: { childOutput: context.childOutput }),
|
|
@@ -594,6 +706,36 @@ export const devMachine = machineSetup.createMachine({
|
|
|
594
706
|
'rememberDecidePath',
|
|
595
707
|
],
|
|
596
708
|
},
|
|
709
|
+
{
|
|
710
|
+
guard: 'isCodeViaPullRequest',
|
|
711
|
+
target: 'createBranch',
|
|
712
|
+
actions: [
|
|
713
|
+
{
|
|
714
|
+
type: 'playbook.acceptedOutcome',
|
|
715
|
+
params: {
|
|
716
|
+
source: 'planAnalysis',
|
|
717
|
+
target: 'createBranch',
|
|
718
|
+
acceptedOutcome: 'codeViaPullRequest',
|
|
719
|
+
},
|
|
720
|
+
},
|
|
721
|
+
'rememberCodeViaPullRequestPath',
|
|
722
|
+
],
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
guard: 'isDecideThenCodeViaPullRequest',
|
|
726
|
+
target: 'createBranch',
|
|
727
|
+
actions: [
|
|
728
|
+
{
|
|
729
|
+
type: 'playbook.acceptedOutcome',
|
|
730
|
+
params: {
|
|
731
|
+
source: 'planAnalysis',
|
|
732
|
+
target: 'createBranch',
|
|
733
|
+
acceptedOutcome: 'decideThenCodeViaPullRequest',
|
|
734
|
+
},
|
|
735
|
+
},
|
|
736
|
+
'rememberDecideThenCodeViaPullRequestPath',
|
|
737
|
+
],
|
|
738
|
+
},
|
|
597
739
|
{
|
|
598
740
|
guard: 'needsBossReply',
|
|
599
741
|
target: 'awaitBossReply',
|
|
@@ -617,6 +759,45 @@ export const devMachine = machineSetup.createMachine({
|
|
|
617
759
|
onError: { target: 'failed', actions: 'rememberActorError' },
|
|
618
760
|
},
|
|
619
761
|
},
|
|
762
|
+
createBranch: {
|
|
763
|
+
id: 'createBranch',
|
|
764
|
+
description: STATE_DESCRIPTIONS.createBranch,
|
|
765
|
+
meta: playbookMeta('createBranch'),
|
|
766
|
+
tags: ['playbook.suspended'],
|
|
767
|
+
invoke: {
|
|
768
|
+
src: 'playbook',
|
|
769
|
+
input: ({ context }) => ({
|
|
770
|
+
stateId: 'createBranch',
|
|
771
|
+
sourceItem: 'DEV-5',
|
|
772
|
+
playbookId: 'branch',
|
|
773
|
+
text: branchCallText(context),
|
|
774
|
+
}),
|
|
775
|
+
onDone: [
|
|
776
|
+
{
|
|
777
|
+
guard: 'isBranchSuccessForCode',
|
|
778
|
+
target: 'callCode',
|
|
779
|
+
actions: 'rememberBranchResult',
|
|
780
|
+
},
|
|
781
|
+
{
|
|
782
|
+
guard: 'isBranchSuccessForDecide',
|
|
783
|
+
target: 'callDecide',
|
|
784
|
+
actions: 'rememberBranchResult',
|
|
785
|
+
},
|
|
786
|
+
{
|
|
787
|
+
target: 'reportedChildFailure',
|
|
788
|
+
actions: 'completeWithInsufficientBranchResult',
|
|
789
|
+
},
|
|
790
|
+
],
|
|
791
|
+
onError: [
|
|
792
|
+
{
|
|
793
|
+
guard: 'authoredBranchFailure',
|
|
794
|
+
target: 'reportedChildFailure',
|
|
795
|
+
actions: 'completeWithBranchFailure',
|
|
796
|
+
},
|
|
797
|
+
{ target: 'failed', actions: 'rememberActorError' },
|
|
798
|
+
],
|
|
799
|
+
},
|
|
800
|
+
},
|
|
620
801
|
callCode: {
|
|
621
802
|
id: 'callCode',
|
|
622
803
|
description: STATE_DESCRIPTIONS.callCode,
|
|
@@ -632,7 +813,12 @@ export const devMachine = machineSetup.createMachine({
|
|
|
632
813
|
}),
|
|
633
814
|
onDone: [
|
|
634
815
|
{
|
|
635
|
-
guard: '
|
|
816
|
+
guard: 'isCodeSuccessViaPullRequest',
|
|
817
|
+
target: 'openPullRequest',
|
|
818
|
+
actions: 'rememberCodeResult',
|
|
819
|
+
},
|
|
820
|
+
{
|
|
821
|
+
guard: 'isPlainCodeSuccess',
|
|
636
822
|
target: 'done',
|
|
637
823
|
actions: 'completeWithChildSuccess',
|
|
638
824
|
},
|
|
@@ -700,7 +886,12 @@ export const devMachine = machineSetup.createMachine({
|
|
|
700
886
|
}),
|
|
701
887
|
onDone: [
|
|
702
888
|
{
|
|
703
|
-
guard: '
|
|
889
|
+
guard: 'isCodeSuccessViaPullRequest',
|
|
890
|
+
target: 'openPullRequest',
|
|
891
|
+
actions: 'rememberCodeResult',
|
|
892
|
+
},
|
|
893
|
+
{
|
|
894
|
+
guard: 'isPlainCodeSuccess',
|
|
704
895
|
target: 'done',
|
|
705
896
|
actions: 'completeWithChildSuccess',
|
|
706
897
|
},
|
|
@@ -719,6 +910,32 @@ export const devMachine = machineSetup.createMachine({
|
|
|
719
910
|
],
|
|
720
911
|
},
|
|
721
912
|
},
|
|
913
|
+
openPullRequest: {
|
|
914
|
+
id: 'openPullRequest',
|
|
915
|
+
description: STATE_DESCRIPTIONS.openPullRequest,
|
|
916
|
+
meta: playbookMeta('openPullRequest'),
|
|
917
|
+
tags: ['playbook.suspended'],
|
|
918
|
+
invoke: {
|
|
919
|
+
src: 'playbook',
|
|
920
|
+
input: ({ context }) => ({
|
|
921
|
+
stateId: 'openPullRequest',
|
|
922
|
+
sourceItem: 'DEV-6',
|
|
923
|
+
playbookId: 'pr',
|
|
924
|
+
text: pullRequestCallText(context),
|
|
925
|
+
}),
|
|
926
|
+
// DR-048: `pr` declares its terminal kinds, so `onDone` alone proves
|
|
927
|
+
// its success; DEV consumes none of its fields by name.
|
|
928
|
+
onDone: { target: 'done', actions: 'completeWithChildSuccess' },
|
|
929
|
+
onError: [
|
|
930
|
+
{
|
|
931
|
+
guard: 'authoredPrFailure',
|
|
932
|
+
target: 'reportedChildFailure',
|
|
933
|
+
actions: 'completeWithPrFailure',
|
|
934
|
+
},
|
|
935
|
+
{ target: 'failed', actions: 'rememberActorError' },
|
|
936
|
+
],
|
|
937
|
+
},
|
|
938
|
+
},
|
|
722
939
|
awaitBossReply: {
|
|
723
940
|
id: 'awaitBossReply',
|
|
724
941
|
description: STATE_DESCRIPTIONS.awaitBossReply,
|