@sublang/playbook 0.9.0 → 1.3.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 +190 -151
- package/package.json +50 -6
- package/reference/sdlc/captain.md +102 -0
- package/reference/sdlc/captain.playbook/captain.fsm.d.ts +227 -0
- package/reference/sdlc/captain.playbook/captain.fsm.js +628 -0
- package/reference/sdlc/captain.playbook/captain.fsm.ts +851 -0
- package/reference/sdlc/captain.playbook/captain.gears.md +60 -0
- package/reference/sdlc/captain.playbook/captain.playbook.d.ts +23 -0
- package/reference/sdlc/captain.playbook/captain.playbook.js +1053 -0
- package/reference/sdlc/captain.playbook/captain.playbook.ts +1144 -0
- package/reference/sdlc/code.playbook/bin/playbook.js +158 -12
- package/reference/sdlc/code.playbook/bin/run.js +999 -0
- package/reference/sdlc/code.playbook/code.fsm.d.ts +11 -4
- package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +2 -2
- package/reference/sdlc/code.playbook/code.fsm.introspect.js +1 -1
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +6 -6
- package/reference/sdlc/code.playbook/code.fsm.js +334 -102
- package/reference/sdlc/code.playbook/code.fsm.ts +467 -180
- package/reference/sdlc/code.playbook/code.gears.md +11 -10
- package/reference/sdlc/code.playbook/code.playbook.d.ts +16 -19
- package/reference/sdlc/code.playbook/code.playbook.js +199 -488
- package/reference/sdlc/code.playbook/code.playbook.ts +327 -566
- package/reference/sdlc/code.playbook/code.registry.d.ts +0 -3
- package/reference/sdlc/code.playbook/code.registry.js +0 -3
- package/reference/sdlc/code.playbook/code.registry.ts +0 -6
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +9 -4
- package/reference/sdlc/code.playbook/playbook-captain.js +889 -210
- package/reference/sdlc/code.playbook/playbook-captain.ts +1136 -257
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +21 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.d.ts +396 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.js +2066 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.ts +2464 -0
- package/reference/sdlc/discuss.playbook/discuss.gears.md +251 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.d.ts +113 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.js +1514 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.ts +1926 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.d.ts +58 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.js +97 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.ts +153 -0
- package/slc/gears2fsm.md +557 -57
- package/slc/link.md +1165 -89
- package/slc/optimize.md +92 -0
- package/slc/text2gears.md +255 -7
- package/src/runtime.d.ts +146 -3
- package/src/runtime.ts +201 -2
- package/src/xstate-playbook-runtime.d.ts +201 -0
- package/src/xstate-playbook-runtime.js +2058 -0
- package/src/xstate-playbook-runtime.ts +2792 -0
- package/src/xstate-runtime.d.ts +95 -0
- package/src/xstate-runtime.js +1258 -0
- package/src/xstate-runtime.ts +1816 -0
package/slc/optimize.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
<!-- SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai> -->
|
|
3
|
+
|
|
4
|
+
# GEARS Optimization Pass
|
|
5
|
+
|
|
6
|
+
Optional optimization pass of a playbook (a state-machine agent orchestrating other agents).
|
|
7
|
+
Rewrites deterministic mechanical behaviors into
|
|
8
|
+
[script behaviors](text2gears.md#script-behaviors-optimizer-introduced) so the
|
|
9
|
+
compiled playbook performs them directly, without an agent call.
|
|
10
|
+
|
|
11
|
+
- Source: a package of GEARS spec items produced by [text2gears](text2gears.md).
|
|
12
|
+
- Target: the same package with eligible items rewritten as script items.
|
|
13
|
+
|
|
14
|
+
The pass is format-preserving: source and target are both GEARS packages, and
|
|
15
|
+
the pass sits between [text2gears](text2gears.md) and
|
|
16
|
+
[gears2fsm](gears2fsm.md) only when the compile requests optimization.
|
|
17
|
+
A playbook compiled without this pass has identical observable behavior; the
|
|
18
|
+
pass trades a compile-time rewrite for cheaper, deterministic runtime steps.
|
|
19
|
+
|
|
20
|
+
## Formats
|
|
21
|
+
|
|
22
|
+
| Role | Format | Extension |
|
|
23
|
+
| ------ | ------ | --------- |
|
|
24
|
+
| source | gears | .md |
|
|
25
|
+
| target | gears | .md |
|
|
26
|
+
|
|
27
|
+
## Eligibility
|
|
28
|
+
|
|
29
|
+
The pass shall rewrite an item only when **all** of the following hold:
|
|
30
|
+
|
|
31
|
+
- The item's behavior is mechanical: a fixed shell command performs it
|
|
32
|
+
completely, with no judgment, no natural-language generation, and no
|
|
33
|
+
reading of conversational context.
|
|
34
|
+
- The command is static: it needs no `<placeholder>` and no runtime value
|
|
35
|
+
beyond the working directory the runtime executes in.
|
|
36
|
+
- No other item's condition or prompt consumes prose this item's acting agent
|
|
37
|
+
would have produced; the item's effect is entirely on the environment
|
|
38
|
+
(files, repository state, directories) plus a success/failure signal.
|
|
39
|
+
- The item's outcome contract collapses to a two-way split decidable by the
|
|
40
|
+
command's exit status. An item whose declared `Results:` distinguish more
|
|
41
|
+
than success/failure, or whose outcomes require extracted output fields,
|
|
42
|
+
is ineligible.
|
|
43
|
+
|
|
44
|
+
The canonical example is environment setup, such as ensuring the working
|
|
45
|
+
directory is a version-control repository before committing to it:
|
|
46
|
+
`git rev-parse --is-inside-work-tree 2>/dev/null || git init`.
|
|
47
|
+
|
|
48
|
+
Judgment stays conservative: when eligibility is uncertain, the pass shall
|
|
49
|
+
leave the item unchanged rather than guess.
|
|
50
|
+
The pass shall not invent items, commands stronger than the item's stated
|
|
51
|
+
behavior, or requirements the source does not state.
|
|
52
|
+
|
|
53
|
+
## Rewriting
|
|
54
|
+
|
|
55
|
+
For each eligible item, the pass shall:
|
|
56
|
+
|
|
57
|
+
- Keep the item's ID, heading form, and condition text unchanged.
|
|
58
|
+
- Replace the acting clause with the literal script form `Captain shall run:`.
|
|
59
|
+
Like guard names, the script clause is fixed machine syntax [[1]] and
|
|
60
|
+
stays in this exact English form even when the surrounding item text is
|
|
61
|
+
in another language.
|
|
62
|
+
- Replace the blockquoted prompt with the exact POSIX shell script that
|
|
63
|
+
performs the behavior, static text only.
|
|
64
|
+
- Emit exactly two `Results:` bullets per
|
|
65
|
+
[text2gears "Script behaviors"](text2gears.md#script-behaviors-optimizer-introduced):
|
|
66
|
+
first the zero-exit guard, then the nonzero-exit guard. When the original
|
|
67
|
+
item declared exactly two guards that align with success and failure, keep
|
|
68
|
+
those guard names in that order; otherwise use `ok` and `failed`.
|
|
69
|
+
- Preserve every other item and every non-item section byte-for-byte.
|
|
70
|
+
|
|
71
|
+
Target shall be written in the same language as Source: rewritten conditions
|
|
72
|
+
and result descriptions stay in the source language; only guard names and the
|
|
73
|
+
shell script are language-independent.
|
|
74
|
+
|
|
75
|
+
## Provenance
|
|
76
|
+
|
|
77
|
+
The pass shall append one `## Optimizations` section at the end of the target
|
|
78
|
+
listing every rewritten item, one bullet per item:
|
|
79
|
+
`- <ITEM-ID>: <original behavior kind> → script`.
|
|
80
|
+
When no item is eligible, the target shall be the source content unchanged,
|
|
81
|
+
with no `## Optimizations` section.
|
|
82
|
+
|
|
83
|
+
## Out of scope
|
|
84
|
+
|
|
85
|
+
- Rewriting captain, player, or nested-playbook behaviors into one another.
|
|
86
|
+
- Reordering, merging, splitting, or deleting items.
|
|
87
|
+
- Any change to prompts, conditions, or result contracts of items the pass
|
|
88
|
+
does not rewrite.
|
|
89
|
+
|
|
90
|
+
## References
|
|
91
|
+
|
|
92
|
+
[1]: GEARS definition shipped by the installed `@sublang/spex` package: `@sublang/spex/scaffold/specs/meta.md` (English) and `@sublang/spex/scaffold/i18n/zh/specs/meta.md` (Chinese); canonical renditions [GEARS: AI-Ready Spec Syntax](https://sublang.ai/ref/gears-ai-ready-spec-syntax) (en) and [GEARS:面向 AI 的规约语法](https://sublang.ai/zh/ref/gears-ai-ready-spec-syntax) (zh)
|
package/slc/text2gears.md
CHANGED
|
@@ -13,10 +13,10 @@ The second phase (spec items → state machine) is out of scope.
|
|
|
13
13
|
|
|
14
14
|
## Formats
|
|
15
15
|
|
|
16
|
-
| Role
|
|
17
|
-
|
|
|
18
|
-
| source | text
|
|
19
|
-
| target | gears
|
|
16
|
+
| Role | Format | Extension |
|
|
17
|
+
| ------ | ------ | --------- |
|
|
18
|
+
| source | text | .md |
|
|
19
|
+
| target | gears | .md |
|
|
20
20
|
|
|
21
21
|
## Players
|
|
22
22
|
|
|
@@ -39,8 +39,50 @@ Capitalize English player names (e.g., `Writer`); quote non-English names (e.g.,
|
|
|
39
39
|
|
|
40
40
|
## Behaviors
|
|
41
41
|
|
|
42
|
-
Each spec item names a condition,
|
|
42
|
+
Each spec item names a condition, one behavior kind, and the complete prompt
|
|
43
|
+
for that behavior.
|
|
44
|
+
Every emitted item shall use the exact Markdown heading form `### <ITEM-ID>`.
|
|
45
|
+
An item heading at `##`, `####`, or another level is not GEARS item syntax and
|
|
46
|
+
will not be visible to downstream compilers or verification.
|
|
47
|
+
The behavior kind shall be one of:
|
|
48
|
+
|
|
49
|
+
- direct Captain work, written `Captain shall <behavior>:` without naming a
|
|
50
|
+
delegated player;
|
|
51
|
+
- delegated player work, written `Captain shall prompt <Player>:` or the
|
|
52
|
+
existing `Captain shall relay ... to <Player> ...:` form; or
|
|
53
|
+
- a literal or dynamic nested playbook call as defined below.
|
|
54
|
+
|
|
55
|
+
Direct Captain work means the coordinating Captain performs the behavior
|
|
56
|
+
itself. It shall not be rewritten as `Captain shall prompt Captain`, because
|
|
57
|
+
Captain is a distinct runtime actor rather than a player binding.
|
|
58
|
+
Delegated work shall name the declared player that receives the prompt.
|
|
43
59
|
Prompts shall be blockquoted, one point per line.
|
|
60
|
+
When Source already supplies the complete blockquoted acting prompt for a
|
|
61
|
+
behavior, text2gears shall preserve those prompt lines exactly (apart from the
|
|
62
|
+
documented Markdown unescaping) and shall not promote surrounding conditions,
|
|
63
|
+
invariants, result fields, or continuation mechanics into that blockquote.
|
|
64
|
+
Those requirements remain in the item's condition or `Results:` metadata.
|
|
65
|
+
Adding control-oriented prompt lines merely to restate them changes the
|
|
66
|
+
Boss-visible contract and is nonconformant.
|
|
67
|
+
|
|
68
|
+
Source statements that assign active-leaf routing, call identity, suspension,
|
|
69
|
+
or return matching to the host describe execution preconditions rather than
|
|
70
|
+
behaviors for Captain to perform. text2gears shall use such a statement only as
|
|
71
|
+
a condition on an actual behavior when needed and shall not emit a standalone
|
|
72
|
+
direct-Captain item that asks Captain to implement host stack bookkeeping.
|
|
73
|
+
The same applies to a host-owned input catalog's immutability: retain it as a
|
|
74
|
+
condition/invariant on the behaviors that consume the catalog, never as an LLM
|
|
75
|
+
action that can replace or mutate host configuration.
|
|
76
|
+
Opening source invariants consumed by later behaviors shall remain explicit in
|
|
77
|
+
the emitted conditions or prompts rather than being summarized away. In
|
|
78
|
+
particular, preserve the declared exact entry shape of a structured host
|
|
79
|
+
catalog and any progress invariant that makes a decide-call-observe plan
|
|
80
|
+
finite, such as `remainingPlan` containing only calls after the selected call
|
|
81
|
+
and strictly shrinking on continuation.
|
|
82
|
+
Likewise, a source invariant that restricts a nested-call target to a
|
|
83
|
+
non-empty member of an input catalog is a condition on that call item, not a
|
|
84
|
+
separate Captain rejection behavior, unless Source requires an observable
|
|
85
|
+
response distinct from taking or skipping the call.
|
|
44
86
|
|
|
45
87
|
E.g.:
|
|
46
88
|
|
|
@@ -48,13 +90,217 @@ E.g.:
|
|
|
48
90
|
### CODE-10
|
|
49
91
|
|
|
50
92
|
When Reviewer is about to review any change, Captain shall prompt Reviewer:
|
|
93
|
+
|
|
51
94
|
> Flag any issues or improvements (numbered; no duplication).
|
|
52
95
|
> Think thoroughly — don't just approve or reject.
|
|
53
96
|
> If the change is ready to commit or push, don't raise nitpicks.
|
|
54
97
|
> Do not edit files or commit; report findings only.
|
|
55
98
|
```
|
|
56
99
|
|
|
57
|
-
|
|
100
|
+
Direct Captain example:
|
|
101
|
+
|
|
102
|
+
```markdown
|
|
103
|
+
### ROUTE-1
|
|
104
|
+
|
|
105
|
+
When Boss gives an intent, Captain shall decide how to handle it:
|
|
106
|
+
|
|
107
|
+
> Preserve Boss's intended outcome and constraints.
|
|
108
|
+
> Ask one question only when its answer would materially change routing.
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Result contracts
|
|
112
|
+
|
|
113
|
+
When Source gives an acting behavior more than one possible outcome,
|
|
114
|
+
text2gears shall emit its machine-facing result contract immediately after the
|
|
115
|
+
complete blockquote, outside the acting prompt, in this exact form:
|
|
116
|
+
|
|
117
|
+
```markdown
|
|
118
|
+
Results:
|
|
119
|
+
- `question`: Captain asked one material question. Output shall include `question: <verbatim final text>`.
|
|
120
|
+
- `delegation`: Captain selected a call. Output shall include `remainingPlan: <JSON-safe array>`, `nextPlaybookId: <stable id>`, and `nextPlaybookInput: <complete request>`.
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
`Results:` shall be a plain label rather than a heading.
|
|
124
|
+
Every result shall occupy one bullet with exactly a backtick-delimited guard
|
|
125
|
+
name, a colon, and a non-empty description.
|
|
126
|
+
The guard name shall match the ASCII identifier pattern
|
|
127
|
+
`[A-Za-z_$][A-Za-z0-9_$]*`.
|
|
128
|
+
The bullet order is authoritative, guard names are unique within the item, and
|
|
129
|
+
the description shall name every required output property with its exact
|
|
130
|
+
case-sensitive identifier.
|
|
131
|
+
|
|
132
|
+
A produced value consumed later shall have a declared producer: where any
|
|
133
|
+
later item's blockquote reads a value through a `<placeholder>`, the item
|
|
134
|
+
whose behavior produces that value shall declare the `Results:` contract
|
|
135
|
+
whose relevant description names the produced output property, using the
|
|
136
|
+
placeholder's exact identifier — this is what lets the FSM thread the value
|
|
137
|
+
through typed context.
|
|
138
|
+
A single-outcome producer then declares exactly one bullet naming the
|
|
139
|
+
property; this consumed-output case is the sole one in which a
|
|
140
|
+
single-outcome behavior carries a `Results:` label.
|
|
141
|
+
|
|
142
|
+
Result metadata is compiler control data, not part of the acting agent's
|
|
143
|
+
prompt.
|
|
144
|
+
text2gears shall not put guard names, result-property schema, JSON control
|
|
145
|
+
instructions, or adjudicator instructions inside the blockquote unless Source
|
|
146
|
+
explicitly requires the acting agent to show that machine syntax to the user.
|
|
147
|
+
It shall move Source's outcome contract into `Results:` while preserving the
|
|
148
|
+
human domain instructions in the blockquote.
|
|
149
|
+
It shall not emit the framework-owned `needsBossReply` result; gears2fsm adds
|
|
150
|
+
that universal result for every Captain- or player-invoking state.
|
|
151
|
+
|
|
152
|
+
Where Source restricts an initial Captain to routing, text2gears shall preserve
|
|
153
|
+
only the authored question and delegation outcomes and shall not infer a
|
|
154
|
+
direct-answer or terminal result merely because Captain is the acting agent.
|
|
155
|
+
|
|
156
|
+
A single-outcome behavior whose output no later item consumes carries no
|
|
157
|
+
`Results:` label; downstream,
|
|
158
|
+
[gears2fsm](gears2fsm.md#setup) gives its state the default single-outcome
|
|
159
|
+
contract, so text2gears shall not invent a one-bullet `Results:` block for it.
|
|
160
|
+
When a later item does consume its output, the produced-value rule above
|
|
161
|
+
applies instead.
|
|
162
|
+
|
|
163
|
+
### Boss-reply continuation
|
|
164
|
+
|
|
165
|
+
Where a direct-Captain or delegated-player behavior may ask Boss a question
|
|
166
|
+
and wait, Boss's answer resumes that same behavior with continuation context;
|
|
167
|
+
it is not a distinct behavior item. text2gears shall keep the question result,
|
|
168
|
+
the wait, and the answer-dependent continuation on the originating item even
|
|
169
|
+
when the answer changes its complete runtime prompt. It shall not emit a
|
|
170
|
+
second item solely for "Boss answers," "after the question," or clearing the
|
|
171
|
+
consumed question/reply. The FSM and linker own the same-leaf suspension,
|
|
172
|
+
continuation blocks, and consumed-context cleanup.
|
|
173
|
+
|
|
174
|
+
This rule is an exception to splitting by accumulated prompt content below.
|
|
175
|
+
Split only when Source requires a genuinely different acting behavior after
|
|
176
|
+
the reply, not when the same decision or task continues with Boss's answer.
|
|
177
|
+
|
|
178
|
+
The same consolidation applies when Source says a fresh directive interrupts
|
|
179
|
+
parked work and *restarts the same behavior* with cleared context. When the
|
|
180
|
+
acting prompt and result contract are identical, retain the interrupt as an
|
|
181
|
+
entry condition on the originating item; do not duplicate that item solely to
|
|
182
|
+
describe the restart. Split only when the fresh directive invokes genuinely
|
|
183
|
+
different acting work or a different prompt/result contract.
|
|
184
|
+
|
|
185
|
+
### Parallel behaviors
|
|
186
|
+
|
|
187
|
+
Where two or more delegated-player items share one trigger and Source requires
|
|
188
|
+
them to run independently before later work uses all results, text2gears shall
|
|
189
|
+
place `Parallel group: <stable-kebab-case-id>` immediately below each item
|
|
190
|
+
heading.
|
|
191
|
+
Every item in one parallel group shall receive the same completed-prior-group
|
|
192
|
+
inputs; no item prompt may depend on another member's result from the current
|
|
193
|
+
group.
|
|
194
|
+
Every member shall delegate to a named player, and the source shall permit
|
|
195
|
+
those members to resolve to distinct players. Direct-Captain work shares one
|
|
196
|
+
Captain session and nested calls share one pending-child stack slot, so neither
|
|
197
|
+
kind may receive parallel-group metadata. If Source explicitly requires either
|
|
198
|
+
unsupported kind to run concurrently, text2gears shall report that the source
|
|
199
|
+
cannot be represented rather than silently serialize it or emit metadata the
|
|
200
|
+
next phase cannot compile.
|
|
201
|
+
|
|
202
|
+
Example:
|
|
203
|
+
|
|
204
|
+
```markdown
|
|
205
|
+
### DISCUSS-1
|
|
206
|
+
|
|
207
|
+
Parallel group: initial-proposals
|
|
208
|
+
|
|
209
|
+
When Boss gives a topic, Captain shall prompt Host:
|
|
210
|
+
|
|
211
|
+
> Propose your design independently.
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Nested playbook calls
|
|
215
|
+
|
|
216
|
+
Where Source requires one playbook to call a statically known playbook,
|
|
217
|
+
text2gears shall emit an item whose behavior uses
|
|
218
|
+
`Captain shall call playbook <playbook-id>:` and whose blockquote is the
|
|
219
|
+
complete JSON-safe input-text template for that call.
|
|
220
|
+
The literal target id shall be a stable configured playbook id, not a slash
|
|
221
|
+
command or module specifier.
|
|
222
|
+
|
|
223
|
+
Example:
|
|
224
|
+
|
|
225
|
+
```markdown
|
|
226
|
+
### RELEASE-8
|
|
227
|
+
|
|
228
|
+
When implementation is ready for review, Captain shall call playbook `code-review`:
|
|
229
|
+
|
|
230
|
+
> Review these changes:
|
|
231
|
+
> <changes>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
Where Source selects the target at runtime, text2gears shall instead emit the
|
|
235
|
+
first-class dynamic form
|
|
236
|
+
``Captain shall call playbook selected by `<playbook-id-context>`:``.
|
|
237
|
+
The backtick-delimited name identifies a typed FSM context field whose runtime
|
|
238
|
+
value is the target playbook id; it is not itself a target id.
|
|
239
|
+
The blockquote shall be exactly one placeholder naming the typed context field
|
|
240
|
+
whose runtime string is the complete child input text.
|
|
241
|
+
|
|
242
|
+
Example:
|
|
243
|
+
|
|
244
|
+
```markdown
|
|
245
|
+
### CAPTAIN-2
|
|
246
|
+
|
|
247
|
+
When Captain selects a next call, Captain shall call playbook selected by `nextPlaybookId`:
|
|
248
|
+
|
|
249
|
+
> <nextPlaybookInput>
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Here `nextPlaybookId` and `nextPlaybookInput` are stable context-field names.
|
|
253
|
+
The dynamic form shall not use a slash command, module specifier, opaque
|
|
254
|
+
expression, or prose from which a downstream compiler would have to infer
|
|
255
|
+
either field.
|
|
256
|
+
|
|
257
|
+
### Script behaviors (optimizer-introduced)
|
|
258
|
+
|
|
259
|
+
A GEARS package may also contain deterministic script behaviors, written
|
|
260
|
+
`Captain shall run:` followed by a blockquote whose lines are the exact POSIX
|
|
261
|
+
shell script to execute.
|
|
262
|
+
text2gears shall never emit this kind: script items enter a GEARS package only
|
|
263
|
+
through the separate [optimize](optimize.md) pass, which rewrites eligible
|
|
264
|
+
compiled items.
|
|
265
|
+
The kind is defined here so every consumer of the GEARS format shares one
|
|
266
|
+
item-syntax contract.
|
|
267
|
+
|
|
268
|
+
A script item's blockquote is static shell text: it shall contain no
|
|
269
|
+
`<placeholder>`, and Markdown escapes resolve exactly as in acting prompts.
|
|
270
|
+
A script item shall carry a `Results:` label with exactly two bullets in this
|
|
271
|
+
fixed interpretation: the first guard reports the script exiting with status
|
|
272
|
+
zero, the second reports a nonzero exit status.
|
|
273
|
+
No other result, and no `needsBossReply`, applies to a script item — a script
|
|
274
|
+
has no agent to surface questions.
|
|
275
|
+
|
|
276
|
+
Example:
|
|
277
|
+
|
|
278
|
+
```markdown
|
|
279
|
+
### CODE-1
|
|
280
|
+
|
|
281
|
+
When the workflow starts, Captain shall run:
|
|
282
|
+
|
|
283
|
+
> git rev-parse --is-inside-work-tree 2>/dev/null || git init
|
|
284
|
+
|
|
285
|
+
Results:
|
|
286
|
+
- `ok`: The command exited with status zero.
|
|
287
|
+
- `failed`: The command exited with a nonzero status.
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
Target shall be written in the same language as Source: an item's condition
|
|
291
|
+
prose, acting prompts, and result descriptions follow the Source language,
|
|
292
|
+
read per the matching localization of the GEARS definition [[1]].
|
|
293
|
+
The four `Captain shall` acting-clause forms defined above (direct,
|
|
294
|
+
delegated, nested playbook call, and script), guard names, and the
|
|
295
|
+
`Players:` and `Results:` labels are fixed machine syntax and stay in this
|
|
296
|
+
exact English form regardless of Source language.
|
|
297
|
+
|
|
298
|
+
## Transformation-spec sources
|
|
299
|
+
|
|
300
|
+
A Source may itself be the normative specification of a transformation — e.g., a compiler phase definition, as when a meta pipeline compiles this file.
|
|
301
|
+
Such a Source declares no players and prompts none; its implied procedure is that Captain performs the specified transformation on request.
|
|
302
|
+
Compose Captain-acting spec items for it: when a transformation request names the specification's source and target, Captain shall carry out the transformation as specified.
|
|
303
|
+
Prompts shall carry the specification's normative requirements as instructions to Captain — deduplicated, one point per line — without inventing players, triggers, or requirements the specification does not state.
|
|
58
304
|
|
|
59
305
|
## Composition
|
|
60
306
|
|
|
@@ -71,6 +317,8 @@ Test: a human shall be able to simulate a run by copying any single item's promp
|
|
|
71
317
|
Use `<placeholder>` for dynamic values in blockquoted prompts.
|
|
72
318
|
Everything else inside a blockquote is static text, not an example; examples belong in surrounding prose.
|
|
73
319
|
|
|
320
|
+
Markdown escaping is Source syntax, not content: extraction shall resolve escapes (e.g. `\<placeholder\>` becomes `<placeholder>`), so compiled artifacts carry plain text.
|
|
321
|
+
|
|
74
322
|
### Split by content discriminator
|
|
75
323
|
|
|
76
324
|
Partition items by every variable that determines prompt content — including accumulated state when the trigger alone doesn't.
|
|
@@ -82,4 +330,4 @@ Dead branches mislead readers and downstream phases.
|
|
|
82
330
|
|
|
83
331
|
## References
|
|
84
332
|
|
|
85
|
-
[1]:
|
|
333
|
+
[1]: GEARS definition shipped by the installed `@sublang/spex` package: `@sublang/spex/scaffold/specs/meta.md` (English) and `@sublang/spex/scaffold/i18n/zh/specs/meta.md` (Chinese); canonical renditions [GEARS: AI-Ready Spec Syntax](https://sublang.ai/ref/gears-ai-ready-spec-syntax) (en) and [GEARS:面向 AI 的规约语法](https://sublang.ai/zh/ref/gears-ai-ready-spec-syntax) (zh)
|
package/src/runtime.d.ts
CHANGED
|
@@ -1,23 +1,166 @@
|
|
|
1
1
|
export interface PlayerResult {
|
|
2
2
|
status: 'ok' | 'aborted' | 'error';
|
|
3
|
+
resumeToken?: string;
|
|
3
4
|
finalText?: string;
|
|
4
5
|
error?: string;
|
|
5
6
|
}
|
|
7
|
+
export interface PlayerCallOptions {
|
|
8
|
+
resume: string | false;
|
|
9
|
+
}
|
|
10
|
+
export interface CaptainCallOptions {
|
|
11
|
+
visibility: 'visible' | 'hidden';
|
|
12
|
+
resume: string | false;
|
|
13
|
+
allowedTools?: readonly string[];
|
|
14
|
+
}
|
|
15
|
+
export interface CaptainResult {
|
|
16
|
+
status: 'ok' | 'aborted' | 'error';
|
|
17
|
+
finalText?: string;
|
|
18
|
+
error?: string;
|
|
19
|
+
}
|
|
20
|
+
export type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
|
|
21
|
+
readonly [key: string]: JsonValue;
|
|
22
|
+
};
|
|
23
|
+
export interface NormalizedError {
|
|
24
|
+
name: string;
|
|
25
|
+
message: string;
|
|
26
|
+
stack?: string;
|
|
27
|
+
}
|
|
28
|
+
export type PlaybookStateValue = string | {
|
|
29
|
+
readonly [key: string]: PlaybookStateValue;
|
|
30
|
+
};
|
|
31
|
+
export interface PlaybookState {
|
|
32
|
+
value: PlaybookStateValue;
|
|
33
|
+
activeStateIds: readonly string[];
|
|
34
|
+
tags: readonly string[];
|
|
35
|
+
status: 'active' | 'done' | 'error' | 'stopped';
|
|
36
|
+
quiescent: boolean;
|
|
37
|
+
stateId?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface PlaybookPendingCall {
|
|
40
|
+
callId: string;
|
|
41
|
+
playbookId: string;
|
|
42
|
+
childSessionId: string;
|
|
43
|
+
}
|
|
44
|
+
export interface PlaybookCallRequest {
|
|
45
|
+
callId: string;
|
|
46
|
+
playbookId: string;
|
|
47
|
+
text: string;
|
|
48
|
+
}
|
|
49
|
+
export type PlaybookCallResult = {
|
|
50
|
+
status: 'ok';
|
|
51
|
+
playbookId: string;
|
|
52
|
+
childSessionId: string;
|
|
53
|
+
state?: PlaybookState;
|
|
54
|
+
output?: JsonValue;
|
|
55
|
+
} | {
|
|
56
|
+
status: 'aborted';
|
|
57
|
+
playbookId: string;
|
|
58
|
+
childSessionId?: string;
|
|
59
|
+
state?: PlaybookState;
|
|
60
|
+
error?: NormalizedError;
|
|
61
|
+
} | {
|
|
62
|
+
status: 'error';
|
|
63
|
+
playbookId: string;
|
|
64
|
+
childSessionId?: string;
|
|
65
|
+
state?: PlaybookState;
|
|
66
|
+
error: NormalizedError;
|
|
67
|
+
};
|
|
68
|
+
export type PlaybookCallStart = {
|
|
69
|
+
state: 'settled';
|
|
70
|
+
result: PlaybookCallResult;
|
|
71
|
+
} | {
|
|
72
|
+
state: 'suspended';
|
|
73
|
+
childSessionId: string;
|
|
74
|
+
};
|
|
75
|
+
export type PlaybookRunResult = {
|
|
76
|
+
outcome: 'quiescent' | 'no-action';
|
|
77
|
+
state: PlaybookState;
|
|
78
|
+
} | {
|
|
79
|
+
outcome: 'failed' | 'aborted';
|
|
80
|
+
state: PlaybookState;
|
|
81
|
+
error?: NormalizedError;
|
|
82
|
+
} | {
|
|
83
|
+
outcome: 'terminal';
|
|
84
|
+
state: PlaybookState;
|
|
85
|
+
output?: JsonValue;
|
|
86
|
+
} | {
|
|
87
|
+
outcome: 'suspended';
|
|
88
|
+
state: PlaybookState;
|
|
89
|
+
pendingCall: PlaybookPendingCall;
|
|
90
|
+
};
|
|
6
91
|
export interface PlaybookPorts {
|
|
7
|
-
callPlayer(playerId: string, prompt: string, signal: AbortSignal): Promise<PlayerResult>;
|
|
92
|
+
callPlayer(playerId: string, prompt: string, signal: AbortSignal, options: PlayerCallOptions): Promise<PlayerResult>;
|
|
93
|
+
callCaptain(prompt: string, signal: AbortSignal, options: CaptainCallOptions): Promise<CaptainResult>;
|
|
8
94
|
callJudge(prompt: string, signal: AbortSignal): Promise<string>;
|
|
95
|
+
callPlaybook(request: PlaybookCallRequest, signal: AbortSignal): Promise<PlaybookCallStart>;
|
|
9
96
|
emitStatus(message: string, data?: unknown): Promise<void>;
|
|
10
97
|
emitTelemetry(event: {
|
|
11
98
|
topic: string;
|
|
12
99
|
payload: unknown;
|
|
13
100
|
}): Promise<void>;
|
|
14
101
|
}
|
|
102
|
+
export interface PlaybookSession {
|
|
103
|
+
sessionId: string;
|
|
104
|
+
playbookId: string;
|
|
105
|
+
rootSessionId: string;
|
|
106
|
+
parentSessionId?: string;
|
|
107
|
+
parentCallId?: string;
|
|
108
|
+
depth: number;
|
|
109
|
+
ports: PlaybookPorts;
|
|
110
|
+
}
|
|
111
|
+
export type PlaybookTraceType = 'session.started' | 'boss.input.received' | 'judge.call.started' | 'judge.call.finished' | 'player.call.started' | 'player.call.finished' | 'captain.call.started' | 'captain.call.finished' | 'playbook.call.started' | 'playbook.call.finished' | 'fsm.transition' | 'status.emitted' | 'boss.input.settled' | 'session.disposed';
|
|
112
|
+
export interface PlaybookTraceEvent {
|
|
113
|
+
schemaVersion: 2;
|
|
114
|
+
sessionId: string;
|
|
115
|
+
playbookId: string;
|
|
116
|
+
rootSessionId: string;
|
|
117
|
+
parentSessionId?: string;
|
|
118
|
+
parentCallId?: string;
|
|
119
|
+
depth: number;
|
|
120
|
+
sequence: number;
|
|
121
|
+
timestamp: number;
|
|
122
|
+
type: PlaybookTraceType;
|
|
123
|
+
turnId?: number;
|
|
124
|
+
callId?: string;
|
|
125
|
+
payload: JsonValue;
|
|
126
|
+
}
|
|
127
|
+
export interface PlaybookPendingBossQuestion {
|
|
128
|
+
questionId: string;
|
|
129
|
+
player: string;
|
|
130
|
+
question: string;
|
|
131
|
+
sourceItem?: string;
|
|
132
|
+
}
|
|
133
|
+
export interface PlaybookRuntimeSnapshot {
|
|
134
|
+
schemaVersion: 1;
|
|
135
|
+
playbookId: string;
|
|
136
|
+
machine: JsonValue;
|
|
137
|
+
playerResumeTokens: {
|
|
138
|
+
readonly [playerId: string]: string;
|
|
139
|
+
};
|
|
140
|
+
sequences: {
|
|
141
|
+
trace: number;
|
|
142
|
+
turn: number;
|
|
143
|
+
judgeCall: number;
|
|
144
|
+
playerCall: number;
|
|
145
|
+
playbookCall: number;
|
|
146
|
+
captainCall?: number;
|
|
147
|
+
};
|
|
148
|
+
state: PlaybookState;
|
|
149
|
+
pendingBossQuestions: readonly PlaybookPendingBossQuestion[];
|
|
150
|
+
}
|
|
15
151
|
export interface PlaybookRuntime {
|
|
16
|
-
init(
|
|
152
|
+
init(session: PlaybookSession): Promise<void>;
|
|
153
|
+
exportSnapshot?(): PlaybookRuntimeSnapshot | undefined;
|
|
154
|
+
restore?(session: PlaybookSession, snapshot: PlaybookRuntimeSnapshot): Promise<void>;
|
|
17
155
|
handleBossInput(turn: {
|
|
18
156
|
text: string;
|
|
19
157
|
signal: AbortSignal;
|
|
20
|
-
}): Promise<
|
|
158
|
+
}): Promise<PlaybookRunResult>;
|
|
159
|
+
resumePlaybookCall(input: {
|
|
160
|
+
callId: string;
|
|
161
|
+
result: PlaybookCallResult;
|
|
162
|
+
signal: AbortSignal;
|
|
163
|
+
}): Promise<PlaybookRunResult>;
|
|
21
164
|
dispose(): Promise<void>;
|
|
22
165
|
}
|
|
23
166
|
export type PlaybookRuntimeFactory<Options = unknown> = (options: Options) => PlaybookRuntime;
|