@sublang/playbook 15.1.0 → 17.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/docs/cli.md +36 -18
- package/docs/configuration.md +7 -5
- package/docs/embedding.md +28 -7
- package/package.json +4 -4
- package/reference/sdlc/branch.playbook/branch.fsm.d.ts +63 -33
- package/reference/sdlc/branch.playbook/branch.fsm.js +190 -108
- package/reference/sdlc/branch.playbook/branch.fsm.ts +269 -147
- package/reference/sdlc/branch.playbook/branch.gears.md +7 -17
- package/reference/sdlc/branch.playbook/branch.playbook.d.ts +12 -16
- package/reference/sdlc/branch.playbook/branch.playbook.js +112 -101
- package/reference/sdlc/branch.playbook/branch.playbook.ts +128 -171
- package/reference/sdlc/branch.playbook/branch.registry.d.ts +3 -2
- package/reference/sdlc/branch.playbook/branch.registry.ts +6 -2
- package/reference/sdlc/captain.md +19 -10
- package/reference/sdlc/captain.playbook/captain.fsm.d.ts +6 -2
- package/reference/sdlc/captain.playbook/captain.fsm.js +19 -7
- package/reference/sdlc/captain.playbook/captain.fsm.ts +25 -10
- package/reference/sdlc/captain.playbook/captain.gears.md +16 -8
- package/reference/sdlc/captain.playbook/captain.playbook.d.ts +1 -1
- package/reference/sdlc/captain.playbook/captain.playbook.js +3 -2
- package/reference/sdlc/captain.playbook/captain.playbook.ts +4 -3
- package/reference/sdlc/code.playbook/bin/interactive-session.js +14 -1
- package/reference/sdlc/code.playbook/bin/portable-codec.js +3 -0
- package/reference/sdlc/code.playbook/bin/repository-effects.js +1 -0
- package/reference/sdlc/code.playbook/bin/run.js +128 -85
- package/reference/sdlc/code.playbook/bin/session-host.js +40 -8
- package/reference/sdlc/code.playbook/bin/session-store.js +162 -34
- package/reference/sdlc/code.playbook/code.fsm.d.ts +146 -93
- package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +8 -8
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +13 -13
- package/reference/sdlc/code.playbook/code.fsm.js +609 -649
- package/reference/sdlc/code.playbook/code.fsm.ts +890 -821
- package/reference/sdlc/code.playbook/code.gears.md +39 -29
- package/reference/sdlc/code.playbook/code.playbook.d.ts +13 -16
- package/reference/sdlc/code.playbook/code.playbook.js +166 -147
- package/reference/sdlc/code.playbook/code.playbook.ts +180 -229
- package/reference/sdlc/code.playbook/code.registry.d.ts +3 -2
- package/reference/sdlc/code.playbook/code.registry.ts +6 -2
- package/reference/sdlc/code.playbook/host-capabilities.d.ts +3 -0
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +74 -2
- package/reference/sdlc/code.playbook/playbook-captain.js +1548 -468
- package/reference/sdlc/code.playbook/playbook-captain.ts +1993 -573
- package/reference/sdlc/code.playbook/session-host.d.ts +4 -1
- package/reference/sdlc/code.playbook/session-store.d.ts +17 -0
- package/reference/sdlc/code.playbook/session-store.js +1 -0
- package/reference/sdlc/decide.md +1 -0
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +273 -157
- package/reference/sdlc/decide.playbook/decide.fsm.js +765 -732
- package/reference/sdlc/decide.playbook/decide.fsm.ts +1167 -945
- package/reference/sdlc/decide.playbook/decide.gears.md +28 -21
- package/reference/sdlc/decide.playbook/decide.playbook.d.ts +11 -59
- package/reference/sdlc/decide.playbook/decide.playbook.js +155 -3696
- package/reference/sdlc/decide.playbook/decide.playbook.ts +186 -5244
- package/reference/sdlc/decide.playbook/decide.registry.d.ts +8 -4
- package/reference/sdlc/decide.playbook/decide.registry.js +2 -2
- package/reference/sdlc/decide.playbook/decide.registry.ts +13 -6
- package/reference/sdlc/dev.playbook/dev.fsm.d.ts +116 -134
- package/reference/sdlc/dev.playbook/dev.fsm.js +517 -575
- package/reference/sdlc/dev.playbook/dev.fsm.ts +667 -787
- package/reference/sdlc/dev.playbook/dev.gears.md +52 -54
- package/reference/sdlc/dev.playbook/dev.playbook.d.ts +13 -10
- package/reference/sdlc/dev.playbook/dev.playbook.js +128 -120
- package/reference/sdlc/dev.playbook/dev.playbook.ts +143 -193
- package/reference/sdlc/dev.playbook/dev.registry.d.ts +3 -2
- package/reference/sdlc/dev.playbook/dev.registry.ts +6 -2
- package/reference/sdlc/pr.playbook/pr.fsm.d.ts +95 -88
- package/reference/sdlc/pr.playbook/pr.fsm.js +461 -518
- package/reference/sdlc/pr.playbook/pr.fsm.ts +533 -663
- package/reference/sdlc/pr.playbook/pr.gears.md +47 -63
- package/reference/sdlc/pr.playbook/pr.playbook.d.ts +13 -23
- package/reference/sdlc/pr.playbook/pr.playbook.js +118 -112
- package/reference/sdlc/pr.playbook/pr.playbook.ts +136 -190
- package/reference/sdlc/pr.playbook/pr.registry.d.ts +3 -2
- package/reference/sdlc/pr.playbook/pr.registry.ts +4 -2
- package/reference/sdlc/review.md +3 -3
- package/reference/sdlc/review.playbook/review.fsm.d.ts +150 -116
- package/reference/sdlc/review.playbook/review.fsm.js +479 -550
- package/reference/sdlc/review.playbook/review.fsm.ts +717 -662
- package/reference/sdlc/review.playbook/review.gears.md +32 -29
- package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -12
- package/reference/sdlc/review.playbook/review.playbook.js +180 -155
- package/reference/sdlc/review.playbook/review.playbook.ts +190 -230
- package/reference/sdlc/review.playbook/review.registry.d.ts +6 -5
- package/reference/sdlc/review.playbook/review.registry.js +3 -3
- package/reference/sdlc/review.playbook/review.registry.ts +9 -5
- package/slc/gears2fsm.md +77 -8
- package/slc/link.md +127 -60
- package/slc/materialize-link.mjs +51 -13
- package/slc/optimize.md +4 -1
- package/slc/prefix-prompts.mjs +29 -28
- package/slc/prefix.md +27 -24
- package/slc/slc.pin-inputs.json +11 -2
- package/slc/text2gears.md +71 -11
- package/src/runtime.d.ts +46 -2
- package/src/runtime.ts +42 -2
- package/src/xstate-playbook-runtime.d.ts +63 -23
- package/src/xstate-playbook-runtime.js +1637 -475
- package/src/xstate-playbook-runtime.ts +2105 -532
- package/src/xstate-runtime.d.ts +3 -4
- package/src/xstate-runtime.js +52 -0
- package/src/xstate-runtime.ts +59 -4
package/README.md
CHANGED
|
@@ -83,6 +83,8 @@ playbook run --session 4f2c0000-0000-4000-8000-000000009ab1 "continue"
|
|
|
83
83
|
|
|
84
84
|
`playbook run` prints the one Boss-visible Captain reply to stdout and operational status to stderr; CODE and DECIDE can complete their nested REVIEW calls there too.
|
|
85
85
|
|
|
86
|
+
If a step fails or needs preparation before your answer, ask Captain to fix the prerequisite and resume; see [Preparing a stopped step](docs/cli.md#preparing-a-stopped-step).
|
|
87
|
+
|
|
86
88
|
See [Using the CLI](docs/cli.md) for flags and durable continuation, [Configuring agents](docs/configuration.md) for the shared lineup, [Embedding](docs/embedding.md) for custom hosts, and the [changelog](https://github.com/sublang-ai/playbook/blob/main/CHANGELOG.md) for releases.
|
|
87
89
|
|
|
88
90
|
## Create your own playbook
|
package/docs/cli.md
CHANGED
|
@@ -144,17 +144,16 @@ uses the exact stable player IDs configured under its `roles` map. Equal IDs
|
|
|
144
144
|
share one pane and provider conversation across nested and later root
|
|
145
145
|
engagements; distinct IDs remain isolated even when their agent settings are
|
|
146
146
|
identical. When a player surfaces a
|
|
147
|
-
clarifying question the
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
clarifying question, the playbook pauses and Captain explains the complete question briefly.
|
|
148
|
+
Answer or ask for clarification through Captain; reading a player pane is unnecessary.
|
|
149
|
+
A request to explain preserves the pending question, while an answer or explicit player follow-up reaches the waiting player
|
|
150
150
|
([[playbook-runtime-2](https://github.com/sublang-ai/playbook/blob/main/specs/packages/playbook-runtime.md#playbook-runtime-2)]).
|
|
151
151
|
|
|
152
152
|
The Captain pane shows start/stop/finished status with `◇` lines and
|
|
153
|
-
streams progress
|
|
153
|
+
streams progress; Captain relays pending questions in its reply
|
|
154
154
|
([[playbook-runtime-3](https://github.com/sublang-ai/playbook/blob/main/specs/packages/playbook-runtime.md#playbook-runtime-3)]), while player
|
|
155
155
|
prompts ride their own panes. A turn that actually did something ends
|
|
156
|
-
with one Captain reply summarizing what changed,
|
|
157
|
-
turn's reported outcome; a turn that changed nothing ends with an
|
|
156
|
+
with one Captain reply summarizing what changed, grounded in that turn's reported outcome and current pending questions; a turn that changed nothing ends with an
|
|
158
157
|
ordinary reply and no saved-counts line
|
|
159
158
|
([[playbook-captain-19](https://github.com/sublang-ai/playbook/blob/main/specs/packages/playbook-captain.md#playbook-captain-19)]).
|
|
160
159
|
|
|
@@ -187,8 +186,8 @@ stderr, and `--verbose` adds only telemetry topic names to stderr.
|
|
|
187
186
|
| `--verbose` | add Captain telemetry topic names to stderr |
|
|
188
187
|
| `--continue` | continue the newest Captain session stored for this working directory, or the reported global fallback |
|
|
189
188
|
| `--session <id>` | continue one durable Captain session explicitly |
|
|
190
|
-
| `--retry-uncertain` | with `--session`,
|
|
191
|
-
| `--discard-uncertain` | with `--session`,
|
|
189
|
+
| `--retry-uncertain` | with `--session`, restore and report interrupted work; then choose a continuation |
|
|
190
|
+
| `--discard-uncertain` | with `--session`, discard an attempt only if no work was recorded |
|
|
192
191
|
| `--` | end options before one literal input or reply |
|
|
193
192
|
| `-h`, `--help` | print the complete grammar without reading stdin or config |
|
|
194
193
|
|
|
@@ -196,8 +195,7 @@ Exit `0` means the Captain turn and its durable hand-off were presented,
|
|
|
196
195
|
even when the selected action reported rejection or failure through the
|
|
197
196
|
Captain reply. Argument, config, catalog, readiness, or pre-turn setup errors
|
|
198
197
|
exit `1`; a started-turn, persistence, lease-release, or presentation failure
|
|
199
|
-
exits `2` with stdout empty. SIGINT, SIGTERM, and SIGHUP preserve
|
|
200
|
-
uncertain boundary, withhold stdout, and are re-raised after lease retirement
|
|
198
|
+
exits `2` with stdout empty. SIGINT, SIGTERM, and SIGHUP withhold stdout, preserve uncertainty unless stopped recovery can save its current work, and are re-raised after lease retirement
|
|
201
199
|
([[playbook-cli-18](https://github.com/sublang-ai/playbook/blob/main/specs/packages/playbook-cli.md#playbook-cli-18)]).
|
|
202
200
|
|
|
203
201
|
The former positional `<from>`, `resume`, `--player`, `--captain`,
|
|
@@ -369,27 +367,47 @@ abandonment disposes the complete engagement without claiming an authored
|
|
|
369
367
|
workflow outcome. The same restricted recovery survives process restart
|
|
370
368
|
([DR-040](https://github.com/sublang-ai/playbook/blob/main/specs/decisions/040-outcome-authority-effect-reconciliation.md)).
|
|
371
369
|
|
|
370
|
+
### Preparing a stopped step
|
|
371
|
+
|
|
372
|
+
Captain automatically tries to prepare and resume a step stopped by an operation in the current turn. You can also supply a missing answer or ask for a repair:
|
|
373
|
+
|
|
374
|
+
```sh
|
|
375
|
+
playbook run --session <id> "Install the missing dependency and continue."
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
This also works in the interactive Boss pane. Captain may inspect prerequisites, prepare local tools, put generated files aside, and adjust local ignore settings. It preserves user work and the task's scope. It cannot do the remaining specialist work, change saved session data, invent a result, or skip a step.
|
|
379
|
+
|
|
380
|
+
The runtime checks the continuation. It retries the interrupted step, keeps earlier commits, and uses saved output when only its assessment was interrupted. If a read-only check left unwanted files, retry requires restoring its original files and HEAD; the original failure stays recorded. A waiting player's repository checkpoint must remain intact.
|
|
381
|
+
|
|
382
|
+
Captain asks Boss for a real missing decision, uncertain permission, or a missing or contradictory playbook transition. Repository checks alone cannot prove that publishing or another outside action is safe to repeat; Captain must check that separately.
|
|
383
|
+
|
|
384
|
+
Preparation allows at most two automatic attempts, each following a stop produced by work in this turn. Resuming saved work or refusing new text does not start preparation. Each preparation has a 150-second deadline. When a turn with recorded progress throws and its calls drain safely, the latest stopped step is saved and accepts a new instruction; the interactive pane stays open. Before every player, script or preparation step, the runner saves its position; it saves the result before advancing. After process loss, Retry only restores and reports. Boss chooses what happens next. Custom hosts must provide cancellation before preparation is available.
|
|
385
|
+
|
|
386
|
+
Custom runtimes can provide the same recovery offer: step prompt, optional preparation conditions and evidence, and a continuation they will validate. Captain needs no list of repair tools or error strings. Failed checkpoints without an invocation position have no step retry; restarting the whole playbook could repeat completed work.
|
|
387
|
+
|
|
388
|
+
Captain may answer a player from the original task when it already answers the question. It reports what it reused, respects later Boss instructions and never sends that original answer twice automatically.
|
|
389
|
+
|
|
390
|
+
If a process loses the exact stopping point, retry settles the attempt in chat without repeating player work. Files and recorded evidence remain; unrelated saved workflows remain available. This also works when the attempt began from chat or used a custom runtime.
|
|
391
|
+
|
|
392
|
+
All applications sharing a session store, including Spex and the CLI, must upgrade together before running this version: every step writes the new progress fields, and every saved shell snapshot carries `presentedEffectPrefix`. Hosts through 16.0.x reject those fields as unknown, so they cannot open any session this version saves.
|
|
393
|
+
|
|
372
394
|
### Recovering an uncertain turn
|
|
373
395
|
|
|
374
396
|
Before model work, the runner takes one exclusive session lease and writes an
|
|
375
397
|
uncertain marker. If the process is interrupted after effects may
|
|
376
398
|
have begun but before settlement is durable, ordinary continuation refuses
|
|
377
|
-
to guess.
|
|
399
|
+
to guess. Retry restores the saved position and reports what happened, without running any work. Discard is a separate explicit request:
|
|
378
400
|
|
|
379
401
|
```sh
|
|
380
402
|
playbook run --session 4f2c0000-0000-4000-8000-000000009ab1 --retry-uncertain
|
|
381
403
|
playbook run --session 4f2c0000-0000-4000-8000-000000009ab1 --discard-uncertain
|
|
382
404
|
```
|
|
383
405
|
|
|
384
|
-
Retry reads no input and
|
|
385
|
-
attempted Captain, player, and per-role model, effort, and fast-mode settings;
|
|
386
|
-
current config cannot retune that attempt, and retry may duplicate external
|
|
387
|
-
effects. Discard
|
|
406
|
+
Retry reads no input and restores the recorded attempt only to report it. It runs no model work. Later turns use the current compatible configuration. A completed step can use its saved result without running again. Before repeating an unfinished step, Boss must confirm that the old worker has stopped and check any outside actions; unchanged files do not prove nothing happened. A runtime that cannot save its position returns to Captain with the work preserved. Discard
|
|
388
407
|
reads no input and runs no model: it restores the exact prior settled boundary,
|
|
389
408
|
or deletes a never-settled fresh session, while abandoning the attempted work.
|
|
390
|
-
An interrupted interactive turn uses the same uncertain record and these
|
|
391
|
-
|
|
392
|
-
refuses if the effect ledger has advanced beyond the prior checkpoint.
|
|
409
|
+
An interrupted interactive turn that could not save a normal pause uses the same uncertain record and these headless recovery commands. Discard preserves the attempt's replay history and
|
|
410
|
+
refuses if the effect ledger has advanced beyond the prior checkpoint or any step was recorded. It does not undo files or commits. Captain never selects discard automatically.
|
|
393
411
|
|
|
394
412
|
Stop old writers before upgrading. When using the ordinary `~/.spex/sessions`
|
|
395
413
|
default, the CLI imports sessions from
|
package/docs/configuration.md
CHANGED
|
@@ -215,15 +215,18 @@ before registry import, host creation, or agent work.
|
|
|
215
215
|
|
|
216
216
|
## Choosing the Captain agent
|
|
217
217
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
instead of doing the work itself. Claude and Gemini enforce that at the
|
|
218
|
+
Ordinary Captain decisions, replies, question checks and adjudication are hidden and tool-free.
|
|
219
|
+
Claude and Gemini enforce the tool restriction at the
|
|
221
220
|
provider level. The Codex, Kimi, and OpenCode adapters cannot — they
|
|
222
221
|
reject any tool list — so a `captain:` using one of them falls back to a
|
|
223
222
|
prompt-level restriction
|
|
224
223
|
([DR-013](https://github.com/sublang-ai/playbook/blob/main/specs/decisions/013-routing-only-captain-control.md) A1).
|
|
225
224
|
Those adapters remain good choices for *players*, where full tools are wanted.
|
|
226
225
|
|
|
226
|
+
Recovery preparation is separate: Captain may use its configured tools and permissions to repair prerequisites for the paused step, within the existing task.
|
|
227
|
+
It may not finish the specialist’s task or invent a decision; discarding work or rewriting history requires your explicit instruction.
|
|
228
|
+
Preparation has a 150-second limit.
|
|
229
|
+
|
|
227
230
|
Adapter readiness is intentionally light: `claude` is ready with local
|
|
228
231
|
Claude Code auth or `ANTHROPIC_API_KEY`; `codex` with local Codex CLI
|
|
229
232
|
auth or `OPENAI_API_KEY`. A known adapter that is not ready blocks the
|
|
@@ -271,8 +274,7 @@ compatible ordinary reopen. A selected session keeps its stored catalog,
|
|
|
271
274
|
player roster, role bindings, adapter, instruction, permissions, and working
|
|
272
275
|
directory; only model, effort, and fast mode may change. The next call reapplies
|
|
273
276
|
both complete model and effort selections and the optional effective fast-mode
|
|
274
|
-
boolean. An uncertain retry accepts no tuning overlay and
|
|
275
|
-
attempted settings already stored with that turn.
|
|
277
|
+
boolean. An uncertain retry accepts no tuning overlay and only restores and reports the recorded attempt. Later turns use the current compatible settings.
|
|
276
278
|
|
|
277
279
|
## Session storage
|
|
278
280
|
|
package/docs/embedding.md
CHANGED
|
@@ -38,7 +38,7 @@ tree, which pnpm's strict linking will not allow.
|
|
|
38
38
|
|
|
39
39
|
```ts
|
|
40
40
|
import createPlaybookRuntime, {
|
|
41
|
-
type
|
|
41
|
+
type PlaybookHostCapabilities,
|
|
42
42
|
} from '@sublang/playbook/review/playbook';
|
|
43
43
|
import type {
|
|
44
44
|
CaptainCallOptions,
|
|
@@ -156,7 +156,7 @@ const playbookSessionId = randomUUID();
|
|
|
156
156
|
// machine input, or a persisted snapshot. A host outside the CLI constructs
|
|
157
157
|
// the repository and effect-ledger members through the facade described in
|
|
158
158
|
// "Constructing worktree host capabilities" below.
|
|
159
|
-
declare const hostCapabilities:
|
|
159
|
+
declare const hostCapabilities: PlaybookHostCapabilities;
|
|
160
160
|
|
|
161
161
|
const runtime = createPlaybookRuntime({
|
|
162
162
|
configuredOptions: {},
|
|
@@ -258,7 +258,7 @@ const inert = createPlaybookRuntime({
|
|
|
258
258
|
```
|
|
259
259
|
|
|
260
260
|
`createWorktreeHostCapabilities()` requires only that `cwd` exist and returns
|
|
261
|
-
exactly `repository: { identity, observe, runExclusive, runDeferred }` and
|
|
261
|
+
exactly `repository: { identity, observe, acquire, runExclusive, runDeferred }` and
|
|
262
262
|
`effectLedger: { snapshot, writeAhead }`. The governed worktree is bound at
|
|
263
263
|
every governed call and observation rather than fixed at construction: it is
|
|
264
264
|
the canonical root of the nearest Git worktree containing `cwd`, or — when
|
|
@@ -279,6 +279,7 @@ CLI uses (process-local until the repository exists, since there is no `.git`
|
|
|
279
279
|
to publish it in), observe before and after the operation, apply the engine's
|
|
280
280
|
correction-budget `writeAhead` mid-completion, and bind, park, continue, and
|
|
281
281
|
restore deferred Boss questions with the engine's exact checkpoint semantics.
|
|
282
|
+
`acquire({signal})` holds that same worktree claim for preparation checks; call `assertOwner()` before checking and `release()` in `finally`.
|
|
282
283
|
Overlapping calls on one worktree run one at a time, in no guaranteed order.
|
|
283
284
|
A write the ledger rejects after a boundary has started leaves the worktree
|
|
284
285
|
claim quarantined, exactly as it would under `playbook run`: treat that
|
|
@@ -413,10 +414,30 @@ Automatic discovery belongs only to the ordinary
|
|
|
413
414
|
`~/.spex/sessions` profile with no `SPEX_HOME` or `sessions` override; custom
|
|
414
415
|
profiles require an explicit migration request.
|
|
415
416
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
417
|
+
Captain may answer a player from the original task when it already answers the question. It reports what it reused, respects later Boss instructions and never sends that original answer twice automatically.
|
|
418
|
+
|
|
419
|
+
If a process loses the exact stopping point, retry settles the attempt in chat without repeating player work. Files and recorded evidence remain; unrelated saved workflows remain available. This also works when the attempt began from chat or used a custom runtime.
|
|
420
|
+
|
|
421
|
+
All applications sharing a session store, including Spex and the CLI, must upgrade together before running this version. Every saved shell snapshot carries `presentedEffectPrefix`, which hosts through 16.0.x reject as unknown, so they cannot open any session this version saves.
|
|
422
|
+
|
|
423
|
+
A single recovery entry point handles either a paused step or an uncertain attempt:
|
|
424
|
+
|
|
425
|
+
```ts
|
|
426
|
+
const controller = await openSessionHost({ store: shared, sessionId, mode: 'recover' });
|
|
427
|
+
try {
|
|
428
|
+
const record = await controller.read();
|
|
429
|
+
await controller.recover(record?.state === 'uncertain' ? undefined : bossInstruction);
|
|
430
|
+
} finally { await controller.dispose(); }
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
For uncertainty it restores the saved position and reports the recorded work using the attempted settings. It runs no player, script or preparation. Boss then chooses an available action or supplies input. Completed results are reused; before repeating unfinished work, Boss must stop any old worker and check outside actions. A runtime without a saved position returns to Captain with work preserved. It never chooses discard. For an already settled pause, `recover(bossInstruction)` requires Boss's instruction or answer and passes it through the same Captain turn as CLI input; an ordinary answer does not force preparation. New input cannot replace an uncertain instruction before recovery.
|
|
434
|
+
|
|
435
|
+
If a turn fails and leaves this open controller uncertain, dispose it and reopen with `mode:'recover'` before calling `recover()` without new input.
|
|
436
|
+
|
|
437
|
+
Explicit `mode:'retry'` and `retry()` remain supported. Module-free
|
|
438
|
+
`discardSessionUncertain(shared, sessionId)` restores the prior recovery, or
|
|
439
|
+
deletes a never-settled fresh session and resolves `undefined`,
|
|
440
|
+
only when `isUncertainTurnDiscardable(record)` returns true: no abandonment, no recorded steps, and a ledger equal to the pre-turn snapshot. Use the same exported predicate to enable a Discard control.
|
|
420
441
|
|
|
421
442
|
`readHistory()` returns readable history and a damaged boundary, including a
|
|
422
443
|
clearly marked synthetic projection when a validated legacy journal has no
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sublang/playbook",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "17.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Composable XState v5 playbook runtime with compiled Captain, CODE, REVIEW, DECIDE, DEV, BRANCH, and PR workflows driven by GEARS specs.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -243,15 +243,15 @@
|
|
|
243
243
|
"provenance": true
|
|
244
244
|
},
|
|
245
245
|
"dependencies": {
|
|
246
|
-
"@sublang/cligent": "^0.
|
|
246
|
+
"@sublang/cligent": "^0.27.0",
|
|
247
247
|
"@sublang/spex": "^3.0.0",
|
|
248
248
|
"p-queue": "^9.3.1",
|
|
249
249
|
"xstate": "^5.19.4",
|
|
250
250
|
"yaml": "^2.9.0"
|
|
251
251
|
},
|
|
252
252
|
"devDependencies": {
|
|
253
|
-
"@anthropic-ai/claude-agent-sdk": "^0.3.
|
|
254
|
-
"@openai/codex-sdk": "^0.
|
|
253
|
+
"@anthropic-ai/claude-agent-sdk": "^0.3.283",
|
|
254
|
+
"@openai/codex-sdk": "^0.157.1",
|
|
255
255
|
"@types/node": "^22.0.0",
|
|
256
256
|
"typescript": "^5.8.0",
|
|
257
257
|
"vitest": "^3.0.0"
|
|
@@ -1,34 +1,46 @@
|
|
|
1
1
|
export type BranchStateId = 'createBranch';
|
|
2
2
|
export type BranchSourceItem = 'BRANCH-1';
|
|
3
|
+
/**
|
|
4
|
+
* Stable working-leaf ids that may suspend on a Boss question and be resumed
|
|
5
|
+
* by `BOSS_REPLY`. The machine has at most one active player task, so the
|
|
6
|
+
* scalar Boss-reply form applies.
|
|
7
|
+
*/
|
|
8
|
+
declare const RESUMABLE_STATE_IDS: readonly ["createBranch"];
|
|
9
|
+
export type ResumableStateId = (typeof RESUMABLE_STATE_IDS)[number];
|
|
10
|
+
/** JSON-safe normalization of a rejected invocation, retained for inspection. */
|
|
11
|
+
export type NormalizedError = {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly message: string;
|
|
14
|
+
readonly stack?: string;
|
|
15
|
+
};
|
|
16
|
+
/** Question record raised by the suspended Coder working leaf. */
|
|
3
17
|
export type PendingBossQuestion = {
|
|
4
|
-
readonly questionId:
|
|
5
|
-
readonly resumeStateId:
|
|
6
|
-
readonly sourceItem:
|
|
18
|
+
readonly questionId: ResumableStateId;
|
|
19
|
+
readonly resumeStateId: ResumableStateId;
|
|
20
|
+
readonly sourceItem: BranchSourceItem;
|
|
7
21
|
readonly asker: {
|
|
8
22
|
readonly kind: 'role';
|
|
9
23
|
readonly roleId: 'coder';
|
|
10
24
|
};
|
|
11
25
|
readonly question: string;
|
|
12
26
|
};
|
|
27
|
+
/** Typed input for the delegated `player` actor. */
|
|
13
28
|
export type PlayerInput = {
|
|
14
29
|
readonly stateId: 'createBranch';
|
|
15
30
|
readonly role: 'coder';
|
|
16
31
|
readonly sourceItem: 'BRANCH-1';
|
|
17
32
|
readonly prompt: string;
|
|
18
33
|
readonly result: Readonly<Record<string, string>>;
|
|
34
|
+
/** Backs the prompt's `<caller-input>` placeholder with the exact caller input. */
|
|
19
35
|
readonly callerInput: string;
|
|
20
36
|
readonly pendingBossQuestion?: PendingBossQuestion;
|
|
21
37
|
readonly bossReply?: string;
|
|
22
38
|
};
|
|
39
|
+
/** Discriminated result contract of the delegated `player` actor. */
|
|
23
40
|
export type PlayerOutput = {
|
|
24
41
|
readonly guard: 'branched';
|
|
25
42
|
readonly branch: string;
|
|
26
|
-
/**
|
|
27
|
-
* Receipt-owned effect evidence (DR-045): the branching call's
|
|
28
|
-
* `unchanged` receipt observes the commit the branch was created from
|
|
29
|
-
* as HEAD, so the linked runtime injects it and never takes it from
|
|
30
|
-
* Coder's prose.
|
|
31
|
-
*/
|
|
43
|
+
/** Exact base revision from repository authority, not from Coder's prose. */
|
|
32
44
|
readonly baseRevision: string;
|
|
33
45
|
readonly issueSummary: string;
|
|
34
46
|
} | {
|
|
@@ -38,47 +50,55 @@ export type PlayerOutput = {
|
|
|
38
50
|
readonly guard: 'needsBossReply';
|
|
39
51
|
readonly question: string;
|
|
40
52
|
};
|
|
53
|
+
/**
|
|
54
|
+
* Terminal result: exactly the packaged `branch` workflow's public output
|
|
55
|
+
* interface (workflow-contracts.json), derived from typed context.
|
|
56
|
+
*/
|
|
41
57
|
export type BranchPlaybookOutput = {
|
|
42
58
|
readonly status: 'branched';
|
|
43
|
-
/** Exact
|
|
59
|
+
/** Exact new branch name. */
|
|
44
60
|
readonly branch: string;
|
|
45
|
-
/** Exact receipt-observed revision the branch was created from. */
|
|
61
|
+
/** Exact receipt-observed repository revision the branch was created from. */
|
|
46
62
|
readonly baseRevision: string;
|
|
47
|
-
/**
|
|
63
|
+
/** Concise issue-and-comments or request summary. */
|
|
48
64
|
readonly issueSummary: string;
|
|
49
65
|
} | {
|
|
50
66
|
readonly status: 'refused';
|
|
51
|
-
/**
|
|
67
|
+
/** Complete refusal report. */
|
|
52
68
|
readonly coderOutput: string;
|
|
53
69
|
};
|
|
54
|
-
|
|
70
|
+
/** The machine reads no input: the caller input arrives on `START_BRANCH`. */
|
|
71
|
+
export type BranchInput = Readonly<Record<never, never>>;
|
|
72
|
+
export type BranchCompletion = 'branched' | 'refused';
|
|
55
73
|
export type BranchContext = {
|
|
56
74
|
readonly callerInput?: string;
|
|
57
75
|
readonly branch?: string;
|
|
58
|
-
/** Observed HEAD of the branching call's unchanged receipt (DR-045). */
|
|
59
76
|
readonly baseRevision?: string;
|
|
60
77
|
readonly issueSummary?: string;
|
|
61
78
|
readonly coderOutput?: string;
|
|
62
|
-
readonly completion?:
|
|
63
|
-
readonly lastError?:
|
|
79
|
+
readonly completion?: BranchCompletion;
|
|
80
|
+
readonly lastError?: NormalizedError;
|
|
64
81
|
readonly pendingBossQuestion?: PendingBossQuestion;
|
|
65
82
|
readonly bossReply?: string;
|
|
66
83
|
};
|
|
84
|
+
/** Typed Boss surfaces: the caller's entry event and the Boss reply. */
|
|
67
85
|
export type BranchEvent = {
|
|
68
86
|
readonly type: 'START_BRANCH';
|
|
69
87
|
readonly callerInput: string;
|
|
70
88
|
} | {
|
|
71
89
|
readonly type: 'BOSS_REPLY';
|
|
72
90
|
readonly answer: string;
|
|
73
|
-
readonly questionId?:
|
|
91
|
+
readonly questionId?: ResumableStateId;
|
|
74
92
|
};
|
|
93
|
+
/** No parallel group in this playbook. */
|
|
94
|
+
export declare const concurrentRoleSets: readonly (readonly string[])[];
|
|
75
95
|
export declare const branchMachine: import("xstate").StateMachine<BranchContext, {
|
|
76
96
|
readonly type: "START_BRANCH";
|
|
77
97
|
readonly callerInput: string;
|
|
78
98
|
} | {
|
|
79
99
|
readonly type: "BOSS_REPLY";
|
|
80
100
|
readonly answer: string;
|
|
81
|
-
readonly questionId?:
|
|
101
|
+
readonly questionId?: ResumableStateId;
|
|
82
102
|
}, {
|
|
83
103
|
[x: string]: import("xstate").ActorRefFromLogic<import("xstate").PromiseActorLogic<PlayerOutput, PlayerInput, import("xstate").EventObject>> | undefined;
|
|
84
104
|
}, {
|
|
@@ -96,16 +116,22 @@ export declare const branchMachine: import("xstate").StateMachine<BranchContext,
|
|
|
96
116
|
type: "rememberActorError";
|
|
97
117
|
params: import("xstate").NonReducibleUnknown;
|
|
98
118
|
} | {
|
|
99
|
-
type: "
|
|
119
|
+
type: "rememberMalformedPlayerOutput";
|
|
100
120
|
params: import("xstate").NonReducibleUnknown;
|
|
101
121
|
} | {
|
|
102
|
-
type: "
|
|
122
|
+
type: "clearBossReplyContext";
|
|
103
123
|
params: import("xstate").NonReducibleUnknown;
|
|
104
124
|
} | {
|
|
105
|
-
type: "
|
|
125
|
+
type: "setPendingBossQuestion";
|
|
126
|
+
params: {
|
|
127
|
+
readonly stateId: ResumableStateId;
|
|
128
|
+
readonly sourceItem: BranchSourceItem;
|
|
129
|
+
};
|
|
130
|
+
} | {
|
|
131
|
+
type: "rememberMalformedBossReply";
|
|
106
132
|
params: import("xstate").NonReducibleUnknown;
|
|
107
133
|
} | {
|
|
108
|
-
type: "
|
|
134
|
+
type: "acceptBossReply";
|
|
109
135
|
params: import("xstate").NonReducibleUnknown;
|
|
110
136
|
} | {
|
|
111
137
|
type: "startBranch";
|
|
@@ -118,9 +144,16 @@ export declare const branchMachine: import("xstate").StateMachine<BranchContext,
|
|
|
118
144
|
params: import("xstate").NonReducibleUnknown;
|
|
119
145
|
}, {
|
|
120
146
|
type: "needsBossReply";
|
|
121
|
-
params:
|
|
147
|
+
params: {
|
|
148
|
+
readonly stateId: ResumableStateId;
|
|
149
|
+
};
|
|
122
150
|
} | {
|
|
123
|
-
type: "
|
|
151
|
+
type: "canResume";
|
|
152
|
+
params: {
|
|
153
|
+
readonly stateId: ResumableStateId;
|
|
154
|
+
};
|
|
155
|
+
} | {
|
|
156
|
+
type: "givesRequest";
|
|
124
157
|
params: unknown;
|
|
125
158
|
} | {
|
|
126
159
|
type: "isBranched";
|
|
@@ -128,20 +161,17 @@ export declare const branchMachine: import("xstate").StateMachine<BranchContext,
|
|
|
128
161
|
} | {
|
|
129
162
|
type: "isRefused";
|
|
130
163
|
params: unknown;
|
|
131
|
-
} | {
|
|
132
|
-
type: "resumesCreateBranch";
|
|
133
|
-
params: unknown;
|
|
134
|
-
}, never, "failed" | "ready" | "awaitBossReply" | "refused" | "createBranch" | "branched", string, Readonly<Record<string, never>>, {
|
|
164
|
+
}, never, "failed" | "ready" | "awaitBossReply" | "refused" | "createBranch" | "branched", string, Readonly<Record<never, never>>, {
|
|
135
165
|
readonly status: "branched";
|
|
136
|
-
/** Exact
|
|
166
|
+
/** Exact new branch name. */
|
|
137
167
|
readonly branch: string;
|
|
138
|
-
/** Exact receipt-observed revision the branch was created from. */
|
|
168
|
+
/** Exact receipt-observed repository revision the branch was created from. */
|
|
139
169
|
readonly baseRevision: string;
|
|
140
|
-
/**
|
|
170
|
+
/** Concise issue-and-comments or request summary. */
|
|
141
171
|
readonly issueSummary: string;
|
|
142
172
|
} | {
|
|
143
173
|
readonly status: "refused";
|
|
144
|
-
/**
|
|
174
|
+
/** Complete refusal report. */
|
|
145
175
|
readonly coderOutput: string;
|
|
146
176
|
}, import("xstate").EventObject, import("xstate").MetaObject, {
|
|
147
177
|
id: "branch";
|