@sublang/playbook 15.0.0 → 16.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/embedding.md +9 -7
- package/package.json +3 -1
- package/reference/sdlc/branch.playbook/branch.fsm.d.ts +63 -33
- package/reference/sdlc/branch.playbook/branch.fsm.js +190 -108
- package/reference/sdlc/branch.playbook/branch.fsm.ts +269 -147
- package/reference/sdlc/branch.playbook/branch.gears.md +7 -17
- package/reference/sdlc/branch.playbook/branch.playbook.d.ts +12 -16
- package/reference/sdlc/branch.playbook/branch.playbook.js +112 -101
- package/reference/sdlc/branch.playbook/branch.playbook.ts +128 -171
- package/reference/sdlc/branch.playbook/branch.registry.d.ts +3 -2
- package/reference/sdlc/branch.playbook/branch.registry.ts +6 -2
- package/reference/sdlc/code.playbook/bin/repository-effects.js +54 -13
- package/reference/sdlc/code.playbook/code.fsm.d.ts +143 -90
- package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +8 -8
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +13 -13
- package/reference/sdlc/code.playbook/code.fsm.js +609 -649
- package/reference/sdlc/code.playbook/code.fsm.ts +890 -821
- package/reference/sdlc/code.playbook/code.gears.md +39 -29
- package/reference/sdlc/code.playbook/code.playbook.d.ts +13 -16
- package/reference/sdlc/code.playbook/code.playbook.js +166 -147
- package/reference/sdlc/code.playbook/code.playbook.ts +180 -229
- package/reference/sdlc/code.playbook/code.registry.d.ts +3 -2
- package/reference/sdlc/code.playbook/code.registry.ts +6 -2
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +42 -0
- package/reference/sdlc/code.playbook/playbook-captain.js +829 -194
- package/reference/sdlc/code.playbook/playbook-captain.ts +1227 -220
- package/reference/sdlc/decide.md +1 -0
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +270 -154
- package/reference/sdlc/decide.playbook/decide.fsm.js +765 -732
- package/reference/sdlc/decide.playbook/decide.fsm.ts +1167 -945
- package/reference/sdlc/decide.playbook/decide.gears.md +28 -21
- package/reference/sdlc/decide.playbook/decide.playbook.d.ts +11 -67
- package/reference/sdlc/decide.playbook/decide.playbook.js +155 -3570
- package/reference/sdlc/decide.playbook/decide.playbook.ts +186 -5061
- package/reference/sdlc/decide.playbook/decide.registry.d.ts +8 -4
- package/reference/sdlc/decide.playbook/decide.registry.js +2 -2
- package/reference/sdlc/decide.playbook/decide.registry.ts +13 -6
- package/reference/sdlc/dev.playbook/dev.fsm.d.ts +113 -131
- package/reference/sdlc/dev.playbook/dev.fsm.js +517 -575
- package/reference/sdlc/dev.playbook/dev.fsm.ts +667 -787
- package/reference/sdlc/dev.playbook/dev.gears.md +52 -54
- package/reference/sdlc/dev.playbook/dev.playbook.d.ts +13 -10
- package/reference/sdlc/dev.playbook/dev.playbook.js +128 -120
- package/reference/sdlc/dev.playbook/dev.playbook.ts +143 -193
- package/reference/sdlc/dev.playbook/dev.registry.d.ts +3 -2
- package/reference/sdlc/dev.playbook/dev.registry.ts +6 -2
- package/reference/sdlc/pr.playbook/pr.fsm.d.ts +92 -85
- package/reference/sdlc/pr.playbook/pr.fsm.js +461 -518
- package/reference/sdlc/pr.playbook/pr.fsm.ts +533 -663
- package/reference/sdlc/pr.playbook/pr.gears.md +47 -63
- package/reference/sdlc/pr.playbook/pr.playbook.d.ts +13 -23
- package/reference/sdlc/pr.playbook/pr.playbook.js +118 -112
- package/reference/sdlc/pr.playbook/pr.playbook.ts +136 -190
- package/reference/sdlc/pr.playbook/pr.registry.d.ts +3 -2
- package/reference/sdlc/pr.playbook/pr.registry.ts +4 -2
- package/reference/sdlc/review.md +3 -3
- package/reference/sdlc/review.playbook/review.fsm.d.ts +150 -116
- package/reference/sdlc/review.playbook/review.fsm.js +479 -550
- package/reference/sdlc/review.playbook/review.fsm.ts +717 -662
- package/reference/sdlc/review.playbook/review.gears.md +32 -29
- package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -12
- package/reference/sdlc/review.playbook/review.playbook.js +180 -155
- package/reference/sdlc/review.playbook/review.playbook.ts +190 -230
- package/reference/sdlc/review.playbook/review.registry.d.ts +6 -5
- package/reference/sdlc/review.playbook/review.registry.js +3 -3
- package/reference/sdlc/review.playbook/review.registry.ts +9 -5
- package/slc/gears2fsm.md +72 -3
- package/slc/link.md +50 -27
- package/slc/materialize-link.mjs +51 -13
- package/slc/optimize.md +4 -1
- package/slc/prefix-prompts.mjs +191 -0
- package/slc/prefix.md +203 -0
- package/slc/slc.pin-inputs.json +11 -1
- package/slc/text2gears.md +71 -11
- package/src/xstate-playbook-runtime.d.ts +82 -9
- package/src/xstate-playbook-runtime.js +1224 -283
- package/src/xstate-playbook-runtime.ts +1671 -338
- package/src/xstate-runtime.d.ts +3 -1
- package/src/xstate-runtime.js +9 -2
- package/src/xstate-runtime.ts +12 -2
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
-
//
|
|
4
|
-
// Generated by slc/gears2fsm.md from ./branch.gears.md.
|
|
5
3
|
import { assign, fromPromise, setup } from 'xstate';
|
|
4
|
+
/**
|
|
5
|
+
* Stable working-leaf ids that may suspend on a Boss question and be resumed
|
|
6
|
+
* by `BOSS_REPLY`. The machine has at most one active player task, so the
|
|
7
|
+
* scalar Boss-reply form applies.
|
|
8
|
+
*/
|
|
9
|
+
const RESUMABLE_STATE_IDS = ['createBranch'];
|
|
10
|
+
/** No parallel group in this playbook. */
|
|
11
|
+
export const concurrentRoleSets = [];
|
|
6
12
|
const CREATE_BRANCH_PROMPT = [
|
|
7
|
-
'> Original request: <caller-input>',
|
|
8
|
-
'',
|
|
9
13
|
'Prepare a new branch for this work without changing any file or making any commit.',
|
|
10
14
|
'Identify the GitHub issue the request names, if any, and read it with its comments (`gh issue view --comments` with the issue number).',
|
|
11
15
|
'If the request could refer to more than one issue, or does not say which work to branch for, ask Boss before creating anything.',
|
|
@@ -14,19 +18,22 @@ const CREATE_BRANCH_PROMPT = [
|
|
|
14
18
|
'Create the branch from the current commit and check it out; do not pull, reset, stash, or move HEAD to another commit.',
|
|
15
19
|
'Report the exact branch name, the commit it was created from, and a concise summary of the issue and its comments, or of the request when no issue is named.',
|
|
16
20
|
'If the working tree is not clean, `gh` is not authenticated, the named issue does not exist or cannot be read, or a branch with that name already exists locally or on the remote, create nothing and report the failure with its reason.',
|
|
21
|
+
'',
|
|
22
|
+
'> Original request: <caller-input>',
|
|
17
23
|
].join('\n');
|
|
24
|
+
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>`.";
|
|
18
25
|
const CREATE_BRANCH_RESULTS = {
|
|
19
|
-
branched:
|
|
20
|
-
refused:
|
|
21
|
-
needsBossReply:
|
|
26
|
+
branched: "Coder affirmatively reported that it created the new branch from the current commit and checked it out, with the exact branch name and a concise summary of the issue and its comments, or of the request when no issue is named; the absence of a reported obstacle is not support. The branch workflow is then complete and returns the exact branch name, the exact base revision taken from repository authority, and the issue summary to its caller. Output shall include `branch: <exact branch name>`, `baseRevision: <exact base revision from repository authority, not from Coder's prose>`, and `issueSummary: <concise summary of the issue and its comments, or of the request when no issue is named>`.",
|
|
27
|
+
refused: "Coder affirmatively reported that it created no branch and gave the failure with its reason, such as a working tree that is not clean, gh not being authenticated, a named issue that does not exist or cannot be read, or a branch with that name already existing locally or on the remote. The branch workflow then fails and reports Coder's complete result with its reason to its caller; no branch was created. Output shall include `coderOutput: <verbatim final text>`.",
|
|
28
|
+
needsBossReply: NEEDS_BOSS_REPLY_RESULT,
|
|
22
29
|
};
|
|
23
30
|
const STATE_DESCRIPTIONS = {
|
|
24
|
-
ready: 'Waiting for a development request to branch for.',
|
|
25
|
-
createBranch: 'Coder is
|
|
26
|
-
awaitBossReply:
|
|
27
|
-
failed: 'The branch workflow failed and is waiting for
|
|
28
|
-
branched:
|
|
29
|
-
refused:
|
|
31
|
+
ready: 'Waiting for the caller to give a development request to branch for.',
|
|
32
|
+
createBranch: 'Coder is identifying the request\'s issue and creating and checking out a new branch at the current commit.',
|
|
33
|
+
awaitBossReply: "Waiting for Boss to answer the acting agent's question.",
|
|
34
|
+
failed: 'The branch workflow failed and is waiting for the caller to give the request again.',
|
|
35
|
+
branched: 'A new branch for the request was created at the current commit and checked out; the workflow returns its exact name, the exact base revision taken from repository authority, and the issue summary.',
|
|
36
|
+
refused: "No branch was created: Coder reported the failure with its reason, and the workflow fails and reports Coder's complete result to its caller.",
|
|
30
37
|
};
|
|
31
38
|
function playbookMeta(stateId, role) {
|
|
32
39
|
return {
|
|
@@ -37,9 +44,7 @@ function playbookMeta(stateId, role) {
|
|
|
37
44
|
},
|
|
38
45
|
};
|
|
39
46
|
}
|
|
40
|
-
|
|
41
|
-
// workflow succeeded or failed, so BRANCH's own caller learns that from the
|
|
42
|
-
// machine rather than from BRANCH's output fields.
|
|
47
|
+
/** A final state also publishes whether its outcome is success or failure. */
|
|
43
48
|
function terminalMeta(stateId, terminal) {
|
|
44
49
|
return {
|
|
45
50
|
playbook: {
|
|
@@ -59,33 +64,69 @@ function isRecord(value) {
|
|
|
59
64
|
function isNonEmptyString(value) {
|
|
60
65
|
return typeof value === 'string' && value.trim().length > 0;
|
|
61
66
|
}
|
|
62
|
-
|
|
63
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Narrows an unknown event's `output` structurally to the declared `player`
|
|
69
|
+
* contract. Output missing a field its guard requires narrows to `undefined`.
|
|
70
|
+
*/
|
|
71
|
+
function playerOutputOf(event) {
|
|
72
|
+
if (!isRecord(event) || !isRecord(event.output))
|
|
64
73
|
return undefined;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
74
|
+
const output = event.output;
|
|
75
|
+
if (output.guard === 'branched' &&
|
|
76
|
+
isNonEmptyString(output.branch) &&
|
|
77
|
+
isNonEmptyString(output.baseRevision) &&
|
|
78
|
+
isNonEmptyString(output.issueSummary)) {
|
|
79
|
+
return {
|
|
80
|
+
guard: 'branched',
|
|
81
|
+
branch: output.branch,
|
|
82
|
+
baseRevision: output.baseRevision,
|
|
83
|
+
issueSummary: output.issueSummary,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
if (output.guard === 'refused' && isNonEmptyString(output.coderOutput)) {
|
|
87
|
+
return { guard: 'refused', coderOutput: output.coderOutput };
|
|
88
|
+
}
|
|
89
|
+
if (output.guard === 'needsBossReply' && isNonEmptyString(output.question)) {
|
|
90
|
+
return { guard: 'needsBossReply', question: output.question };
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
73
93
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
94
|
+
/** Narrows an unknown event's `error` structurally to a JSON-safe record. */
|
|
95
|
+
function normalizedErrorOf(event) {
|
|
96
|
+
const error = isRecord(event) ? event.error : undefined;
|
|
97
|
+
if (error instanceof Error) {
|
|
98
|
+
const name = error.name || 'Error';
|
|
99
|
+
return typeof error.stack === 'string'
|
|
100
|
+
? { name, message: error.message, stack: error.stack }
|
|
101
|
+
: { name, message: error.message };
|
|
102
|
+
}
|
|
103
|
+
if (isRecord(error)) {
|
|
104
|
+
const name = typeof error.name === 'string' ? error.name : 'Error';
|
|
105
|
+
const message = typeof error.message === 'string'
|
|
106
|
+
? error.message
|
|
107
|
+
: 'player actor rejected without a normalized error';
|
|
108
|
+
return typeof error.stack === 'string'
|
|
109
|
+
? { name, message, stack: error.stack }
|
|
110
|
+
: { name, message };
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
name: 'Error',
|
|
114
|
+
message: typeof error === 'string'
|
|
115
|
+
? error
|
|
116
|
+
: 'player actor rejected without a normalized error',
|
|
117
|
+
};
|
|
81
118
|
}
|
|
82
|
-
function
|
|
83
|
-
return (
|
|
84
|
-
outputString(event, 'coderOutput') !== undefined);
|
|
119
|
+
function isResumableStateId(value) {
|
|
120
|
+
return RESUMABLE_STATE_IDS.includes(value);
|
|
85
121
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
122
|
+
/** Builds one guarded `BOSS_REPLY` resume arm per registered working-leaf id. */
|
|
123
|
+
function resumableStates(ids) {
|
|
124
|
+
return ids.map((id) => ({
|
|
125
|
+
guard: { type: 'canResume', params: { stateId: id } },
|
|
126
|
+
target: `#${id}`,
|
|
127
|
+
reenter: true,
|
|
128
|
+
actions: 'acceptBossReply',
|
|
129
|
+
}));
|
|
89
130
|
}
|
|
90
131
|
const machineSetup = setup({
|
|
91
132
|
types: {},
|
|
@@ -95,87 +136,114 @@ const machineSetup = setup({
|
|
|
95
136
|
}),
|
|
96
137
|
},
|
|
97
138
|
guards: {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
139
|
+
// The entry guard validates the text the current event supplies, before
|
|
140
|
+
// the entry action copies it into context.
|
|
141
|
+
givesRequest: ({ event }) => event.type === 'START_BRANCH' && isNonEmptyString(event.callerInput),
|
|
142
|
+
isBranched: ({ event }) => playerOutputOf(event)?.guard === 'branched',
|
|
143
|
+
isRefused: ({ event }) => playerOutputOf(event)?.guard === 'refused',
|
|
144
|
+
needsBossReply: ({ event }, params) => playerOutputOf(event)?.guard === 'needsBossReply' &&
|
|
145
|
+
isResumableStateId(params.stateId),
|
|
146
|
+
canResume: ({ context, event }, params) => {
|
|
147
|
+
if (event.type !== 'BOSS_REPLY' || !isNonEmptyString(event.answer)) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
const pending = context.pendingBossQuestion;
|
|
151
|
+
if (pending === undefined || pending.resumeStateId !== params.stateId) {
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
return (event.questionId === undefined ||
|
|
155
|
+
event.questionId === pending.questionId);
|
|
156
|
+
},
|
|
106
157
|
},
|
|
107
158
|
actions: {
|
|
108
159
|
'playbook.acceptedOutcome': (_args, _params) => undefined,
|
|
109
|
-
startBranch: assign(({ event }) => {
|
|
160
|
+
startBranch: assign(({ context, event }) => {
|
|
110
161
|
if (event.type !== 'START_BRANCH')
|
|
111
162
|
return {};
|
|
112
163
|
return {
|
|
113
164
|
callerInput: event.callerInput,
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
lastError: undefined,
|
|
120
|
-
pendingBossQuestion: undefined,
|
|
121
|
-
bossReply: undefined,
|
|
165
|
+
...(context.lastError === undefined ? {} : { lastError: undefined }),
|
|
166
|
+
...(context.pendingBossQuestion === undefined
|
|
167
|
+
? {}
|
|
168
|
+
: { pendingBossQuestion: undefined }),
|
|
169
|
+
...(context.bossReply === undefined ? {} : { bossReply: undefined }),
|
|
122
170
|
};
|
|
123
171
|
}),
|
|
124
|
-
rememberBranched: assign(({ event }) =>
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
const
|
|
141
|
-
if (
|
|
142
|
-
return {
|
|
143
|
-
|
|
172
|
+
rememberBranched: assign(({ context, event }) => {
|
|
173
|
+
const output = playerOutputOf(event);
|
|
174
|
+
if (output?.guard !== 'branched')
|
|
175
|
+
return {};
|
|
176
|
+
return {
|
|
177
|
+
branch: output.branch,
|
|
178
|
+
baseRevision: output.baseRevision,
|
|
179
|
+
issueSummary: output.issueSummary,
|
|
180
|
+
completion: 'branched',
|
|
181
|
+
...(context.pendingBossQuestion === undefined
|
|
182
|
+
? {}
|
|
183
|
+
: { pendingBossQuestion: undefined }),
|
|
184
|
+
...(context.bossReply === undefined ? {} : { bossReply: undefined }),
|
|
185
|
+
};
|
|
186
|
+
}),
|
|
187
|
+
rememberRefused: assign(({ context, event }) => {
|
|
188
|
+
const output = playerOutputOf(event);
|
|
189
|
+
if (output?.guard !== 'refused')
|
|
190
|
+
return {};
|
|
191
|
+
return {
|
|
192
|
+
coderOutput: output.coderOutput,
|
|
193
|
+
completion: 'refused',
|
|
194
|
+
...(context.pendingBossQuestion === undefined
|
|
195
|
+
? {}
|
|
196
|
+
: { pendingBossQuestion: undefined }),
|
|
197
|
+
...(context.bossReply === undefined ? {} : { bossReply: undefined }),
|
|
198
|
+
};
|
|
199
|
+
}),
|
|
200
|
+
setPendingBossQuestion: assign(({ context, event }, params) => {
|
|
201
|
+
const output = playerOutputOf(event);
|
|
202
|
+
if (output?.guard !== 'needsBossReply')
|
|
203
|
+
return {};
|
|
144
204
|
return {
|
|
145
205
|
pendingBossQuestion: {
|
|
146
|
-
questionId:
|
|
147
|
-
resumeStateId:
|
|
148
|
-
sourceItem:
|
|
206
|
+
questionId: params.stateId,
|
|
207
|
+
resumeStateId: params.stateId,
|
|
208
|
+
sourceItem: params.sourceItem,
|
|
149
209
|
asker: { kind: 'role', roleId: 'coder' },
|
|
150
|
-
question,
|
|
210
|
+
question: output.question,
|
|
151
211
|
},
|
|
152
|
-
bossReply: undefined,
|
|
212
|
+
...(context.bossReply === undefined ? {} : { bossReply: undefined }),
|
|
153
213
|
};
|
|
154
214
|
}),
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
bossReply: undefined,
|
|
160
|
-
}),
|
|
215
|
+
acceptBossReply: assign(({ event }) => event.type === 'BOSS_REPLY' ? { bossReply: event.answer } : {}),
|
|
216
|
+
clearBossReplyContext: assign(({ context }) => context.pendingBossQuestion === undefined &&
|
|
217
|
+
context.bossReply === undefined
|
|
218
|
+
? {}
|
|
219
|
+
: { pendingBossQuestion: undefined, bossReply: undefined }),
|
|
161
220
|
rememberActorError: assign(({ event }) => ({
|
|
162
|
-
lastError: event
|
|
221
|
+
lastError: normalizedErrorOf(event),
|
|
222
|
+
})),
|
|
223
|
+
rememberMalformedPlayerOutput: assign(() => ({
|
|
224
|
+
lastError: {
|
|
225
|
+
name: 'MalformedPlayerOutput',
|
|
226
|
+
message: 'Coder result for BRANCH-1 did not satisfy a declared outcome of its result contract.',
|
|
227
|
+
},
|
|
228
|
+
})),
|
|
229
|
+
rememberMalformedBossReply: assign(() => ({
|
|
230
|
+
lastError: {
|
|
231
|
+
name: 'MalformedBossReply',
|
|
232
|
+
message: 'BOSS_REPLY carried an empty answer or named no pending question.',
|
|
233
|
+
},
|
|
163
234
|
})),
|
|
164
|
-
rememberMalformedPlayerOutput: assign({
|
|
165
|
-
lastError: () => new Error('Coder result for BRANCH-1 did not match an available outcome.'),
|
|
166
|
-
}),
|
|
167
235
|
},
|
|
168
236
|
});
|
|
169
237
|
export const branchMachine = machineSetup.createMachine({
|
|
170
238
|
id: 'branch',
|
|
171
239
|
initial: 'ready',
|
|
172
|
-
context: {},
|
|
240
|
+
context: () => ({}),
|
|
173
241
|
output: ({ context }) => {
|
|
174
242
|
if (context.completion === 'branched') {
|
|
175
243
|
if (!isNonEmptyString(context.branch) ||
|
|
176
244
|
!isNonEmptyString(context.baseRevision) ||
|
|
177
245
|
!isNonEmptyString(context.issueSummary)) {
|
|
178
|
-
throw new Error('BRANCH reached branched without the exact branch name,
|
|
246
|
+
throw new Error('BRANCH reached branched without the exact branch name, base revision, and issue summary');
|
|
179
247
|
}
|
|
180
248
|
return {
|
|
181
249
|
status: 'branched',
|
|
@@ -186,7 +254,7 @@ export const branchMachine = machineSetup.createMachine({
|
|
|
186
254
|
}
|
|
187
255
|
if (context.completion === 'refused') {
|
|
188
256
|
if (!isNonEmptyString(context.coderOutput)) {
|
|
189
|
-
throw new Error("BRANCH reached refused without Coder's
|
|
257
|
+
throw new Error("BRANCH reached refused without Coder's complete result");
|
|
190
258
|
}
|
|
191
259
|
return { status: 'refused', coderOutput: context.coderOutput };
|
|
192
260
|
}
|
|
@@ -199,7 +267,11 @@ export const branchMachine = machineSetup.createMachine({
|
|
|
199
267
|
meta: playbookMeta('ready'),
|
|
200
268
|
tags: ['playbook.parked'],
|
|
201
269
|
on: {
|
|
202
|
-
START_BRANCH: {
|
|
270
|
+
START_BRANCH: {
|
|
271
|
+
guard: 'givesRequest',
|
|
272
|
+
target: 'createBranch',
|
|
273
|
+
actions: 'startBranch',
|
|
274
|
+
},
|
|
203
275
|
},
|
|
204
276
|
},
|
|
205
277
|
createBranch: {
|
|
@@ -215,6 +287,8 @@ export const branchMachine = machineSetup.createMachine({
|
|
|
215
287
|
sourceItem: 'BRANCH-1',
|
|
216
288
|
prompt: CREATE_BRANCH_PROMPT,
|
|
217
289
|
result: CREATE_BRANCH_RESULTS,
|
|
290
|
+
// Entry is guarded on a non-empty caller input, so this state is
|
|
291
|
+
// never entered without it.
|
|
218
292
|
callerInput: context.callerInput ?? '',
|
|
219
293
|
...(context.pendingBossQuestion === undefined
|
|
220
294
|
? {}
|
|
@@ -255,7 +329,10 @@ export const branchMachine = machineSetup.createMachine({
|
|
|
255
329
|
],
|
|
256
330
|
},
|
|
257
331
|
{
|
|
258
|
-
guard:
|
|
332
|
+
guard: {
|
|
333
|
+
type: 'needsBossReply',
|
|
334
|
+
params: { stateId: 'createBranch' },
|
|
335
|
+
},
|
|
259
336
|
target: 'awaitBossReply',
|
|
260
337
|
actions: [
|
|
261
338
|
{
|
|
@@ -266,7 +343,10 @@ export const branchMachine = machineSetup.createMachine({
|
|
|
266
343
|
acceptedOutcome: 'needsBossReply',
|
|
267
344
|
},
|
|
268
345
|
},
|
|
269
|
-
|
|
346
|
+
{
|
|
347
|
+
type: 'setPendingBossQuestion',
|
|
348
|
+
params: { stateId: 'createBranch', sourceItem: 'BRANCH-1' },
|
|
349
|
+
},
|
|
270
350
|
],
|
|
271
351
|
},
|
|
272
352
|
{
|
|
@@ -284,19 +364,17 @@ export const branchMachine = machineSetup.createMachine({
|
|
|
284
364
|
tags: ['playbook.parked'],
|
|
285
365
|
on: {
|
|
286
366
|
BOSS_REPLY: [
|
|
367
|
+
...resumableStates(RESUMABLE_STATE_IDS),
|
|
287
368
|
{
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
actions: 'rememberEmptyBossReplyError',
|
|
291
|
-
},
|
|
292
|
-
{
|
|
293
|
-
guard: 'resumesCreateBranch',
|
|
294
|
-
target: '#createBranch',
|
|
295
|
-
reenter: true,
|
|
296
|
-
actions: 'rememberBossReply',
|
|
369
|
+
target: 'failed',
|
|
370
|
+
actions: ['rememberMalformedBossReply', 'clearBossReplyContext'],
|
|
297
371
|
},
|
|
298
372
|
],
|
|
299
|
-
START_BRANCH: {
|
|
373
|
+
START_BRANCH: {
|
|
374
|
+
guard: 'givesRequest',
|
|
375
|
+
target: 'createBranch',
|
|
376
|
+
actions: 'startBranch',
|
|
377
|
+
},
|
|
300
378
|
},
|
|
301
379
|
},
|
|
302
380
|
failed: {
|
|
@@ -305,7 +383,11 @@ export const branchMachine = machineSetup.createMachine({
|
|
|
305
383
|
meta: playbookMeta('failed'),
|
|
306
384
|
tags: ['playbook.parked'],
|
|
307
385
|
on: {
|
|
308
|
-
START_BRANCH: {
|
|
386
|
+
START_BRANCH: {
|
|
387
|
+
guard: 'givesRequest',
|
|
388
|
+
target: 'createBranch',
|
|
389
|
+
actions: 'startBranch',
|
|
390
|
+
},
|
|
309
391
|
},
|
|
310
392
|
},
|
|
311
393
|
branched: {
|