@sublang/playbook 4.0.0 → 6.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 +69 -122
- package/docs/assets/playbook-venn.svg +13 -0
- package/docs/cli.md +43 -26
- package/docs/configuration.md +63 -18
- package/docs/embedding.md +24 -16
- package/package.json +43 -22
- package/reference/sdlc/captain.md +70 -83
- package/reference/sdlc/captain.playbook/captain.fsm.d.ts +127 -142
- package/reference/sdlc/captain.playbook/captain.fsm.js +349 -470
- package/reference/sdlc/captain.playbook/captain.fsm.ts +535 -598
- package/reference/sdlc/captain.playbook/captain.gears.md +37 -41
- package/reference/sdlc/captain.playbook/captain.playbook.d.ts +90 -15
- package/reference/sdlc/captain.playbook/captain.playbook.js +466 -976
- package/reference/sdlc/captain.playbook/captain.playbook.ts +698 -1001
- package/reference/sdlc/code.md +55 -97
- package/reference/sdlc/code.playbook/code.fsm.d.ts +229 -94
- package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +26 -44
- package/reference/sdlc/code.playbook/code.fsm.introspect.js +61 -66
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +100 -149
- package/reference/sdlc/code.playbook/code.fsm.js +587 -1347
- package/reference/sdlc/code.playbook/code.fsm.ts +809 -1650
- package/reference/sdlc/code.playbook/code.gears.md +51 -263
- package/reference/sdlc/code.playbook/code.playbook.d.ts +8 -47
- package/reference/sdlc/code.playbook/code.playbook.js +69 -639
- package/reference/sdlc/code.playbook/code.playbook.ts +90 -850
- package/reference/sdlc/code.playbook/code.registry.d.ts +9 -25
- package/reference/sdlc/code.playbook/code.registry.js +20 -78
- package/reference/sdlc/code.playbook/code.registry.ts +58 -122
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +2 -0
- package/reference/sdlc/code.playbook/playbook-captain.js +1877 -251
- package/reference/sdlc/code.playbook/playbook-captain.ts +2385 -352
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +33 -22
- package/reference/sdlc/decide.md +54 -0
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +261 -0
- package/reference/sdlc/decide.playbook/decide.fsm.js +894 -0
- package/reference/sdlc/decide.playbook/decide.fsm.ts +1152 -0
- package/reference/sdlc/decide.playbook/decide.gears.md +88 -0
- package/reference/sdlc/decide.playbook/decide.playbook.d.ts +67 -0
- package/reference/sdlc/{discuss.playbook/discuss.playbook.js → decide.playbook/decide.playbook.js} +511 -370
- package/reference/sdlc/{discuss.playbook/discuss.playbook.ts → decide.playbook/decide.playbook.ts} +616 -451
- package/reference/sdlc/decide.playbook/decide.registry.d.ts +41 -0
- package/reference/sdlc/decide.playbook/decide.registry.js +60 -0
- package/reference/sdlc/decide.playbook/decide.registry.ts +125 -0
- package/reference/sdlc/review.md +81 -0
- package/reference/sdlc/review.playbook/review.fsm.d.ts +183 -0
- package/reference/sdlc/review.playbook/review.fsm.js +524 -0
- package/reference/sdlc/review.playbook/review.fsm.ts +652 -0
- package/reference/sdlc/review.playbook/review.gears.md +112 -0
- package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -0
- package/reference/sdlc/review.playbook/review.playbook.js +112 -0
- package/reference/sdlc/review.playbook/review.playbook.ts +201 -0
- package/reference/sdlc/review.playbook/review.registry.d.ts +43 -0
- package/reference/sdlc/review.playbook/review.registry.js +73 -0
- package/reference/sdlc/review.playbook/review.registry.ts +138 -0
- package/slc/gears2fsm.md +67 -6
- package/slc/link.md +339 -25
- package/slc/text2gears.md +22 -2
- package/src/runtime.d.ts +36 -1
- package/src/runtime.ts +59 -0
- package/src/xstate-playbook-runtime.d.ts +96 -7
- package/src/xstate-playbook-runtime.js +1018 -49
- package/src/xstate-playbook-runtime.ts +1283 -59
- package/src/xstate-runtime.js +25 -0
- package/src/xstate-runtime.ts +51 -0
- package/reference/sdlc/discuss.md +0 -93
- package/reference/sdlc/discuss.playbook/discuss.fsm.d.ts +0 -396
- package/reference/sdlc/discuss.playbook/discuss.fsm.js +0 -2067
- package/reference/sdlc/discuss.playbook/discuss.fsm.ts +0 -2465
- package/reference/sdlc/discuss.playbook/discuss.gears.md +0 -258
- package/reference/sdlc/discuss.playbook/discuss.playbook.d.ts +0 -113
- package/reference/sdlc/discuss.playbook/discuss.registry.d.ts +0 -58
- package/reference/sdlc/discuss.playbook/discuss.registry.js +0 -97
- package/reference/sdlc/discuss.playbook/discuss.registry.ts +0 -153
|
@@ -1,2465 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
-
|
|
4
|
-
// FSM object artifact compiled from discuss.gears.md.
|
|
5
|
-
// This module defines the machine, actor contracts, and typed inputs only.
|
|
6
|
-
// It binds no runner and supplies no concrete player implementation; the runner
|
|
7
|
-
// provides the `player` actor via `.provide(...)`.
|
|
8
|
-
|
|
9
|
-
import { assign, fromPromise, setup } from 'xstate';
|
|
10
|
-
|
|
11
|
-
type Player = 'Host' | 'Participant' | 'Committer';
|
|
12
|
-
|
|
13
|
-
type ReviewScope = 'specItems' | 'decisionRecords' | 'mixed';
|
|
14
|
-
|
|
15
|
-
type JumpableStateId =
|
|
16
|
-
| 'ready'
|
|
17
|
-
| 'initialProposalRound'
|
|
18
|
-
| 'reconciliationRound'
|
|
19
|
-
| 'hostWritesAgreement'
|
|
20
|
-
| 'commitInitialChanges'
|
|
21
|
-
| 'reviewSpecInitialCommit'
|
|
22
|
-
| 'reviewSpecHostChanges'
|
|
23
|
-
| 'reviewDrInitialCommit'
|
|
24
|
-
| 'reviewDrHostChanges'
|
|
25
|
-
| 'reviewMixedInitialCommit'
|
|
26
|
-
| 'reviewMixedHostChanges'
|
|
27
|
-
| 'hostAddressesFindings'
|
|
28
|
-
| 'participantAddressesRebuttals'
|
|
29
|
-
| 'commitReviewedChanges'
|
|
30
|
-
| 'failed';
|
|
31
|
-
|
|
32
|
-
type ResumableStateId =
|
|
33
|
-
| 'askHostInitial'
|
|
34
|
-
| 'askParticipantInitial'
|
|
35
|
-
| 'hostInitialRound'
|
|
36
|
-
| 'participantInitialRound'
|
|
37
|
-
| Exclude<
|
|
38
|
-
JumpableStateId,
|
|
39
|
-
| 'ready'
|
|
40
|
-
| 'initialProposalRound'
|
|
41
|
-
| 'reconciliationRound'
|
|
42
|
-
| 'failed'
|
|
43
|
-
>;
|
|
44
|
-
|
|
45
|
-
export interface PendingBossQuestion {
|
|
46
|
-
questionId: ResumableStateId;
|
|
47
|
-
resumeStateId: ResumableStateId;
|
|
48
|
-
sourceItem: string;
|
|
49
|
-
player: Player;
|
|
50
|
-
question: string;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
type PendingBossQuestions = Partial<
|
|
54
|
-
Record<ResumableStateId, PendingBossQuestion>
|
|
55
|
-
>;
|
|
56
|
-
|
|
57
|
-
type BossReplies = Partial<Record<ResumableStateId, string>>;
|
|
58
|
-
|
|
59
|
-
type PendingBossQuestionParams = Omit<PendingBossQuestion, 'questionId'>;
|
|
60
|
-
|
|
61
|
-
export interface DiscussContext {
|
|
62
|
-
hostPlayer?: string;
|
|
63
|
-
participantPlayer?: string;
|
|
64
|
-
committerPlayer?: string;
|
|
65
|
-
topic?: string;
|
|
66
|
-
hostLlm?: string;
|
|
67
|
-
participantLlm?: string;
|
|
68
|
-
hostProposal?: string;
|
|
69
|
-
participantProposal?: string;
|
|
70
|
-
agreement?: string;
|
|
71
|
-
latestChanges?: string;
|
|
72
|
-
reviewScope?: ReviewScope;
|
|
73
|
-
reviewItems?: string;
|
|
74
|
-
rebuttals?: string;
|
|
75
|
-
lastResult?: PlayerOutput;
|
|
76
|
-
lastError?: unknown;
|
|
77
|
-
pendingBossQuestions?: PendingBossQuestions;
|
|
78
|
-
bossReplies?: BossReplies;
|
|
79
|
-
stagedHostResult?: PlayerOutput;
|
|
80
|
-
stagedParticipantResult?: PlayerOutput;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export type DiscussEvent =
|
|
84
|
-
| {
|
|
85
|
-
type: 'START_DISCUSSION';
|
|
86
|
-
topic: string;
|
|
87
|
-
hostLlm?: string;
|
|
88
|
-
participantLlm?: string;
|
|
89
|
-
}
|
|
90
|
-
| {
|
|
91
|
-
type: 'START_REVIEW';
|
|
92
|
-
latestChanges: string;
|
|
93
|
-
reviewScope: ReviewScope;
|
|
94
|
-
rebuttals?: string;
|
|
95
|
-
}
|
|
96
|
-
| { type: 'BOSS_INTERRUPT'; targetId: JumpableStateId }
|
|
97
|
-
| {
|
|
98
|
-
type: 'BOSS_REPLY';
|
|
99
|
-
questionId?: ResumableStateId;
|
|
100
|
-
answer: string;
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
export interface DiscussInput {
|
|
104
|
-
host?: string;
|
|
105
|
-
participant?: string;
|
|
106
|
-
committer?: string;
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export interface PlayerInput {
|
|
110
|
-
stateId: ResumableStateId;
|
|
111
|
-
sourceItem: string;
|
|
112
|
-
prompt: string;
|
|
113
|
-
result: Record<string, string>;
|
|
114
|
-
player: Player;
|
|
115
|
-
topic?: string;
|
|
116
|
-
hostLlm?: string;
|
|
117
|
-
participantLlm?: string;
|
|
118
|
-
hostProposal?: string;
|
|
119
|
-
participantProposal?: string;
|
|
120
|
-
agreement?: string;
|
|
121
|
-
latestChanges?: string;
|
|
122
|
-
reviewScope?: ReviewScope;
|
|
123
|
-
reviewItems?: string;
|
|
124
|
-
rebuttals?: string;
|
|
125
|
-
hostPlayer?: string;
|
|
126
|
-
participantPlayer?: string;
|
|
127
|
-
committerPlayer?: string;
|
|
128
|
-
pendingBossQuestion?: PendingBossQuestion;
|
|
129
|
-
bossReply?: string;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
type AdditionalPlayerFields = {
|
|
133
|
-
proposal?: string;
|
|
134
|
-
agreement?: string;
|
|
135
|
-
latestChanges?: string;
|
|
136
|
-
reviewScope?: ReviewScope;
|
|
137
|
-
reviewItems?: string;
|
|
138
|
-
rebuttals?: string;
|
|
139
|
-
question?: string;
|
|
140
|
-
readonly [key: string]: unknown;
|
|
141
|
-
};
|
|
142
|
-
|
|
143
|
-
export type PlayerOutput =
|
|
144
|
-
| ({ guard: 'proposalMade'; proposal: string } & AdditionalPlayerFields)
|
|
145
|
-
| ({ guard: 'endedInitialDiscussion'; agreement?: string } & AdditionalPlayerFields)
|
|
146
|
-
| ({
|
|
147
|
-
guard: 'wroteChanges';
|
|
148
|
-
latestChanges: string;
|
|
149
|
-
reviewScope: ReviewScope;
|
|
150
|
-
} & AdditionalPlayerFields)
|
|
151
|
-
| ({
|
|
152
|
-
guard: 'committed';
|
|
153
|
-
latestChanges?: string;
|
|
154
|
-
reviewScope?: ReviewScope;
|
|
155
|
-
} & AdditionalPlayerFields)
|
|
156
|
-
| ({ guard: 'noFindings' } & AdditionalPlayerFields)
|
|
157
|
-
| ({ guard: 'findingsRaised'; reviewItems: string } & AdditionalPlayerFields)
|
|
158
|
-
| ({
|
|
159
|
-
guard: 'changesMade';
|
|
160
|
-
latestChanges?: string;
|
|
161
|
-
reviewScope?: ReviewScope;
|
|
162
|
-
} & AdditionalPlayerFields)
|
|
163
|
-
| ({ guard: 'rebuttalsRaised'; rebuttals: string } & AdditionalPlayerFields)
|
|
164
|
-
| ({ guard: 'rebuttalsAddressed'; rebuttals?: string } & AdditionalPlayerFields)
|
|
165
|
-
| ({ guard: 'needsBossReply'; question: string } & AdditionalPlayerFields);
|
|
166
|
-
|
|
167
|
-
type PlayerDoneEvent = { type: string; output: PlayerOutput };
|
|
168
|
-
type PlayerErrorEvent = { type: string; error: unknown };
|
|
169
|
-
|
|
170
|
-
const NEEDS_BOSS_REPLY_DESCRIPTION =
|
|
171
|
-
"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>`.";
|
|
172
|
-
|
|
173
|
-
const DISCUSS_1_PROMPT = [
|
|
174
|
-
"Boss's topic: <topic>",
|
|
175
|
-
"Assess whether Boss's topic above is better expressed as a few spec items (per @specs/meta.md) or requires one or more DRs added to @specs/decisions/.",
|
|
176
|
-
'Consult @specs/map.md, if necessary, to find relevant context.',
|
|
177
|
-
'Each DR should be coherent and focused.',
|
|
178
|
-
'Propose your design in reply.',
|
|
179
|
-
'DRs, if any, need not include full detail here - describe the key points at a high level.',
|
|
180
|
-
"Don't change any code.",
|
|
181
|
-
].join('\n');
|
|
182
|
-
|
|
183
|
-
const DISCUSS_2_PROMPT = [
|
|
184
|
-
"Boss's topic: <topic>",
|
|
185
|
-
"Assess whether Boss's topic above is better expressed as a few spec items (per @specs/meta.md) or requires one or more DRs added to @specs/decisions/.",
|
|
186
|
-
'Consult @specs/map.md, if necessary, to find relevant context.',
|
|
187
|
-
'Each DR should be coherent and focused.',
|
|
188
|
-
'Propose your design in reply.',
|
|
189
|
-
'DRs, if any, need not include full detail here - describe the key points at a high level.',
|
|
190
|
-
"Don't change any code.",
|
|
191
|
-
].join('\n');
|
|
192
|
-
|
|
193
|
-
const DISCUSS_3_PROMPT = [
|
|
194
|
-
"Other agent's proposal: <participant-proposal>",
|
|
195
|
-
'Your previous proposal: <host-previous-proposal>',
|
|
196
|
-
"Consider the other agent's proposal below.",
|
|
197
|
-
'(1) If there are essentially different points (including creation or division of DRs), list them, accept any reasonable ones, and challenge the rest with strong reasoning, solid evidence, and comprehensive thinking - make your argument.',
|
|
198
|
-
"(2) Only if your proposal of the previous round is equivalent to the other's, with nothing to reconcile, state the end of initial discussion.",
|
|
199
|
-
"Don't change any code.",
|
|
200
|
-
].join('\n');
|
|
201
|
-
|
|
202
|
-
const DISCUSS_4_PROMPT = [
|
|
203
|
-
"Other agent's proposal: <host-proposal>",
|
|
204
|
-
'Your previous proposal: <participant-previous-proposal>',
|
|
205
|
-
"Consider the other agent's proposal below.",
|
|
206
|
-
'(1) If there are essentially different points (including creation or division of DRs), list them, accept any reasonable ones, and challenge the rest with strong reasoning, solid evidence, and comprehensive thinking - make your argument.',
|
|
207
|
-
"(2) Only if your proposal of the previous round is equivalent to the other's, with nothing to reconcile, state the end of initial discussion.",
|
|
208
|
-
"Don't change any code.",
|
|
209
|
-
].join('\n');
|
|
210
|
-
|
|
211
|
-
const DISCUSS_5_PROMPT = [
|
|
212
|
-
'Agreement: <agreement>',
|
|
213
|
-
'Write spec items or DRs according to the agreement.',
|
|
214
|
-
'Update @specs/map.md to reflect your changes (if any) when done.',
|
|
215
|
-
].join('\n');
|
|
216
|
-
|
|
217
|
-
const DISCUSS_6_PROMPT = [
|
|
218
|
-
'Latest changes: <changes>',
|
|
219
|
-
'Rebuttals to address, if any: <rebuttals>',
|
|
220
|
-
'Review the latest spec changes, address any rebuttals, and raise any findings.',
|
|
221
|
-
'Verify any new or updated spec items are:',
|
|
222
|
-
'Complete & coherent: sufficient for you to reimplement code.',
|
|
223
|
-
'Right level: external behavior users rely on or internal system behavior (organized per @specs/meta.md), not implementation specifics; integration/system testing, not unit testing.',
|
|
224
|
-
'Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
225
|
-
'Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
226
|
-
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
227
|
-
"Think thoroughly - don't just approve or reject.",
|
|
228
|
-
'For context discovery, consult @specs/map.md; @specs/meta.md describes the spec format.',
|
|
229
|
-
'Verify @specs/map.md reflects the changes.',
|
|
230
|
-
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
231
|
-
'Do not edit files or commit; report findings only.',
|
|
232
|
-
].join('\n');
|
|
233
|
-
|
|
234
|
-
const DISCUSS_7_PROMPT = DISCUSS_6_PROMPT;
|
|
235
|
-
|
|
236
|
-
const DISCUSS_8_PROMPT = [
|
|
237
|
-
'Latest changes: <changes>',
|
|
238
|
-
'Rebuttals to address, if any: <rebuttals>',
|
|
239
|
-
'Review the latest spec changes, address any rebuttals, and raise any findings.',
|
|
240
|
-
'Review any new/updated decision following @specs/meta.md (reread if necessary).',
|
|
241
|
-
'Flag any issues or propose any design suggestions (numbered; no duplication), with strong reasoning and evidence.',
|
|
242
|
-
'Key statements must be backed by references unless they are common sense or widely acknowledged best practices.',
|
|
243
|
-
"If the decision is well-thought-out and well-written, don't raise nitpicks.",
|
|
244
|
-
'Remember to keep the DR simple and minimal.',
|
|
245
|
-
"Think thoroughly - don't just approve or reject.",
|
|
246
|
-
'For context discovery, consult @specs/map.md; @specs/meta.md describes the spec format.',
|
|
247
|
-
'Verify @specs/map.md reflects the changes.',
|
|
248
|
-
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
249
|
-
'Do not edit files or commit; report findings only.',
|
|
250
|
-
].join('\n');
|
|
251
|
-
|
|
252
|
-
const DISCUSS_9_PROMPT = DISCUSS_8_PROMPT;
|
|
253
|
-
|
|
254
|
-
const DISCUSS_10_PROMPT = [
|
|
255
|
-
'Latest changes: <changes>',
|
|
256
|
-
'Rebuttals to address, if any: <rebuttals>',
|
|
257
|
-
'Review the latest spec changes, address any rebuttals, and raise any findings.',
|
|
258
|
-
'Verify any new or updated spec items are:',
|
|
259
|
-
'Complete & coherent: sufficient for you to reimplement code.',
|
|
260
|
-
'Right level: external behavior users rely on or internal system behavior (organized per @specs/meta.md), not implementation specifics; integration/system testing, not unit testing.',
|
|
261
|
-
'Minimal: essential and concise; every item earns its place; also check with other items.',
|
|
262
|
-
'Well organized: spec packages are finely scoped, with high cohesion and low coupling.',
|
|
263
|
-
'Flag anything missing, redundant, over-specified, or under-specified.',
|
|
264
|
-
'Review any new/updated decision following @specs/meta.md (reread if necessary).',
|
|
265
|
-
'Flag any issues or propose any design suggestions (numbered; no duplication), with strong reasoning and evidence.',
|
|
266
|
-
'Key statements must be backed by references unless they are common sense or widely acknowledged best practices.',
|
|
267
|
-
"If the decision is well-thought-out and well-written, don't raise nitpicks.",
|
|
268
|
-
'Remember to keep the DR simple and minimal.',
|
|
269
|
-
"Think thoroughly - don't just approve or reject.",
|
|
270
|
-
'For context discovery, consult @specs/map.md; @specs/meta.md describes the spec format.',
|
|
271
|
-
'Verify @specs/map.md reflects the changes.',
|
|
272
|
-
"If the change is ready to commit or push, don't raise nitpicks.",
|
|
273
|
-
'Do not edit files or commit; report findings only.',
|
|
274
|
-
].join('\n');
|
|
275
|
-
|
|
276
|
-
const DISCUSS_11_PROMPT = DISCUSS_10_PROMPT;
|
|
277
|
-
|
|
278
|
-
const DISCUSS_12_PROMPT = [
|
|
279
|
-
'Review items: <review-items>',
|
|
280
|
-
'For each review item below for the above changes, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.',
|
|
281
|
-
'Stage all current changes that belong in the repo before making any edits, and leave your edits unstaged/untracked.',
|
|
282
|
-
].join('\n');
|
|
283
|
-
|
|
284
|
-
const DISCUSS_13_PROMPT = [
|
|
285
|
-
'Rebuttals: <rebuttals>',
|
|
286
|
-
'For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.',
|
|
287
|
-
].join('\n');
|
|
288
|
-
|
|
289
|
-
const DISCUSS_14_PROMPT = [
|
|
290
|
-
'Then make a commit of the changes that belong in the repo, following @specs/packages/git.md (reread if necessary).',
|
|
291
|
-
"If that spec is absent, follow the legacy @specs/dev/git.md; if neither exists, follow the repository's existing commit conventions and do not search elsewhere.",
|
|
292
|
-
'Write the commit message concisely.',
|
|
293
|
-
'Host is <host-llm>.',
|
|
294
|
-
'Participant is <participant-llm>.',
|
|
295
|
-
'Format the Host and Participant model IDs as conventional human forms.',
|
|
296
|
-
].join('\n');
|
|
297
|
-
|
|
298
|
-
const DISCUSS_15_PROMPT = DISCUSS_14_PROMPT;
|
|
299
|
-
|
|
300
|
-
const jumpableStateIds = [
|
|
301
|
-
'ready',
|
|
302
|
-
'initialProposalRound',
|
|
303
|
-
'reconciliationRound',
|
|
304
|
-
'hostWritesAgreement',
|
|
305
|
-
'commitInitialChanges',
|
|
306
|
-
'reviewSpecInitialCommit',
|
|
307
|
-
'reviewSpecHostChanges',
|
|
308
|
-
'reviewDrInitialCommit',
|
|
309
|
-
'reviewDrHostChanges',
|
|
310
|
-
'reviewMixedInitialCommit',
|
|
311
|
-
'reviewMixedHostChanges',
|
|
312
|
-
'hostAddressesFindings',
|
|
313
|
-
'participantAddressesRebuttals',
|
|
314
|
-
'commitReviewedChanges',
|
|
315
|
-
'failed',
|
|
316
|
-
] as const satisfies readonly JumpableStateId[];
|
|
317
|
-
|
|
318
|
-
const resumableStateIds = [
|
|
319
|
-
'askHostInitial',
|
|
320
|
-
'askParticipantInitial',
|
|
321
|
-
'hostInitialRound',
|
|
322
|
-
'participantInitialRound',
|
|
323
|
-
'hostWritesAgreement',
|
|
324
|
-
'commitInitialChanges',
|
|
325
|
-
'reviewSpecInitialCommit',
|
|
326
|
-
'reviewSpecHostChanges',
|
|
327
|
-
'reviewDrInitialCommit',
|
|
328
|
-
'reviewDrHostChanges',
|
|
329
|
-
'reviewMixedInitialCommit',
|
|
330
|
-
'reviewMixedHostChanges',
|
|
331
|
-
'hostAddressesFindings',
|
|
332
|
-
'participantAddressesRebuttals',
|
|
333
|
-
'commitReviewedChanges',
|
|
334
|
-
] as const satisfies readonly ResumableStateId[];
|
|
335
|
-
|
|
336
|
-
const outputOf = (event: unknown): PlayerOutput =>
|
|
337
|
-
(event as PlayerDoneEvent).output;
|
|
338
|
-
|
|
339
|
-
const guardIs =
|
|
340
|
-
(guard: string) =>
|
|
341
|
-
({ event }: { event: unknown }) =>
|
|
342
|
-
outputOf(event).guard === guard;
|
|
343
|
-
|
|
344
|
-
const needsBossReplyWithQuestion = ({ event }: { event: unknown }) => {
|
|
345
|
-
const output = outputOf(event);
|
|
346
|
-
return (
|
|
347
|
-
output.guard === 'needsBossReply' &&
|
|
348
|
-
typeof output.question === 'string' &&
|
|
349
|
-
output.question.trim().length > 0
|
|
350
|
-
);
|
|
351
|
-
};
|
|
352
|
-
|
|
353
|
-
const needsBossReplyWithoutQuestion = ({ event }: { event: unknown }) => {
|
|
354
|
-
const output = outputOf(event);
|
|
355
|
-
return (
|
|
356
|
-
output.guard === 'needsBossReply' &&
|
|
357
|
-
(typeof output.question !== 'string' || output.question.trim().length === 0)
|
|
358
|
-
);
|
|
359
|
-
};
|
|
360
|
-
|
|
361
|
-
const emptyBossReply = ({ event }: { event: DiscussEvent }) =>
|
|
362
|
-
event.type === 'BOSS_REPLY' && event.answer.trim().length === 0;
|
|
363
|
-
|
|
364
|
-
const pendingQuestionIds = (context: DiscussContext): ResumableStateId[] =>
|
|
365
|
-
Object.keys(context.pendingBossQuestions ?? {}) as ResumableStateId[];
|
|
366
|
-
|
|
367
|
-
const resolvedQuestionId = (
|
|
368
|
-
context: DiscussContext,
|
|
369
|
-
event: DiscussEvent,
|
|
370
|
-
): ResumableStateId | undefined => {
|
|
371
|
-
if (event.type !== 'BOSS_REPLY') return undefined;
|
|
372
|
-
if (event.questionId) return event.questionId;
|
|
373
|
-
const ids = pendingQuestionIds(context);
|
|
374
|
-
return ids.length === 1 ? ids[0] : undefined;
|
|
375
|
-
};
|
|
376
|
-
|
|
377
|
-
const bossReplyTargets =
|
|
378
|
-
(stateId: ResumableStateId, requireAnswer: boolean) =>
|
|
379
|
-
({ context, event }: { context: DiscussContext; event: DiscussEvent }) =>
|
|
380
|
-
event.type === 'BOSS_REPLY' &&
|
|
381
|
-
resolvedQuestionId(context, event) === stateId &&
|
|
382
|
-
(requireAnswer
|
|
383
|
-
? event.answer.trim().length > 0
|
|
384
|
-
: event.answer.trim().length === 0);
|
|
385
|
-
|
|
386
|
-
const hasReviewScope =
|
|
387
|
-
(scope: ReviewScope) =>
|
|
388
|
-
({ context, event }: { context: DiscussContext; event: DiscussEvent }) =>
|
|
389
|
-
event.type === 'START_REVIEW'
|
|
390
|
-
? event.reviewScope === scope
|
|
391
|
-
: context.reviewScope === scope;
|
|
392
|
-
|
|
393
|
-
const hasContextText = (value: unknown): value is string =>
|
|
394
|
-
typeof value === 'string' && value.trim().length > 0;
|
|
395
|
-
|
|
396
|
-
const hasKnownReviewScope = (
|
|
397
|
-
context: DiscussContext,
|
|
398
|
-
scope?: ReviewScope,
|
|
399
|
-
): boolean =>
|
|
400
|
-
scope === undefined
|
|
401
|
-
? context.reviewScope === 'specItems' ||
|
|
402
|
-
context.reviewScope === 'decisionRecords' ||
|
|
403
|
-
context.reviewScope === 'mixed'
|
|
404
|
-
: context.reviewScope === scope;
|
|
405
|
-
|
|
406
|
-
function canInterruptTo(
|
|
407
|
-
context: DiscussContext,
|
|
408
|
-
targetId: JumpableStateId,
|
|
409
|
-
): boolean {
|
|
410
|
-
switch (targetId) {
|
|
411
|
-
case 'ready':
|
|
412
|
-
case 'failed':
|
|
413
|
-
return true;
|
|
414
|
-
case 'initialProposalRound':
|
|
415
|
-
return hasContextText(context.topic);
|
|
416
|
-
case 'reconciliationRound':
|
|
417
|
-
return (
|
|
418
|
-
hasContextText(context.hostProposal) &&
|
|
419
|
-
hasContextText(context.participantProposal)
|
|
420
|
-
);
|
|
421
|
-
case 'hostWritesAgreement':
|
|
422
|
-
return hasContextText(context.agreement);
|
|
423
|
-
case 'commitInitialChanges':
|
|
424
|
-
return (
|
|
425
|
-
hasContextText(context.latestChanges) &&
|
|
426
|
-
hasKnownReviewScope(context)
|
|
427
|
-
);
|
|
428
|
-
case 'reviewSpecInitialCommit':
|
|
429
|
-
case 'reviewSpecHostChanges':
|
|
430
|
-
return (
|
|
431
|
-
hasContextText(context.latestChanges) &&
|
|
432
|
-
hasKnownReviewScope(context, 'specItems')
|
|
433
|
-
);
|
|
434
|
-
case 'reviewDrInitialCommit':
|
|
435
|
-
case 'reviewDrHostChanges':
|
|
436
|
-
return (
|
|
437
|
-
hasContextText(context.latestChanges) &&
|
|
438
|
-
hasKnownReviewScope(context, 'decisionRecords')
|
|
439
|
-
);
|
|
440
|
-
case 'reviewMixedInitialCommit':
|
|
441
|
-
case 'reviewMixedHostChanges':
|
|
442
|
-
return (
|
|
443
|
-
hasContextText(context.latestChanges) &&
|
|
444
|
-
hasKnownReviewScope(context, 'mixed')
|
|
445
|
-
);
|
|
446
|
-
case 'hostAddressesFindings':
|
|
447
|
-
return (
|
|
448
|
-
hasContextText(context.latestChanges) &&
|
|
449
|
-
hasContextText(context.reviewItems) &&
|
|
450
|
-
hasKnownReviewScope(context)
|
|
451
|
-
);
|
|
452
|
-
case 'participantAddressesRebuttals':
|
|
453
|
-
return (
|
|
454
|
-
hasContextText(context.latestChanges) &&
|
|
455
|
-
hasContextText(context.reviewItems) &&
|
|
456
|
-
hasContextText(context.rebuttals) &&
|
|
457
|
-
hasKnownReviewScope(context)
|
|
458
|
-
);
|
|
459
|
-
case 'commitReviewedChanges':
|
|
460
|
-
return hasContextText(context.latestChanges);
|
|
461
|
-
}
|
|
462
|
-
}
|
|
463
|
-
|
|
464
|
-
type DiscussActionName =
|
|
465
|
-
| 'copyStartDiscussion'
|
|
466
|
-
| 'copyStartReview'
|
|
467
|
-
| 'rememberHostProposal'
|
|
468
|
-
| 'rememberParticipantProposal'
|
|
469
|
-
| 'rememberAgreement'
|
|
470
|
-
| 'rememberWrittenChanges'
|
|
471
|
-
| 'rememberCommittedChanges'
|
|
472
|
-
| 'rememberReviewFindings'
|
|
473
|
-
| 'rememberHostReviewResponse'
|
|
474
|
-
| 'rememberParticipantRebuttalResponse'
|
|
475
|
-
| 'rememberCaptainResult'
|
|
476
|
-
| 'rememberCaptainError'
|
|
477
|
-
| 'rememberMalformedCaptainOutput'
|
|
478
|
-
| 'rememberMalformedBossReply'
|
|
479
|
-
| 'setPendingBossQuestion'
|
|
480
|
-
| 'rememberBossReply'
|
|
481
|
-
| 'clearBranchBossReplyContext'
|
|
482
|
-
| 'clearParallelRoundContext'
|
|
483
|
-
| 'clearBossReplyContext';
|
|
484
|
-
|
|
485
|
-
function bossInterrupts(
|
|
486
|
-
ids: readonly JumpableStateId[],
|
|
487
|
-
actions?: DiscussActionName | DiscussActionName[],
|
|
488
|
-
): any[] {
|
|
489
|
-
return ids.map((id) => ({
|
|
490
|
-
guard: ({
|
|
491
|
-
context,
|
|
492
|
-
event,
|
|
493
|
-
}: {
|
|
494
|
-
context: DiscussContext;
|
|
495
|
-
event: DiscussEvent;
|
|
496
|
-
}) =>
|
|
497
|
-
event.type === 'BOSS_INTERRUPT' &&
|
|
498
|
-
event.targetId === id &&
|
|
499
|
-
canInterruptTo(context, id),
|
|
500
|
-
target: `#${id}`,
|
|
501
|
-
reenter: true,
|
|
502
|
-
...(actions ? { actions } : {}),
|
|
503
|
-
}));
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
function resumableStates(ids: readonly string[]): any[] {
|
|
507
|
-
return ids.map((id) => ({
|
|
508
|
-
guard: ({
|
|
509
|
-
context,
|
|
510
|
-
event,
|
|
511
|
-
}: {
|
|
512
|
-
context: DiscussContext;
|
|
513
|
-
event: DiscussEvent;
|
|
514
|
-
}) =>
|
|
515
|
-
event.type === 'BOSS_REPLY' &&
|
|
516
|
-
event.answer.trim().length > 0 &&
|
|
517
|
-
resolvedQuestionId(context, event) === id,
|
|
518
|
-
target: `#${id}`,
|
|
519
|
-
reenter: true,
|
|
520
|
-
actions: 'rememberBossReply',
|
|
521
|
-
}));
|
|
522
|
-
}
|
|
523
|
-
|
|
524
|
-
const bossReplyFields = (
|
|
525
|
-
context: DiscussContext,
|
|
526
|
-
stateId: ResumableStateId,
|
|
527
|
-
) => ({
|
|
528
|
-
...(context.pendingBossQuestions?.[stateId]
|
|
529
|
-
? { pendingBossQuestion: context.pendingBossQuestions[stateId] }
|
|
530
|
-
: {}),
|
|
531
|
-
...(context.bossReplies?.[stateId]
|
|
532
|
-
? { bossReply: context.bossReplies[stateId] }
|
|
533
|
-
: {}),
|
|
534
|
-
});
|
|
535
|
-
|
|
536
|
-
const withoutKey = <T>(
|
|
537
|
-
record: Partial<Record<ResumableStateId, T>> | undefined,
|
|
538
|
-
stateId: ResumableStateId,
|
|
539
|
-
): Partial<Record<ResumableStateId, T>> | undefined => {
|
|
540
|
-
if (!record || record[stateId] === undefined) return record;
|
|
541
|
-
const next = { ...record };
|
|
542
|
-
delete next[stateId];
|
|
543
|
-
return Object.keys(next).length > 0 ? next : undefined;
|
|
544
|
-
};
|
|
545
|
-
|
|
546
|
-
const bothEndedInitialDiscussion = ({ context }: { context: DiscussContext }) =>
|
|
547
|
-
context.stagedHostResult?.guard === 'endedInitialDiscussion' &&
|
|
548
|
-
context.stagedParticipantResult?.guard === 'endedInitialDiscussion';
|
|
549
|
-
|
|
550
|
-
const withNeedsBossReply = <T extends Record<string, string>>(result: T) => ({
|
|
551
|
-
...result,
|
|
552
|
-
needsBossReply: NEEDS_BOSS_REPLY_DESCRIPTION,
|
|
553
|
-
});
|
|
554
|
-
|
|
555
|
-
const captainStateMetadata: Record<
|
|
556
|
-
ResumableStateId,
|
|
557
|
-
{ sourceItem: string; player: Player }
|
|
558
|
-
> = {
|
|
559
|
-
askHostInitial: { sourceItem: 'DISCUSS-1', player: 'Host' },
|
|
560
|
-
askParticipantInitial: { sourceItem: 'DISCUSS-2', player: 'Participant' },
|
|
561
|
-
hostInitialRound: { sourceItem: 'DISCUSS-3', player: 'Host' },
|
|
562
|
-
participantInitialRound: { sourceItem: 'DISCUSS-4', player: 'Participant' },
|
|
563
|
-
hostWritesAgreement: { sourceItem: 'DISCUSS-5', player: 'Host' },
|
|
564
|
-
commitInitialChanges: { sourceItem: 'DISCUSS-14', player: 'Committer' },
|
|
565
|
-
reviewSpecInitialCommit: { sourceItem: 'DISCUSS-6', player: 'Participant' },
|
|
566
|
-
reviewSpecHostChanges: { sourceItem: 'DISCUSS-7', player: 'Participant' },
|
|
567
|
-
reviewDrInitialCommit: { sourceItem: 'DISCUSS-8', player: 'Participant' },
|
|
568
|
-
reviewDrHostChanges: { sourceItem: 'DISCUSS-9', player: 'Participant' },
|
|
569
|
-
reviewMixedInitialCommit: { sourceItem: 'DISCUSS-10', player: 'Participant' },
|
|
570
|
-
reviewMixedHostChanges: { sourceItem: 'DISCUSS-11', player: 'Participant' },
|
|
571
|
-
hostAddressesFindings: { sourceItem: 'DISCUSS-12', player: 'Host' },
|
|
572
|
-
participantAddressesRebuttals: {
|
|
573
|
-
sourceItem: 'DISCUSS-13',
|
|
574
|
-
player: 'Participant',
|
|
575
|
-
},
|
|
576
|
-
commitReviewedChanges: { sourceItem: 'DISCUSS-15', player: 'Committer' },
|
|
577
|
-
};
|
|
578
|
-
|
|
579
|
-
const reviewTargets = {
|
|
580
|
-
specItems: {
|
|
581
|
-
initial: 'reviewSpecInitialCommit',
|
|
582
|
-
afterChanges: 'reviewSpecHostChanges',
|
|
583
|
-
},
|
|
584
|
-
decisionRecords: {
|
|
585
|
-
initial: 'reviewDrInitialCommit',
|
|
586
|
-
afterChanges: 'reviewDrHostChanges',
|
|
587
|
-
},
|
|
588
|
-
mixed: {
|
|
589
|
-
initial: 'reviewMixedInitialCommit',
|
|
590
|
-
afterChanges: 'reviewMixedHostChanges',
|
|
591
|
-
},
|
|
592
|
-
} satisfies Record<ReviewScope, { initial: string; afterChanges: string }>;
|
|
593
|
-
|
|
594
|
-
export const discussMachine = setup({
|
|
595
|
-
types: {
|
|
596
|
-
context: {} as DiscussContext,
|
|
597
|
-
events: {} as DiscussEvent,
|
|
598
|
-
input: {} as DiscussInput,
|
|
599
|
-
},
|
|
600
|
-
actors: {
|
|
601
|
-
player: fromPromise<PlayerOutput, PlayerInput>(async () => {
|
|
602
|
-
throw new Error('player actor must be provided by the runner');
|
|
603
|
-
}),
|
|
604
|
-
},
|
|
605
|
-
actions: {
|
|
606
|
-
copyStartDiscussion: assign({
|
|
607
|
-
topic: ({ event }) =>
|
|
608
|
-
event.type === 'START_DISCUSSION' ? event.topic : undefined,
|
|
609
|
-
// Optional per-run identities: an event that omits them must not clear
|
|
610
|
-
// the input-seeded context values (gears2fsm.md, Boss entry events).
|
|
611
|
-
hostLlm: ({ context, event }) =>
|
|
612
|
-
event.type === 'START_DISCUSSION'
|
|
613
|
-
? (event.hostLlm ?? context.hostLlm)
|
|
614
|
-
: context.hostLlm,
|
|
615
|
-
participantLlm: ({ context, event }) =>
|
|
616
|
-
event.type === 'START_DISCUSSION'
|
|
617
|
-
? (event.participantLlm ?? context.participantLlm)
|
|
618
|
-
: context.participantLlm,
|
|
619
|
-
hostProposal: undefined,
|
|
620
|
-
participantProposal: undefined,
|
|
621
|
-
agreement: undefined,
|
|
622
|
-
latestChanges: undefined,
|
|
623
|
-
reviewScope: undefined,
|
|
624
|
-
reviewItems: undefined,
|
|
625
|
-
rebuttals: undefined,
|
|
626
|
-
lastResult: undefined,
|
|
627
|
-
lastError: undefined,
|
|
628
|
-
pendingBossQuestions: undefined,
|
|
629
|
-
bossReplies: undefined,
|
|
630
|
-
stagedHostResult: undefined,
|
|
631
|
-
stagedParticipantResult: undefined,
|
|
632
|
-
}),
|
|
633
|
-
copyStartReview: assign({
|
|
634
|
-
latestChanges: ({ event }) =>
|
|
635
|
-
event.type === 'START_REVIEW' ? event.latestChanges : undefined,
|
|
636
|
-
reviewScope: ({ event }) =>
|
|
637
|
-
event.type === 'START_REVIEW' ? event.reviewScope : undefined,
|
|
638
|
-
rebuttals: ({ event }) =>
|
|
639
|
-
event.type === 'START_REVIEW' ? event.rebuttals : undefined,
|
|
640
|
-
reviewItems: undefined,
|
|
641
|
-
lastResult: undefined,
|
|
642
|
-
lastError: undefined,
|
|
643
|
-
pendingBossQuestions: undefined,
|
|
644
|
-
bossReplies: undefined,
|
|
645
|
-
stagedHostResult: undefined,
|
|
646
|
-
stagedParticipantResult: undefined,
|
|
647
|
-
}),
|
|
648
|
-
rememberHostProposal: assign({
|
|
649
|
-
hostProposal: ({ event }) => outputOf(event).proposal,
|
|
650
|
-
lastResult: ({ event }) => outputOf(event),
|
|
651
|
-
lastError: undefined,
|
|
652
|
-
}),
|
|
653
|
-
rememberParticipantProposal: assign({
|
|
654
|
-
participantProposal: ({ event }) => outputOf(event).proposal,
|
|
655
|
-
lastResult: ({ event }) => outputOf(event),
|
|
656
|
-
lastError: undefined,
|
|
657
|
-
}),
|
|
658
|
-
stageHostResult: assign({
|
|
659
|
-
stagedHostResult: ({ event }) => outputOf(event),
|
|
660
|
-
lastResult: ({ event }) => outputOf(event),
|
|
661
|
-
lastError: undefined,
|
|
662
|
-
}),
|
|
663
|
-
stageParticipantResult: assign({
|
|
664
|
-
stagedParticipantResult: ({ event }) => outputOf(event),
|
|
665
|
-
lastResult: ({ event }) => outputOf(event),
|
|
666
|
-
lastError: undefined,
|
|
667
|
-
}),
|
|
668
|
-
promoteInitialResults: assign({
|
|
669
|
-
hostProposal: ({ context }) => context.stagedHostResult?.proposal,
|
|
670
|
-
participantProposal: ({ context }) =>
|
|
671
|
-
context.stagedParticipantResult?.proposal,
|
|
672
|
-
stagedHostResult: undefined,
|
|
673
|
-
stagedParticipantResult: undefined,
|
|
674
|
-
lastResult: undefined,
|
|
675
|
-
lastError: undefined,
|
|
676
|
-
}),
|
|
677
|
-
promoteReconciliationResults: assign({
|
|
678
|
-
hostProposal: ({ context }) =>
|
|
679
|
-
context.stagedHostResult?.proposal ?? context.hostProposal,
|
|
680
|
-
participantProposal: ({ context }) =>
|
|
681
|
-
context.stagedParticipantResult?.proposal ??
|
|
682
|
-
context.participantProposal,
|
|
683
|
-
agreement: ({ context }) => {
|
|
684
|
-
const host = context.stagedHostResult;
|
|
685
|
-
const participant = context.stagedParticipantResult;
|
|
686
|
-
if (
|
|
687
|
-
host?.guard === 'endedInitialDiscussion' &&
|
|
688
|
-
participant?.guard === 'endedInitialDiscussion'
|
|
689
|
-
) {
|
|
690
|
-
return (
|
|
691
|
-
participant.agreement ??
|
|
692
|
-
host.agreement ??
|
|
693
|
-
context.agreement ??
|
|
694
|
-
participant.proposal ??
|
|
695
|
-
host.proposal ??
|
|
696
|
-
context.participantProposal ??
|
|
697
|
-
context.hostProposal
|
|
698
|
-
);
|
|
699
|
-
}
|
|
700
|
-
if (participant?.guard === 'endedInitialDiscussion') {
|
|
701
|
-
return participant.agreement ?? context.agreement;
|
|
702
|
-
}
|
|
703
|
-
if (host?.guard === 'endedInitialDiscussion') {
|
|
704
|
-
return host.agreement ?? context.agreement;
|
|
705
|
-
}
|
|
706
|
-
return context.agreement;
|
|
707
|
-
},
|
|
708
|
-
stagedHostResult: undefined,
|
|
709
|
-
stagedParticipantResult: undefined,
|
|
710
|
-
lastResult: undefined,
|
|
711
|
-
lastError: undefined,
|
|
712
|
-
}),
|
|
713
|
-
rememberAgreement: assign({
|
|
714
|
-
agreement: ({ context, event }) =>
|
|
715
|
-
outputOf(event).agreement ??
|
|
716
|
-
context.agreement ??
|
|
717
|
-
outputOf(event).proposal ??
|
|
718
|
-
context.hostProposal,
|
|
719
|
-
hostProposal: ({ context, event }) =>
|
|
720
|
-
outputOf(event).proposal ?? context.hostProposal,
|
|
721
|
-
participantProposal: ({ context }) => context.participantProposal,
|
|
722
|
-
lastResult: ({ event }) => outputOf(event),
|
|
723
|
-
lastError: undefined,
|
|
724
|
-
}),
|
|
725
|
-
rememberWrittenChanges: assign({
|
|
726
|
-
latestChanges: ({ event }) => outputOf(event).latestChanges,
|
|
727
|
-
reviewScope: ({ event }) => outputOf(event).reviewScope,
|
|
728
|
-
agreement: ({ context, event }) =>
|
|
729
|
-
outputOf(event).agreement ?? context.agreement,
|
|
730
|
-
lastResult: ({ event }) => outputOf(event),
|
|
731
|
-
lastError: undefined,
|
|
732
|
-
}),
|
|
733
|
-
rememberCommittedChanges: assign({
|
|
734
|
-
latestChanges: ({ context, event }) =>
|
|
735
|
-
outputOf(event).latestChanges ?? context.latestChanges,
|
|
736
|
-
reviewScope: ({ context, event }) =>
|
|
737
|
-
outputOf(event).reviewScope ?? context.reviewScope,
|
|
738
|
-
lastResult: ({ event }) => outputOf(event),
|
|
739
|
-
lastError: undefined,
|
|
740
|
-
}),
|
|
741
|
-
rememberReviewFindings: assign({
|
|
742
|
-
reviewItems: ({ event }) => outputOf(event).reviewItems,
|
|
743
|
-
rebuttals: ({ context, event }) =>
|
|
744
|
-
outputOf(event).rebuttals ?? context.rebuttals,
|
|
745
|
-
lastResult: ({ event }) => outputOf(event),
|
|
746
|
-
lastError: undefined,
|
|
747
|
-
}),
|
|
748
|
-
rememberHostReviewResponse: assign({
|
|
749
|
-
latestChanges: ({ context, event }) =>
|
|
750
|
-
outputOf(event).latestChanges ?? context.latestChanges,
|
|
751
|
-
rebuttals: ({ event }) => outputOf(event).rebuttals,
|
|
752
|
-
lastResult: ({ event }) => outputOf(event),
|
|
753
|
-
lastError: undefined,
|
|
754
|
-
}),
|
|
755
|
-
rememberParticipantRebuttalResponse: assign({
|
|
756
|
-
rebuttals: ({ event }) => outputOf(event).rebuttals,
|
|
757
|
-
lastResult: ({ event }) => outputOf(event),
|
|
758
|
-
lastError: undefined,
|
|
759
|
-
}),
|
|
760
|
-
rememberCaptainResult: assign({
|
|
761
|
-
lastResult: ({ event }) => outputOf(event),
|
|
762
|
-
lastError: undefined,
|
|
763
|
-
}),
|
|
764
|
-
rememberCaptainError: assign({
|
|
765
|
-
lastError: ({ event }) => (event as unknown as PlayerErrorEvent).error,
|
|
766
|
-
}),
|
|
767
|
-
rememberMalformedCaptainOutput: assign({
|
|
768
|
-
lastError: ({ event }) => outputOf(event),
|
|
769
|
-
}),
|
|
770
|
-
rememberMalformedBossReply: assign({
|
|
771
|
-
lastError: ({ event }) => event,
|
|
772
|
-
}),
|
|
773
|
-
setPendingBossQuestion: assign({
|
|
774
|
-
pendingBossQuestions: (
|
|
775
|
-
{ context, event },
|
|
776
|
-
params: PendingBossQuestionParams,
|
|
777
|
-
) => ({
|
|
778
|
-
...context.pendingBossQuestions,
|
|
779
|
-
[params.resumeStateId]: {
|
|
780
|
-
...params,
|
|
781
|
-
questionId: params.resumeStateId,
|
|
782
|
-
question: outputOf(event).question ?? '',
|
|
783
|
-
},
|
|
784
|
-
}),
|
|
785
|
-
bossReplies: ({ context }, params: PendingBossQuestionParams) =>
|
|
786
|
-
withoutKey(context.bossReplies, params.resumeStateId),
|
|
787
|
-
lastResult: ({ event }) => outputOf(event),
|
|
788
|
-
lastError: undefined,
|
|
789
|
-
}),
|
|
790
|
-
rememberBossReply: assign({
|
|
791
|
-
bossReplies: ({ context, event }) => {
|
|
792
|
-
const questionId = resolvedQuestionId(context, event);
|
|
793
|
-
return event.type === 'BOSS_REPLY' && questionId
|
|
794
|
-
? { ...context.bossReplies, [questionId]: event.answer }
|
|
795
|
-
: context.bossReplies;
|
|
796
|
-
},
|
|
797
|
-
lastError: undefined,
|
|
798
|
-
}),
|
|
799
|
-
clearBranchBossReplyContext: assign({
|
|
800
|
-
pendingBossQuestions: (
|
|
801
|
-
{ context },
|
|
802
|
-
params: { stateId: ResumableStateId },
|
|
803
|
-
) => withoutKey(context.pendingBossQuestions, params.stateId),
|
|
804
|
-
bossReplies: ({ context }, params: { stateId: ResumableStateId }) =>
|
|
805
|
-
withoutKey(context.bossReplies, params.stateId),
|
|
806
|
-
}),
|
|
807
|
-
clearParallelRoundContext: assign({
|
|
808
|
-
pendingBossQuestions: undefined,
|
|
809
|
-
bossReplies: undefined,
|
|
810
|
-
stagedHostResult: undefined,
|
|
811
|
-
stagedParticipantResult: undefined,
|
|
812
|
-
}),
|
|
813
|
-
clearBossReplyContext: assign({
|
|
814
|
-
pendingBossQuestions: undefined,
|
|
815
|
-
bossReplies: undefined,
|
|
816
|
-
}),
|
|
817
|
-
},
|
|
818
|
-
guards: {
|
|
819
|
-
needsBossReplyWithQuestion,
|
|
820
|
-
needsBossReplyWithoutQuestion,
|
|
821
|
-
emptyBossReply,
|
|
822
|
-
bothEndedInitialDiscussion,
|
|
823
|
-
proposalMade: guardIs('proposalMade'),
|
|
824
|
-
endedInitialDiscussion: guardIs('endedInitialDiscussion'),
|
|
825
|
-
wroteChanges: guardIs('wroteChanges'),
|
|
826
|
-
committed: guardIs('committed'),
|
|
827
|
-
noFindings: guardIs('noFindings'),
|
|
828
|
-
findingsRaised: guardIs('findingsRaised'),
|
|
829
|
-
changesMade: guardIs('changesMade'),
|
|
830
|
-
rebuttalsRaised: guardIs('rebuttalsRaised'),
|
|
831
|
-
rebuttalsAddressed: guardIs('rebuttalsAddressed'),
|
|
832
|
-
specReview: hasReviewScope('specItems'),
|
|
833
|
-
drReview: hasReviewScope('decisionRecords'),
|
|
834
|
-
mixedReview: hasReviewScope('mixed'),
|
|
835
|
-
},
|
|
836
|
-
}).createMachine({
|
|
837
|
-
id: 'discuss',
|
|
838
|
-
initial: 'ready',
|
|
839
|
-
context: ({ input }): DiscussContext => ({
|
|
840
|
-
hostPlayer: input.host,
|
|
841
|
-
participantPlayer: input.participant,
|
|
842
|
-
committerPlayer: input.committer,
|
|
843
|
-
// Per-run identities seed the <host-llm>/<participant-llm> substitutions;
|
|
844
|
-
// a START_DISCUSSION that names identities overrides them (gears2fsm.md:
|
|
845
|
-
// per-run parameters flow in via the machine's input).
|
|
846
|
-
hostLlm: input.host,
|
|
847
|
-
participantLlm: input.participant,
|
|
848
|
-
}),
|
|
849
|
-
on: {
|
|
850
|
-
START_DISCUSSION: {
|
|
851
|
-
target: '#initialProposalRound',
|
|
852
|
-
reenter: true,
|
|
853
|
-
actions: ['clearParallelRoundContext', 'copyStartDiscussion'],
|
|
854
|
-
},
|
|
855
|
-
START_REVIEW: [
|
|
856
|
-
{
|
|
857
|
-
guard: 'specReview',
|
|
858
|
-
target: '#reviewSpecInitialCommit',
|
|
859
|
-
reenter: true,
|
|
860
|
-
actions: ['clearParallelRoundContext', 'copyStartReview'],
|
|
861
|
-
},
|
|
862
|
-
{
|
|
863
|
-
guard: 'drReview',
|
|
864
|
-
target: '#reviewDrInitialCommit',
|
|
865
|
-
reenter: true,
|
|
866
|
-
actions: ['clearParallelRoundContext', 'copyStartReview'],
|
|
867
|
-
},
|
|
868
|
-
{
|
|
869
|
-
guard: 'mixedReview',
|
|
870
|
-
target: '#reviewMixedInitialCommit',
|
|
871
|
-
reenter: true,
|
|
872
|
-
actions: ['clearParallelRoundContext', 'copyStartReview'],
|
|
873
|
-
},
|
|
874
|
-
],
|
|
875
|
-
BOSS_INTERRUPT: bossInterrupts(
|
|
876
|
-
jumpableStateIds,
|
|
877
|
-
'clearParallelRoundContext',
|
|
878
|
-
),
|
|
879
|
-
},
|
|
880
|
-
states: {
|
|
881
|
-
ready: {
|
|
882
|
-
id: 'ready',
|
|
883
|
-
tags: 'playbook.parked',
|
|
884
|
-
description: 'Idle hub awaiting a Boss discussion or review directive.',
|
|
885
|
-
meta: {
|
|
886
|
-
playbook: {
|
|
887
|
-
stateId: 'ready',
|
|
888
|
-
description:
|
|
889
|
-
'Idle hub awaiting a Boss discussion or review directive.',
|
|
890
|
-
},
|
|
891
|
-
},
|
|
892
|
-
on: {
|
|
893
|
-
START_DISCUSSION: {
|
|
894
|
-
target: 'initialProposalRound',
|
|
895
|
-
actions: 'copyStartDiscussion',
|
|
896
|
-
},
|
|
897
|
-
START_REVIEW: [
|
|
898
|
-
{
|
|
899
|
-
guard: 'specReview',
|
|
900
|
-
target: reviewTargets.specItems.initial,
|
|
901
|
-
actions: 'copyStartReview',
|
|
902
|
-
},
|
|
903
|
-
{
|
|
904
|
-
guard: 'drReview',
|
|
905
|
-
target: reviewTargets.decisionRecords.initial,
|
|
906
|
-
actions: 'copyStartReview',
|
|
907
|
-
},
|
|
908
|
-
{
|
|
909
|
-
guard: 'mixedReview',
|
|
910
|
-
target: reviewTargets.mixed.initial,
|
|
911
|
-
actions: 'copyStartReview',
|
|
912
|
-
},
|
|
913
|
-
],
|
|
914
|
-
},
|
|
915
|
-
},
|
|
916
|
-
initialProposalRound: {
|
|
917
|
-
id: 'initialProposalRound',
|
|
918
|
-
type: 'parallel',
|
|
919
|
-
description: 'Host and Participant independently propose designs.',
|
|
920
|
-
meta: {
|
|
921
|
-
playbook: {
|
|
922
|
-
stateId: 'initialProposalRound',
|
|
923
|
-
description: 'Host and Participant independently propose designs.',
|
|
924
|
-
},
|
|
925
|
-
},
|
|
926
|
-
states: {
|
|
927
|
-
host: {
|
|
928
|
-
id: 'initialProposalHost',
|
|
929
|
-
initial: 'working',
|
|
930
|
-
description: 'Host branch for the parallel initial proposal round.',
|
|
931
|
-
meta: {
|
|
932
|
-
playbook: {
|
|
933
|
-
stateId: 'initialProposalHost',
|
|
934
|
-
description:
|
|
935
|
-
'Host branch for the parallel initial proposal round.',
|
|
936
|
-
},
|
|
937
|
-
},
|
|
938
|
-
states: {
|
|
939
|
-
working: {
|
|
940
|
-
id: 'askHostInitial',
|
|
941
|
-
tags: 'playbook.busy',
|
|
942
|
-
description:
|
|
943
|
-
'Host proposes whether the Boss topic should become spec items or DRs.',
|
|
944
|
-
meta: {
|
|
945
|
-
playbook: {
|
|
946
|
-
stateId: 'askHostInitial',
|
|
947
|
-
description:
|
|
948
|
-
'Host proposes whether the Boss topic should become spec items or DRs.',
|
|
949
|
-
},
|
|
950
|
-
},
|
|
951
|
-
invoke: {
|
|
952
|
-
id: 'askHostInitialCaptain',
|
|
953
|
-
src: 'player',
|
|
954
|
-
input: ({ context }): PlayerInput => ({
|
|
955
|
-
stateId: 'askHostInitial',
|
|
956
|
-
player: 'Host',
|
|
957
|
-
sourceItem: 'DISCUSS-1',
|
|
958
|
-
prompt: DISCUSS_1_PROMPT,
|
|
959
|
-
result: withNeedsBossReply({
|
|
960
|
-
proposalMade:
|
|
961
|
-
'Host proposed a design. Output shall include `proposal: <host proposal>`.',
|
|
962
|
-
}),
|
|
963
|
-
topic: context.topic,
|
|
964
|
-
hostPlayer: context.hostPlayer,
|
|
965
|
-
...bossReplyFields(context, 'askHostInitial'),
|
|
966
|
-
}),
|
|
967
|
-
onDone: [
|
|
968
|
-
{
|
|
969
|
-
guard: 'needsBossReplyWithQuestion',
|
|
970
|
-
target: 'waiting',
|
|
971
|
-
actions: {
|
|
972
|
-
type: 'setPendingBossQuestion',
|
|
973
|
-
params: {
|
|
974
|
-
...captainStateMetadata.askHostInitial,
|
|
975
|
-
resumeStateId: 'askHostInitial',
|
|
976
|
-
question: '',
|
|
977
|
-
},
|
|
978
|
-
},
|
|
979
|
-
},
|
|
980
|
-
{
|
|
981
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
982
|
-
target: '#failed',
|
|
983
|
-
actions: [
|
|
984
|
-
'rememberMalformedCaptainOutput',
|
|
985
|
-
'clearParallelRoundContext',
|
|
986
|
-
],
|
|
987
|
-
},
|
|
988
|
-
{
|
|
989
|
-
guard: 'proposalMade',
|
|
990
|
-
target: 'complete',
|
|
991
|
-
actions: [
|
|
992
|
-
'stageHostResult',
|
|
993
|
-
{
|
|
994
|
-
type: 'clearBranchBossReplyContext',
|
|
995
|
-
params: { stateId: 'askHostInitial' },
|
|
996
|
-
},
|
|
997
|
-
],
|
|
998
|
-
},
|
|
999
|
-
{
|
|
1000
|
-
target: '#failed',
|
|
1001
|
-
actions: [
|
|
1002
|
-
'rememberMalformedCaptainOutput',
|
|
1003
|
-
'clearParallelRoundContext',
|
|
1004
|
-
],
|
|
1005
|
-
},
|
|
1006
|
-
],
|
|
1007
|
-
onError: {
|
|
1008
|
-
target: '#failed',
|
|
1009
|
-
actions: [
|
|
1010
|
-
'rememberCaptainError',
|
|
1011
|
-
'clearParallelRoundContext',
|
|
1012
|
-
],
|
|
1013
|
-
},
|
|
1014
|
-
},
|
|
1015
|
-
},
|
|
1016
|
-
waiting: {
|
|
1017
|
-
id: 'waitHostInitialReply',
|
|
1018
|
-
tags: 'playbook.parked',
|
|
1019
|
-
description:
|
|
1020
|
-
'Host waits for Boss to answer its proposal question.',
|
|
1021
|
-
meta: {
|
|
1022
|
-
playbook: {
|
|
1023
|
-
stateId: 'waitHostInitialReply',
|
|
1024
|
-
description:
|
|
1025
|
-
'Host waits for Boss to answer its proposal question.',
|
|
1026
|
-
},
|
|
1027
|
-
},
|
|
1028
|
-
on: {
|
|
1029
|
-
BOSS_REPLY: [
|
|
1030
|
-
{
|
|
1031
|
-
guard: bossReplyTargets('askHostInitial', false),
|
|
1032
|
-
target: '#failed',
|
|
1033
|
-
actions: [
|
|
1034
|
-
'rememberMalformedBossReply',
|
|
1035
|
-
'clearParallelRoundContext',
|
|
1036
|
-
],
|
|
1037
|
-
},
|
|
1038
|
-
{
|
|
1039
|
-
guard: bossReplyTargets('askHostInitial', true),
|
|
1040
|
-
target: 'working',
|
|
1041
|
-
actions: 'rememberBossReply',
|
|
1042
|
-
},
|
|
1043
|
-
],
|
|
1044
|
-
},
|
|
1045
|
-
},
|
|
1046
|
-
complete: {
|
|
1047
|
-
id: 'hostInitialProposalComplete',
|
|
1048
|
-
type: 'final',
|
|
1049
|
-
description:
|
|
1050
|
-
'Host initial proposal is staged for the round join.',
|
|
1051
|
-
meta: {
|
|
1052
|
-
playbook: {
|
|
1053
|
-
stateId: 'hostInitialProposalComplete',
|
|
1054
|
-
description:
|
|
1055
|
-
'Host initial proposal is staged for the round join.',
|
|
1056
|
-
},
|
|
1057
|
-
},
|
|
1058
|
-
},
|
|
1059
|
-
},
|
|
1060
|
-
},
|
|
1061
|
-
participant: {
|
|
1062
|
-
id: 'initialProposalParticipant',
|
|
1063
|
-
initial: 'working',
|
|
1064
|
-
description:
|
|
1065
|
-
'Participant branch for the parallel initial proposal round.',
|
|
1066
|
-
meta: {
|
|
1067
|
-
playbook: {
|
|
1068
|
-
stateId: 'initialProposalParticipant',
|
|
1069
|
-
description:
|
|
1070
|
-
'Participant branch for the parallel initial proposal round.',
|
|
1071
|
-
},
|
|
1072
|
-
},
|
|
1073
|
-
states: {
|
|
1074
|
-
working: {
|
|
1075
|
-
id: 'askParticipantInitial',
|
|
1076
|
-
tags: 'playbook.busy',
|
|
1077
|
-
description:
|
|
1078
|
-
'Participant independently proposes whether the Boss topic should become spec items or DRs.',
|
|
1079
|
-
meta: {
|
|
1080
|
-
playbook: {
|
|
1081
|
-
stateId: 'askParticipantInitial',
|
|
1082
|
-
description:
|
|
1083
|
-
'Participant independently proposes whether the Boss topic should become spec items or DRs.',
|
|
1084
|
-
},
|
|
1085
|
-
},
|
|
1086
|
-
invoke: {
|
|
1087
|
-
id: 'askParticipantInitialCaptain',
|
|
1088
|
-
src: 'player',
|
|
1089
|
-
input: ({ context }): PlayerInput => ({
|
|
1090
|
-
stateId: 'askParticipantInitial',
|
|
1091
|
-
player: 'Participant',
|
|
1092
|
-
sourceItem: 'DISCUSS-2',
|
|
1093
|
-
prompt: DISCUSS_2_PROMPT,
|
|
1094
|
-
result: withNeedsBossReply({
|
|
1095
|
-
proposalMade:
|
|
1096
|
-
'Participant proposed a design. Output shall include `proposal: <participant proposal>`.',
|
|
1097
|
-
}),
|
|
1098
|
-
topic: context.topic,
|
|
1099
|
-
participantPlayer: context.participantPlayer,
|
|
1100
|
-
...bossReplyFields(context, 'askParticipantInitial'),
|
|
1101
|
-
}),
|
|
1102
|
-
onDone: [
|
|
1103
|
-
{
|
|
1104
|
-
guard: 'needsBossReplyWithQuestion',
|
|
1105
|
-
target: 'waiting',
|
|
1106
|
-
actions: {
|
|
1107
|
-
type: 'setPendingBossQuestion',
|
|
1108
|
-
params: {
|
|
1109
|
-
...captainStateMetadata.askParticipantInitial,
|
|
1110
|
-
resumeStateId: 'askParticipantInitial',
|
|
1111
|
-
question: '',
|
|
1112
|
-
},
|
|
1113
|
-
},
|
|
1114
|
-
},
|
|
1115
|
-
{
|
|
1116
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
1117
|
-
target: '#failed',
|
|
1118
|
-
actions: [
|
|
1119
|
-
'rememberMalformedCaptainOutput',
|
|
1120
|
-
'clearParallelRoundContext',
|
|
1121
|
-
],
|
|
1122
|
-
},
|
|
1123
|
-
{
|
|
1124
|
-
guard: 'proposalMade',
|
|
1125
|
-
target: 'complete',
|
|
1126
|
-
actions: [
|
|
1127
|
-
'stageParticipantResult',
|
|
1128
|
-
{
|
|
1129
|
-
type: 'clearBranchBossReplyContext',
|
|
1130
|
-
params: { stateId: 'askParticipantInitial' },
|
|
1131
|
-
},
|
|
1132
|
-
],
|
|
1133
|
-
},
|
|
1134
|
-
{
|
|
1135
|
-
target: '#failed',
|
|
1136
|
-
actions: [
|
|
1137
|
-
'rememberMalformedCaptainOutput',
|
|
1138
|
-
'clearParallelRoundContext',
|
|
1139
|
-
],
|
|
1140
|
-
},
|
|
1141
|
-
],
|
|
1142
|
-
onError: {
|
|
1143
|
-
target: '#failed',
|
|
1144
|
-
actions: [
|
|
1145
|
-
'rememberCaptainError',
|
|
1146
|
-
'clearParallelRoundContext',
|
|
1147
|
-
],
|
|
1148
|
-
},
|
|
1149
|
-
},
|
|
1150
|
-
},
|
|
1151
|
-
waiting: {
|
|
1152
|
-
id: 'waitParticipantInitialReply',
|
|
1153
|
-
tags: 'playbook.parked',
|
|
1154
|
-
description:
|
|
1155
|
-
'Participant waits for Boss to answer its proposal question.',
|
|
1156
|
-
meta: {
|
|
1157
|
-
playbook: {
|
|
1158
|
-
stateId: 'waitParticipantInitialReply',
|
|
1159
|
-
description:
|
|
1160
|
-
'Participant waits for Boss to answer its proposal question.',
|
|
1161
|
-
},
|
|
1162
|
-
},
|
|
1163
|
-
on: {
|
|
1164
|
-
BOSS_REPLY: [
|
|
1165
|
-
{
|
|
1166
|
-
guard: bossReplyTargets('askParticipantInitial', false),
|
|
1167
|
-
target: '#failed',
|
|
1168
|
-
actions: [
|
|
1169
|
-
'rememberMalformedBossReply',
|
|
1170
|
-
'clearParallelRoundContext',
|
|
1171
|
-
],
|
|
1172
|
-
},
|
|
1173
|
-
{
|
|
1174
|
-
guard: bossReplyTargets('askParticipantInitial', true),
|
|
1175
|
-
target: 'working',
|
|
1176
|
-
actions: 'rememberBossReply',
|
|
1177
|
-
},
|
|
1178
|
-
],
|
|
1179
|
-
},
|
|
1180
|
-
},
|
|
1181
|
-
complete: {
|
|
1182
|
-
id: 'participantInitialProposalComplete',
|
|
1183
|
-
type: 'final',
|
|
1184
|
-
description:
|
|
1185
|
-
'Participant initial proposal is staged for the round join.',
|
|
1186
|
-
meta: {
|
|
1187
|
-
playbook: {
|
|
1188
|
-
stateId: 'participantInitialProposalComplete',
|
|
1189
|
-
description:
|
|
1190
|
-
'Participant initial proposal is staged for the round join.',
|
|
1191
|
-
},
|
|
1192
|
-
},
|
|
1193
|
-
},
|
|
1194
|
-
},
|
|
1195
|
-
},
|
|
1196
|
-
},
|
|
1197
|
-
onDone: {
|
|
1198
|
-
target: 'reconciliationRound',
|
|
1199
|
-
actions: 'promoteInitialResults',
|
|
1200
|
-
},
|
|
1201
|
-
},
|
|
1202
|
-
reconciliationRound: {
|
|
1203
|
-
id: 'reconciliationRound',
|
|
1204
|
-
type: 'parallel',
|
|
1205
|
-
description:
|
|
1206
|
-
'Host and Participant independently reconcile one completed prior round.',
|
|
1207
|
-
meta: {
|
|
1208
|
-
playbook: {
|
|
1209
|
-
stateId: 'reconciliationRound',
|
|
1210
|
-
description:
|
|
1211
|
-
'Host and Participant independently reconcile one completed prior round.',
|
|
1212
|
-
},
|
|
1213
|
-
},
|
|
1214
|
-
states: {
|
|
1215
|
-
host: {
|
|
1216
|
-
id: 'reconciliationHost',
|
|
1217
|
-
initial: 'working',
|
|
1218
|
-
description: 'Host branch for the parallel reconciliation round.',
|
|
1219
|
-
meta: {
|
|
1220
|
-
playbook: {
|
|
1221
|
-
stateId: 'reconciliationHost',
|
|
1222
|
-
description: 'Host branch for the parallel reconciliation round.',
|
|
1223
|
-
},
|
|
1224
|
-
},
|
|
1225
|
-
states: {
|
|
1226
|
-
working: {
|
|
1227
|
-
id: 'hostInitialRound',
|
|
1228
|
-
tags: 'playbook.busy',
|
|
1229
|
-
description:
|
|
1230
|
-
'Host reconciles the Participant proposal during initial discussion.',
|
|
1231
|
-
meta: {
|
|
1232
|
-
playbook: {
|
|
1233
|
-
stateId: 'hostInitialRound',
|
|
1234
|
-
description:
|
|
1235
|
-
'Host reconciles the Participant proposal during initial discussion.',
|
|
1236
|
-
},
|
|
1237
|
-
},
|
|
1238
|
-
invoke: {
|
|
1239
|
-
id: 'hostInitialRoundCaptain',
|
|
1240
|
-
src: 'player',
|
|
1241
|
-
input: ({ context }): PlayerInput => ({
|
|
1242
|
-
stateId: 'hostInitialRound',
|
|
1243
|
-
player: 'Host',
|
|
1244
|
-
sourceItem: 'DISCUSS-3',
|
|
1245
|
-
prompt: DISCUSS_3_PROMPT,
|
|
1246
|
-
result: withNeedsBossReply({
|
|
1247
|
-
proposalMade:
|
|
1248
|
-
'Host continued the discussion with a revised or challenged proposal. Output shall include `proposal: <host proposal>`.',
|
|
1249
|
-
endedInitialDiscussion:
|
|
1250
|
-
'Host stated the end of initial discussion. Output may include `agreement: <agreement>`.',
|
|
1251
|
-
}),
|
|
1252
|
-
hostProposal: context.hostProposal,
|
|
1253
|
-
participantProposal: context.participantProposal,
|
|
1254
|
-
hostPlayer: context.hostPlayer,
|
|
1255
|
-
...bossReplyFields(context, 'hostInitialRound'),
|
|
1256
|
-
}),
|
|
1257
|
-
onDone: [
|
|
1258
|
-
{
|
|
1259
|
-
guard: 'needsBossReplyWithQuestion',
|
|
1260
|
-
target: 'waiting',
|
|
1261
|
-
actions: {
|
|
1262
|
-
type: 'setPendingBossQuestion',
|
|
1263
|
-
params: {
|
|
1264
|
-
...captainStateMetadata.hostInitialRound,
|
|
1265
|
-
resumeStateId: 'hostInitialRound',
|
|
1266
|
-
question: '',
|
|
1267
|
-
},
|
|
1268
|
-
},
|
|
1269
|
-
},
|
|
1270
|
-
{
|
|
1271
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
1272
|
-
target: '#failed',
|
|
1273
|
-
actions: [
|
|
1274
|
-
'rememberMalformedCaptainOutput',
|
|
1275
|
-
'clearParallelRoundContext',
|
|
1276
|
-
],
|
|
1277
|
-
},
|
|
1278
|
-
{
|
|
1279
|
-
guard: 'proposalMade',
|
|
1280
|
-
target: 'complete',
|
|
1281
|
-
actions: [
|
|
1282
|
-
'stageHostResult',
|
|
1283
|
-
{
|
|
1284
|
-
type: 'clearBranchBossReplyContext',
|
|
1285
|
-
params: { stateId: 'hostInitialRound' },
|
|
1286
|
-
},
|
|
1287
|
-
],
|
|
1288
|
-
},
|
|
1289
|
-
{
|
|
1290
|
-
guard: 'endedInitialDiscussion',
|
|
1291
|
-
target: 'complete',
|
|
1292
|
-
actions: [
|
|
1293
|
-
'stageHostResult',
|
|
1294
|
-
{
|
|
1295
|
-
type: 'clearBranchBossReplyContext',
|
|
1296
|
-
params: { stateId: 'hostInitialRound' },
|
|
1297
|
-
},
|
|
1298
|
-
],
|
|
1299
|
-
},
|
|
1300
|
-
{
|
|
1301
|
-
target: '#failed',
|
|
1302
|
-
actions: [
|
|
1303
|
-
'rememberMalformedCaptainOutput',
|
|
1304
|
-
'clearParallelRoundContext',
|
|
1305
|
-
],
|
|
1306
|
-
},
|
|
1307
|
-
],
|
|
1308
|
-
onError: {
|
|
1309
|
-
target: '#failed',
|
|
1310
|
-
actions: [
|
|
1311
|
-
'rememberCaptainError',
|
|
1312
|
-
'clearParallelRoundContext',
|
|
1313
|
-
],
|
|
1314
|
-
},
|
|
1315
|
-
},
|
|
1316
|
-
},
|
|
1317
|
-
waiting: {
|
|
1318
|
-
id: 'waitHostReconciliationReply',
|
|
1319
|
-
tags: 'playbook.parked',
|
|
1320
|
-
description:
|
|
1321
|
-
'Host waits for Boss to answer its reconciliation question.',
|
|
1322
|
-
meta: {
|
|
1323
|
-
playbook: {
|
|
1324
|
-
stateId: 'waitHostReconciliationReply',
|
|
1325
|
-
description:
|
|
1326
|
-
'Host waits for Boss to answer its reconciliation question.',
|
|
1327
|
-
},
|
|
1328
|
-
},
|
|
1329
|
-
on: {
|
|
1330
|
-
BOSS_REPLY: [
|
|
1331
|
-
{
|
|
1332
|
-
guard: bossReplyTargets('hostInitialRound', false),
|
|
1333
|
-
target: '#failed',
|
|
1334
|
-
actions: [
|
|
1335
|
-
'rememberMalformedBossReply',
|
|
1336
|
-
'clearParallelRoundContext',
|
|
1337
|
-
],
|
|
1338
|
-
},
|
|
1339
|
-
{
|
|
1340
|
-
guard: bossReplyTargets('hostInitialRound', true),
|
|
1341
|
-
target: 'working',
|
|
1342
|
-
actions: 'rememberBossReply',
|
|
1343
|
-
},
|
|
1344
|
-
],
|
|
1345
|
-
},
|
|
1346
|
-
},
|
|
1347
|
-
complete: {
|
|
1348
|
-
id: 'hostReconciliationComplete',
|
|
1349
|
-
type: 'final',
|
|
1350
|
-
description: 'Host reconciliation result is staged for the join.',
|
|
1351
|
-
meta: {
|
|
1352
|
-
playbook: {
|
|
1353
|
-
stateId: 'hostReconciliationComplete',
|
|
1354
|
-
description:
|
|
1355
|
-
'Host reconciliation result is staged for the join.',
|
|
1356
|
-
},
|
|
1357
|
-
},
|
|
1358
|
-
},
|
|
1359
|
-
},
|
|
1360
|
-
},
|
|
1361
|
-
participant: {
|
|
1362
|
-
id: 'reconciliationParticipant',
|
|
1363
|
-
initial: 'working',
|
|
1364
|
-
description:
|
|
1365
|
-
'Participant branch for the parallel reconciliation round.',
|
|
1366
|
-
meta: {
|
|
1367
|
-
playbook: {
|
|
1368
|
-
stateId: 'reconciliationParticipant',
|
|
1369
|
-
description:
|
|
1370
|
-
'Participant branch for the parallel reconciliation round.',
|
|
1371
|
-
},
|
|
1372
|
-
},
|
|
1373
|
-
states: {
|
|
1374
|
-
working: {
|
|
1375
|
-
id: 'participantInitialRound',
|
|
1376
|
-
tags: 'playbook.busy',
|
|
1377
|
-
description:
|
|
1378
|
-
'Participant reconciles the Host proposal during initial discussion.',
|
|
1379
|
-
meta: {
|
|
1380
|
-
playbook: {
|
|
1381
|
-
stateId: 'participantInitialRound',
|
|
1382
|
-
description:
|
|
1383
|
-
'Participant reconciles the Host proposal during initial discussion.',
|
|
1384
|
-
},
|
|
1385
|
-
},
|
|
1386
|
-
invoke: {
|
|
1387
|
-
id: 'participantInitialRoundCaptain',
|
|
1388
|
-
src: 'player',
|
|
1389
|
-
input: ({ context }): PlayerInput => ({
|
|
1390
|
-
stateId: 'participantInitialRound',
|
|
1391
|
-
player: 'Participant',
|
|
1392
|
-
sourceItem: 'DISCUSS-4',
|
|
1393
|
-
prompt: DISCUSS_4_PROMPT,
|
|
1394
|
-
result: withNeedsBossReply({
|
|
1395
|
-
proposalMade:
|
|
1396
|
-
'Participant continued the discussion with a revised or challenged proposal. Output shall include `proposal: <participant proposal>`.',
|
|
1397
|
-
endedInitialDiscussion:
|
|
1398
|
-
'Participant stated the end of initial discussion. Output may include `agreement: <agreement>`.',
|
|
1399
|
-
}),
|
|
1400
|
-
hostProposal: context.hostProposal,
|
|
1401
|
-
participantProposal: context.participantProposal,
|
|
1402
|
-
agreement: context.agreement,
|
|
1403
|
-
participantPlayer: context.participantPlayer,
|
|
1404
|
-
...bossReplyFields(context, 'participantInitialRound'),
|
|
1405
|
-
}),
|
|
1406
|
-
onDone: [
|
|
1407
|
-
{
|
|
1408
|
-
guard: 'needsBossReplyWithQuestion',
|
|
1409
|
-
target: 'waiting',
|
|
1410
|
-
actions: {
|
|
1411
|
-
type: 'setPendingBossQuestion',
|
|
1412
|
-
params: {
|
|
1413
|
-
...captainStateMetadata.participantInitialRound,
|
|
1414
|
-
resumeStateId: 'participantInitialRound',
|
|
1415
|
-
question: '',
|
|
1416
|
-
},
|
|
1417
|
-
},
|
|
1418
|
-
},
|
|
1419
|
-
{
|
|
1420
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
1421
|
-
target: '#failed',
|
|
1422
|
-
actions: [
|
|
1423
|
-
'rememberMalformedCaptainOutput',
|
|
1424
|
-
'clearParallelRoundContext',
|
|
1425
|
-
],
|
|
1426
|
-
},
|
|
1427
|
-
{
|
|
1428
|
-
guard: 'proposalMade',
|
|
1429
|
-
target: 'complete',
|
|
1430
|
-
actions: [
|
|
1431
|
-
'stageParticipantResult',
|
|
1432
|
-
{
|
|
1433
|
-
type: 'clearBranchBossReplyContext',
|
|
1434
|
-
params: { stateId: 'participantInitialRound' },
|
|
1435
|
-
},
|
|
1436
|
-
],
|
|
1437
|
-
},
|
|
1438
|
-
{
|
|
1439
|
-
guard: 'endedInitialDiscussion',
|
|
1440
|
-
target: 'complete',
|
|
1441
|
-
actions: [
|
|
1442
|
-
'stageParticipantResult',
|
|
1443
|
-
{
|
|
1444
|
-
type: 'clearBranchBossReplyContext',
|
|
1445
|
-
params: { stateId: 'participantInitialRound' },
|
|
1446
|
-
},
|
|
1447
|
-
],
|
|
1448
|
-
},
|
|
1449
|
-
{
|
|
1450
|
-
target: '#failed',
|
|
1451
|
-
actions: [
|
|
1452
|
-
'rememberMalformedCaptainOutput',
|
|
1453
|
-
'clearParallelRoundContext',
|
|
1454
|
-
],
|
|
1455
|
-
},
|
|
1456
|
-
],
|
|
1457
|
-
onError: {
|
|
1458
|
-
target: '#failed',
|
|
1459
|
-
actions: [
|
|
1460
|
-
'rememberCaptainError',
|
|
1461
|
-
'clearParallelRoundContext',
|
|
1462
|
-
],
|
|
1463
|
-
},
|
|
1464
|
-
},
|
|
1465
|
-
},
|
|
1466
|
-
waiting: {
|
|
1467
|
-
id: 'waitParticipantReconciliationReply',
|
|
1468
|
-
tags: 'playbook.parked',
|
|
1469
|
-
description:
|
|
1470
|
-
'Participant waits for Boss to answer its reconciliation question.',
|
|
1471
|
-
meta: {
|
|
1472
|
-
playbook: {
|
|
1473
|
-
stateId: 'waitParticipantReconciliationReply',
|
|
1474
|
-
description:
|
|
1475
|
-
'Participant waits for Boss to answer its reconciliation question.',
|
|
1476
|
-
},
|
|
1477
|
-
},
|
|
1478
|
-
on: {
|
|
1479
|
-
BOSS_REPLY: [
|
|
1480
|
-
{
|
|
1481
|
-
guard: bossReplyTargets('participantInitialRound', false),
|
|
1482
|
-
target: '#failed',
|
|
1483
|
-
actions: [
|
|
1484
|
-
'rememberMalformedBossReply',
|
|
1485
|
-
'clearParallelRoundContext',
|
|
1486
|
-
],
|
|
1487
|
-
},
|
|
1488
|
-
{
|
|
1489
|
-
guard: bossReplyTargets('participantInitialRound', true),
|
|
1490
|
-
target: 'working',
|
|
1491
|
-
actions: 'rememberBossReply',
|
|
1492
|
-
},
|
|
1493
|
-
],
|
|
1494
|
-
},
|
|
1495
|
-
},
|
|
1496
|
-
complete: {
|
|
1497
|
-
id: 'participantReconciliationComplete',
|
|
1498
|
-
type: 'final',
|
|
1499
|
-
description:
|
|
1500
|
-
'Participant reconciliation result is staged for the join.',
|
|
1501
|
-
meta: {
|
|
1502
|
-
playbook: {
|
|
1503
|
-
stateId: 'participantReconciliationComplete',
|
|
1504
|
-
description:
|
|
1505
|
-
'Participant reconciliation result is staged for the join.',
|
|
1506
|
-
},
|
|
1507
|
-
},
|
|
1508
|
-
},
|
|
1509
|
-
},
|
|
1510
|
-
},
|
|
1511
|
-
},
|
|
1512
|
-
onDone: [
|
|
1513
|
-
{
|
|
1514
|
-
guard: 'bothEndedInitialDiscussion',
|
|
1515
|
-
target: 'hostWritesAgreement',
|
|
1516
|
-
actions: 'promoteReconciliationResults',
|
|
1517
|
-
},
|
|
1518
|
-
{
|
|
1519
|
-
target: 'reconciliationRound',
|
|
1520
|
-
reenter: true,
|
|
1521
|
-
actions: 'promoteReconciliationResults',
|
|
1522
|
-
},
|
|
1523
|
-
],
|
|
1524
|
-
},
|
|
1525
|
-
hostWritesAgreement: {
|
|
1526
|
-
id: 'hostWritesAgreement',
|
|
1527
|
-
tags: 'playbook.busy',
|
|
1528
|
-
description:
|
|
1529
|
-
'Host writes the agreed spec items or DRs and updates the spec map.',
|
|
1530
|
-
meta: {
|
|
1531
|
-
playbook: {
|
|
1532
|
-
stateId: 'hostWritesAgreement',
|
|
1533
|
-
description:
|
|
1534
|
-
'Host writes the agreed spec items or DRs and updates the spec map.',
|
|
1535
|
-
},
|
|
1536
|
-
},
|
|
1537
|
-
invoke: {
|
|
1538
|
-
id: 'hostWritesAgreementCaptain',
|
|
1539
|
-
src: 'player',
|
|
1540
|
-
input: ({ context }): PlayerInput => ({
|
|
1541
|
-
stateId: 'hostWritesAgreement',
|
|
1542
|
-
player: 'Host',
|
|
1543
|
-
sourceItem: 'DISCUSS-5',
|
|
1544
|
-
prompt: DISCUSS_5_PROMPT,
|
|
1545
|
-
result: withNeedsBossReply({
|
|
1546
|
-
wroteChanges:
|
|
1547
|
-
'Host wrote the agreed changes. Output shall include `latestChanges: <summary>` and `reviewScope: "specItems" | "decisionRecords" | "mixed"`.',
|
|
1548
|
-
}),
|
|
1549
|
-
agreement: context.agreement,
|
|
1550
|
-
hostPlayer: context.hostPlayer,
|
|
1551
|
-
...bossReplyFields(context, 'hostWritesAgreement'),
|
|
1552
|
-
}),
|
|
1553
|
-
onDone: [
|
|
1554
|
-
{
|
|
1555
|
-
guard: 'needsBossReplyWithQuestion',
|
|
1556
|
-
target: 'awaitBossReply',
|
|
1557
|
-
actions: {
|
|
1558
|
-
type: 'setPendingBossQuestion',
|
|
1559
|
-
params: {
|
|
1560
|
-
...captainStateMetadata.hostWritesAgreement,
|
|
1561
|
-
resumeStateId: 'hostWritesAgreement',
|
|
1562
|
-
question: '',
|
|
1563
|
-
},
|
|
1564
|
-
},
|
|
1565
|
-
},
|
|
1566
|
-
{
|
|
1567
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
1568
|
-
target: 'failed',
|
|
1569
|
-
actions: [
|
|
1570
|
-
'rememberMalformedCaptainOutput',
|
|
1571
|
-
'clearBossReplyContext',
|
|
1572
|
-
],
|
|
1573
|
-
},
|
|
1574
|
-
{
|
|
1575
|
-
guard: 'wroteChanges',
|
|
1576
|
-
target: 'commitInitialChanges',
|
|
1577
|
-
actions: ['rememberWrittenChanges', 'clearBossReplyContext'],
|
|
1578
|
-
},
|
|
1579
|
-
{
|
|
1580
|
-
target: 'failed',
|
|
1581
|
-
actions: [
|
|
1582
|
-
'rememberMalformedCaptainOutput',
|
|
1583
|
-
'clearBossReplyContext',
|
|
1584
|
-
],
|
|
1585
|
-
},
|
|
1586
|
-
],
|
|
1587
|
-
onError: {
|
|
1588
|
-
target: 'failed',
|
|
1589
|
-
actions: ['rememberCaptainError', 'clearBossReplyContext'],
|
|
1590
|
-
},
|
|
1591
|
-
},
|
|
1592
|
-
},
|
|
1593
|
-
commitInitialChanges: {
|
|
1594
|
-
id: 'commitInitialChanges',
|
|
1595
|
-
tags: 'playbook.busy',
|
|
1596
|
-
description:
|
|
1597
|
-
'Committer commits the changes produced at the end of initial discussion.',
|
|
1598
|
-
meta: {
|
|
1599
|
-
playbook: {
|
|
1600
|
-
stateId: 'commitInitialChanges',
|
|
1601
|
-
description:
|
|
1602
|
-
'Committer commits the changes produced at the end of initial discussion.',
|
|
1603
|
-
},
|
|
1604
|
-
},
|
|
1605
|
-
invoke: {
|
|
1606
|
-
id: 'commitInitialChangesCaptain',
|
|
1607
|
-
src: 'player',
|
|
1608
|
-
input: ({ context }): PlayerInput => ({
|
|
1609
|
-
stateId: 'commitInitialChanges',
|
|
1610
|
-
player: 'Committer',
|
|
1611
|
-
sourceItem: 'DISCUSS-14',
|
|
1612
|
-
prompt: DISCUSS_14_PROMPT,
|
|
1613
|
-
result: withNeedsBossReply({
|
|
1614
|
-
committed:
|
|
1615
|
-
'Committer made the initial-discussion commit. Output may include `latestChanges: <summary>` and `reviewScope: "specItems" | "decisionRecords" | "mixed"`.',
|
|
1616
|
-
}),
|
|
1617
|
-
latestChanges: context.latestChanges,
|
|
1618
|
-
reviewScope: context.reviewScope,
|
|
1619
|
-
hostLlm: context.hostLlm,
|
|
1620
|
-
participantLlm: context.participantLlm,
|
|
1621
|
-
committerPlayer: context.committerPlayer,
|
|
1622
|
-
...bossReplyFields(context, 'commitInitialChanges'),
|
|
1623
|
-
}),
|
|
1624
|
-
onDone: [
|
|
1625
|
-
{
|
|
1626
|
-
guard: 'needsBossReplyWithQuestion',
|
|
1627
|
-
target: 'awaitBossReply',
|
|
1628
|
-
actions: {
|
|
1629
|
-
type: 'setPendingBossQuestion',
|
|
1630
|
-
params: {
|
|
1631
|
-
...captainStateMetadata.commitInitialChanges,
|
|
1632
|
-
resumeStateId: 'commitInitialChanges',
|
|
1633
|
-
question: '',
|
|
1634
|
-
},
|
|
1635
|
-
},
|
|
1636
|
-
},
|
|
1637
|
-
{
|
|
1638
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
1639
|
-
target: 'failed',
|
|
1640
|
-
actions: [
|
|
1641
|
-
'rememberMalformedCaptainOutput',
|
|
1642
|
-
'clearBossReplyContext',
|
|
1643
|
-
],
|
|
1644
|
-
},
|
|
1645
|
-
{
|
|
1646
|
-
guard: ({ context, event }) =>
|
|
1647
|
-
outputOf(event).guard === 'committed' &&
|
|
1648
|
-
(outputOf(event).reviewScope ?? context.reviewScope) ===
|
|
1649
|
-
'specItems',
|
|
1650
|
-
target: reviewTargets.specItems.initial,
|
|
1651
|
-
actions: ['rememberCommittedChanges', 'clearBossReplyContext'],
|
|
1652
|
-
},
|
|
1653
|
-
{
|
|
1654
|
-
guard: ({ context, event }) =>
|
|
1655
|
-
outputOf(event).guard === 'committed' &&
|
|
1656
|
-
(outputOf(event).reviewScope ?? context.reviewScope) ===
|
|
1657
|
-
'decisionRecords',
|
|
1658
|
-
target: reviewTargets.decisionRecords.initial,
|
|
1659
|
-
actions: ['rememberCommittedChanges', 'clearBossReplyContext'],
|
|
1660
|
-
},
|
|
1661
|
-
{
|
|
1662
|
-
guard: ({ context, event }) =>
|
|
1663
|
-
outputOf(event).guard === 'committed' &&
|
|
1664
|
-
(outputOf(event).reviewScope ?? context.reviewScope) === 'mixed',
|
|
1665
|
-
target: reviewTargets.mixed.initial,
|
|
1666
|
-
actions: ['rememberCommittedChanges', 'clearBossReplyContext'],
|
|
1667
|
-
},
|
|
1668
|
-
{
|
|
1669
|
-
target: 'failed',
|
|
1670
|
-
actions: [
|
|
1671
|
-
'rememberMalformedCaptainOutput',
|
|
1672
|
-
'clearBossReplyContext',
|
|
1673
|
-
],
|
|
1674
|
-
},
|
|
1675
|
-
],
|
|
1676
|
-
onError: {
|
|
1677
|
-
target: 'failed',
|
|
1678
|
-
actions: ['rememberCaptainError', 'clearBossReplyContext'],
|
|
1679
|
-
},
|
|
1680
|
-
},
|
|
1681
|
-
},
|
|
1682
|
-
reviewSpecInitialCommit: {
|
|
1683
|
-
id: 'reviewSpecInitialCommit',
|
|
1684
|
-
tags: 'playbook.busy',
|
|
1685
|
-
description: 'Participant reviews newly committed spec-item changes.',
|
|
1686
|
-
meta: {
|
|
1687
|
-
playbook: {
|
|
1688
|
-
stateId: 'reviewSpecInitialCommit',
|
|
1689
|
-
description: 'Participant reviews newly committed spec-item changes.',
|
|
1690
|
-
},
|
|
1691
|
-
},
|
|
1692
|
-
invoke: {
|
|
1693
|
-
id: 'reviewSpecInitialCommitCaptain',
|
|
1694
|
-
src: 'player',
|
|
1695
|
-
input: ({ context }): PlayerInput => ({
|
|
1696
|
-
stateId: 'reviewSpecInitialCommit',
|
|
1697
|
-
player: 'Participant',
|
|
1698
|
-
sourceItem: 'DISCUSS-6',
|
|
1699
|
-
prompt: DISCUSS_6_PROMPT,
|
|
1700
|
-
result: withNeedsBossReply({
|
|
1701
|
-
noFindings: 'Participant raised no findings.',
|
|
1702
|
-
findingsRaised:
|
|
1703
|
-
'Participant raised findings. Output shall include `reviewItems: <findings>`.',
|
|
1704
|
-
}),
|
|
1705
|
-
latestChanges: context.latestChanges,
|
|
1706
|
-
rebuttals: context.rebuttals,
|
|
1707
|
-
participantPlayer: context.participantPlayer,
|
|
1708
|
-
...bossReplyFields(context, 'reviewSpecInitialCommit'),
|
|
1709
|
-
}),
|
|
1710
|
-
onDone: [
|
|
1711
|
-
{
|
|
1712
|
-
guard: 'needsBossReplyWithQuestion',
|
|
1713
|
-
target: 'awaitBossReply',
|
|
1714
|
-
actions: {
|
|
1715
|
-
type: 'setPendingBossQuestion',
|
|
1716
|
-
params: {
|
|
1717
|
-
...captainStateMetadata.reviewSpecInitialCommit,
|
|
1718
|
-
resumeStateId: 'reviewSpecInitialCommit',
|
|
1719
|
-
question: '',
|
|
1720
|
-
},
|
|
1721
|
-
},
|
|
1722
|
-
},
|
|
1723
|
-
{
|
|
1724
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
1725
|
-
target: 'failed',
|
|
1726
|
-
actions: [
|
|
1727
|
-
'rememberMalformedCaptainOutput',
|
|
1728
|
-
'clearBossReplyContext',
|
|
1729
|
-
],
|
|
1730
|
-
},
|
|
1731
|
-
{
|
|
1732
|
-
guard: 'noFindings',
|
|
1733
|
-
target: 'commitReviewedChanges',
|
|
1734
|
-
actions: ['rememberCaptainResult', 'clearBossReplyContext'],
|
|
1735
|
-
},
|
|
1736
|
-
{
|
|
1737
|
-
guard: 'findingsRaised',
|
|
1738
|
-
target: 'hostAddressesFindings',
|
|
1739
|
-
actions: ['rememberReviewFindings', 'clearBossReplyContext'],
|
|
1740
|
-
},
|
|
1741
|
-
{
|
|
1742
|
-
target: 'failed',
|
|
1743
|
-
actions: [
|
|
1744
|
-
'rememberMalformedCaptainOutput',
|
|
1745
|
-
'clearBossReplyContext',
|
|
1746
|
-
],
|
|
1747
|
-
},
|
|
1748
|
-
],
|
|
1749
|
-
onError: {
|
|
1750
|
-
target: 'failed',
|
|
1751
|
-
actions: ['rememberCaptainError', 'clearBossReplyContext'],
|
|
1752
|
-
},
|
|
1753
|
-
},
|
|
1754
|
-
},
|
|
1755
|
-
reviewSpecHostChanges: {
|
|
1756
|
-
id: 'reviewSpecHostChanges',
|
|
1757
|
-
tags: 'playbook.busy',
|
|
1758
|
-
description:
|
|
1759
|
-
'Participant reviews Host changes to spec items after findings.',
|
|
1760
|
-
meta: {
|
|
1761
|
-
playbook: {
|
|
1762
|
-
stateId: 'reviewSpecHostChanges',
|
|
1763
|
-
description:
|
|
1764
|
-
'Participant reviews Host changes to spec items after findings.',
|
|
1765
|
-
},
|
|
1766
|
-
},
|
|
1767
|
-
invoke: {
|
|
1768
|
-
id: 'reviewSpecHostChangesCaptain',
|
|
1769
|
-
src: 'player',
|
|
1770
|
-
input: ({ context }): PlayerInput => ({
|
|
1771
|
-
stateId: 'reviewSpecHostChanges',
|
|
1772
|
-
player: 'Participant',
|
|
1773
|
-
sourceItem: 'DISCUSS-7',
|
|
1774
|
-
prompt: DISCUSS_7_PROMPT,
|
|
1775
|
-
result: withNeedsBossReply({
|
|
1776
|
-
noFindings: 'Participant raised no findings.',
|
|
1777
|
-
findingsRaised:
|
|
1778
|
-
'Participant raised findings. Output shall include `reviewItems: <findings>`.',
|
|
1779
|
-
}),
|
|
1780
|
-
latestChanges: context.latestChanges,
|
|
1781
|
-
rebuttals: context.rebuttals,
|
|
1782
|
-
participantPlayer: context.participantPlayer,
|
|
1783
|
-
...bossReplyFields(context, 'reviewSpecHostChanges'),
|
|
1784
|
-
}),
|
|
1785
|
-
onDone: [
|
|
1786
|
-
{
|
|
1787
|
-
guard: 'needsBossReplyWithQuestion',
|
|
1788
|
-
target: 'awaitBossReply',
|
|
1789
|
-
actions: {
|
|
1790
|
-
type: 'setPendingBossQuestion',
|
|
1791
|
-
params: {
|
|
1792
|
-
...captainStateMetadata.reviewSpecHostChanges,
|
|
1793
|
-
resumeStateId: 'reviewSpecHostChanges',
|
|
1794
|
-
question: '',
|
|
1795
|
-
},
|
|
1796
|
-
},
|
|
1797
|
-
},
|
|
1798
|
-
{
|
|
1799
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
1800
|
-
target: 'failed',
|
|
1801
|
-
actions: [
|
|
1802
|
-
'rememberMalformedCaptainOutput',
|
|
1803
|
-
'clearBossReplyContext',
|
|
1804
|
-
],
|
|
1805
|
-
},
|
|
1806
|
-
{
|
|
1807
|
-
guard: 'noFindings',
|
|
1808
|
-
target: 'commitReviewedChanges',
|
|
1809
|
-
actions: ['rememberCaptainResult', 'clearBossReplyContext'],
|
|
1810
|
-
},
|
|
1811
|
-
{
|
|
1812
|
-
guard: 'findingsRaised',
|
|
1813
|
-
target: 'hostAddressesFindings',
|
|
1814
|
-
actions: ['rememberReviewFindings', 'clearBossReplyContext'],
|
|
1815
|
-
},
|
|
1816
|
-
{
|
|
1817
|
-
target: 'failed',
|
|
1818
|
-
actions: [
|
|
1819
|
-
'rememberMalformedCaptainOutput',
|
|
1820
|
-
'clearBossReplyContext',
|
|
1821
|
-
],
|
|
1822
|
-
},
|
|
1823
|
-
],
|
|
1824
|
-
onError: {
|
|
1825
|
-
target: 'failed',
|
|
1826
|
-
actions: ['rememberCaptainError', 'clearBossReplyContext'],
|
|
1827
|
-
},
|
|
1828
|
-
},
|
|
1829
|
-
},
|
|
1830
|
-
reviewDrInitialCommit: {
|
|
1831
|
-
id: 'reviewDrInitialCommit',
|
|
1832
|
-
tags: 'playbook.busy',
|
|
1833
|
-
description:
|
|
1834
|
-
'Participant reviews newly committed decision-record changes.',
|
|
1835
|
-
meta: {
|
|
1836
|
-
playbook: {
|
|
1837
|
-
stateId: 'reviewDrInitialCommit',
|
|
1838
|
-
description:
|
|
1839
|
-
'Participant reviews newly committed decision-record changes.',
|
|
1840
|
-
},
|
|
1841
|
-
},
|
|
1842
|
-
invoke: {
|
|
1843
|
-
id: 'reviewDrInitialCommitCaptain',
|
|
1844
|
-
src: 'player',
|
|
1845
|
-
input: ({ context }): PlayerInput => ({
|
|
1846
|
-
stateId: 'reviewDrInitialCommit',
|
|
1847
|
-
player: 'Participant',
|
|
1848
|
-
sourceItem: 'DISCUSS-8',
|
|
1849
|
-
prompt: DISCUSS_8_PROMPT,
|
|
1850
|
-
result: withNeedsBossReply({
|
|
1851
|
-
noFindings: 'Participant raised no findings.',
|
|
1852
|
-
findingsRaised:
|
|
1853
|
-
'Participant raised findings. Output shall include `reviewItems: <findings>`.',
|
|
1854
|
-
}),
|
|
1855
|
-
latestChanges: context.latestChanges,
|
|
1856
|
-
rebuttals: context.rebuttals,
|
|
1857
|
-
participantPlayer: context.participantPlayer,
|
|
1858
|
-
...bossReplyFields(context, 'reviewDrInitialCommit'),
|
|
1859
|
-
}),
|
|
1860
|
-
onDone: [
|
|
1861
|
-
{
|
|
1862
|
-
guard: 'needsBossReplyWithQuestion',
|
|
1863
|
-
target: 'awaitBossReply',
|
|
1864
|
-
actions: {
|
|
1865
|
-
type: 'setPendingBossQuestion',
|
|
1866
|
-
params: {
|
|
1867
|
-
...captainStateMetadata.reviewDrInitialCommit,
|
|
1868
|
-
resumeStateId: 'reviewDrInitialCommit',
|
|
1869
|
-
question: '',
|
|
1870
|
-
},
|
|
1871
|
-
},
|
|
1872
|
-
},
|
|
1873
|
-
{
|
|
1874
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
1875
|
-
target: 'failed',
|
|
1876
|
-
actions: [
|
|
1877
|
-
'rememberMalformedCaptainOutput',
|
|
1878
|
-
'clearBossReplyContext',
|
|
1879
|
-
],
|
|
1880
|
-
},
|
|
1881
|
-
{
|
|
1882
|
-
guard: 'noFindings',
|
|
1883
|
-
target: 'commitReviewedChanges',
|
|
1884
|
-
actions: ['rememberCaptainResult', 'clearBossReplyContext'],
|
|
1885
|
-
},
|
|
1886
|
-
{
|
|
1887
|
-
guard: 'findingsRaised',
|
|
1888
|
-
target: 'hostAddressesFindings',
|
|
1889
|
-
actions: ['rememberReviewFindings', 'clearBossReplyContext'],
|
|
1890
|
-
},
|
|
1891
|
-
{
|
|
1892
|
-
target: 'failed',
|
|
1893
|
-
actions: [
|
|
1894
|
-
'rememberMalformedCaptainOutput',
|
|
1895
|
-
'clearBossReplyContext',
|
|
1896
|
-
],
|
|
1897
|
-
},
|
|
1898
|
-
],
|
|
1899
|
-
onError: {
|
|
1900
|
-
target: 'failed',
|
|
1901
|
-
actions: ['rememberCaptainError', 'clearBossReplyContext'],
|
|
1902
|
-
},
|
|
1903
|
-
},
|
|
1904
|
-
},
|
|
1905
|
-
reviewDrHostChanges: {
|
|
1906
|
-
id: 'reviewDrHostChanges',
|
|
1907
|
-
tags: 'playbook.busy',
|
|
1908
|
-
description:
|
|
1909
|
-
'Participant reviews Host changes to decision records after findings.',
|
|
1910
|
-
meta: {
|
|
1911
|
-
playbook: {
|
|
1912
|
-
stateId: 'reviewDrHostChanges',
|
|
1913
|
-
description:
|
|
1914
|
-
'Participant reviews Host changes to decision records after findings.',
|
|
1915
|
-
},
|
|
1916
|
-
},
|
|
1917
|
-
invoke: {
|
|
1918
|
-
id: 'reviewDrHostChangesCaptain',
|
|
1919
|
-
src: 'player',
|
|
1920
|
-
input: ({ context }): PlayerInput => ({
|
|
1921
|
-
stateId: 'reviewDrHostChanges',
|
|
1922
|
-
player: 'Participant',
|
|
1923
|
-
sourceItem: 'DISCUSS-9',
|
|
1924
|
-
prompt: DISCUSS_9_PROMPT,
|
|
1925
|
-
result: withNeedsBossReply({
|
|
1926
|
-
noFindings: 'Participant raised no findings.',
|
|
1927
|
-
findingsRaised:
|
|
1928
|
-
'Participant raised findings. Output shall include `reviewItems: <findings>`.',
|
|
1929
|
-
}),
|
|
1930
|
-
latestChanges: context.latestChanges,
|
|
1931
|
-
rebuttals: context.rebuttals,
|
|
1932
|
-
participantPlayer: context.participantPlayer,
|
|
1933
|
-
...bossReplyFields(context, 'reviewDrHostChanges'),
|
|
1934
|
-
}),
|
|
1935
|
-
onDone: [
|
|
1936
|
-
{
|
|
1937
|
-
guard: 'needsBossReplyWithQuestion',
|
|
1938
|
-
target: 'awaitBossReply',
|
|
1939
|
-
actions: {
|
|
1940
|
-
type: 'setPendingBossQuestion',
|
|
1941
|
-
params: {
|
|
1942
|
-
...captainStateMetadata.reviewDrHostChanges,
|
|
1943
|
-
resumeStateId: 'reviewDrHostChanges',
|
|
1944
|
-
question: '',
|
|
1945
|
-
},
|
|
1946
|
-
},
|
|
1947
|
-
},
|
|
1948
|
-
{
|
|
1949
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
1950
|
-
target: 'failed',
|
|
1951
|
-
actions: [
|
|
1952
|
-
'rememberMalformedCaptainOutput',
|
|
1953
|
-
'clearBossReplyContext',
|
|
1954
|
-
],
|
|
1955
|
-
},
|
|
1956
|
-
{
|
|
1957
|
-
guard: 'noFindings',
|
|
1958
|
-
target: 'commitReviewedChanges',
|
|
1959
|
-
actions: ['rememberCaptainResult', 'clearBossReplyContext'],
|
|
1960
|
-
},
|
|
1961
|
-
{
|
|
1962
|
-
guard: 'findingsRaised',
|
|
1963
|
-
target: 'hostAddressesFindings',
|
|
1964
|
-
actions: ['rememberReviewFindings', 'clearBossReplyContext'],
|
|
1965
|
-
},
|
|
1966
|
-
{
|
|
1967
|
-
target: 'failed',
|
|
1968
|
-
actions: [
|
|
1969
|
-
'rememberMalformedCaptainOutput',
|
|
1970
|
-
'clearBossReplyContext',
|
|
1971
|
-
],
|
|
1972
|
-
},
|
|
1973
|
-
],
|
|
1974
|
-
onError: {
|
|
1975
|
-
target: 'failed',
|
|
1976
|
-
actions: ['rememberCaptainError', 'clearBossReplyContext'],
|
|
1977
|
-
},
|
|
1978
|
-
},
|
|
1979
|
-
},
|
|
1980
|
-
reviewMixedInitialCommit: {
|
|
1981
|
-
id: 'reviewMixedInitialCommit',
|
|
1982
|
-
tags: 'playbook.busy',
|
|
1983
|
-
description:
|
|
1984
|
-
'Participant reviews newly committed mixed spec-item and DR changes.',
|
|
1985
|
-
meta: {
|
|
1986
|
-
playbook: {
|
|
1987
|
-
stateId: 'reviewMixedInitialCommit',
|
|
1988
|
-
description:
|
|
1989
|
-
'Participant reviews newly committed mixed spec-item and DR changes.',
|
|
1990
|
-
},
|
|
1991
|
-
},
|
|
1992
|
-
invoke: {
|
|
1993
|
-
id: 'reviewMixedInitialCommitCaptain',
|
|
1994
|
-
src: 'player',
|
|
1995
|
-
input: ({ context }): PlayerInput => ({
|
|
1996
|
-
stateId: 'reviewMixedInitialCommit',
|
|
1997
|
-
player: 'Participant',
|
|
1998
|
-
sourceItem: 'DISCUSS-10',
|
|
1999
|
-
prompt: DISCUSS_10_PROMPT,
|
|
2000
|
-
result: withNeedsBossReply({
|
|
2001
|
-
noFindings: 'Participant raised no findings.',
|
|
2002
|
-
findingsRaised:
|
|
2003
|
-
'Participant raised findings. Output shall include `reviewItems: <findings>`.',
|
|
2004
|
-
}),
|
|
2005
|
-
latestChanges: context.latestChanges,
|
|
2006
|
-
rebuttals: context.rebuttals,
|
|
2007
|
-
participantPlayer: context.participantPlayer,
|
|
2008
|
-
...bossReplyFields(context, 'reviewMixedInitialCommit'),
|
|
2009
|
-
}),
|
|
2010
|
-
onDone: [
|
|
2011
|
-
{
|
|
2012
|
-
guard: 'needsBossReplyWithQuestion',
|
|
2013
|
-
target: 'awaitBossReply',
|
|
2014
|
-
actions: {
|
|
2015
|
-
type: 'setPendingBossQuestion',
|
|
2016
|
-
params: {
|
|
2017
|
-
...captainStateMetadata.reviewMixedInitialCommit,
|
|
2018
|
-
resumeStateId: 'reviewMixedInitialCommit',
|
|
2019
|
-
question: '',
|
|
2020
|
-
},
|
|
2021
|
-
},
|
|
2022
|
-
},
|
|
2023
|
-
{
|
|
2024
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
2025
|
-
target: 'failed',
|
|
2026
|
-
actions: [
|
|
2027
|
-
'rememberMalformedCaptainOutput',
|
|
2028
|
-
'clearBossReplyContext',
|
|
2029
|
-
],
|
|
2030
|
-
},
|
|
2031
|
-
{
|
|
2032
|
-
guard: 'noFindings',
|
|
2033
|
-
target: 'commitReviewedChanges',
|
|
2034
|
-
actions: ['rememberCaptainResult', 'clearBossReplyContext'],
|
|
2035
|
-
},
|
|
2036
|
-
{
|
|
2037
|
-
guard: 'findingsRaised',
|
|
2038
|
-
target: 'hostAddressesFindings',
|
|
2039
|
-
actions: ['rememberReviewFindings', 'clearBossReplyContext'],
|
|
2040
|
-
},
|
|
2041
|
-
{
|
|
2042
|
-
target: 'failed',
|
|
2043
|
-
actions: [
|
|
2044
|
-
'rememberMalformedCaptainOutput',
|
|
2045
|
-
'clearBossReplyContext',
|
|
2046
|
-
],
|
|
2047
|
-
},
|
|
2048
|
-
],
|
|
2049
|
-
onError: {
|
|
2050
|
-
target: 'failed',
|
|
2051
|
-
actions: ['rememberCaptainError', 'clearBossReplyContext'],
|
|
2052
|
-
},
|
|
2053
|
-
},
|
|
2054
|
-
},
|
|
2055
|
-
reviewMixedHostChanges: {
|
|
2056
|
-
id: 'reviewMixedHostChanges',
|
|
2057
|
-
tags: 'playbook.busy',
|
|
2058
|
-
description:
|
|
2059
|
-
'Participant reviews Host changes to mixed spec items and DRs after findings.',
|
|
2060
|
-
meta: {
|
|
2061
|
-
playbook: {
|
|
2062
|
-
stateId: 'reviewMixedHostChanges',
|
|
2063
|
-
description:
|
|
2064
|
-
'Participant reviews Host changes to mixed spec items and DRs after findings.',
|
|
2065
|
-
},
|
|
2066
|
-
},
|
|
2067
|
-
invoke: {
|
|
2068
|
-
id: 'reviewMixedHostChangesCaptain',
|
|
2069
|
-
src: 'player',
|
|
2070
|
-
input: ({ context }): PlayerInput => ({
|
|
2071
|
-
stateId: 'reviewMixedHostChanges',
|
|
2072
|
-
player: 'Participant',
|
|
2073
|
-
sourceItem: 'DISCUSS-11',
|
|
2074
|
-
prompt: DISCUSS_11_PROMPT,
|
|
2075
|
-
result: withNeedsBossReply({
|
|
2076
|
-
noFindings: 'Participant raised no findings.',
|
|
2077
|
-
findingsRaised:
|
|
2078
|
-
'Participant raised findings. Output shall include `reviewItems: <findings>`.',
|
|
2079
|
-
}),
|
|
2080
|
-
latestChanges: context.latestChanges,
|
|
2081
|
-
rebuttals: context.rebuttals,
|
|
2082
|
-
participantPlayer: context.participantPlayer,
|
|
2083
|
-
...bossReplyFields(context, 'reviewMixedHostChanges'),
|
|
2084
|
-
}),
|
|
2085
|
-
onDone: [
|
|
2086
|
-
{
|
|
2087
|
-
guard: 'needsBossReplyWithQuestion',
|
|
2088
|
-
target: 'awaitBossReply',
|
|
2089
|
-
actions: {
|
|
2090
|
-
type: 'setPendingBossQuestion',
|
|
2091
|
-
params: {
|
|
2092
|
-
...captainStateMetadata.reviewMixedHostChanges,
|
|
2093
|
-
resumeStateId: 'reviewMixedHostChanges',
|
|
2094
|
-
question: '',
|
|
2095
|
-
},
|
|
2096
|
-
},
|
|
2097
|
-
},
|
|
2098
|
-
{
|
|
2099
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
2100
|
-
target: 'failed',
|
|
2101
|
-
actions: [
|
|
2102
|
-
'rememberMalformedCaptainOutput',
|
|
2103
|
-
'clearBossReplyContext',
|
|
2104
|
-
],
|
|
2105
|
-
},
|
|
2106
|
-
{
|
|
2107
|
-
guard: 'noFindings',
|
|
2108
|
-
target: 'commitReviewedChanges',
|
|
2109
|
-
actions: ['rememberCaptainResult', 'clearBossReplyContext'],
|
|
2110
|
-
},
|
|
2111
|
-
{
|
|
2112
|
-
guard: 'findingsRaised',
|
|
2113
|
-
target: 'hostAddressesFindings',
|
|
2114
|
-
actions: ['rememberReviewFindings', 'clearBossReplyContext'],
|
|
2115
|
-
},
|
|
2116
|
-
{
|
|
2117
|
-
target: 'failed',
|
|
2118
|
-
actions: [
|
|
2119
|
-
'rememberMalformedCaptainOutput',
|
|
2120
|
-
'clearBossReplyContext',
|
|
2121
|
-
],
|
|
2122
|
-
},
|
|
2123
|
-
],
|
|
2124
|
-
onError: {
|
|
2125
|
-
target: 'failed',
|
|
2126
|
-
actions: ['rememberCaptainError', 'clearBossReplyContext'],
|
|
2127
|
-
},
|
|
2128
|
-
},
|
|
2129
|
-
},
|
|
2130
|
-
hostAddressesFindings: {
|
|
2131
|
-
id: 'hostAddressesFindings',
|
|
2132
|
-
tags: 'playbook.busy',
|
|
2133
|
-
description:
|
|
2134
|
-
'Host accepts or challenges review findings and stages repo changes.',
|
|
2135
|
-
meta: {
|
|
2136
|
-
playbook: {
|
|
2137
|
-
stateId: 'hostAddressesFindings',
|
|
2138
|
-
description:
|
|
2139
|
-
'Host accepts or challenges review findings and stages repo changes.',
|
|
2140
|
-
},
|
|
2141
|
-
},
|
|
2142
|
-
invoke: {
|
|
2143
|
-
id: 'hostAddressesFindingsCaptain',
|
|
2144
|
-
src: 'player',
|
|
2145
|
-
input: ({ context }): PlayerInput => ({
|
|
2146
|
-
stateId: 'hostAddressesFindings',
|
|
2147
|
-
player: 'Host',
|
|
2148
|
-
sourceItem: 'DISCUSS-12',
|
|
2149
|
-
prompt: DISCUSS_12_PROMPT,
|
|
2150
|
-
result: withNeedsBossReply({
|
|
2151
|
-
changesMade:
|
|
2152
|
-
'Host accepted findings and made changes. Output may include `latestChanges: <summary>`.',
|
|
2153
|
-
rebuttalsRaised:
|
|
2154
|
-
'Host raised rebuttals. Output shall include `rebuttals: <rebuttals>`.',
|
|
2155
|
-
}),
|
|
2156
|
-
reviewItems: context.reviewItems,
|
|
2157
|
-
latestChanges: context.latestChanges,
|
|
2158
|
-
hostPlayer: context.hostPlayer,
|
|
2159
|
-
...bossReplyFields(context, 'hostAddressesFindings'),
|
|
2160
|
-
}),
|
|
2161
|
-
onDone: [
|
|
2162
|
-
{
|
|
2163
|
-
guard: 'needsBossReplyWithQuestion',
|
|
2164
|
-
target: 'awaitBossReply',
|
|
2165
|
-
actions: {
|
|
2166
|
-
type: 'setPendingBossQuestion',
|
|
2167
|
-
params: {
|
|
2168
|
-
...captainStateMetadata.hostAddressesFindings,
|
|
2169
|
-
resumeStateId: 'hostAddressesFindings',
|
|
2170
|
-
question: '',
|
|
2171
|
-
},
|
|
2172
|
-
},
|
|
2173
|
-
},
|
|
2174
|
-
{
|
|
2175
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
2176
|
-
target: 'failed',
|
|
2177
|
-
actions: [
|
|
2178
|
-
'rememberMalformedCaptainOutput',
|
|
2179
|
-
'clearBossReplyContext',
|
|
2180
|
-
],
|
|
2181
|
-
},
|
|
2182
|
-
{
|
|
2183
|
-
guard: ({ context, event }) =>
|
|
2184
|
-
outputOf(event).guard === 'changesMade' &&
|
|
2185
|
-
(outputOf(event).reviewScope ?? context.reviewScope) ===
|
|
2186
|
-
'specItems',
|
|
2187
|
-
target: reviewTargets.specItems.afterChanges,
|
|
2188
|
-
actions: ['rememberHostReviewResponse', 'clearBossReplyContext'],
|
|
2189
|
-
},
|
|
2190
|
-
{
|
|
2191
|
-
guard: ({ context, event }) =>
|
|
2192
|
-
outputOf(event).guard === 'changesMade' &&
|
|
2193
|
-
(outputOf(event).reviewScope ?? context.reviewScope) ===
|
|
2194
|
-
'decisionRecords',
|
|
2195
|
-
target: reviewTargets.decisionRecords.afterChanges,
|
|
2196
|
-
actions: ['rememberHostReviewResponse', 'clearBossReplyContext'],
|
|
2197
|
-
},
|
|
2198
|
-
{
|
|
2199
|
-
guard: ({ context, event }) =>
|
|
2200
|
-
outputOf(event).guard === 'changesMade' &&
|
|
2201
|
-
(outputOf(event).reviewScope ?? context.reviewScope) === 'mixed',
|
|
2202
|
-
target: reviewTargets.mixed.afterChanges,
|
|
2203
|
-
actions: ['rememberHostReviewResponse', 'clearBossReplyContext'],
|
|
2204
|
-
},
|
|
2205
|
-
{
|
|
2206
|
-
guard: 'rebuttalsRaised',
|
|
2207
|
-
target: 'participantAddressesRebuttals',
|
|
2208
|
-
actions: ['rememberHostReviewResponse', 'clearBossReplyContext'],
|
|
2209
|
-
},
|
|
2210
|
-
{
|
|
2211
|
-
target: 'failed',
|
|
2212
|
-
actions: [
|
|
2213
|
-
'rememberMalformedCaptainOutput',
|
|
2214
|
-
'clearBossReplyContext',
|
|
2215
|
-
],
|
|
2216
|
-
},
|
|
2217
|
-
],
|
|
2218
|
-
onError: {
|
|
2219
|
-
target: 'failed',
|
|
2220
|
-
actions: ['rememberCaptainError', 'clearBossReplyContext'],
|
|
2221
|
-
},
|
|
2222
|
-
},
|
|
2223
|
-
},
|
|
2224
|
-
participantAddressesRebuttals: {
|
|
2225
|
-
id: 'participantAddressesRebuttals',
|
|
2226
|
-
tags: 'playbook.busy',
|
|
2227
|
-
description: 'Participant accepts or challenges Host rebuttals.',
|
|
2228
|
-
meta: {
|
|
2229
|
-
playbook: {
|
|
2230
|
-
stateId: 'participantAddressesRebuttals',
|
|
2231
|
-
description: 'Participant accepts or challenges Host rebuttals.',
|
|
2232
|
-
},
|
|
2233
|
-
},
|
|
2234
|
-
invoke: {
|
|
2235
|
-
id: 'participantAddressesRebuttalsCaptain',
|
|
2236
|
-
src: 'player',
|
|
2237
|
-
input: ({ context }): PlayerInput => ({
|
|
2238
|
-
stateId: 'participantAddressesRebuttals',
|
|
2239
|
-
player: 'Participant',
|
|
2240
|
-
sourceItem: 'DISCUSS-13',
|
|
2241
|
-
prompt: DISCUSS_13_PROMPT,
|
|
2242
|
-
result: withNeedsBossReply({
|
|
2243
|
-
rebuttalsAddressed:
|
|
2244
|
-
'Participant addressed Host rebuttals. Output may include `rebuttals: <remaining rebuttal context>`.',
|
|
2245
|
-
}),
|
|
2246
|
-
rebuttals: context.rebuttals,
|
|
2247
|
-
participantPlayer: context.participantPlayer,
|
|
2248
|
-
...bossReplyFields(context, 'participantAddressesRebuttals'),
|
|
2249
|
-
}),
|
|
2250
|
-
onDone: [
|
|
2251
|
-
{
|
|
2252
|
-
guard: 'needsBossReplyWithQuestion',
|
|
2253
|
-
target: 'awaitBossReply',
|
|
2254
|
-
actions: {
|
|
2255
|
-
type: 'setPendingBossQuestion',
|
|
2256
|
-
params: {
|
|
2257
|
-
...captainStateMetadata.participantAddressesRebuttals,
|
|
2258
|
-
resumeStateId: 'participantAddressesRebuttals',
|
|
2259
|
-
question: '',
|
|
2260
|
-
},
|
|
2261
|
-
},
|
|
2262
|
-
},
|
|
2263
|
-
{
|
|
2264
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
2265
|
-
target: 'failed',
|
|
2266
|
-
actions: [
|
|
2267
|
-
'rememberMalformedCaptainOutput',
|
|
2268
|
-
'clearBossReplyContext',
|
|
2269
|
-
],
|
|
2270
|
-
},
|
|
2271
|
-
{
|
|
2272
|
-
guard: 'rebuttalsAddressed',
|
|
2273
|
-
target: 'hostAddressesFindings',
|
|
2274
|
-
actions: [
|
|
2275
|
-
'rememberParticipantRebuttalResponse',
|
|
2276
|
-
'clearBossReplyContext',
|
|
2277
|
-
],
|
|
2278
|
-
},
|
|
2279
|
-
{
|
|
2280
|
-
target: 'failed',
|
|
2281
|
-
actions: [
|
|
2282
|
-
'rememberMalformedCaptainOutput',
|
|
2283
|
-
'clearBossReplyContext',
|
|
2284
|
-
],
|
|
2285
|
-
},
|
|
2286
|
-
],
|
|
2287
|
-
onError: {
|
|
2288
|
-
target: 'failed',
|
|
2289
|
-
actions: ['rememberCaptainError', 'clearBossReplyContext'],
|
|
2290
|
-
},
|
|
2291
|
-
},
|
|
2292
|
-
},
|
|
2293
|
-
commitReviewedChanges: {
|
|
2294
|
-
id: 'commitReviewedChanges',
|
|
2295
|
-
tags: 'playbook.busy',
|
|
2296
|
-
description:
|
|
2297
|
-
'Committer commits reviewed changes once Participant raises no findings.',
|
|
2298
|
-
meta: {
|
|
2299
|
-
playbook: {
|
|
2300
|
-
stateId: 'commitReviewedChanges',
|
|
2301
|
-
description:
|
|
2302
|
-
'Committer commits reviewed changes once Participant raises no findings.',
|
|
2303
|
-
},
|
|
2304
|
-
},
|
|
2305
|
-
invoke: {
|
|
2306
|
-
id: 'commitReviewedChangesCaptain',
|
|
2307
|
-
src: 'player',
|
|
2308
|
-
input: ({ context }): PlayerInput => ({
|
|
2309
|
-
stateId: 'commitReviewedChanges',
|
|
2310
|
-
player: 'Committer',
|
|
2311
|
-
sourceItem: 'DISCUSS-15',
|
|
2312
|
-
prompt: DISCUSS_15_PROMPT,
|
|
2313
|
-
result: withNeedsBossReply({
|
|
2314
|
-
committed: 'Committer made the reviewed-changes commit.',
|
|
2315
|
-
}),
|
|
2316
|
-
latestChanges: context.latestChanges,
|
|
2317
|
-
hostLlm: context.hostLlm,
|
|
2318
|
-
participantLlm: context.participantLlm,
|
|
2319
|
-
committerPlayer: context.committerPlayer,
|
|
2320
|
-
...bossReplyFields(context, 'commitReviewedChanges'),
|
|
2321
|
-
}),
|
|
2322
|
-
onDone: [
|
|
2323
|
-
{
|
|
2324
|
-
guard: 'needsBossReplyWithQuestion',
|
|
2325
|
-
target: 'awaitBossReply',
|
|
2326
|
-
actions: {
|
|
2327
|
-
type: 'setPendingBossQuestion',
|
|
2328
|
-
params: {
|
|
2329
|
-
...captainStateMetadata.commitReviewedChanges,
|
|
2330
|
-
resumeStateId: 'commitReviewedChanges',
|
|
2331
|
-
question: '',
|
|
2332
|
-
},
|
|
2333
|
-
},
|
|
2334
|
-
},
|
|
2335
|
-
{
|
|
2336
|
-
guard: 'needsBossReplyWithoutQuestion',
|
|
2337
|
-
target: 'failed',
|
|
2338
|
-
actions: [
|
|
2339
|
-
'rememberMalformedCaptainOutput',
|
|
2340
|
-
'clearBossReplyContext',
|
|
2341
|
-
],
|
|
2342
|
-
},
|
|
2343
|
-
{
|
|
2344
|
-
guard: 'committed',
|
|
2345
|
-
target: 'done',
|
|
2346
|
-
actions: ['rememberCaptainResult', 'clearBossReplyContext'],
|
|
2347
|
-
},
|
|
2348
|
-
{
|
|
2349
|
-
target: 'failed',
|
|
2350
|
-
actions: [
|
|
2351
|
-
'rememberMalformedCaptainOutput',
|
|
2352
|
-
'clearBossReplyContext',
|
|
2353
|
-
],
|
|
2354
|
-
},
|
|
2355
|
-
],
|
|
2356
|
-
onError: {
|
|
2357
|
-
target: 'failed',
|
|
2358
|
-
actions: ['rememberCaptainError', 'clearBossReplyContext'],
|
|
2359
|
-
},
|
|
2360
|
-
},
|
|
2361
|
-
},
|
|
2362
|
-
awaitBossReply: {
|
|
2363
|
-
id: 'awaitBossReply',
|
|
2364
|
-
tags: 'playbook.parked',
|
|
2365
|
-
description: 'Waiting for Boss to answer a player question.',
|
|
2366
|
-
meta: {
|
|
2367
|
-
playbook: {
|
|
2368
|
-
stateId: 'awaitBossReply',
|
|
2369
|
-
description: 'Waiting for Boss to answer a player question.',
|
|
2370
|
-
},
|
|
2371
|
-
},
|
|
2372
|
-
on: {
|
|
2373
|
-
BOSS_REPLY: [
|
|
2374
|
-
{
|
|
2375
|
-
guard: 'emptyBossReply',
|
|
2376
|
-
target: 'failed',
|
|
2377
|
-
actions: ['rememberMalformedBossReply', 'clearBossReplyContext'],
|
|
2378
|
-
},
|
|
2379
|
-
...resumableStates(resumableStateIds),
|
|
2380
|
-
{
|
|
2381
|
-
target: 'failed',
|
|
2382
|
-
actions: ['rememberMalformedBossReply', 'clearBossReplyContext'],
|
|
2383
|
-
},
|
|
2384
|
-
],
|
|
2385
|
-
BOSS_INTERRUPT: bossInterrupts(
|
|
2386
|
-
jumpableStateIds,
|
|
2387
|
-
'clearBossReplyContext',
|
|
2388
|
-
),
|
|
2389
|
-
START_DISCUSSION: {
|
|
2390
|
-
target: 'initialProposalRound',
|
|
2391
|
-
actions: ['clearBossReplyContext', 'copyStartDiscussion'],
|
|
2392
|
-
},
|
|
2393
|
-
START_REVIEW: [
|
|
2394
|
-
{
|
|
2395
|
-
guard: 'specReview',
|
|
2396
|
-
target: reviewTargets.specItems.initial,
|
|
2397
|
-
actions: ['clearBossReplyContext', 'copyStartReview'],
|
|
2398
|
-
},
|
|
2399
|
-
{
|
|
2400
|
-
guard: 'drReview',
|
|
2401
|
-
target: reviewTargets.decisionRecords.initial,
|
|
2402
|
-
actions: ['clearBossReplyContext', 'copyStartReview'],
|
|
2403
|
-
},
|
|
2404
|
-
{
|
|
2405
|
-
guard: 'mixedReview',
|
|
2406
|
-
target: reviewTargets.mixed.initial,
|
|
2407
|
-
actions: ['clearBossReplyContext', 'copyStartReview'],
|
|
2408
|
-
},
|
|
2409
|
-
],
|
|
2410
|
-
},
|
|
2411
|
-
},
|
|
2412
|
-
failed: {
|
|
2413
|
-
id: 'failed',
|
|
2414
|
-
tags: 'playbook.parked',
|
|
2415
|
-
description:
|
|
2416
|
-
'The discussion workflow failed and is waiting for Boss recovery.',
|
|
2417
|
-
meta: {
|
|
2418
|
-
playbook: {
|
|
2419
|
-
stateId: 'failed',
|
|
2420
|
-
description:
|
|
2421
|
-
'The discussion workflow failed and is waiting for Boss recovery.',
|
|
2422
|
-
},
|
|
2423
|
-
},
|
|
2424
|
-
on: {
|
|
2425
|
-
START_DISCUSSION: {
|
|
2426
|
-
target: 'initialProposalRound',
|
|
2427
|
-
actions: 'copyStartDiscussion',
|
|
2428
|
-
},
|
|
2429
|
-
START_REVIEW: [
|
|
2430
|
-
{
|
|
2431
|
-
guard: 'specReview',
|
|
2432
|
-
target: reviewTargets.specItems.initial,
|
|
2433
|
-
actions: 'copyStartReview',
|
|
2434
|
-
},
|
|
2435
|
-
{
|
|
2436
|
-
guard: 'drReview',
|
|
2437
|
-
target: reviewTargets.decisionRecords.initial,
|
|
2438
|
-
actions: 'copyStartReview',
|
|
2439
|
-
},
|
|
2440
|
-
{
|
|
2441
|
-
guard: 'mixedReview',
|
|
2442
|
-
target: reviewTargets.mixed.initial,
|
|
2443
|
-
actions: 'copyStartReview',
|
|
2444
|
-
},
|
|
2445
|
-
],
|
|
2446
|
-
},
|
|
2447
|
-
},
|
|
2448
|
-
done: {
|
|
2449
|
-
id: 'done',
|
|
2450
|
-
type: 'final',
|
|
2451
|
-
description: 'The discussion workflow completed with a reviewed commit.',
|
|
2452
|
-
meta: {
|
|
2453
|
-
playbook: {
|
|
2454
|
-
stateId: 'done',
|
|
2455
|
-
description:
|
|
2456
|
-
'The discussion workflow completed with a reviewed commit.',
|
|
2457
|
-
},
|
|
2458
|
-
},
|
|
2459
|
-
},
|
|
2460
|
-
},
|
|
2461
|
-
});
|
|
2462
|
-
|
|
2463
|
-
export { bossInterrupts, resumableStates };
|
|
2464
|
-
|
|
2465
|
-
export default discussMachine;
|