@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.
- package/README.md +1 -1
- package/docs/embedding.md +9 -7
- package/package.json +3 -1
- 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/code.playbook/bin/repository-effects.js +54 -13
- package/reference/sdlc/code.playbook/code.fsm.d.ts +143 -90
- 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/playbook-captain.d.ts +42 -0
- package/reference/sdlc/code.playbook/playbook-captain.js +829 -194
- package/reference/sdlc/code.playbook/playbook-captain.ts +1227 -220
- package/reference/sdlc/decide.md +1 -0
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +270 -154
- 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 -67
- package/reference/sdlc/decide.playbook/decide.playbook.js +155 -3570
- package/reference/sdlc/decide.playbook/decide.playbook.ts +186 -5061
- 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 +113 -131
- 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 +92 -85
- 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 +72 -3
- package/slc/link.md +50 -27
- package/slc/materialize-link.mjs +51 -13
- package/slc/optimize.md +4 -1
- package/slc/prefix-prompts.mjs +191 -0
- package/slc/prefix.md +203 -0
- package/slc/slc.pin-inputs.json +11 -1
- package/slc/text2gears.md +71 -11
- package/src/xstate-playbook-runtime.d.ts +82 -9
- package/src/xstate-playbook-runtime.js +1224 -283
- package/src/xstate-playbook-runtime.ts +1671 -338
- package/src/xstate-runtime.d.ts +3 -1
- package/src/xstate-runtime.js +9 -2
- package/src/xstate-runtime.ts +12 -2
package/slc/prefix.md
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
<!-- SPDX-License-Identifier: Apache-2.0 -->
|
|
2
|
+
<!-- SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai> -->
|
|
3
|
+
|
|
4
|
+
# GEARS Prompt-Prefix Pass
|
|
5
|
+
|
|
6
|
+
Optional optimization pass of a playbook (a state-machine agent orchestrating
|
|
7
|
+
other agents).
|
|
8
|
+
Reorders each acting prompt so that its static instructions come first and the
|
|
9
|
+
runtime values relayed into it come last, giving every run of the same item an
|
|
10
|
+
identical prompt prefix that an LLM provider's prompt cache can serve.
|
|
11
|
+
|
|
12
|
+
- Source: a package of GEARS spec items produced by [text2gears](text2gears.md)
|
|
13
|
+
and, when scheduled, already rewritten by [optimize](optimize.md).
|
|
14
|
+
- Target: the same package with eligible prompts laid out prefix-first.
|
|
15
|
+
|
|
16
|
+
The pass is format-preserving: source and target are both GEARS packages, and
|
|
17
|
+
the pass sits between [text2gears](text2gears.md) and
|
|
18
|
+
[gears2fsm](gears2fsm.md), after [optimize](optimize.md) by pass-name order.
|
|
19
|
+
A playbook compiled without this pass has identical observable behavior; the
|
|
20
|
+
pass trades a compile-time rewrite for cheaper prompt processing at run time.
|
|
21
|
+
|
|
22
|
+
Prompt caches are prefix caches: a provider serves the longest prefix it has
|
|
23
|
+
already seen and processes everything after the first differing token afresh
|
|
24
|
+
[[1]], [[2]], [[3]].
|
|
25
|
+
A prompt that opens with this run's relayed request therefore shares nothing
|
|
26
|
+
with the previous run's prompt for the same item, while one that opens with
|
|
27
|
+
the item's instructions shares them all.
|
|
28
|
+
|
|
29
|
+
## Formats
|
|
30
|
+
|
|
31
|
+
| Role | Format | Extension |
|
|
32
|
+
| ------ | ------ | --------- |
|
|
33
|
+
| source | gears | .md |
|
|
34
|
+
| target | gears | .md |
|
|
35
|
+
|
|
36
|
+
## Prompt regions
|
|
37
|
+
|
|
38
|
+
Within an item's blockquote, each prompt line is one of:
|
|
39
|
+
|
|
40
|
+
- a **relay line** — prompt content that begins with the literal quote marker
|
|
41
|
+
`>` (written `> > …` in the GEARS file), which is how
|
|
42
|
+
[text2gears](text2gears.md#authored-prompt-fragments) relays a runtime value
|
|
43
|
+
such as `> Original request: <caller-input>`;
|
|
44
|
+
- a **blank line** — an empty prompt line, written `>`;
|
|
45
|
+
- an **instruction line** — any other prompt line.
|
|
46
|
+
|
|
47
|
+
A **relay block** is a maximal run of consecutive relay lines bounded by blank
|
|
48
|
+
lines or the blockquote's edges, whether Source authored it as a separate
|
|
49
|
+
quoted relay or set it apart with blank lines inside a fenced instruction.
|
|
50
|
+
A relay line adjacent to an instruction line is authored content of that
|
|
51
|
+
instruction — a quoted example inside a fenced instruction, for instance — and
|
|
52
|
+
belongs to the instruction, not to a relay block.
|
|
53
|
+
|
|
54
|
+
An instruction line may carry an inline `<placeholder>`, such as a configured
|
|
55
|
+
model name; the pass never splits or rewrites an instruction line to isolate
|
|
56
|
+
it.
|
|
57
|
+
|
|
58
|
+
## Eligibility
|
|
59
|
+
|
|
60
|
+
The pass shall rewrite an item only when **all** of the following hold:
|
|
61
|
+
|
|
62
|
+
- The item is an acting item with a prompt: a direct-Captain, delegated-role,
|
|
63
|
+
or nested-playbook-call blockquote.
|
|
64
|
+
A script item (`Captain shall run:`) has no prompt and is never rewritten.
|
|
65
|
+
- At least one relay block precedes an instruction line.
|
|
66
|
+
An item whose relay blocks already trail every instruction line is already
|
|
67
|
+
prefix-first and stays unchanged.
|
|
68
|
+
- No instruction line depends on a relayed value standing before it — one
|
|
69
|
+
that refers to the relayed text as above or preceding, or that continues a
|
|
70
|
+
sentence the relay began.
|
|
71
|
+
A reference to the relayed text as below or following stays true after the
|
|
72
|
+
move.
|
|
73
|
+
|
|
74
|
+
Judgment stays conservative: when eligibility is uncertain, the pass shall
|
|
75
|
+
leave the item unchanged rather than guess.
|
|
76
|
+
The pass shall not invent prompt lines, labels, or separators, and shall not
|
|
77
|
+
rewrite, merge, split, or drop any line.
|
|
78
|
+
|
|
79
|
+
Source prose that places a relay after an instruction, or an instruction at
|
|
80
|
+
the end of the prompt, tells [text2gears](text2gears.md) how to compose the
|
|
81
|
+
prompt faithfully; it does not make the item ineligible.
|
|
82
|
+
This pass overrides that composition order by design, and `--no-optimize`
|
|
83
|
+
restores it.
|
|
84
|
+
|
|
85
|
+
## Rewriting
|
|
86
|
+
|
|
87
|
+
For each eligible item, the pass shall rewrite only the blockquote:
|
|
88
|
+
|
|
89
|
+
- Emit every line that is not part of a relay block, in its original order,
|
|
90
|
+
keeping each line byte-for-byte, dropping leading and trailing blank lines,
|
|
91
|
+
and replacing each run of removed relay blocks together with the blank lines
|
|
92
|
+
bounding it by the first of those blank lines where it separated two
|
|
93
|
+
remaining lines; every other blank line, such as one inside a fenced
|
|
94
|
+
template, stays where it is.
|
|
95
|
+
- Emit one blank line.
|
|
96
|
+
- Emit the relay blocks in their original order, each byte-for-byte, with one
|
|
97
|
+
blank line between consecutive blocks.
|
|
98
|
+
- Keep the item's ID, heading, condition, acting clause, `Results:`, and any
|
|
99
|
+
other metadata unchanged.
|
|
100
|
+
- Preserve every other item and every non-item section byte-for-byte,
|
|
101
|
+
including an `## Optimizations` section the optimize pass appended, except
|
|
102
|
+
a legacy `## Prefixed prompts` section (see [Provenance](#provenance)).
|
|
103
|
+
|
|
104
|
+
Because no line changes, the target stays in the Source language and every
|
|
105
|
+
authored fragment remains intact; only the order of relay blocks relative to
|
|
106
|
+
instructions changes.
|
|
107
|
+
|
|
108
|
+
E.g., the source item
|
|
109
|
+
|
|
110
|
+
```markdown
|
|
111
|
+
### REVIEW-2
|
|
112
|
+
|
|
113
|
+
When Reviewer raises or keeps any finding, Captain shall relay the caller input and Reviewer's findings to Coder with the disposition prompt:
|
|
114
|
+
|
|
115
|
+
> > Original request: <caller-input>
|
|
116
|
+
> > Reviewer findings: <reviewer-output>
|
|
117
|
+
>
|
|
118
|
+
> For each review item, accept or reject it.
|
|
119
|
+
> Report every disposition, all relevant run results, and every rebuttal.
|
|
120
|
+
|
|
121
|
+
Results:
|
|
122
|
+
- `committed`: Coder accepted at least one item and added one new review-fix commit. Output shall include `coderOutput: <verbatim final text>` and `latestCommit: <commit identity>`.
|
|
123
|
+
- `rejectedAll`: Coder rejected every item and made no commit. Output shall include `coderOutput: <verbatim final text>`.
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
becomes
|
|
127
|
+
|
|
128
|
+
```markdown
|
|
129
|
+
### REVIEW-2
|
|
130
|
+
|
|
131
|
+
When Reviewer raises or keeps any finding, Captain shall relay the caller input and Reviewer's findings to Coder with the disposition prompt:
|
|
132
|
+
|
|
133
|
+
> For each review item, accept or reject it.
|
|
134
|
+
> Report every disposition, all relevant run results, and every rebuttal.
|
|
135
|
+
>
|
|
136
|
+
> > Original request: <caller-input>
|
|
137
|
+
> > Reviewer findings: <reviewer-output>
|
|
138
|
+
|
|
139
|
+
Results:
|
|
140
|
+
- `committed`: Coder accepted at least one item and added one new review-fix commit. Output shall include `coderOutput: <verbatim final text>` and `latestCommit: <commit identity>`.
|
|
141
|
+
- `rejectedAll`: Coder rejected every item and made no commit. Output shall include `coderOutput: <verbatim final text>`.
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Provenance
|
|
145
|
+
|
|
146
|
+
The pass shall record nothing beside the rewritten prompts, whose layout
|
|
147
|
+
shows the rewrite.
|
|
148
|
+
A `## Prefixed prompts` section an earlier version of this pass appended shall
|
|
149
|
+
be removed — up to the next heading, and at the end of the file with the blank
|
|
150
|
+
lines before it; when no item is eligible and no such section is present, the
|
|
151
|
+
target shall be the source content unchanged.
|
|
152
|
+
Re-running the pass is a no-op by layout: an item whose relays already trail
|
|
153
|
+
is not eligible.
|
|
154
|
+
|
|
155
|
+
A Source-to-GEARS fidelity checker therefore reads the layout from each prompt:
|
|
156
|
+
it accepts an item either in Source order throughout or in the prefix-first
|
|
157
|
+
layout, which requires each instruction and relay block of the fragments the
|
|
158
|
+
item carries intact, blank lines inside a block included, and used exactly
|
|
159
|
+
once, the instruction blocks in Source order, the relay blocks in Source order,
|
|
160
|
+
and every relay after the last instruction, a relay Source joined directly to
|
|
161
|
+
an instruction staying beside it with its authored boundary, a bare relay the
|
|
162
|
+
prose authored free to trail, and one occurrence standing for one authored
|
|
163
|
+
fragment.
|
|
164
|
+
|
|
165
|
+
## Deterministic rewriting
|
|
166
|
+
|
|
167
|
+
The adjacent `prefix-prompts.mjs` tool performs this rewrite exactly:
|
|
168
|
+
|
|
169
|
+
```sh
|
|
170
|
+
node "<definition-directory>/prefix-prompts.mjs" --source "<source.gears.md>" --target "<target.gears.md>" [--keep <ITEM-ID>]...
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
It reads the source, rewrites every item eligible by the mechanical rules
|
|
174
|
+
above, removes a legacy `## Prefixed prompts` section, writes the target, and
|
|
175
|
+
prints the rewritten item IDs — or reports that no item was eligible.
|
|
176
|
+
`--keep` excludes an item the tool would otherwise rewrite.
|
|
177
|
+
|
|
178
|
+
The pass shall use the tool rather than rewrite by hand:
|
|
179
|
+
|
|
180
|
+
1. Read the source and decide, for each item with a relay block preceding an
|
|
181
|
+
instruction line, whether an instruction depends on a relay standing before
|
|
182
|
+
it; that judgment is the pass's only non-mechanical step.
|
|
183
|
+
2. Run the tool with `--keep` for each item so excluded.
|
|
184
|
+
3. Read the target and confirm that every rewritten item's instructions and
|
|
185
|
+
relays are intact and that nothing changed beyond the rewritten items and
|
|
186
|
+
the removal of a legacy `## Prefixed prompts` section.
|
|
187
|
+
|
|
188
|
+
The tool writes only the declared target and never modifies the source.
|
|
189
|
+
|
|
190
|
+
## Out of scope
|
|
191
|
+
|
|
192
|
+
- Any change to prompt wording, conditions, result contracts, or item order.
|
|
193
|
+
- Rewriting behaviors into one another; that is the [optimize](optimize.md)
|
|
194
|
+
pass.
|
|
195
|
+
- Where a transport sends a prompt as one content block, the provider's cache
|
|
196
|
+
boundary is the transport's concern; this pass only makes the shared prefix
|
|
197
|
+
exist.
|
|
198
|
+
|
|
199
|
+
## References
|
|
200
|
+
|
|
201
|
+
[1]: https://platform.claude.com/docs/en/docs/build-with-claude/prompt-caching "Anthropic — Prompt caching: place static content at the beginning of the prompt"
|
|
202
|
+
[2]: https://developers.openai.com/api/docs/guides/prompt-caching "OpenAI — Prompt caching: put stable instructions first, dynamic content at the end"
|
|
203
|
+
[3]: https://ai.google.dev/gemini-api/docs/caching "Google — Gemini context caching: put large and common contents at the beginning of the prompt"
|
package/slc/slc.pin-inputs.json
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "sublang.slc.pin-inputs.v1",
|
|
3
3
|
"closures": {
|
|
4
|
-
"
|
|
4
|
+
"text2gears": [
|
|
5
|
+
"workflow-contracts.json"
|
|
6
|
+
],
|
|
7
|
+
"gears2fsm": [
|
|
8
|
+
"text2gears.md",
|
|
9
|
+
"link.md",
|
|
10
|
+
"workflow-contracts.json"
|
|
11
|
+
],
|
|
12
|
+
"prefix": [
|
|
13
|
+
"prefix-prompts.mjs"
|
|
14
|
+
],
|
|
5
15
|
"link": [
|
|
6
16
|
"text2gears.md",
|
|
7
17
|
"gears2fsm.md",
|
package/slc/text2gears.md
CHANGED
|
@@ -157,13 +157,37 @@ Keep each declaration outside plain-text parentheses; explanatory symbols in
|
|
|
157
157
|
parenthetical guidance use plain text, never separate backticks, because those
|
|
158
158
|
backticks would declare extra required fields. Guidance may instead occur
|
|
159
159
|
inside a field's complete annotation, including any parentheses there.
|
|
160
|
-
For example, use `` `
|
|
161
|
-
`` `
|
|
160
|
+
For example, use `` `latestCommit` (new code-owned commit) `` or
|
|
161
|
+
`` `latestCommit: <commit identity>` ``, without backticks around code.
|
|
162
|
+
The commit a call itself creates is always declared as `latestCommit`, the
|
|
163
|
+
canonical effect-owned property every linked runtime fills from the
|
|
164
|
+
repository receipt and every terminal output projects from.
|
|
162
165
|
An output property name shall match the same ASCII identifier pattern as a
|
|
163
166
|
guard name: a kebab-case Source placeholder such as `<coder-output>` names the
|
|
164
167
|
property `coderOutput` through the canonical kebab-token-to-camel-field mapping
|
|
165
168
|
of [link](link.md), never a quoted kebab-case key, because downstream artifacts
|
|
166
169
|
and calling playbooks consume these properties by name.
|
|
170
|
+
A result shall declare an output property only where a consumer requires it:
|
|
171
|
+
a later item's `<placeholder>`, the workflow's terminal return, or the
|
|
172
|
+
workflow's declared public interface below.
|
|
173
|
+
A detail the acting agent reports only within its final text — a reason, a
|
|
174
|
+
summary, a list — travels in the result's verbatim final-text property and is
|
|
175
|
+
not a separate judge-authored property.
|
|
176
|
+
|
|
177
|
+
Where the selected pipeline supplies the
|
|
178
|
+
[workflow contracts](workflow-contracts.json) catalog and the Source's basename
|
|
179
|
+
is one of its `literalTargetBindings`, the compiled workflow is held to that
|
|
180
|
+
builtin's declared output interface, because callers compiled against the
|
|
181
|
+
catalog address it by that id: a result property whose value that interface
|
|
182
|
+
returns shall take the interface's property name — `branch`, `issueSummary`,
|
|
183
|
+
and `coderOutput` for `branch`; `evaluatedRevision` for the revision a clean
|
|
184
|
+
review round evaluated — whether the value is semantic, presentation, or
|
|
185
|
+
effect-owned, while the commit a call itself creates keeps the canonical
|
|
186
|
+
`latestCommit` for the FSM to project into the interface's field.
|
|
187
|
+
A Source placeholder that names such a value otherwise is an inconsistency
|
|
188
|
+
between the Source and the catalog: leave the Target unwritten and report it
|
|
189
|
+
as an incompatible compiler input rather than rename or invent.
|
|
190
|
+
A Source outside those ids is named from its own words as above.
|
|
167
191
|
|
|
168
192
|
A produced value consumed later shall have a declared producer: where any
|
|
169
193
|
later item's blockquote reads a value through a `<placeholder>`, the item
|
|
@@ -172,14 +196,37 @@ whose relevant description names the produced output property, using the
|
|
|
172
196
|
placeholder's exact identifier — this is what lets the FSM thread the value
|
|
173
197
|
through typed context.
|
|
174
198
|
A single-outcome producer then declares exactly one bullet naming the
|
|
175
|
-
property; this consumed-output case
|
|
176
|
-
single-outcome behavior carries a `Results:` label.
|
|
199
|
+
property; this consumed-output case and the qualified-outcome case below are
|
|
200
|
+
the two in which a single-outcome behavior carries a `Results:` label.
|
|
201
|
+
The commit a call itself creates is the one exception to naming the property
|
|
202
|
+
after the placeholder: its producer declares `latestCommit: <commit identity>`
|
|
203
|
+
whatever placeholder a later prompt reads it through — `<code-commit>` or
|
|
204
|
+
`<decide-commit>`, for instance — because the linked runtime fills that
|
|
205
|
+
property from the repository receipt rather than from the player, and
|
|
206
|
+
[gears2fsm](gears2fsm.md#context-and-prompts) binds the Source's placeholder
|
|
207
|
+
to the retained commit.
|
|
208
|
+
A placeholder the Source defines as a labelled section of another relayed
|
|
209
|
+
value, naming the label that opens the section and the labels that end it —
|
|
210
|
+
`<original-intent>` as the `Original intent:` section of the caller's request,
|
|
211
|
+
which runs to the `Review scope:` line or to the end of the request, for
|
|
212
|
+
instance — is derived, not produced: text2gears shall keep that defining
|
|
213
|
+
sentence verbatim in the package introduction, or in the item's prose where the
|
|
214
|
+
Source states it there, name the placeholder as the Source does, and declare no
|
|
215
|
+
result property for it, because no player produces the value and
|
|
216
|
+
[gears2fsm](gears2fsm.md#context-and-prompts) derives it from the relayed text.
|
|
177
217
|
|
|
178
218
|
Where a later prompt relays a delegated player's whole final response as quoted context, the producer shall declare that property in the exact annotated form `` `<field>: <verbatim final text>` ``.
|
|
179
219
|
The annotation makes the field runtime-owned: the adjudicator selects the result guard, while the linked runtime carries the player's canonical final text into that field instead of asking a judge to reproduce it.
|
|
180
220
|
A distinct typed field extracted from that response remains judge-authored even when a later prompt quotes its exact value; quoting a field does not turn it into the player's whole final response.
|
|
181
221
|
One property name shall not be annotated as verbatim in one result contract and judge-authored in another; text2gears shall choose distinct properties or report that the Source cannot be represented by the current contract.
|
|
182
222
|
|
|
223
|
+
A Source statement that qualifies an outcome's evidence — what affirmatively
|
|
224
|
+
supports it, what supports no outcome, such as "a progress report, status
|
|
225
|
+
update, or promise of a later result supports no review outcome" — shall be
|
|
226
|
+
carried in that outcome's result description, the only text the adjudicator
|
|
227
|
+
reads when it selects the guard; left in the item's prose, it reaches no
|
|
228
|
+
judge.
|
|
229
|
+
|
|
183
230
|
Result metadata is compiler control data, not part of the acting agent's
|
|
184
231
|
prompt.
|
|
185
232
|
text2gears shall not put guard names, result-property schema, JSON control
|
|
@@ -194,12 +241,16 @@ Where Source restricts an initial Captain to routing, text2gears shall preserve
|
|
|
194
241
|
only the authored question and delegation outcomes and shall not infer a
|
|
195
242
|
direct-answer or terminal result merely because Captain is the acting agent.
|
|
196
243
|
|
|
197
|
-
A single-outcome behavior whose output no later item consumes
|
|
198
|
-
`Results:` label; downstream,
|
|
244
|
+
A single-outcome behavior whose output no later item consumes and whose
|
|
245
|
+
outcome Source leaves unqualified carries no `Results:` label; downstream,
|
|
199
246
|
[gears2fsm](gears2fsm.md#setup) gives its state the default single-outcome
|
|
200
247
|
contract, so text2gears shall not invent a one-bullet `Results:` block for it.
|
|
201
248
|
When a later item does consume its output, the produced-value rule above
|
|
202
|
-
applies instead
|
|
249
|
+
applies instead; when Source qualifies the one outcome's evidence — what
|
|
250
|
+
affirmatively supports it, what supports no outcome — the behavior carries
|
|
251
|
+
exactly one `Results:` bullet naming that outcome and carrying the
|
|
252
|
+
qualification, with an output property only where a consumer requires one,
|
|
253
|
+
because the adjudicator reads the qualification nowhere else.
|
|
203
254
|
|
|
204
255
|
When Source requires a terminal return to the caller, preserve every returned value or fact and its return condition as an explicit workflow output obligation in GEARS.
|
|
205
256
|
Merely naming a value in a completion predicate or an acting result does not state that the workflow returns it.
|
|
@@ -215,10 +266,16 @@ when the answer changes its complete runtime prompt. It shall not emit a
|
|
|
215
266
|
second item solely for "Boss answers," "after the question," or clearing the
|
|
216
267
|
consumed question/reply. The FSM and linker own the same-leaf suspension,
|
|
217
268
|
continuation blocks, and consumed-context cleanup.
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
269
|
+
Outside the decide-call-observe routing contract, an authored Boss question
|
|
270
|
+
is the framework-owned `needsBossReply` outcome that
|
|
271
|
+
[gears2fsm](gears2fsm.md#boss-reply-suspension) adds to every Captain- or
|
|
272
|
+
player-invoking state: text2gears shall keep the question's conditions in the
|
|
273
|
+
prompt and its continuation in the item's prose and shall declare no result
|
|
274
|
+
for it, because a second guard for the same wait would give the adjudicator
|
|
275
|
+
two equivalent outcomes.
|
|
276
|
+
Only the routing contract's own `question` and `followUpQuestion` results
|
|
277
|
+
declare the question, as `question: <verbatim final text>`; there, the result
|
|
278
|
+
name or prose saying that a question is asked is not the field declaration.
|
|
222
279
|
|
|
223
280
|
This rule is an exception to splitting by accumulated prompt content below.
|
|
224
281
|
Split only when Source requires a genuinely different acting behavior after
|
|
@@ -395,6 +452,9 @@ Markdown escaping is Source syntax, not content: extraction shall resolve escape
|
|
|
395
452
|
|
|
396
453
|
Partition items by every variable that determines prompt content — including accumulated state when the trigger alone doesn't.
|
|
397
454
|
|
|
455
|
+
Conversely, do not split by trigger alone: where two or more triggers lead to one behavior with the same acting clause, prompt, and result contract — a nested call Source says a later path makes "with the same input as" an earlier path's, for instance — text2gears shall emit one item whose condition joins the triggers and shall keep each path's continuation as that item's prose.
|
|
456
|
+
An item per trigger duplicates an identical prompt and multiplies the FSM's states without a content difference.
|
|
457
|
+
|
|
398
458
|
### Prune dead disjuncts
|
|
399
459
|
|
|
400
460
|
Drop disjunctive branches incompatible with the rest of an item's condition or prompt.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AnyStateMachine, EventObject, PromiseActorLogic } from 'xstate';
|
|
2
|
-
import type { CaptainResult, JsonValue, PlaybookEffectBoundary, PlaybookEffectBoundaryStart, PlaybookEffectLedger, PlaybookEffectLedgerCapability, NormalizedError, PlaybookPendingBossQuestion, PlaybookPorts, PlaybookRepositoryReceipt, PlaybookRuntimeFactory, PlaybookSession, PlaybookState, PlayerResult } from './runtime.js';
|
|
2
|
+
import type { CaptainResult, JsonValue, PlaybookEffectBoundary, PlaybookEffectBoundaryStart, PlaybookEffectLedger, PlaybookEffectLedgerCapability, NormalizedError, PlaybookFailureCause, PlaybookPendingBossQuestion, PlaybookPorts, PlaybookRepositoryReceipt, PlaybookRuntimeFactory, PlaybookSession, PlaybookState, PlayerResult } from './runtime.js';
|
|
3
3
|
export interface PlaybookPendingBossQuestionContext {
|
|
4
4
|
questionId: string;
|
|
5
5
|
resumeStateId: string;
|
|
@@ -63,7 +63,7 @@ export interface RuntimeBoundaryCalls {
|
|
|
63
63
|
* with the cause the boundary decided at the call itself, where the role,
|
|
64
64
|
* the resolved player, and the reported error are known.
|
|
65
65
|
*/
|
|
66
|
-
markPlayerResultFailure?(error: Error): Error;
|
|
66
|
+
markPlayerResultFailure?(error: Error, result?: PlayerResult): Error;
|
|
67
67
|
callJudge(purpose: JudgePurpose, stateId: string | undefined, prompt: string, signal: AbortSignal): Promise<string>;
|
|
68
68
|
callCaptain?(input: PlaybookCaptainInput, prompt: string, signal: AbortSignal, callOptions?: XStateCaptainCallOptions): Promise<CaptainResult>;
|
|
69
69
|
}
|
|
@@ -115,6 +115,34 @@ export declare const BOSS_REPLY_ERRORS: {
|
|
|
115
115
|
readonly missingQuestion: "needsBossReply outcome missing 'question' field";
|
|
116
116
|
readonly unregisteredState: (stateId: string) => string;
|
|
117
117
|
};
|
|
118
|
+
export declare const ABORTED_FAILURE_CAUSE: PlaybookFailureCause;
|
|
119
|
+
export declare function runtimeDefectCause(reason: string): PlaybookFailureCause;
|
|
120
|
+
export declare function playerFailureCause(input: {
|
|
121
|
+
readonly roleId: string;
|
|
122
|
+
readonly playerId?: string;
|
|
123
|
+
readonly error: unknown;
|
|
124
|
+
}): PlaybookFailureCause;
|
|
125
|
+
/**
|
|
126
|
+
* DR-063 §1: the cause of an unresolved governed settlement. A reconciled
|
|
127
|
+
* mismatch supplies its own receipt-read cause; the reasons a runtime owns map
|
|
128
|
+
* to adjudication, abort, and runtime-defect codes. Exported so linked
|
|
129
|
+
* machinery of an artifact's own decides the same reasons.
|
|
130
|
+
*/
|
|
131
|
+
export declare function governedSettlementCause(reason: string, error: unknown, aborted: boolean, supplied: PlaybookFailureCause | undefined): PlaybookFailureCause;
|
|
132
|
+
/**
|
|
133
|
+
* DR-063 §2: the causes decided for thrown values that cannot carry the
|
|
134
|
+
* marker — a string, a frozen error — and for the record a machine keeps in
|
|
135
|
+
* place of the thrown value, kept by identity for as long as the failure
|
|
136
|
+
* stands, so every surface that reads the FSM's own `lastError` publishes the
|
|
137
|
+
* cause decided for exactly that failure, whatever turn reads it. A value
|
|
138
|
+
* that carries the marker answers from it; the map is bounded, since only
|
|
139
|
+
* values that lack the marker need an entry.
|
|
140
|
+
*/
|
|
141
|
+
export interface PlaybookFailureCauseRetention {
|
|
142
|
+
retain(error: unknown, cause: PlaybookFailureCause): void;
|
|
143
|
+
causeOf(error: unknown): PlaybookFailureCause | undefined;
|
|
144
|
+
}
|
|
145
|
+
export declare function createFailureCauseRetention(): PlaybookFailureCauseRetention;
|
|
118
146
|
interface XStateRepositoryOperationSettlement<T> {
|
|
119
147
|
readonly status: 'fulfilled';
|
|
120
148
|
readonly value: T;
|
|
@@ -168,6 +196,17 @@ interface XStateRepositoryDeferredRestoreResult {
|
|
|
168
196
|
readonly effectLedger: PlaybookEffectLedger;
|
|
169
197
|
}
|
|
170
198
|
type XStateEffectBoundarySeed = Omit<PlaybookEffectBoundaryStart, 'playbookId' | 'canonicalWorktree' | 'baseline' | 'cohortId'>;
|
|
199
|
+
/** One member's completion inside a repository cohort (DR-067 §1). */
|
|
200
|
+
type XStateRepositoryCohortCompletion<T> = XStateRepositoryExclusiveCompletion<T> & {
|
|
201
|
+
readonly roleId: string;
|
|
202
|
+
};
|
|
203
|
+
interface XStateRepositoryCohortResult<T> {
|
|
204
|
+
readonly baseline: PlaybookRepositoryReceipt['baseline'];
|
|
205
|
+
readonly invocationId: string;
|
|
206
|
+
readonly operations: Readonly<Record<string, XStateRepositoryOperationSettlement<T> | XStateRepositoryOperationRejection>>;
|
|
207
|
+
readonly receipts: Readonly<Record<string, PlaybookRepositoryReceipt>>;
|
|
208
|
+
readonly effectLedger: PlaybookEffectLedger;
|
|
209
|
+
}
|
|
171
210
|
export interface XStateRepositoryCapability {
|
|
172
211
|
runExclusive<T>(options: {
|
|
173
212
|
readonly signal: AbortSignal;
|
|
@@ -195,6 +234,27 @@ export interface XStateRepositoryCapability {
|
|
|
195
234
|
readonly signal: AbortSignal;
|
|
196
235
|
readonly operationId: string;
|
|
197
236
|
}): Promise<XStateRepositoryDeferredParked | XStateRepositoryDeferredRestoreResult>;
|
|
237
|
+
/**
|
|
238
|
+
* DR-067 §1 / PBRT-73: one repository claim over the working leaves of a
|
|
239
|
+
* parallel state entered together — every member an `unchanged` boundary
|
|
240
|
+
* of one cohort, the operations run concurrently under that claim, and
|
|
241
|
+
* one completion callback per member. Required for an artifact that
|
|
242
|
+
* declares a parallel state.
|
|
243
|
+
*/
|
|
244
|
+
runCohort?<T>(options: {
|
|
245
|
+
readonly signal: AbortSignal;
|
|
246
|
+
readonly invocationId: string;
|
|
247
|
+
readonly roleIds: readonly string[];
|
|
248
|
+
readonly dispositionsByRole: Readonly<Record<string, readonly ['unchanged']>>;
|
|
249
|
+
readonly effectBoundaries: Readonly<Record<string, XStateEffectBoundarySeed>>;
|
|
250
|
+
readonly operations: Readonly<Record<string, (context: {
|
|
251
|
+
readonly baseline: PlaybookRepositoryReceipt['baseline'];
|
|
252
|
+
readonly identity: unknown;
|
|
253
|
+
readonly invocationId: string;
|
|
254
|
+
readonly roleId: string;
|
|
255
|
+
}) => Promise<T>>>;
|
|
256
|
+
readonly completeEffectBoundary: (completion: XStateRepositoryCohortCompletion<T>) => XStateRepositoryCompletionEvidence | Promise<XStateRepositoryCompletionEvidence>;
|
|
257
|
+
}): Promise<XStateRepositoryCohortResult<T>>;
|
|
198
258
|
}
|
|
199
259
|
/** The runtime ABI this engine implements (DR-022). */
|
|
200
260
|
export declare const RUNTIME_ABI = 1;
|
|
@@ -389,6 +449,13 @@ export declare function normalizeErrorFull(err: unknown): NormalizedError | unde
|
|
|
389
449
|
export declare function pendingBossQuestionFromContext(context: Record<string, unknown>): PlaybookPendingBossQuestionContext | undefined;
|
|
390
450
|
/** Add clarification context without repeating the question in a live conversation. */
|
|
391
451
|
export declare function composePlayerContinuation(input: Pick<PlaybookPlayerInput, 'pendingBossQuestion' | 'bossReply'>, body: string, resuming?: boolean): string;
|
|
452
|
+
/**
|
|
453
|
+
* The block for one governed call, or `undefined` where the call is not
|
|
454
|
+
* effect-authorized — a call whose declared outcomes carry no
|
|
455
|
+
* `one-descendant-commit` disposition may commit nothing, so it is told
|
|
456
|
+
* nothing.
|
|
457
|
+
*/
|
|
458
|
+
export declare function effectAuthorizedPreExistingBlock(effectBoundary: Pick<PlaybookEffectBoundaryStart, 'dispositions'>, baseline: PlaybookRepositoryReceipt['baseline'] | undefined): string | undefined;
|
|
392
459
|
/**
|
|
393
460
|
* Default player-prompt composer (slc/link.md §Player prompt composition).
|
|
394
461
|
* One callback-based pass substitutes each `<fieldName>` placeholder whose
|
|
@@ -424,8 +491,8 @@ export declare function defaultBuildJudgePrompt(input: PlaybookPlayerInput, fina
|
|
|
424
491
|
* so the judge omits it. Rendering the clause verbatim asked the judge for
|
|
425
492
|
* `question`, `planningResult`, or `evaluatedRevision`, which the reconciler
|
|
426
493
|
* rejects as a structural error, spending the single correction on a
|
|
427
|
-
* self-inflicted defect. Exported so
|
|
428
|
-
*
|
|
494
|
+
* self-inflicted defect. Exported so linked machinery of an artifact's own
|
|
495
|
+
* renders the identical contract instead of restating it.
|
|
429
496
|
*/
|
|
430
497
|
export declare function renderGovernedOutcomeContract(guard: string, description: string, outcome: XStateGovernedOutcomeSpec | undefined): string[];
|
|
431
498
|
export interface PlayerAdjudicationSpec {
|
|
@@ -461,7 +528,11 @@ export declare function defaultBuildCaptainJudgePrompt(input: {
|
|
|
461
528
|
readonly sourceItem: string;
|
|
462
529
|
readonly result: Readonly<Record<string, string>>;
|
|
463
530
|
}, finalText: string): string;
|
|
464
|
-
/**
|
|
531
|
+
/**
|
|
532
|
+
* Targets of the FSM's `awaitBossReply` BOSS_REPLY transitions, plus — for
|
|
533
|
+
* the parallel shape gears2fsm compiles (DR-067) — the targets of each
|
|
534
|
+
* region wait leaf's branch-local BOSS_REPLY arms, resolved to state ids.
|
|
535
|
+
*/
|
|
465
536
|
export declare function resumableStateIdsFromMachine(machine: AnyStateMachine): ReadonlySet<string>;
|
|
466
537
|
/**
|
|
467
538
|
* Source state descriptions by state key, node id, and `meta.playbook`
|
|
@@ -490,10 +561,12 @@ export declare function terminalOutcomesFromMachine(machine: AnyStateMachine, la
|
|
|
490
561
|
* the optional parked-session snapshot capability (DR-014) and the retained-
|
|
491
562
|
* snapshot adoption capability (DR-038).
|
|
492
563
|
*
|
|
493
|
-
* Scope: flat single-region machines —
|
|
494
|
-
*
|
|
495
|
-
* state
|
|
496
|
-
*
|
|
564
|
+
* Scope: flat single-region machines — every root state's
|
|
565
|
+
* `meta.playbook.stateId` equal to its state key, so each snapshot exposes
|
|
566
|
+
* exactly one playbook state id — plus the parallel profile of DR-067: root
|
|
567
|
+
* `type: 'parallel'` states of the shape gears2fsm compiles, whose regions
|
|
568
|
+
* run as one all-`unchanged` repository cohort with keyed pending questions.
|
|
569
|
+
* A machine declaring a parallel state omits `adopt`.
|
|
497
570
|
*/
|
|
498
571
|
export declare function createXStatePlaybookRuntime<TOptions, THostCapabilities extends object>(machine: AnyStateMachine, spec: XStatePlaybookRuntimeSpecV3<TOptions>): XStatePlaybookRuntimeFactory<XStatePlaybookRuntimeConstruction<TOptions, THostCapabilities>, 3>;
|
|
499
572
|
export {};
|