@sublang/playbook 15.0.0 → 16.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/README.md +1 -1
  2. package/docs/embedding.md +9 -7
  3. package/package.json +3 -1
  4. package/reference/sdlc/branch.playbook/branch.fsm.d.ts +63 -33
  5. package/reference/sdlc/branch.playbook/branch.fsm.js +190 -108
  6. package/reference/sdlc/branch.playbook/branch.fsm.ts +269 -147
  7. package/reference/sdlc/branch.playbook/branch.gears.md +7 -17
  8. package/reference/sdlc/branch.playbook/branch.playbook.d.ts +12 -16
  9. package/reference/sdlc/branch.playbook/branch.playbook.js +112 -101
  10. package/reference/sdlc/branch.playbook/branch.playbook.ts +128 -171
  11. package/reference/sdlc/branch.playbook/branch.registry.d.ts +3 -2
  12. package/reference/sdlc/branch.playbook/branch.registry.ts +6 -2
  13. package/reference/sdlc/code.playbook/bin/repository-effects.js +54 -13
  14. package/reference/sdlc/code.playbook/code.fsm.d.ts +143 -90
  15. package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +8 -8
  16. package/reference/sdlc/code.playbook/code.fsm.introspect.ts +13 -13
  17. package/reference/sdlc/code.playbook/code.fsm.js +609 -649
  18. package/reference/sdlc/code.playbook/code.fsm.ts +890 -821
  19. package/reference/sdlc/code.playbook/code.gears.md +39 -29
  20. package/reference/sdlc/code.playbook/code.playbook.d.ts +13 -16
  21. package/reference/sdlc/code.playbook/code.playbook.js +166 -147
  22. package/reference/sdlc/code.playbook/code.playbook.ts +180 -229
  23. package/reference/sdlc/code.playbook/code.registry.d.ts +3 -2
  24. package/reference/sdlc/code.playbook/code.registry.ts +6 -2
  25. package/reference/sdlc/code.playbook/playbook-captain.d.ts +42 -0
  26. package/reference/sdlc/code.playbook/playbook-captain.js +829 -194
  27. package/reference/sdlc/code.playbook/playbook-captain.ts +1227 -220
  28. package/reference/sdlc/decide.md +1 -0
  29. package/reference/sdlc/decide.playbook/decide.fsm.d.ts +270 -154
  30. package/reference/sdlc/decide.playbook/decide.fsm.js +765 -732
  31. package/reference/sdlc/decide.playbook/decide.fsm.ts +1167 -945
  32. package/reference/sdlc/decide.playbook/decide.gears.md +28 -21
  33. package/reference/sdlc/decide.playbook/decide.playbook.d.ts +11 -67
  34. package/reference/sdlc/decide.playbook/decide.playbook.js +155 -3570
  35. package/reference/sdlc/decide.playbook/decide.playbook.ts +186 -5061
  36. package/reference/sdlc/decide.playbook/decide.registry.d.ts +8 -4
  37. package/reference/sdlc/decide.playbook/decide.registry.js +2 -2
  38. package/reference/sdlc/decide.playbook/decide.registry.ts +13 -6
  39. package/reference/sdlc/dev.playbook/dev.fsm.d.ts +113 -131
  40. package/reference/sdlc/dev.playbook/dev.fsm.js +517 -575
  41. package/reference/sdlc/dev.playbook/dev.fsm.ts +667 -787
  42. package/reference/sdlc/dev.playbook/dev.gears.md +52 -54
  43. package/reference/sdlc/dev.playbook/dev.playbook.d.ts +13 -10
  44. package/reference/sdlc/dev.playbook/dev.playbook.js +128 -120
  45. package/reference/sdlc/dev.playbook/dev.playbook.ts +143 -193
  46. package/reference/sdlc/dev.playbook/dev.registry.d.ts +3 -2
  47. package/reference/sdlc/dev.playbook/dev.registry.ts +6 -2
  48. package/reference/sdlc/pr.playbook/pr.fsm.d.ts +92 -85
  49. package/reference/sdlc/pr.playbook/pr.fsm.js +461 -518
  50. package/reference/sdlc/pr.playbook/pr.fsm.ts +533 -663
  51. package/reference/sdlc/pr.playbook/pr.gears.md +47 -63
  52. package/reference/sdlc/pr.playbook/pr.playbook.d.ts +13 -23
  53. package/reference/sdlc/pr.playbook/pr.playbook.js +118 -112
  54. package/reference/sdlc/pr.playbook/pr.playbook.ts +136 -190
  55. package/reference/sdlc/pr.playbook/pr.registry.d.ts +3 -2
  56. package/reference/sdlc/pr.playbook/pr.registry.ts +4 -2
  57. package/reference/sdlc/review.md +3 -3
  58. package/reference/sdlc/review.playbook/review.fsm.d.ts +150 -116
  59. package/reference/sdlc/review.playbook/review.fsm.js +479 -550
  60. package/reference/sdlc/review.playbook/review.fsm.ts +717 -662
  61. package/reference/sdlc/review.playbook/review.gears.md +32 -29
  62. package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -12
  63. package/reference/sdlc/review.playbook/review.playbook.js +180 -155
  64. package/reference/sdlc/review.playbook/review.playbook.ts +190 -230
  65. package/reference/sdlc/review.playbook/review.registry.d.ts +6 -5
  66. package/reference/sdlc/review.playbook/review.registry.js +3 -3
  67. package/reference/sdlc/review.playbook/review.registry.ts +9 -5
  68. package/slc/gears2fsm.md +72 -3
  69. package/slc/link.md +50 -27
  70. package/slc/materialize-link.mjs +51 -13
  71. package/slc/optimize.md +4 -1
  72. package/slc/prefix-prompts.mjs +191 -0
  73. package/slc/prefix.md +203 -0
  74. package/slc/slc.pin-inputs.json +11 -1
  75. package/slc/text2gears.md +71 -11
  76. package/src/xstate-playbook-runtime.d.ts +82 -9
  77. package/src/xstate-playbook-runtime.js +1224 -283
  78. package/src/xstate-playbook-runtime.ts +1671 -338
  79. package/src/xstate-runtime.d.ts +3 -1
  80. package/src/xstate-runtime.js +9 -2
  81. package/src/xstate-runtime.ts +12 -2
@@ -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: Pull-Request Delivery Workflow
4
+ # PR
5
5
 
6
6
  Roles:
7
7
 
8
8
  - Coder
9
9
 
10
- 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.
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 pushed the branch with its upstream set and reported the open pull request for it. Output shall include `pullRequest: <pull request number>` and `pullRequestUrl: <pull request URL>`.
36
- - `notPublished`: Coder reported that the branch could not be published or its pull request could not be opened, with the reason. Output shall include `coderOutput: <verbatim final text>`.
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 pull request's checks passed, or the repository still reported no checks after a brief wait for them to register.
60
- - `checksFailed`: The command exited with a nonzero status: the pull request's checks failed.
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
- Workflow outcomes:
76
- - `pr` makes no more than one fix attempt.
77
- - Only after `code` succeeds does `pr` publish the fix and wait for the checks again.
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: the fix is pushed and the pull request's head is the pushed commit.
96
- - `fixNotPublished`: The command exited with a nonzero status: the checkout no longer infers the published pull request, the push was rejected, or the pull request's head did not advance to the pushed commit.
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 pull request's checks passed after the fix, or the repository still reported no checks after a brief wait for them to register.
117
- - `checksStillFailing`: The command exited with a nonzero status: the pull request's checks are still failing after the one fix attempt.
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 targeted the repository default branch and is merged into it with a merge commit, deletion of the remote and local branch was requested, and the local default branch is checked out.
138
- - `mergeRefused`: The command exited with a nonzero status: the checkout no longer infers the published pull request, the pull request does not target the repository default branch, GitHub refused the merge, its merged state could not be confirmed, or the local switch to the default branch or the branch deletion failed.
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 XStatePlaybookRuntimeFactory, type XStatePlaybookRuntimeConstruction } from '@sublang/playbook/xstate-runtime';
2
- import { type PlayerInput, type PrInput } from './pr.fsm.js';
3
- import type { PlaybookHostConstructionCapabilities } from '../code.playbook/playbook-captain.js';
4
- import type { CaptainCallOptions, CaptainResult, JsonValue, NormalizedError, PlayerCallOptions, PlaybookCallRequest, PlaybookCallResult, PlaybookCallStart, PlaybookControlReceipt, PlaybookControlView, PlaybookPendingCall, PlaybookPorts, PlaybookRunResult, PlaybookRuntime, PlaybookRuntimeFactory, PlaybookRuntimeSnapshot, PlaybookSession, PlaybookState, PlaybookStateValue, PlaybookTraceEvent, PlaybookTraceType, PlayerResult, PlayerSessionStore } from '@sublang/playbook/runtime';
5
- export type { CaptainCallOptions, CaptainResult, JsonValue, NormalizedError, PlayerCallOptions, PlaybookCallRequest, PlaybookCallResult, PlaybookCallStart, PlaybookControlReceipt, PlaybookControlView, PlaybookPendingCall, PlaybookPorts, PlaybookRunResult, PlaybookRuntime, PlaybookRuntimeFactory, PlaybookRuntimeSnapshot, PlaybookSession, PlaybookState, PlaybookStateValue, PlaybookTraceEvent, PlaybookTraceType, PlayerResult, PlayerSessionStore, };
6
- /**
7
- * PR's per-run options. The machine reads no input of its own; the one
8
- * linker-owned option is the working directory its five script states run
9
- * in (slc/link.md §Script execution). Absent, the process working directory.
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: typeof composePlayerPrompt;
23
- VERBATIM_PAYLOAD_FIELDS: ReadonlySet<string>;
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<PrPlaybookOptions, PrPlaybookHostCapabilities>, 3>;
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
- // Generated by slc/link.md (FSM-to-Runtime linker).
5
- // Source FSM: ./pr.fsm.ts
6
- // Role metadata: Coder→coder (canonical local role)
7
- // Boss event: deterministic START_PR entry; exact Boss text becomes
8
- // callerInput; pending Coder questions retain BOSS_REPLY
9
- // Adjudication: LLM judge for the one Coder state; coderOutput is carried
10
- // verbatim; pullRequest and pullRequestUrl are judge-authored
11
- // semantic fields; every arm is governed `unchanged`
12
- // Scripts: five DR-016 script states run through the shared factory's
13
- // `sh -c` actor in the optional `cwd` option
14
- // Nested calls: literal code target through the shared bridge
15
- // Compat: artifact schema 3 / runtime ABI 1
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
- 'notPublished',
28
- 'fixFailed',
29
- 'fixNotPublished',
30
- 'checksStillFailing',
31
- 'mergeRefused',
18
+ "notPublished",
19
+ "fixFailed",
20
+ "fixNotPublished",
21
+ "checksFailed",
22
+ "mergeUnconfirmed"
32
23
  ]);
33
- function snapshotPrOptions(value) {
34
- const captured = snapshotJsonValue(value, 'PR runtime options');
35
- if (captured === null ||
36
- typeof captured !== 'object' ||
37
- Array.isArray(captured)) {
38
- throw new TypeError('PR runtime options must be an object');
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 record = captured;
41
- for (const [key, option] of Object.entries(record)) {
42
- if (!OPTION_KEYS.has(key)) {
43
- throw new TypeError(`PR runtime options.${key} is not declared`);
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 option !== 'string' || option.length === 0) {
46
- throw new TypeError(`PR runtime options.${key} must be a non-empty string`);
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 placeholderField(token) {
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 body = input.prompt.replace(PLACEHOLDER, (match, token, offset, source) => {
67
- const value = fields[placeholderField(token)];
68
- if (typeof value !== 'string')
69
- return match;
70
- const lineStart = source.lastIndexOf('\n', offset - 1) + 1;
71
- return source.slice(lineStart, offset).startsWith('> ')
72
- ? quotedContinuation(value)
73
- : value;
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
- export const _internal = {
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
- label: 'PR',
84
- // DR-022 / slc/link.md: the declaration carries the value current at link
85
- // time — a literal, never the loading engine's RUNTIME_ABI self-report,
86
- // which would follow whatever engine loads the module and make the
87
- // factory's skew check compare that engine with itself.
88
- compat: { artifactSchema: 3, runtimeAbi: 1 },
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
- // DR-050: PR owns no repository commit — pushing a branch and opening a
105
- // pull request move only remote-tracking refs and forge state, so every
106
- // Coder outcome is governed with the `unchanged` repository disposition.
107
- // The pull request number and URL are judge-authored semantic fields; the
108
- // Coder's report on a refused publication is carried verbatim.
109
- outcomeAuthority: {
110
- governedPlayerStates: {
111
- openPullRequest: {
112
- opened: {
113
- fields: { pullRequest: 'semantic', pullRequestUrl: 'semantic' },
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
- composePlayerPrompt: (input, _identity, resuming) => composePlayerPrompt(input, resuming),
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
- controlContextFields: [],
130
+ resumableStateIds: RESUMABLE_STATE_IDS,
130
131
  unfinishedFinalStateIds: UNFINISHED_FINAL_STATE_IDS,
131
- transitionEventFields: ['callerInput', 'answer', 'questionId'],
132
132
  };
133
- const createPlaybookRuntime = createXStatePlaybookRuntime(prMachine, runtimeSpec);
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;