@sublang/playbook 15.1.0 → 17.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 +2 -0
- package/docs/cli.md +36 -18
- package/docs/configuration.md +7 -5
- package/docs/embedding.md +28 -7
- package/package.json +4 -4
- package/reference/sdlc/branch.playbook/branch.fsm.d.ts +63 -33
- package/reference/sdlc/branch.playbook/branch.fsm.js +190 -108
- package/reference/sdlc/branch.playbook/branch.fsm.ts +269 -147
- package/reference/sdlc/branch.playbook/branch.gears.md +7 -17
- package/reference/sdlc/branch.playbook/branch.playbook.d.ts +12 -16
- package/reference/sdlc/branch.playbook/branch.playbook.js +112 -101
- package/reference/sdlc/branch.playbook/branch.playbook.ts +128 -171
- package/reference/sdlc/branch.playbook/branch.registry.d.ts +3 -2
- package/reference/sdlc/branch.playbook/branch.registry.ts +6 -2
- package/reference/sdlc/captain.md +19 -10
- package/reference/sdlc/captain.playbook/captain.fsm.d.ts +6 -2
- package/reference/sdlc/captain.playbook/captain.fsm.js +19 -7
- package/reference/sdlc/captain.playbook/captain.fsm.ts +25 -10
- package/reference/sdlc/captain.playbook/captain.gears.md +16 -8
- package/reference/sdlc/captain.playbook/captain.playbook.d.ts +1 -1
- package/reference/sdlc/captain.playbook/captain.playbook.js +3 -2
- package/reference/sdlc/captain.playbook/captain.playbook.ts +4 -3
- package/reference/sdlc/code.playbook/bin/interactive-session.js +14 -1
- package/reference/sdlc/code.playbook/bin/portable-codec.js +3 -0
- package/reference/sdlc/code.playbook/bin/repository-effects.js +1 -0
- package/reference/sdlc/code.playbook/bin/run.js +128 -85
- package/reference/sdlc/code.playbook/bin/session-host.js +40 -8
- package/reference/sdlc/code.playbook/bin/session-store.js +162 -34
- package/reference/sdlc/code.playbook/code.fsm.d.ts +146 -93
- package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +8 -8
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +13 -13
- package/reference/sdlc/code.playbook/code.fsm.js +609 -649
- package/reference/sdlc/code.playbook/code.fsm.ts +890 -821
- package/reference/sdlc/code.playbook/code.gears.md +39 -29
- package/reference/sdlc/code.playbook/code.playbook.d.ts +13 -16
- package/reference/sdlc/code.playbook/code.playbook.js +166 -147
- package/reference/sdlc/code.playbook/code.playbook.ts +180 -229
- package/reference/sdlc/code.playbook/code.registry.d.ts +3 -2
- package/reference/sdlc/code.playbook/code.registry.ts +6 -2
- package/reference/sdlc/code.playbook/host-capabilities.d.ts +3 -0
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +74 -2
- package/reference/sdlc/code.playbook/playbook-captain.js +1548 -468
- package/reference/sdlc/code.playbook/playbook-captain.ts +1993 -573
- package/reference/sdlc/code.playbook/session-host.d.ts +4 -1
- package/reference/sdlc/code.playbook/session-store.d.ts +17 -0
- package/reference/sdlc/code.playbook/session-store.js +1 -0
- package/reference/sdlc/decide.md +1 -0
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +273 -157
- package/reference/sdlc/decide.playbook/decide.fsm.js +765 -732
- package/reference/sdlc/decide.playbook/decide.fsm.ts +1167 -945
- package/reference/sdlc/decide.playbook/decide.gears.md +28 -21
- package/reference/sdlc/decide.playbook/decide.playbook.d.ts +11 -59
- package/reference/sdlc/decide.playbook/decide.playbook.js +155 -3696
- package/reference/sdlc/decide.playbook/decide.playbook.ts +186 -5244
- package/reference/sdlc/decide.playbook/decide.registry.d.ts +8 -4
- package/reference/sdlc/decide.playbook/decide.registry.js +2 -2
- package/reference/sdlc/decide.playbook/decide.registry.ts +13 -6
- package/reference/sdlc/dev.playbook/dev.fsm.d.ts +116 -134
- package/reference/sdlc/dev.playbook/dev.fsm.js +517 -575
- package/reference/sdlc/dev.playbook/dev.fsm.ts +667 -787
- package/reference/sdlc/dev.playbook/dev.gears.md +52 -54
- package/reference/sdlc/dev.playbook/dev.playbook.d.ts +13 -10
- package/reference/sdlc/dev.playbook/dev.playbook.js +128 -120
- package/reference/sdlc/dev.playbook/dev.playbook.ts +143 -193
- package/reference/sdlc/dev.playbook/dev.registry.d.ts +3 -2
- package/reference/sdlc/dev.playbook/dev.registry.ts +6 -2
- package/reference/sdlc/pr.playbook/pr.fsm.d.ts +95 -88
- package/reference/sdlc/pr.playbook/pr.fsm.js +461 -518
- package/reference/sdlc/pr.playbook/pr.fsm.ts +533 -663
- package/reference/sdlc/pr.playbook/pr.gears.md +47 -63
- package/reference/sdlc/pr.playbook/pr.playbook.d.ts +13 -23
- package/reference/sdlc/pr.playbook/pr.playbook.js +118 -112
- package/reference/sdlc/pr.playbook/pr.playbook.ts +136 -190
- package/reference/sdlc/pr.playbook/pr.registry.d.ts +3 -2
- package/reference/sdlc/pr.playbook/pr.registry.ts +4 -2
- package/reference/sdlc/review.md +3 -3
- package/reference/sdlc/review.playbook/review.fsm.d.ts +150 -116
- package/reference/sdlc/review.playbook/review.fsm.js +479 -550
- package/reference/sdlc/review.playbook/review.fsm.ts +717 -662
- package/reference/sdlc/review.playbook/review.gears.md +32 -29
- package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -12
- package/reference/sdlc/review.playbook/review.playbook.js +180 -155
- package/reference/sdlc/review.playbook/review.playbook.ts +190 -230
- package/reference/sdlc/review.playbook/review.registry.d.ts +6 -5
- package/reference/sdlc/review.playbook/review.registry.js +3 -3
- package/reference/sdlc/review.playbook/review.registry.ts +9 -5
- package/slc/gears2fsm.md +77 -8
- package/slc/link.md +127 -60
- package/slc/materialize-link.mjs +51 -13
- package/slc/optimize.md +4 -1
- package/slc/prefix-prompts.mjs +29 -28
- package/slc/prefix.md +27 -24
- package/slc/slc.pin-inputs.json +11 -2
- package/slc/text2gears.md +71 -11
- package/src/runtime.d.ts +46 -2
- package/src/runtime.ts +42 -2
- package/src/xstate-playbook-runtime.d.ts +63 -23
- package/src/xstate-playbook-runtime.js +1637 -475
- package/src/xstate-playbook-runtime.ts +2105 -532
- package/src/xstate-runtime.d.ts +3 -4
- package/src/xstate-runtime.js +52 -0
- package/src/xstate-runtime.ts +59 -4
|
@@ -1,28 +1,23 @@
|
|
|
1
1
|
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
2
2
|
<!-- SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai> -->
|
|
3
3
|
|
|
4
|
-
# PR
|
|
4
|
+
# PR
|
|
5
5
|
|
|
6
6
|
Roles:
|
|
7
7
|
|
|
8
8
|
- Coder
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
`pr` delivers a reviewed branch into the repository default branch through a GitHub pull request: it publishes the branch, waits for the pull request's checks, fixes red checks through playbook `code` no more than once, and merges.
|
|
12
|
-
It changes no files and owns no repository commit; the one fix it may request is owned by `code`.
|
|
13
|
-
The check waits, the fix publication, the merge, and the local update are mechanical steps: each runs one fixed command whose exit status alone decides its two outcomes, reads no conversation, and produces no prose.
|
|
14
|
-
`gh` infers the pull request from the checked-out branch, which the run does not own: the nested `code` call suspends across Boss turns, so the checkout can change before the fix is published or the merge runs.
|
|
15
|
-
The two steps that act on the pull request itself therefore carry one runtime value — the pull request `pr` published — and refuse unless the checkout still infers exactly it.
|
|
16
|
-
That identity is reported text, so it binds as a single-quoted shell literal: the command compares it as data and never executes it as shell syntax.
|
|
17
|
-
|
|
18
|
-
## Coder
|
|
10
|
+
## Workflow
|
|
19
11
|
|
|
20
12
|
### PR-1
|
|
21
13
|
|
|
14
|
+
The caller supplies the original request, including the issue it names, if any; the issue summary; the branch to deliver and the base revision it was created from; the last `code`-owned commit and the exact evaluated repository revision; and optional relevant context.
|
|
15
|
+
`pr` delivers a reviewed branch into the repository default branch through a GitHub pull request; it changes no files and owns no repository commit.
|
|
16
|
+
Each outcome requires affirmative support in Coder's result, and no outcome depends on a fixed presentation format of Coder's reply.
|
|
17
|
+
Every outcome keeps the repository exact: pushing a branch and opening a pull request change neither HEAD's commit nor the working tree.
|
|
18
|
+
|
|
22
19
|
When the caller gives its input, Captain shall relay the complete caller input in quotes (`>`) to Coder, along with the following instruction:
|
|
23
20
|
|
|
24
|
-
> > Original request: <caller-input>
|
|
25
|
-
>
|
|
26
21
|
> Publish the branch and open its pull request without changing any file or making any commit.
|
|
27
22
|
> Confirm that the working tree is clean and that the checked-out branch is the branch to deliver, not the repository default branch.
|
|
28
23
|
> Push the branch to the repository's GitHub remote with its upstream set; never force-push.
|
|
@@ -30,21 +25,17 @@ When the caller gives its input, Captain shall relay the complete caller input i
|
|
|
30
25
|
> Give the pull request a title naming the change and a body with a summary of what changed and why from the base revision to the last commit, the verification the commits report, and a `Closes #N` line for issue number N when the request names one.
|
|
31
26
|
> Report the pull request number and URL exactly.
|
|
32
27
|
> If the working tree is not clean, the checked-out branch is wrong, the push is rejected, or the pull request cannot be opened, open nothing further and report the failure with its reason.
|
|
28
|
+
>
|
|
29
|
+
> > Original request: <caller-input>
|
|
33
30
|
|
|
34
31
|
Results:
|
|
35
|
-
- `opened`: Coder
|
|
36
|
-
- `notPublished`: Coder
|
|
37
|
-
|
|
38
|
-
Workflow outcomes:
|
|
39
|
-
- The result has two semantic outcomes: opened and not published.
|
|
40
|
-
- Each outcome requires affirmative support in Coder's result, and no outcome depends on a fixed presentation format of Coder's reply.
|
|
41
|
-
- Every outcome keeps the repository exact: pushing a branch and opening a pull request change neither HEAD's commit nor the working tree.
|
|
42
|
-
- For not published, `pr` fails and reports Coder's complete result with its reason to its caller.
|
|
43
|
-
|
|
44
|
-
## Checks, the one fix, and the merge
|
|
32
|
+
- `opened`: Coder's result affirmatively supports that the pull request is open. Output shall include `pullRequest: <exact pull request number as reported>` and `pullRequestUrl: <exact pull request URL as reported>`.
|
|
33
|
+
- `notPublished`: Coder's result affirmatively supports that the branch or its pull request was not published; the workflow fails and returns Coder's complete result with its reason to its caller. Output shall include `coderOutput: <verbatim final text>`.
|
|
45
34
|
|
|
46
35
|
### PR-2
|
|
47
36
|
|
|
37
|
+
The check wait is a mechanical step: it runs one fixed command whose exit status alone decides its two outcomes, reads no conversation, and produces no prose.
|
|
38
|
+
|
|
48
39
|
When the pull request is open and no fix has been attempted, Captain shall run:
|
|
49
40
|
|
|
50
41
|
> n=0
|
|
@@ -56,30 +47,32 @@ When the pull request is open and no fix has been attempted, Captain shall run:
|
|
|
56
47
|
> gh pr checks --watch --fail-fast >/dev/null 2>&1
|
|
57
48
|
|
|
58
49
|
Results:
|
|
59
|
-
- `checksPassed`: The command exited with status zero: the
|
|
60
|
-
- `checksFailed`: The command exited with a nonzero status: the
|
|
61
|
-
|
|
62
|
-
Workflow outcomes:
|
|
63
|
-
- The wait has exactly two outcomes decided by the command's exit status alone: checks passed on status zero and checks failed otherwise.
|
|
64
|
-
- A pull request whose repository still reports no checks after a brief wait for them to register counts as passed.
|
|
65
|
-
- Checks passed continues with the merge; checks failed continues with the one `code` fix attempt.
|
|
50
|
+
- `checksPassed`: The command exited with status zero: the checks passed; a pull request whose repository still reports no checks after a brief wait for them to register counts as passed.
|
|
51
|
+
- `checksFailed`: The command exited with a nonzero status: the checks failed.
|
|
66
52
|
|
|
67
53
|
### PR-3
|
|
68
54
|
|
|
55
|
+
`pr` makes no more than one fix attempt, and the one fix it may request is owned by `code`.
|
|
56
|
+
The call input carries the original request, the pull request, and the coding request in quotes (`>`).
|
|
57
|
+
|
|
69
58
|
When the checks fail before any fix attempt, Captain shall call playbook `code`:
|
|
70
59
|
|
|
71
60
|
> > Original request: <caller-input>
|
|
72
61
|
> > Pull request: <pull-request-url>
|
|
73
62
|
> > Coding request: The pull request's checks are red on the checked-out branch. Inspect the failing checks with `gh pr checks` and `gh run view --log-failed`, fix their cause on this branch with a minimal change, and make the checks pass.
|
|
74
63
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
- An authored `code` abort or failure, or a terminal `code` result that does not prove its success, terminates `pr` with that canonical result relayed and the pull request left open.
|
|
79
|
-
- Any other nested-call error parks `pr` as failed and retains the control-plane error.
|
|
64
|
+
Only after `code` succeeds shall `pr` publish the fix and wait for the checks again.
|
|
65
|
+
When `code` returns an authored abort or failure, or a terminal result that does not prove its success, `pr` shall fail relaying that canonical result and shall leave the pull request open.
|
|
66
|
+
When the nested `code` call fails outside that authored result contract, `pr` shall park as failed and retain the control-plane error instead of reporting an authored outcome.
|
|
80
67
|
|
|
81
68
|
### PR-4
|
|
82
69
|
|
|
70
|
+
The fix publication is a mechanical step: it runs one fixed command whose exit status alone decides its two outcomes, reads no conversation, and produces no prose.
|
|
71
|
+
`gh` infers the pull request from the checked-out branch, which the run does not own: the nested `code` call suspends across Boss turns, so the checkout can change before the fix is published.
|
|
72
|
+
This step therefore carries one runtime value — the pull request `pr` published — and refuses unless the checkout still infers exactly it.
|
|
73
|
+
That identity is reported text, so it binds as a single-quoted shell literal: the command compares it as data and never executes it as shell syntax.
|
|
74
|
+
The command pushes nothing until the checked-out branch infers the pull request `pr` published, so a checkout that changed while `code` ran publishes to no other branch.
|
|
75
|
+
|
|
83
76
|
When `code` succeeds, Captain shall run:
|
|
84
77
|
|
|
85
78
|
> [ "$(gh pr view --json url --jq .url)" = '<pull-request-url>' ] || exit 1
|
|
@@ -92,16 +85,13 @@ When `code` succeeds, Captain shall run:
|
|
|
92
85
|
> done
|
|
93
86
|
|
|
94
87
|
Results:
|
|
95
|
-
- `fixPublished`: The command exited with status zero
|
|
96
|
-
- `fixNotPublished`: The command exited with a nonzero status: the
|
|
97
|
-
|
|
98
|
-
Workflow outcomes:
|
|
99
|
-
- The publication has exactly two outcomes decided by the exit status alone: fix published on status zero, once the pull request's head is the pushed commit, and fix not published otherwise.
|
|
100
|
-
- The command pushes nothing until the checked-out branch infers the pull request `pr` published, so a checkout that changed while `code` ran publishes to no other branch.
|
|
101
|
-
- Fix not published is an authored failure that leaves the pull request open.
|
|
88
|
+
- `fixPublished`: The command exited with status zero, once the pull request's head is the pushed commit: the fix is published.
|
|
89
|
+
- `fixNotPublished`: The command exited with a nonzero status: the fix is not published, an authored failure of the workflow that leaves the pull request open.
|
|
102
90
|
|
|
103
91
|
### PR-5
|
|
104
92
|
|
|
93
|
+
The second check wait is a mechanical step: it runs one fixed command whose exit status alone decides its two outcomes, reads no conversation, and produces no prose.
|
|
94
|
+
|
|
105
95
|
When the fix is published, Captain shall run:
|
|
106
96
|
|
|
107
97
|
> n=0
|
|
@@ -113,15 +103,19 @@ When the fix is published, Captain shall run:
|
|
|
113
103
|
> gh pr checks --watch --fail-fast >/dev/null 2>&1
|
|
114
104
|
|
|
115
105
|
Results:
|
|
116
|
-
- `checksPassed`: The command exited with status zero: the
|
|
117
|
-
- `checksStillFailing`: The command exited with a nonzero status: the
|
|
118
|
-
|
|
119
|
-
Workflow outcomes:
|
|
120
|
-
- This wait has exactly two outcomes decided by the exit status alone: checks passed on status zero and checks still failing otherwise.
|
|
121
|
-
- Checks still failing is an authored failure that leaves the pull request open; there is no second fix attempt.
|
|
106
|
+
- `checksPassed`: The command exited with status zero: the checks passed.
|
|
107
|
+
- `checksStillFailing`: The command exited with a nonzero status: the checks are still failing, an authored failure of the workflow that leaves the pull request open; there is no second fix attempt.
|
|
122
108
|
|
|
123
109
|
### PR-6
|
|
124
110
|
|
|
111
|
+
The merge is a mechanical step: it runs one fixed command whose exit status alone decides its two outcomes, reads no conversation, and produces no prose.
|
|
112
|
+
`gh` infers the pull request from the checked-out branch, which the run does not own: the nested `code` call suspends across Boss turns, so the checkout can change before the merge runs.
|
|
113
|
+
This step therefore carries one runtime value — the pull request `pr` published — and refuses unless the checkout still infers exactly it.
|
|
114
|
+
That identity is reported text, so it binds as a single-quoted shell literal: the command compares it as data and never executes it as shell syntax.
|
|
115
|
+
The merge creates a merge commit on the repository default branch, requests deletion of the remote and local branch, and checks out the local default branch; GitHub closes the linked issue on merge.
|
|
116
|
+
The command requires the inferred pull request to be the one `pr` published and to target the repository default branch before the irreversible merge, and confirms that same pull request's merged state and the default-branch checkout after the merge command succeeds; a queued pull request is not a merged result.
|
|
117
|
+
No outcome claims a branch was deleted, because `gh` skips the remote deletion for a pull request from another repository or one already merged and exits zero anyway.
|
|
118
|
+
|
|
125
119
|
When the checks pass, before or after the one fix attempt, Captain shall run:
|
|
126
120
|
|
|
127
121
|
> pr=$(gh pr view --json url --jq .url) || exit 1
|
|
@@ -134,30 +128,20 @@ When the checks pass, before or after the one fix attempt, Captain shall run:
|
|
|
134
128
|
> [ "$(git branch --show-current)" = "$base" ]
|
|
135
129
|
|
|
136
130
|
Results:
|
|
137
|
-
- `merged`: The command exited with status zero: the pull request
|
|
138
|
-
- `mergeRefused`: The command exited with a nonzero status: the checkout no longer infers the published pull request, the pull request
|
|
139
|
-
|
|
140
|
-
Workflow outcomes:
|
|
141
|
-
- The merge creates a merge commit on the repository default branch, requests deletion of the remote and local branch, and checks out the local default branch; GitHub closes the linked issue on merge.
|
|
142
|
-
- The merge has exactly two outcomes decided by the exit status alone: merged on status zero and merge refused otherwise.
|
|
143
|
-
- The command requires the inferred pull request to be the one `pr` published and to target the repository default branch before the irreversible merge, and confirms that same pull request's merged state and the default-branch checkout after the merge command succeeds; a queued pull request is not a merged result.
|
|
144
|
-
- Merge refused is an authored failure that leaves the pull request in the state GitHub reports: the checkout no longer infers the published pull request, the pull request targets another branch, GitHub refused the merge for a conflict, a branch protection, a forbidden merge method, or a head that moved, or the merge may have landed while its confirmation, the local switch to the default branch, or the branch deletion failed.
|
|
145
|
-
- A refused merge does not establish that the pull request is unmerged, so `pr` reports it as an unconfirmed merge rather than as not merged, and no outcome claims a branch was deleted, because `gh` skips the remote deletion for a pull request from another repository or one already merged and exits zero anyway.
|
|
131
|
+
- `merged`: The command exited with status zero: the pull request is merged.
|
|
132
|
+
- `mergeRefused`: The command exited with a nonzero status: the merge is refused, an authored failure of the workflow that leaves the pull request in the state GitHub reports, because the checkout no longer infers the published pull request, the pull request targets another branch, GitHub refused the merge for a conflict, a branch protection, a forbidden merge method, or a head that moved, or the merge may have landed while its confirmation, the local switch to the default branch, or the branch deletion failed; a refused merge does not establish that the pull request is unmerged, so the workflow reports it as an unconfirmed merge rather than as not merged.
|
|
146
133
|
|
|
147
134
|
### PR-7
|
|
148
135
|
|
|
136
|
+
The local update is a mechanical step: it runs one fixed command whose exit status alone decides its two outcomes, reads no conversation, and produces no prose.
|
|
137
|
+
|
|
149
138
|
When the pull request is merged, Captain shall run:
|
|
150
139
|
|
|
151
140
|
> git pull --ff-only
|
|
152
141
|
|
|
153
142
|
Results:
|
|
154
|
-
- `localDefaultUpdated`: The command exited with status zero: the local default branch is fast-forwarded to the merged head.
|
|
155
|
-
- `localDefaultNotUpdated`: The command exited with a nonzero status: the local default branch was not fast-forwarded to the merged head.
|
|
156
|
-
|
|
157
|
-
Workflow outcomes:
|
|
158
|
-
- The update has exactly two outcomes decided by the exit status alone: local default updated on status zero and local default not updated otherwise.
|
|
159
|
-
- Both complete `pr`: the pull request is merged either way, and the result states whether the local default branch was fast-forwarded to the merged head.
|
|
160
|
-
- On completion, `pr` returns the pull request number and URL, the fact that the pull request is merged, and whether the local default branch was fast-forwarded to the merged head.
|
|
143
|
+
- `localDefaultUpdated`: The command exited with status zero: the local default branch is updated; the workflow completes, returning the pull request number and URL, the fact that the pull request is merged, and that the local default branch was fast-forwarded to the merged head.
|
|
144
|
+
- `localDefaultNotUpdated`: The command exited with a nonzero status: the local default branch is not updated; the workflow completes, since the pull request is merged either way, returning the pull request number and URL, the fact that the pull request is merged, and that the local default branch was not fast-forwarded to the merged head.
|
|
161
145
|
|
|
162
146
|
## Optimizations
|
|
163
147
|
|
|
@@ -1,27 +1,17 @@
|
|
|
1
|
-
import { type
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
*/
|
|
11
|
-
export type PrPlaybookOptions = PrInput & {
|
|
12
|
-
readonly cwd?: string;
|
|
13
|
-
};
|
|
14
|
-
export type PrPlaybookHostCapabilities = PlaybookHostConstructionCapabilities & XStatePlaybookRuntimeConstruction<PrPlaybookOptions, object>['hostCapabilities'];
|
|
15
|
-
/**
|
|
16
|
-
* Preserve the authored Markdown quote marker around every line of the
|
|
17
|
-
* relayed caller input. The generic composer preserves the marker itself;
|
|
18
|
-
* PR's override additionally keeps a multiline value inside that quote.
|
|
19
|
-
*/
|
|
20
|
-
declare function composePlayerPrompt(input: PlayerInput, resuming?: boolean): string;
|
|
1
|
+
import { type XStatePromptIdentity, type PlaybookPlayerInput, type XStatePlaybookRuntimeConstruction, type XStatePlaybookRuntimeFactory } from '@sublang/playbook/xstate-runtime';
|
|
2
|
+
export type { PlayerResult, PlayerCallOptions, PlayerSessionStore, CaptainResult, CaptainCallOptions, JsonValue, NormalizedError, PlaybookCallRequest, PlaybookCallResult, PlaybookCallStart, PlaybookStateValue, PlaybookState, PlaybookPendingCall, PlaybookRunResult, PlaybookRuntime, PlaybookRuntimeFactory, PlaybookRuntimeSnapshot, PlaybookSession, PlaybookPorts, PlaybookTraceEvent, PlaybookTraceType, PlaybookControlReceipt, PlaybookControlView, } from '@sublang/playbook/runtime';
|
|
3
|
+
export interface PlaybookRuntimeOptions {
|
|
4
|
+
readonly "cwd"?: string;
|
|
5
|
+
}
|
|
6
|
+
export type PlaybookHostCapabilities = XStatePlaybookRuntimeConstruction<PlaybookRuntimeOptions, {
|
|
7
|
+
readonly authority: object;
|
|
8
|
+
}>['hostCapabilities'];
|
|
9
|
+
export declare function validateOptions(value: unknown): PlaybookRuntimeOptions;
|
|
21
10
|
export declare const _internal: {
|
|
22
|
-
composePlayerPrompt:
|
|
23
|
-
|
|
11
|
+
composePlayerPrompt: (input: PlaybookPlayerInput, promptIdentity: XStatePromptIdentity, resuming?: boolean) => string;
|
|
12
|
+
RESUMABLE_STATE_IDS: ReadonlySet<string>;
|
|
24
13
|
UNFINISHED_FINAL_STATE_IDS: ReadonlySet<string>;
|
|
14
|
+
VERBATIM_PAYLOAD_FIELDS: ReadonlySet<string>;
|
|
25
15
|
};
|
|
26
|
-
declare const createPlaybookRuntime: XStatePlaybookRuntimeFactory<XStatePlaybookRuntimeConstruction<
|
|
16
|
+
declare const createPlaybookRuntime: XStatePlaybookRuntimeFactory<XStatePlaybookRuntimeConstruction<PlaybookRuntimeOptions, PlaybookHostCapabilities>, 3>;
|
|
27
17
|
export default createPlaybookRuntime;
|
|
@@ -1,134 +1,140 @@
|
|
|
1
1
|
// SPDX-License-Identifier: Apache-2.0
|
|
2
2
|
// SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
import { createXStatePlaybookRuntime, composePlayerContinuation, snapshotJsonValue, } from '@sublang/playbook/xstate-runtime';
|
|
17
|
-
import { prMachine, } from './pr.fsm.js';
|
|
18
|
-
const OPTION_KEYS = new Set(['cwd']);
|
|
19
|
-
const PLACEHOLDER = /<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>/g;
|
|
20
|
-
const VERBATIM_PAYLOAD_FIELDS = new Set([
|
|
21
|
-
'coderOutput',
|
|
3
|
+
// Generated by slc/materialize-link.mjs; governed by the complete slc/link.md.
|
|
4
|
+
// FSM: "./pr.fsm.js"; export: prMachine; strategies: shared defaults with labelled string relays and nested actors.
|
|
5
|
+
import { prMachine as machine } from "./pr.fsm.js";
|
|
6
|
+
import { createXStatePlaybookRuntime, snapshotJsonValue, composePlayerContinuation, } from '@sublang/playbook/xstate-runtime';
|
|
7
|
+
const OPTION_SCHEMA = {
|
|
8
|
+
"cwd": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"required": false
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
const INPUT_MAPPING = {};
|
|
14
|
+
const RESUMABLE_STATE_IDS = new Set([
|
|
15
|
+
"openPullRequest"
|
|
22
16
|
]);
|
|
23
|
-
// Every failure terminal leaves the delivery unfinished: no pull request is
|
|
24
|
-
// guaranteed to exist after notPublished, the three fix terminals leave it
|
|
25
|
-
// open, and mergeRefused leaves it in the state GitHub reports.
|
|
26
17
|
const UNFINISHED_FINAL_STATE_IDS = new Set([
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
18
|
+
"notPublished",
|
|
19
|
+
"fixFailed",
|
|
20
|
+
"fixNotPublished",
|
|
21
|
+
"checksFailed",
|
|
22
|
+
"mergeUnconfirmed"
|
|
32
23
|
]);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
24
|
+
const VERBATIM_PAYLOAD_FIELDS = new Set([
|
|
25
|
+
"coderOutput"
|
|
26
|
+
]);
|
|
27
|
+
export function validateOptions(value) {
|
|
28
|
+
const captured = snapshotJsonValue(value === undefined ? {} : value, "PR runtime options");
|
|
29
|
+
if (captured === null || typeof captured !== 'object' || Array.isArray(captured)) {
|
|
30
|
+
throw new TypeError("PR runtime options must be an object");
|
|
31
|
+
}
|
|
32
|
+
const fields = captured;
|
|
33
|
+
for (const key of Object.keys(captured)) {
|
|
34
|
+
if (!Object.hasOwn(OPTION_SCHEMA, key))
|
|
35
|
+
throw new TypeError("PR runtime options." + key + ' is not declared');
|
|
39
36
|
}
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
for (const [key, schema] of Object.entries(OPTION_SCHEMA)) {
|
|
38
|
+
if (!Object.hasOwn(captured, key)) {
|
|
39
|
+
if (schema.required)
|
|
40
|
+
throw new TypeError("PR runtime options." + key + ' is required');
|
|
44
41
|
}
|
|
45
|
-
if (typeof
|
|
46
|
-
throw new TypeError(
|
|
42
|
+
else if (typeof fields[key] !== schema.type || (schema.type === 'number' && !Number.isFinite(fields[key]))) {
|
|
43
|
+
throw new TypeError("PR runtime options." + key + ' must be a ' + schema.type);
|
|
47
44
|
}
|
|
48
45
|
}
|
|
49
46
|
return captured;
|
|
50
47
|
}
|
|
51
|
-
function
|
|
52
|
-
if (token === '#')
|
|
53
|
-
return 'irNumber';
|
|
54
|
-
return token.replace(/-([A-Za-z0-9_$])/g, (_match, next) => next.toUpperCase());
|
|
55
|
-
}
|
|
56
|
-
function quotedContinuation(value) {
|
|
57
|
-
return value.replaceAll('\n', '\n> ');
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Preserve the authored Markdown quote marker around every line of the
|
|
61
|
-
* relayed caller input. The generic composer preserves the marker itself;
|
|
62
|
-
* PR's override additionally keeps a multiline value inside that quote.
|
|
63
|
-
*/
|
|
64
|
-
function composePlayerPrompt(input, resuming = false) {
|
|
48
|
+
function renderPlayerPrompt(input, promptIdentity, resuming = false) {
|
|
65
49
|
const fields = input;
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
50
|
+
const mapping = {};
|
|
51
|
+
const identities = {};
|
|
52
|
+
const omitted = new Set([]);
|
|
53
|
+
const fieldFor = (token) => Object.hasOwn(mapping, token) ? mapping[token] : (token === '#' ? 'irNumber' : token.replace(/-([A-Za-z0-9_$])/g, (_match, next) => next.toUpperCase()));
|
|
54
|
+
const parts = input.prompt.split(/(\r?\n)/);
|
|
55
|
+
let body = '';
|
|
56
|
+
for (let index = 0; index < parts.length; index += 2) {
|
|
57
|
+
const line = parts[index];
|
|
58
|
+
if (omitted.has(line)) {
|
|
59
|
+
const token = /<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>$/.exec(line)[1];
|
|
60
|
+
if (fields[fieldFor(token)] === '')
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
body += line.replace(/<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>/g, (match, token) => {
|
|
64
|
+
const value = Object.hasOwn(identities, token) ? promptIdentity(identities[token]) : fields[fieldFor(token)];
|
|
65
|
+
if (typeof value !== 'string')
|
|
66
|
+
return match;
|
|
67
|
+
return line.startsWith('> ') ? value.replace(/\r?\n/g, (ending) => ending + '> ') : value;
|
|
68
|
+
}) + (parts[index + 1] ?? '');
|
|
69
|
+
}
|
|
75
70
|
return composePlayerContinuation(input, body, resuming);
|
|
76
71
|
}
|
|
77
|
-
|
|
78
|
-
composePlayerPrompt,
|
|
79
|
-
VERBATIM_PAYLOAD_FIELDS,
|
|
80
|
-
UNFINISHED_FINAL_STATE_IDS,
|
|
81
|
-
};
|
|
72
|
+
const composePlayerPrompt = (input, promptIdentity, resuming) => renderPlayerPrompt(input, promptIdentity, resuming);
|
|
82
73
|
const runtimeSpec = {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
snapshotOptions: snapshotPrOptions,
|
|
90
|
-
entryEvent: {
|
|
91
|
-
type: 'START_PR',
|
|
92
|
-
textField: 'callerInput',
|
|
93
|
-
// `startPr` copies the entry text here, so the failure-state retry reads
|
|
94
|
-
// it back from the persisted machine snapshot and survives a continued
|
|
95
|
-
// session (DR-034).
|
|
96
|
-
contextField: 'callerInput',
|
|
97
|
-
},
|
|
98
|
-
roleStates: {
|
|
99
|
-
openPullRequest: {
|
|
100
|
-
role: 'coder',
|
|
101
|
-
label: 'Coder is publishing the branch and opening its pull request.',
|
|
74
|
+
composePlayerPrompt,
|
|
75
|
+
...{
|
|
76
|
+
"label": "PR",
|
|
77
|
+
"compat": {
|
|
78
|
+
"artifactSchema": 3,
|
|
79
|
+
"runtimeAbi": 1
|
|
102
80
|
},
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
repositoryDisposition: 'unchanged',
|
|
115
|
-
},
|
|
116
|
-
notPublished: {
|
|
117
|
-
fields: { coderOutput: 'presentation' },
|
|
118
|
-
repositoryDisposition: 'unchanged',
|
|
119
|
-
},
|
|
120
|
-
needsBossReply: {
|
|
121
|
-
fields: { question: 'presentation' },
|
|
122
|
-
repositoryDisposition: 'unchanged',
|
|
123
|
-
},
|
|
124
|
-
},
|
|
81
|
+
"entryEvent": {
|
|
82
|
+
"type": "START_PR",
|
|
83
|
+
"textField": "callerInput",
|
|
84
|
+
"contextField": "callerInput"
|
|
85
|
+
},
|
|
86
|
+
"bossEvents": [],
|
|
87
|
+
"roleStates": {
|
|
88
|
+
"openPullRequest": {
|
|
89
|
+
"role": "coder",
|
|
90
|
+
"label": "Coder is publishing the branch and opening its pull request without changing any file or making any commit."
|
|
91
|
+
}
|
|
125
92
|
},
|
|
93
|
+
"outcomeAuthority": {
|
|
94
|
+
"governedPlayerStates": {
|
|
95
|
+
"openPullRequest": {
|
|
96
|
+
"opened": {
|
|
97
|
+
"fields": {
|
|
98
|
+
"pullRequest": "semantic",
|
|
99
|
+
"pullRequestUrl": "semantic"
|
|
100
|
+
},
|
|
101
|
+
"repositoryDisposition": "unchanged"
|
|
102
|
+
},
|
|
103
|
+
"notPublished": {
|
|
104
|
+
"fields": {
|
|
105
|
+
"coderOutput": "presentation"
|
|
106
|
+
},
|
|
107
|
+
"repositoryDisposition": "unchanged"
|
|
108
|
+
},
|
|
109
|
+
"needsBossReply": {
|
|
110
|
+
"fields": {
|
|
111
|
+
"question": "presentation"
|
|
112
|
+
},
|
|
113
|
+
"repositoryDisposition": "unchanged"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"placeholderFields": {},
|
|
119
|
+
"transitionEventFields": [
|
|
120
|
+
"callerInput",
|
|
121
|
+
"answer",
|
|
122
|
+
"questionId"
|
|
123
|
+
],
|
|
124
|
+
"controlContextFields": []
|
|
126
125
|
},
|
|
127
|
-
|
|
126
|
+
snapshotOptions: validateOptions,
|
|
127
|
+
machineInput: (options) => Object.fromEntries(Object.entries(INPUT_MAPPING).filter(([, key]) => options[key] !== undefined)
|
|
128
|
+
.map(([field, key]) => [field, options[key]])),
|
|
128
129
|
verbatimPayloadFields: VERBATIM_PAYLOAD_FIELDS,
|
|
129
|
-
|
|
130
|
+
resumableStateIds: RESUMABLE_STATE_IDS,
|
|
130
131
|
unfinishedFinalStateIds: UNFINISHED_FINAL_STATE_IDS,
|
|
131
|
-
transitionEventFields: ['callerInput', 'answer', 'questionId'],
|
|
132
132
|
};
|
|
133
|
-
const
|
|
133
|
+
export const _internal = {
|
|
134
|
+
composePlayerPrompt,
|
|
135
|
+
RESUMABLE_STATE_IDS,
|
|
136
|
+
UNFINISHED_FINAL_STATE_IDS,
|
|
137
|
+
VERBATIM_PAYLOAD_FIELDS,
|
|
138
|
+
};
|
|
139
|
+
const createPlaybookRuntime = createXStatePlaybookRuntime(machine, runtimeSpec);
|
|
134
140
|
export default createPlaybookRuntime;
|