@sublang/playbook 9.0.0 → 11.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/docs/cli.md +109 -21
- package/docs/configuration.md +89 -40
- package/docs/embedding.md +126 -12
- package/package.json +14 -3
- package/reference/sdlc/captain.md +14 -10
- package/reference/sdlc/captain.playbook/captain.fsm.d.ts +33 -13
- package/reference/sdlc/captain.playbook/captain.fsm.js +80 -9
- package/reference/sdlc/captain.playbook/captain.fsm.ts +137 -18
- package/reference/sdlc/captain.playbook/captain.gears.md +10 -6
- package/reference/sdlc/captain.playbook/captain.playbook.d.ts +5 -1
- package/reference/sdlc/captain.playbook/captain.playbook.js +140 -10
- package/reference/sdlc/captain.playbook/captain.playbook.ts +188 -16
- package/reference/sdlc/code.md +35 -16
- package/reference/sdlc/code.playbook/bin/interactive-session.js +228 -23
- package/reference/sdlc/code.playbook/bin/launch-config.js +611 -221
- package/reference/sdlc/code.playbook/bin/playbook.js +304 -178
- package/reference/sdlc/code.playbook/bin/replay-observer.js +221 -0
- package/reference/sdlc/code.playbook/bin/repository-effects.js +2930 -0
- package/reference/sdlc/code.playbook/bin/run.js +669 -215
- package/reference/sdlc/code.playbook/bin/session-store.js +4546 -502
- package/reference/sdlc/code.playbook/code.fsm.d.ts +7 -0
- package/reference/sdlc/code.playbook/code.fsm.js +74 -25
- package/reference/sdlc/code.playbook/code.fsm.ts +83 -29
- package/reference/sdlc/code.playbook/code.gears.md +0 -2
- package/reference/sdlc/code.playbook/code.playbook.d.ts +5 -2
- package/reference/sdlc/code.playbook/code.playbook.js +54 -2
- package/reference/sdlc/code.playbook/code.playbook.ts +75 -6
- package/reference/sdlc/code.playbook/code.registry.d.ts +10 -3
- package/reference/sdlc/code.playbook/code.registry.js +10 -3
- package/reference/sdlc/code.playbook/code.registry.ts +23 -5
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +103 -8
- package/reference/sdlc/code.playbook/playbook-captain.js +1871 -75
- package/reference/sdlc/code.playbook/playbook-captain.ts +2801 -102
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +14 -10
- package/reference/sdlc/code.playbook/session-store.d.ts +82 -0
- package/reference/sdlc/code.playbook/session-store.js +113 -0
- package/reference/sdlc/decide.md +24 -16
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +7 -0
- package/reference/sdlc/decide.playbook/decide.fsm.js +80 -29
- package/reference/sdlc/decide.playbook/decide.fsm.ts +89 -31
- package/reference/sdlc/decide.playbook/decide.gears.md +0 -1
- package/reference/sdlc/decide.playbook/decide.playbook.d.ts +13 -5
- package/reference/sdlc/decide.playbook/decide.playbook.js +1712 -91
- package/reference/sdlc/decide.playbook/decide.playbook.ts +2677 -136
- package/reference/sdlc/decide.playbook/decide.registry.d.ts +7 -3
- package/reference/sdlc/decide.playbook/decide.registry.js +10 -3
- package/reference/sdlc/decide.playbook/decide.registry.ts +20 -5
- package/reference/sdlc/review.md +36 -18
- package/reference/sdlc/review.playbook/review.fsm.d.ts +7 -0
- package/reference/sdlc/review.playbook/review.fsm.js +133 -12
- package/reference/sdlc/review.playbook/review.fsm.ts +140 -12
- package/reference/sdlc/review.playbook/review.playbook.d.ts +5 -2
- package/reference/sdlc/review.playbook/review.playbook.js +65 -2
- package/reference/sdlc/review.playbook/review.playbook.ts +83 -6
- package/reference/sdlc/review.playbook/review.registry.d.ts +10 -3
- package/reference/sdlc/review.playbook/review.registry.js +10 -3
- package/reference/sdlc/review.playbook/review.registry.ts +23 -5
- package/slc/gears2fsm.md +6 -5
- package/slc/link.md +544 -41
- package/src/accepted-outcome.d.ts +18 -0
- package/src/accepted-outcome.js +94 -0
- package/src/accepted-outcome.ts +140 -0
- package/src/runtime.d.ts +164 -3
- package/src/runtime.ts +213 -2
- package/src/xstate-playbook-runtime.d.ts +149 -10
- package/src/xstate-playbook-runtime.js +2569 -270
- package/src/xstate-playbook-runtime.ts +4133 -490
- package/src/xstate-runtime.d.ts +59 -1
- package/src/xstate-runtime.js +866 -7
- package/src/xstate-runtime.ts +1397 -7
|
@@ -8,9 +8,10 @@
|
|
|
8
8
|
|
|
9
9
|
# The Captain and each stable session player carries its own defaults inline:
|
|
10
10
|
# an adapter shorthand (claude, codex) or a block with
|
|
11
|
-
# adapter/model/effort/permissions. A role may override only model
|
|
12
|
-
#
|
|
13
|
-
#
|
|
11
|
+
# adapter/model/effort/fastMode/permissions. A role may override only model,
|
|
12
|
+
# effort, or fastMode.
|
|
13
|
+
# Omit an override to inherit the player default. For model and effort, false
|
|
14
|
+
# selects the provider default; fastMode false is a literal disabled request.
|
|
14
15
|
|
|
15
16
|
# Each adapter needs its vendor SDK installed as its own top-level
|
|
16
17
|
# install root — they are optional peer dependencies, so you pay only
|
|
@@ -29,7 +30,7 @@
|
|
|
29
30
|
# list, so those captains degrade to a prompt-level restriction (DR-013 A1).
|
|
30
31
|
captain:
|
|
31
32
|
adapter: claude
|
|
32
|
-
model: claude-opus-
|
|
33
|
+
model: claude-opus-5
|
|
33
34
|
effort: high
|
|
34
35
|
permissions:
|
|
35
36
|
mode: auto
|
|
@@ -45,19 +46,22 @@ notifications:
|
|
|
45
46
|
# shares one provider conversation across those playbooks.
|
|
46
47
|
players:
|
|
47
48
|
dev.coder:
|
|
48
|
-
adapter:
|
|
49
|
-
model:
|
|
50
|
-
effort:
|
|
49
|
+
adapter: codex
|
|
50
|
+
model: gpt-5.6-sol
|
|
51
|
+
effort: ultra
|
|
52
|
+
# Adapter-scoped fast mode is validated by the installed Cligent contract;
|
|
53
|
+
# omitting it takes the provider default.
|
|
54
|
+
fastMode: true
|
|
51
55
|
permissions:
|
|
52
56
|
mode: auto
|
|
57
|
+
writablePaths: ['.git']
|
|
53
58
|
|
|
54
59
|
dev.reviewer:
|
|
55
|
-
adapter:
|
|
56
|
-
model:
|
|
60
|
+
adapter: claude
|
|
61
|
+
model: claude-opus-5
|
|
57
62
|
effort: xhigh
|
|
58
63
|
permissions:
|
|
59
64
|
mode: auto
|
|
60
|
-
writablePaths: ['.git']
|
|
61
65
|
|
|
62
66
|
# Enabled playbooks. Each is loaded from its explicit `from` module; the
|
|
63
67
|
# `<id>` key must equal that module's manifest id. `from`, `command`, and
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
+
|
|
4
|
+
export declare const RECORDS_STREAM_VERSION: 1;
|
|
5
|
+
export declare function defaultSessionsDir(): string;
|
|
6
|
+
export declare function openSessionStore(
|
|
7
|
+
sessionsDir: string,
|
|
8
|
+
): PlaybookSessionStore;
|
|
9
|
+
|
|
10
|
+
export type ReplayJsonValue =
|
|
11
|
+
| null
|
|
12
|
+
| boolean
|
|
13
|
+
| number
|
|
14
|
+
| string
|
|
15
|
+
| readonly ReplayJsonValue[]
|
|
16
|
+
| ReplayRecord;
|
|
17
|
+
export type ReplayRecord = {
|
|
18
|
+
readonly [key: string]: ReplayJsonValue;
|
|
19
|
+
};
|
|
20
|
+
export interface ReplayStreamEntry {
|
|
21
|
+
readonly v: 1;
|
|
22
|
+
readonly seq: number;
|
|
23
|
+
readonly role?: string;
|
|
24
|
+
readonly record: ReplayRecord;
|
|
25
|
+
}
|
|
26
|
+
export interface ReplayStreamReadOptions {
|
|
27
|
+
readonly afterSeq?: number;
|
|
28
|
+
}
|
|
29
|
+
export interface ReplayStreamReadResult {
|
|
30
|
+
readonly entries: readonly ReplayStreamEntry[];
|
|
31
|
+
readonly lastReadableSeq: number;
|
|
32
|
+
}
|
|
33
|
+
export interface LeaseReplayStreamReadResult extends ReplayStreamReadResult {
|
|
34
|
+
readonly lastDurableSeq: number;
|
|
35
|
+
readonly incomplete: boolean;
|
|
36
|
+
}
|
|
37
|
+
export type ReplayStreamStatus =
|
|
38
|
+
| {
|
|
39
|
+
readonly lastReadableSeq: number;
|
|
40
|
+
readonly lastDurableSeq: number;
|
|
41
|
+
readonly incomplete: boolean;
|
|
42
|
+
}
|
|
43
|
+
| {
|
|
44
|
+
readonly lastReadableSeq: null;
|
|
45
|
+
readonly lastDurableSeq: null;
|
|
46
|
+
readonly incomplete: true;
|
|
47
|
+
};
|
|
48
|
+
export interface PlaybookSessionSummary {
|
|
49
|
+
readonly schemaVersion: number;
|
|
50
|
+
readonly sessionId: string;
|
|
51
|
+
readonly state: 'settled' | 'uncertain';
|
|
52
|
+
readonly cwd: string;
|
|
53
|
+
readonly updatedAt: string;
|
|
54
|
+
}
|
|
55
|
+
export interface SkippedPlaybookSession {
|
|
56
|
+
readonly sessionId: string;
|
|
57
|
+
readonly reason: string;
|
|
58
|
+
}
|
|
59
|
+
export interface PlaybookSessionListResult {
|
|
60
|
+
readonly sessions: readonly PlaybookSessionSummary[];
|
|
61
|
+
readonly skipped: readonly SkippedPlaybookSession[];
|
|
62
|
+
}
|
|
63
|
+
export interface PlaybookSessionStore {
|
|
64
|
+
readonly sessionsDir: string;
|
|
65
|
+
list(): Promise<PlaybookSessionListResult>;
|
|
66
|
+
read(sessionId: string): Promise<PlaybookSessionSummary>;
|
|
67
|
+
readStream(
|
|
68
|
+
sessionId: string,
|
|
69
|
+
options?: ReplayStreamReadOptions,
|
|
70
|
+
): Promise<ReplayStreamReadResult>;
|
|
71
|
+
acquire(sessionId: string): Promise<PlaybookSessionLease>;
|
|
72
|
+
}
|
|
73
|
+
export interface PlaybookSessionLease {
|
|
74
|
+
readonly sessionId: string;
|
|
75
|
+
readonly ownerToken: string;
|
|
76
|
+
append(record: object, role?: string): Promise<void>;
|
|
77
|
+
readStream(
|
|
78
|
+
options?: ReplayStreamReadOptions,
|
|
79
|
+
): Promise<LeaseReplayStreamReadResult>;
|
|
80
|
+
streamStatus(): ReplayStreamStatus;
|
|
81
|
+
release(): Promise<ReplayStreamStatus>;
|
|
82
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
RECORDS_STREAM_VERSION,
|
|
6
|
+
createCaptainSessionStore,
|
|
7
|
+
defaultCaptainSessionsDir,
|
|
8
|
+
} from './bin/session-store.js';
|
|
9
|
+
|
|
10
|
+
export { RECORDS_STREAM_VERSION };
|
|
11
|
+
|
|
12
|
+
export function defaultSessionsDir() {
|
|
13
|
+
return defaultCaptainSessionsDir();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function openSessionStore(sessionsDir) {
|
|
17
|
+
if (typeof sessionsDir !== 'string') {
|
|
18
|
+
throw new TypeError('session store path must be a string');
|
|
19
|
+
}
|
|
20
|
+
return wrapStore(createCaptainSessionStore({ sessionsDir }));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function wrapStore(store) {
|
|
24
|
+
return Object.freeze({
|
|
25
|
+
sessionsDir: store.sessionsDir,
|
|
26
|
+
list: async () => projectListResult(await store.listSummaries()),
|
|
27
|
+
read: async (sessionId) =>
|
|
28
|
+
projectSummary(await store.readSummary(sessionId)),
|
|
29
|
+
readStream: async (sessionId, options) =>
|
|
30
|
+
projectReadResult(await store.readStream(sessionId, options)),
|
|
31
|
+
acquire: async (sessionId) => wrapLease(await store.acquire(sessionId)),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function wrapLease(lease) {
|
|
36
|
+
let finalStatus;
|
|
37
|
+
let releaseInFlight;
|
|
38
|
+
|
|
39
|
+
const release = () => {
|
|
40
|
+
if (finalStatus !== undefined) return Promise.resolve(finalStatus);
|
|
41
|
+
if (releaseInFlight !== undefined) return releaseInFlight;
|
|
42
|
+
const operation = lease.release();
|
|
43
|
+
releaseInFlight = operation.then(
|
|
44
|
+
(status) => {
|
|
45
|
+
finalStatus = projectStatus(status);
|
|
46
|
+
return finalStatus;
|
|
47
|
+
},
|
|
48
|
+
(cause) => {
|
|
49
|
+
releaseInFlight = undefined;
|
|
50
|
+
throw cause;
|
|
51
|
+
},
|
|
52
|
+
);
|
|
53
|
+
return releaseInFlight;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
return Object.freeze({
|
|
57
|
+
sessionId: lease.sessionId,
|
|
58
|
+
ownerToken: lease.ownerToken,
|
|
59
|
+
append: (record, role) => lease.append(record, role),
|
|
60
|
+
readStream: async (options) => {
|
|
61
|
+
if (finalStatus !== undefined) {
|
|
62
|
+
throw new Error('released session lease has no live replay reader');
|
|
63
|
+
}
|
|
64
|
+
return projectLeaseReadResult(await lease.readStream(options));
|
|
65
|
+
},
|
|
66
|
+
streamStatus: () => finalStatus ?? projectStatus(lease.streamStatus()),
|
|
67
|
+
release,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function projectListResult(result) {
|
|
72
|
+
return Object.freeze({
|
|
73
|
+
sessions: Object.freeze(result.sessions.map(projectSummary)),
|
|
74
|
+
skipped: Object.freeze(
|
|
75
|
+
result.skipped.map(({ sessionId, reason }) =>
|
|
76
|
+
Object.freeze({ sessionId, reason }),
|
|
77
|
+
),
|
|
78
|
+
),
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function projectSummary(summary) {
|
|
83
|
+
return Object.freeze({
|
|
84
|
+
schemaVersion: summary.schemaVersion,
|
|
85
|
+
sessionId: summary.sessionId,
|
|
86
|
+
state: summary.state,
|
|
87
|
+
cwd: summary.cwd,
|
|
88
|
+
updatedAt: summary.updatedAt,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function projectReadResult(result) {
|
|
93
|
+
return Object.freeze({
|
|
94
|
+
entries: Object.freeze([...result.entries]),
|
|
95
|
+
lastReadableSeq: result.lastReadableSeq,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function projectLeaseReadResult(result) {
|
|
100
|
+
return Object.freeze({
|
|
101
|
+
...projectReadResult(result),
|
|
102
|
+
lastDurableSeq: result.lastDurableSeq,
|
|
103
|
+
incomplete: result.incomplete,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function projectStatus(status) {
|
|
108
|
+
return Object.freeze({
|
|
109
|
+
lastReadableSeq: status.lastReadableSeq,
|
|
110
|
+
lastDurableSeq: status.lastDurableSeq,
|
|
111
|
+
incomplete: status.incomplete,
|
|
112
|
+
});
|
|
113
|
+
}
|
package/reference/sdlc/decide.md
CHANGED
|
@@ -23,32 +23,40 @@ Consult @specs/map.md for relevant context and @specs/meta.md for spec requireme
|
|
|
23
23
|
Do not change any files.
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Neither role's player shall receive the other role's proposal until both proposals are complete
|
|
26
|
+
Neither role's player shall receive the other role's proposal until both proposals are complete.
|
|
27
|
+
Each proposal is complete only when its player affirmatively provides a complete design proposal.
|
|
28
|
+
A progress report, status update, or promise of a later proposal supports no proposal outcome.
|
|
27
29
|
A Boss interrupt during the parallel proposal pair shall restart the whole pair so both players receive the same new topic and remain independent.
|
|
28
30
|
|
|
29
|
-
When both proposals are complete, Captain shall
|
|
31
|
+
When both proposals are complete, Captain shall give Coder the following instruction, with the complete topic and Reviewer's complete proposal inserted under their own labels in quotes (`>`):
|
|
30
32
|
|
|
31
33
|
```markdown
|
|
32
|
-
|
|
34
|
+
Synthesize your independent proposal with Reviewer's proposal below.
|
|
35
|
+
Keep to the original topic below and follow what it asks.
|
|
36
|
+
Keep the best, essential parts of either proposal and reject any point that is unsound, unnecessary, or outside the topic.
|
|
37
|
+
Turn the resulting design into the necessary DRs and/or spec items.
|
|
33
38
|
Follow @specs/meta.md and update @specs/map.md when needed.
|
|
34
|
-
Do not
|
|
35
|
-
Do not change code or implement the proposal.
|
|
39
|
+
Do not change code or implement the design.
|
|
36
40
|
|
|
37
41
|
Commit the result as one new commit, following @specs/packages/git.md.
|
|
38
42
|
Make the commit message explain concisely what changed and why.
|
|
39
|
-
|
|
40
|
-
Coder is <coder-llm
|
|
43
|
+
Identify every new commit you make.
|
|
44
|
+
Coder is <coder-llm> and Reviewer is <reviewer-llm>.
|
|
45
|
+
|
|
46
|
+
> Original topic: \<caller-topic\>
|
|
47
|
+
> Reviewer's independent proposal: \<reviewer-proposal\>
|
|
41
48
|
```
|
|
42
49
|
|
|
43
|
-
|
|
50
|
+
No transition shall depend on a fixed presentation format of either player's reply.
|
|
51
|
+
Captain shall use the repository-effect receipt as the authoritative identity of Coder's new `decide`-owned commit.
|
|
52
|
+
|
|
53
|
+
After Coder commits, Captain shall call playbook `review` with the following input in quotes (`>`):
|
|
44
54
|
|
|
45
|
-
>
|
|
46
|
-
>
|
|
47
|
-
>
|
|
48
|
-
>
|
|
49
|
-
> Initial intent: \<caller-topic\>.
|
|
50
|
-
> Coder's independent proposal: \<coder-proposal\>.
|
|
55
|
+
> Original intent: \<caller-topic\>
|
|
56
|
+
> Review scope: the `decide`-owned commit \<decide-commit\> and its resulting repository state.
|
|
57
|
+
> Coder output: \<coder-output\>
|
|
51
58
|
|
|
52
|
-
`decide` is complete when `review` returns the
|
|
53
|
-
|
|
59
|
+
`decide` is complete only when `review` returns a result that applies to the supplied review scope, gives the exact evaluated repository revision, and affirmatively establishes that no unsettled findings remain.
|
|
60
|
+
It then returns the `decide`-owned commit and that evaluated revision to its caller.
|
|
61
|
+
When `review` returns an authored abort or failure, or a terminal result that does not establish those facts, `decide` shall report the failure and the last `decide`-owned commit to its caller.
|
|
54
62
|
When the nested `review` call fails outside that authored result contract, `decide` shall park as failed and retain the control-plane error instead of reporting an authored review outcome.
|
|
@@ -127,6 +127,13 @@ export declare const decideMachine: import("xstate").StateMachine<DecideContext,
|
|
|
127
127
|
logic: import("xstate").PromiseActorLogic<PlayerOutput, PlayerInput, import("xstate").EventObject>;
|
|
128
128
|
id: string | undefined;
|
|
129
129
|
}, {
|
|
130
|
+
type: "playbook.acceptedOutcome";
|
|
131
|
+
params: {
|
|
132
|
+
readonly source: string;
|
|
133
|
+
readonly target: string;
|
|
134
|
+
readonly acceptedOutcome: string;
|
|
135
|
+
};
|
|
136
|
+
} | {
|
|
130
137
|
type: "rememberActorError";
|
|
131
138
|
params: import("xstate").NonReducibleUnknown;
|
|
132
139
|
} | {
|
|
@@ -23,7 +23,6 @@ const COMMIT_CODER_PROMPT = [
|
|
|
23
23
|
'',
|
|
24
24
|
'Commit the result as one new commit, following @specs/packages/git.md.',
|
|
25
25
|
'Make the commit message explain concisely what changed and why.',
|
|
26
|
-
'Include exactly one final-response line beginning `Commit: `, followed only by the exact commit identity; other final-response content may appear on other lines.',
|
|
27
26
|
'Coder is <coder-llm>; format the model token in conventional human form.',
|
|
28
27
|
].join('\n');
|
|
29
28
|
const REVIEW_INPUT_TEMPLATE = [
|
|
@@ -59,13 +58,6 @@ function commitOutput(event) {
|
|
|
59
58
|
!isNonEmptyString(output.latestCommit)) {
|
|
60
59
|
return undefined;
|
|
61
60
|
}
|
|
62
|
-
const commitLines = output.coderOutput
|
|
63
|
-
.split('\n')
|
|
64
|
-
.filter((line) => line.startsWith('Commit: '));
|
|
65
|
-
if (commitLines.length !== 1 ||
|
|
66
|
-
commitLines[0] !== `Commit: ${output.latestCommit}`) {
|
|
67
|
-
return undefined;
|
|
68
|
-
}
|
|
69
61
|
return {
|
|
70
62
|
coderOutput: output.coderOutput,
|
|
71
63
|
latestCommit: output.latestCommit,
|
|
@@ -305,6 +297,7 @@ export const decideMachine = setup({
|
|
|
305
297
|
}),
|
|
306
298
|
},
|
|
307
299
|
actions: {
|
|
300
|
+
'playbook.acceptedOutcome': (_args, _params) => undefined,
|
|
308
301
|
copyStartTopic: assign({
|
|
309
302
|
callerTopic: ({ event }) => event.type === 'START_DECIDE' ? event.callerTopic : undefined,
|
|
310
303
|
coderProposal: undefined,
|
|
@@ -514,14 +507,24 @@ export const decideMachine = setup({
|
|
|
514
507
|
{
|
|
515
508
|
guard: 'needsBossReplyWithQuestion',
|
|
516
509
|
target: 'waiting',
|
|
517
|
-
actions:
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
510
|
+
actions: [
|
|
511
|
+
{
|
|
512
|
+
type: 'playbook.acceptedOutcome',
|
|
513
|
+
params: {
|
|
514
|
+
source: 'askCoderProposal',
|
|
515
|
+
target: 'waitCoderProposalReply',
|
|
516
|
+
acceptedOutcome: 'needsBossReply',
|
|
517
|
+
},
|
|
523
518
|
},
|
|
524
|
-
|
|
519
|
+
{
|
|
520
|
+
type: 'setPendingBossQuestion',
|
|
521
|
+
params: {
|
|
522
|
+
...stateMetadata.askCoderProposal,
|
|
523
|
+
resumeStateId: 'askCoderProposal',
|
|
524
|
+
question: '',
|
|
525
|
+
},
|
|
526
|
+
},
|
|
527
|
+
],
|
|
525
528
|
},
|
|
526
529
|
{
|
|
527
530
|
guard: 'needsBossReplyWithoutQuestion',
|
|
@@ -535,6 +538,16 @@ export const decideMachine = setup({
|
|
|
535
538
|
guard: 'coderProposed',
|
|
536
539
|
target: 'complete',
|
|
537
540
|
actions: [
|
|
541
|
+
{
|
|
542
|
+
type: 'playbook.acceptedOutcome',
|
|
543
|
+
params: ({ context }) => ({
|
|
544
|
+
source: 'askCoderProposal',
|
|
545
|
+
target: context.stagedReviewerResult === undefined
|
|
546
|
+
? 'coderProposalComplete'
|
|
547
|
+
: 'commitCoderProposal',
|
|
548
|
+
acceptedOutcome: 'proposed',
|
|
549
|
+
}),
|
|
550
|
+
},
|
|
538
551
|
'stageCoderProposal',
|
|
539
552
|
{
|
|
540
553
|
type: 'clearBranchBossReplyContext',
|
|
@@ -630,14 +643,24 @@ export const decideMachine = setup({
|
|
|
630
643
|
{
|
|
631
644
|
guard: 'needsBossReplyWithQuestion',
|
|
632
645
|
target: 'waiting',
|
|
633
|
-
actions:
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
646
|
+
actions: [
|
|
647
|
+
{
|
|
648
|
+
type: 'playbook.acceptedOutcome',
|
|
649
|
+
params: {
|
|
650
|
+
source: 'askReviewerProposal',
|
|
651
|
+
target: 'waitReviewerProposalReply',
|
|
652
|
+
acceptedOutcome: 'needsBossReply',
|
|
653
|
+
},
|
|
639
654
|
},
|
|
640
|
-
|
|
655
|
+
{
|
|
656
|
+
type: 'setPendingBossQuestion',
|
|
657
|
+
params: {
|
|
658
|
+
...stateMetadata.askReviewerProposal,
|
|
659
|
+
resumeStateId: 'askReviewerProposal',
|
|
660
|
+
question: '',
|
|
661
|
+
},
|
|
662
|
+
},
|
|
663
|
+
],
|
|
641
664
|
},
|
|
642
665
|
{
|
|
643
666
|
guard: 'needsBossReplyWithoutQuestion',
|
|
@@ -651,6 +674,16 @@ export const decideMachine = setup({
|
|
|
651
674
|
guard: 'reviewerProposed',
|
|
652
675
|
target: 'complete',
|
|
653
676
|
actions: [
|
|
677
|
+
{
|
|
678
|
+
type: 'playbook.acceptedOutcome',
|
|
679
|
+
params: ({ context }) => ({
|
|
680
|
+
source: 'askReviewerProposal',
|
|
681
|
+
target: context.stagedCoderResult === undefined
|
|
682
|
+
? 'reviewerProposalComplete'
|
|
683
|
+
: 'commitCoderProposal',
|
|
684
|
+
acceptedOutcome: 'proposed',
|
|
685
|
+
}),
|
|
686
|
+
},
|
|
654
687
|
'stageReviewerProposal',
|
|
655
688
|
{
|
|
656
689
|
type: 'clearBranchBossReplyContext',
|
|
@@ -748,14 +781,24 @@ export const decideMachine = setup({
|
|
|
748
781
|
{
|
|
749
782
|
guard: 'needsBossReplyWithQuestion',
|
|
750
783
|
target: 'awaitBossReply',
|
|
751
|
-
actions:
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
784
|
+
actions: [
|
|
785
|
+
{
|
|
786
|
+
type: 'playbook.acceptedOutcome',
|
|
787
|
+
params: {
|
|
788
|
+
source: 'commitCoderProposal',
|
|
789
|
+
target: 'awaitBossReply',
|
|
790
|
+
acceptedOutcome: 'needsBossReply',
|
|
791
|
+
},
|
|
757
792
|
},
|
|
758
|
-
|
|
793
|
+
{
|
|
794
|
+
type: 'setPendingBossQuestion',
|
|
795
|
+
params: {
|
|
796
|
+
...stateMetadata.commitCoderProposal,
|
|
797
|
+
resumeStateId: 'commitCoderProposal',
|
|
798
|
+
question: '',
|
|
799
|
+
},
|
|
800
|
+
},
|
|
801
|
+
],
|
|
759
802
|
},
|
|
760
803
|
{
|
|
761
804
|
guard: 'needsBossReplyWithoutQuestion',
|
|
@@ -769,6 +812,14 @@ export const decideMachine = setup({
|
|
|
769
812
|
guard: 'committed',
|
|
770
813
|
target: 'reviewCommit',
|
|
771
814
|
actions: [
|
|
815
|
+
{
|
|
816
|
+
type: 'playbook.acceptedOutcome',
|
|
817
|
+
params: {
|
|
818
|
+
source: 'commitCoderProposal',
|
|
819
|
+
target: 'reviewCommit',
|
|
820
|
+
acceptedOutcome: 'committed',
|
|
821
|
+
},
|
|
822
|
+
},
|
|
772
823
|
'rememberCommit',
|
|
773
824
|
{
|
|
774
825
|
type: 'clearBranchBossReplyContext',
|