@sublang/playbook 5.0.0 → 7.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 +22 -14
- package/docs/cli.md +138 -90
- package/docs/configuration.md +113 -29
- package/docs/embedding.md +24 -16
- package/package.json +42 -21
- package/reference/sdlc/captain.playbook/captain.playbook.js +2 -0
- package/reference/sdlc/captain.playbook/captain.playbook.ts +2 -0
- package/reference/sdlc/code.md +55 -97
- package/reference/sdlc/code.playbook/bin/launch-config.js +938 -0
- package/reference/sdlc/code.playbook/bin/playbook.js +145 -562
- package/reference/sdlc/code.playbook/bin/provision.js +84 -38
- package/reference/sdlc/code.playbook/bin/run.js +1171 -983
- package/reference/sdlc/code.playbook/bin/session-store.js +1169 -0
- package/reference/sdlc/code.playbook/code.fsm.d.ts +229 -94
- package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +26 -44
- package/reference/sdlc/code.playbook/code.fsm.introspect.js +61 -66
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +100 -149
- package/reference/sdlc/code.playbook/code.fsm.js +587 -1347
- package/reference/sdlc/code.playbook/code.fsm.ts +809 -1650
- package/reference/sdlc/code.playbook/code.gears.md +51 -263
- package/reference/sdlc/code.playbook/code.playbook.d.ts +8 -47
- package/reference/sdlc/code.playbook/code.playbook.js +69 -656
- package/reference/sdlc/code.playbook/code.playbook.ts +90 -867
- package/reference/sdlc/code.playbook/code.registry.d.ts +9 -25
- package/reference/sdlc/code.playbook/code.registry.js +20 -78
- package/reference/sdlc/code.playbook/code.registry.ts +58 -122
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +70 -3
- package/reference/sdlc/code.playbook/playbook-captain.js +954 -80
- package/reference/sdlc/code.playbook/playbook-captain.ts +1408 -80
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +37 -36
- package/reference/sdlc/decide.md +54 -0
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +261 -0
- package/reference/sdlc/decide.playbook/decide.fsm.js +894 -0
- package/reference/sdlc/decide.playbook/decide.fsm.ts +1152 -0
- package/reference/sdlc/decide.playbook/decide.gears.md +88 -0
- package/reference/sdlc/decide.playbook/decide.playbook.d.ts +67 -0
- package/reference/sdlc/{discuss.playbook/discuss.playbook.js → decide.playbook/decide.playbook.js} +545 -372
- package/reference/sdlc/{discuss.playbook/discuss.playbook.ts → decide.playbook/decide.playbook.ts} +665 -454
- package/reference/sdlc/decide.playbook/decide.registry.d.ts +41 -0
- package/reference/sdlc/decide.playbook/decide.registry.js +60 -0
- package/reference/sdlc/decide.playbook/decide.registry.ts +125 -0
- package/reference/sdlc/review.md +81 -0
- package/reference/sdlc/review.playbook/review.fsm.d.ts +183 -0
- package/reference/sdlc/review.playbook/review.fsm.js +524 -0
- package/reference/sdlc/review.playbook/review.fsm.ts +652 -0
- package/reference/sdlc/review.playbook/review.gears.md +112 -0
- package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -0
- package/reference/sdlc/review.playbook/review.playbook.js +112 -0
- package/reference/sdlc/review.playbook/review.playbook.ts +201 -0
- package/reference/sdlc/review.playbook/review.registry.d.ts +43 -0
- package/reference/sdlc/review.playbook/review.registry.js +73 -0
- package/reference/sdlc/review.playbook/review.registry.ts +138 -0
- package/slc/gears2fsm.md +13 -4
- package/slc/link.md +83 -14
- package/slc/text2gears.md +22 -2
- package/src/runtime.d.ts +21 -2
- package/src/runtime.ts +38 -6
- package/src/xstate-playbook-runtime.d.ts +9 -2
- package/src/xstate-playbook-runtime.js +319 -35
- package/src/xstate-playbook-runtime.ts +412 -41
- package/src/xstate-runtime.d.ts +19 -2
- package/src/xstate-runtime.js +384 -57
- package/src/xstate-runtime.ts +542 -71
- package/reference/sdlc/discuss.md +0 -93
- package/reference/sdlc/discuss.playbook/discuss.fsm.d.ts +0 -396
- package/reference/sdlc/discuss.playbook/discuss.fsm.js +0 -2067
- package/reference/sdlc/discuss.playbook/discuss.fsm.ts +0 -2465
- package/reference/sdlc/discuss.playbook/discuss.gears.md +0 -258
- package/reference/sdlc/discuss.playbook/discuss.playbook.d.ts +0 -113
- package/reference/sdlc/discuss.playbook/discuss.registry.d.ts +0 -58
- package/reference/sdlc/discuss.playbook/discuss.registry.js +0 -97
- package/reference/sdlc/discuss.playbook/discuss.registry.ts +0 -153
package/slc/gears2fsm.md
CHANGED
|
@@ -167,6 +167,7 @@ The default never applies to an item carrying a `Results:` label, and it does
|
|
|
167
167
|
not license inferring any richer contract from prose.
|
|
168
168
|
The item's blockquote alone becomes `invoke.input.prompt`; the `Results:`
|
|
169
169
|
label and bullets shall never enter that prompt.
|
|
170
|
+
A `>` that remains at the start of a prompt line after removing the outer GEARS blockquote marker is literal quoted-context content and shall remain in `invoke.input.prompt` unchanged.
|
|
170
171
|
Each result description shall name every additional output field its accepting
|
|
171
172
|
guard requires, using the exact case-sensitive property names. For example, a
|
|
172
173
|
delegation or continuing-call description whose guard reads the planned child
|
|
@@ -243,13 +244,15 @@ Each state shall declare:
|
|
|
243
244
|
- a stable `id` (for `#id` targeting and Boss interrupts);
|
|
244
245
|
- an intuitive state key (the property name under `states: { ... }`);
|
|
245
246
|
- a one-line `description` (for inspector tools and documentation);
|
|
246
|
-
- JSON-safe `meta: { playbook: { stateId, description } }` repeating
|
|
247
|
-
stable id and description so linked runtimes can discover active public
|
|
248
|
-
identities through `snapshot.getMeta()` without private XState nodes
|
|
247
|
+
- JSON-safe `meta: { playbook: { stateId, description, player? } }` repeating
|
|
248
|
+
its stable id and description so linked runtimes can discover active public
|
|
249
|
+
identities through `snapshot.getMeta()` without private XState nodes. A
|
|
250
|
+
delegated-player state shall also carry the exact source player in
|
|
251
|
+
`meta.playbook.player`; every other state shall omit `player`;
|
|
249
252
|
- if it invokes the direct `captain` actor: `invoke.input` carrying
|
|
250
253
|
`sourceItem`, `prompt`, and `result` (per [Setup](#setup));
|
|
251
254
|
- if it invokes the delegated `player` actor: `invoke.input` additionally
|
|
252
|
-
carrying `player`;
|
|
255
|
+
carrying the same source-derived `player` as `meta.playbook.player`;
|
|
253
256
|
- if it invokes the `script` actor: `invoke.input` carrying `stateId`,
|
|
254
257
|
`sourceItem`, `command`, and `result` (per [Setup](#setup)) — no `prompt`
|
|
255
258
|
and no `player`.
|
|
@@ -598,6 +601,11 @@ context precondition required to enter that target safely. It shall not jump
|
|
|
598
601
|
into a working or reassessment state with missing intent, prior result, plan,
|
|
599
602
|
or other required context and shall not invent defaults merely to make an
|
|
600
603
|
interrupt target executable.
|
|
604
|
+
Control-action discovery probes these guards with optional textual fields
|
|
605
|
+
omitted. Before applying a string operation such as `trim()`, a generated
|
|
606
|
+
guard shall narrow the field to a string; a missing required textual field
|
|
607
|
+
shall make the guard return false, never throw, so the control view remains
|
|
608
|
+
total and omits an action whose payload the runtime cannot source.
|
|
601
609
|
XState automatically stops the current state's invoked actor on transition [[2]].
|
|
602
610
|
Where the default Captain's routing state accepts a fresh intent while another
|
|
603
611
|
state or Boss-reply wait is active, its `BOSS_INTERRUPT` event shall carry a
|
|
@@ -642,6 +650,7 @@ decision state would add a seventh outcome to a closed six-action contract
|
|
|
642
650
|
whose guard discriminants [Setup](#setup) fixes, and is nonconformant.
|
|
643
651
|
There is no source-level opt-in annotation and no `needsBossReply` result metadata in GEARS output.
|
|
644
652
|
The FSM compiler shall preserve the GEARS blockquote as the state's domain `prompt` body and shall not inject any Boss-question instruction into `invoke.input.prompt`.
|
|
653
|
+
This preservation includes every literal leading `>` carried inside the outer GEARS blockquote for quoted runtime context.
|
|
645
654
|
|
|
646
655
|
For every captain- and player-invoking state outside a controller machine,
|
|
647
656
|
the compiler shall add
|
package/slc/link.md
CHANGED
|
@@ -59,9 +59,17 @@ interface PlaybookSession {
|
|
|
59
59
|
parentSessionId?: string;
|
|
60
60
|
parentCallId?: string;
|
|
61
61
|
depth: number;
|
|
62
|
+
playerSessions?: PlayerSessionStore;
|
|
62
63
|
ports: PlaybookPorts;
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
interface PlayerSessionStore {
|
|
67
|
+
select(playerId: string): string | false;
|
|
68
|
+
update(playerId: string, resumeToken?: string): void;
|
|
69
|
+
snapshot(): Readonly<Record<string, string>>;
|
|
70
|
+
restore(tokens: Readonly<Record<string, string>>): void;
|
|
71
|
+
}
|
|
72
|
+
|
|
65
73
|
type JsonValue =
|
|
66
74
|
| null
|
|
67
75
|
| boolean
|
|
@@ -379,6 +387,11 @@ interface PlaybookTraceEvent {
|
|
|
379
387
|
}
|
|
380
388
|
```
|
|
381
389
|
|
|
390
|
+
A composing host may supply `playerSessions` as a frame-local view of player continuation owned by the root engagement tree.
|
|
391
|
+
The runtime shall select through that view before allocating or tracing a player call and shall update or clear it from a validated player result before emitting the matching finish trace.
|
|
392
|
+
Snapshot export and restore shall use the same view, failed restore shall leave its prior contents unchanged, and child disposal shall not clear host-owned continuation.
|
|
393
|
+
A host that omits the view retains the runtime's private per-session continuation behavior.
|
|
394
|
+
|
|
382
395
|
The trace types are `session.started`, `boss.input.received`,
|
|
383
396
|
`judge.call.started`, `judge.call.finished`, `player.call.started`,
|
|
384
397
|
`player.call.finished`, `captain.call.started`, `captain.call.finished`,
|
|
@@ -531,6 +544,7 @@ decides only the `callPlayer` invocation.
|
|
|
531
544
|
The runtime shall compose the actual player prompt from the state's
|
|
532
545
|
`PlayerInput`.
|
|
533
546
|
`input.prompt` is the GEARS-derived domain prompt body and shall not be mutated, re-flowed, or treated as a place to store framework control instructions.
|
|
547
|
+
A leading `>` inside that body is authored quoted-context content and shall reach the player unchanged.
|
|
534
548
|
|
|
535
549
|
The composer may prepend structured labelled blocks from typed `PlayerInput`
|
|
536
550
|
fields the FSM exposes (for example `Boss intent:`, `Review items:`,
|
|
@@ -731,6 +745,9 @@ clause (or equivalent typed output metadata). Backticked prose before that
|
|
|
731
745
|
clause can name statuses, guards, or concepts such as `ok`, `aborted`, and
|
|
732
746
|
`error`; those names are not output properties and shall never become required
|
|
733
747
|
judge fields.
|
|
748
|
+
For a delegated-player field annotated exactly `` `<field>: <verbatim final text>` ``, the judge shall select the guard but the runtime shall replace any judge-supplied value with the player's canonical non-empty final text before returning the actor output.
|
|
749
|
+
The linker shall derive the complete `verbatimPayloadFields` set from those annotations across the FSM result maps.
|
|
750
|
+
A field name that is annotated in one result map and unannotated in another is a link error because the shared adjudication strategy cannot give one property both ownership policies.
|
|
734
751
|
For a direct Captain result, `question` and `response` are human-presentation
|
|
735
752
|
fields owned by the visible call rather than fields authored by the hidden
|
|
736
753
|
judge.
|
|
@@ -784,8 +801,8 @@ structured adjudication merely to present the same response.
|
|
|
784
801
|
That visible-call presentation — visible Captain prose as the Boss
|
|
785
802
|
presentation, a separate hidden adjudicator that never authors the
|
|
786
803
|
`question`/`response` fields, and runtime injection of the visible
|
|
787
|
-
`finalText` — stays scoped to
|
|
788
|
-
|
|
804
|
+
`finalText` — stays scoped to a working playbook whose FSM declares a visible
|
|
805
|
+
direct-Captain state. For a controller playbook, whose FSM declares the controller
|
|
789
806
|
decision-state class of [gears2fsm "Setup"](gears2fsm.md#setup), the
|
|
790
807
|
Captain-call presentation admits the hidden controller form instead
|
|
791
808
|
(DR-029): the decision and closing-reply Captain calls run
|
|
@@ -1174,6 +1191,23 @@ The `PlaybookRuntime` shall:
|
|
|
1174
1191
|
failure cannot skip the parent disposal boundary or leave the runtime bound.
|
|
1175
1192
|
|
|
1176
1193
|
The actor's `lastError` field shall be surfaced via `emitStatus` when the machine enters its `failed` state.
|
|
1194
|
+
Presence of linker-emitted `playerStates` selects the canonical
|
|
1195
|
+
factory-backed status profile. That profile shall emit the selected Boss event type
|
|
1196
|
+
before sending that event, exactly `→ <guard>` (with no payload-count or tally
|
|
1197
|
+
rider) when a settling actor output carries a guard, and
|
|
1198
|
+
`⤷ <Player>: <label>` only when the entered state appears in the
|
|
1199
|
+
linked module's `playerStates` metadata. It shall emit no raw state-id fallback
|
|
1200
|
+
for any other state. `playerStates` shall be a complete map of the FSM states
|
|
1201
|
+
that invoke the typed `player` actor; each value carries the exact player from
|
|
1202
|
+
that state's source-derived `meta.playbook.player` and the state's exact FSM
|
|
1203
|
+
description as `{ player, label }`. The factory shall reject an incomplete
|
|
1204
|
+
entry, a non-player state, or a player or label that differs from the FSM
|
|
1205
|
+
metadata. A schema-1 legacy module that predates this metadata
|
|
1206
|
+
shall preserve the prior factory status defaults, including no classification
|
|
1207
|
+
line, `Entered <stateId>.` for ordinary state entry, the single question line,
|
|
1208
|
+
and the unglyphed failure line. The new profile is opt-in so adding the seam
|
|
1209
|
+
does not silently reinterpret an already-linked artifact without an ABI or
|
|
1210
|
+
artifact-schema bump.
|
|
1177
1211
|
For the default Captain runtime, an initial `ready` state and a terminal `done`
|
|
1178
1212
|
state shall not emit human status. The terminal response is already visible
|
|
1179
1213
|
Captain prose; a synthetic “entered done” message would present it twice.
|
|
@@ -1206,12 +1240,12 @@ durability, the pair shall behave as follows.
|
|
|
1206
1240
|
|
|
1207
1241
|
`exportSnapshot()` shall return `undefined` unless the runtime is at a safe
|
|
1208
1242
|
capture point: initialized, not disposing or disposed, no active
|
|
1209
|
-
`handleBossInput`/`resumePlaybookCall` boundary,
|
|
1210
|
-
|
|
1243
|
+
`handleBossInput`/`resumePlaybookCall` boundary, and the root actor at a
|
|
1244
|
+
quiescent state with actor status `active`.
|
|
1211
1245
|
At a safe capture point it shall return a JSON-safe
|
|
1212
1246
|
`PlaybookRuntimeSnapshot` carrying:
|
|
1213
1247
|
|
|
1214
|
-
- `schemaVersion`: literal `
|
|
1248
|
+
- `schemaVersion`: literal `2`.
|
|
1215
1249
|
- `playbookId`: the bound session's playbook id.
|
|
1216
1250
|
- `machine`: the root actor's `getPersistedSnapshot()` result, passed
|
|
1217
1251
|
through the shared JSON detachment with any raw `Error` context value
|
|
@@ -1221,19 +1255,33 @@ At a safe capture point it shall return a JSON-safe
|
|
|
1221
1255
|
(§PlaybookPorts contract).
|
|
1222
1256
|
- `sequences`: the live `trace`, `turn`, `judgeCall`, `playerCall`, and
|
|
1223
1257
|
`playbookCall` counters, plus `captainCall` when the runtime supports direct
|
|
1224
|
-
Captain calls.
|
|
1225
|
-
|
|
1258
|
+
Captain calls. A direct-Captain-capable runtime shall persist it in current
|
|
1259
|
+
schema-version-2 exports; it remains optional in legacy schema-version-1
|
|
1260
|
+
input, where restore uses `trace` as its collision-safe floor.
|
|
1226
1261
|
- `state`: the current normalized state descriptor.
|
|
1227
1262
|
- `pendingBossQuestions`: the pending Boss question(s) from FSM context as
|
|
1228
1263
|
a list of `{ questionId, player, question, sourceItem? }`, empty when the
|
|
1229
1264
|
parked state awaits no reply. This list exists so hosts can surface the
|
|
1230
1265
|
question without parsing status lines or telemetry.
|
|
1266
|
+
- `suspendedCall`: omitted when no nested call is pending; otherwise the
|
|
1267
|
+
shared nested bridge's complete `callId`, source `stateId`, target
|
|
1268
|
+
`playbookId`, exact handed-off `text`, and `childSessionId`, enriched with
|
|
1269
|
+
the call-to-turn map's optional `turnId`.
|
|
1270
|
+
|
|
1271
|
+
A pending nested call is exportable only when the bridge's pending identity
|
|
1272
|
+
and complete descriptor agree and the call-to-turn map owns that exact call
|
|
1273
|
+
id, including ownership whose value is absent. A bridge descriptor that
|
|
1274
|
+
already carries a turn id shall equal that map value. Any missing or
|
|
1275
|
+
inconsistent bridge, descriptor, or turn-ownership record makes the capture
|
|
1276
|
+
unsafe and returns `undefined`.
|
|
1231
1277
|
|
|
1232
1278
|
`restore(session, snapshot)` is an alternative to `init` under the same
|
|
1233
1279
|
lifecycle guards (§Session lifecycle): it shall reject when already
|
|
1234
1280
|
initialized, disposing, or disposed, and shall validate
|
|
1235
|
-
`
|
|
1236
|
-
`session.playbookId` before touching state.
|
|
1281
|
+
schema version `1` or `2` and that `snapshot.playbookId` equals
|
|
1282
|
+
`session.playbookId` before touching state. Schema version `1` remains a
|
|
1283
|
+
descriptor-free legacy input; schema version `2` may carry the suspended-call
|
|
1284
|
+
descriptor above.
|
|
1237
1285
|
The host supplies the same immutable `PlaybookSession` identity the
|
|
1238
1286
|
snapshot was exported under and recreates the runtime through the same
|
|
1239
1287
|
factory with equivalent options; the runtime does not diff options, and
|
|
@@ -1244,13 +1292,22 @@ make before calling `restore`.
|
|
|
1244
1292
|
sequence counters (using the persisted global `trace` counter as a
|
|
1245
1293
|
collision-safe floor for an absent legacy `captainCall`), and the
|
|
1246
1294
|
prior-state descriptor from the snapshot,
|
|
1247
|
-
|
|
1295
|
+
prepare the shared nested bridge with the suspended-call descriptor or its
|
|
1296
|
+
explicit absence, restore a descriptor's call-to-turn map entry, construct
|
|
1297
|
+
the actor with the persisted `machine` snapshot, and start it
|
|
1248
1298
|
with root inspection emissions suppressed so rehydration emits no
|
|
1249
1299
|
`session.started` trace, no transition trace, and no human status — the
|
|
1250
1300
|
session already started, and the next public boundary continues the
|
|
1251
|
-
contiguous trace sequence. After start,
|
|
1252
|
-
|
|
1253
|
-
|
|
1301
|
+
contiguous trace sequence. After start, the runtime shall normalize the
|
|
1302
|
+
actual actor state with the prepared suspended call as its pending identity
|
|
1303
|
+
and require it to equal the detached persisted state exactly, including
|
|
1304
|
+
active status. It shall drain suppressed startup work and invoke the bridge's
|
|
1305
|
+
`confirmRestore` as the final fallible restore step, publishing the pending
|
|
1306
|
+
identity only after every other validation succeeds. A missing, extra, or
|
|
1307
|
+
mismatched reconstructed invocation, an actual/persisted state mismatch, or
|
|
1308
|
+
any other failed validation shall fail `restore` through the same
|
|
1309
|
+
failed-start cleanup path as `init`, rolling back provisional bridge and turn
|
|
1310
|
+
ownership without a child-host call or duplicate start/finish boundary.
|
|
1254
1311
|
A restore failure shall leave the runtime unbound so `dispose` remains
|
|
1255
1312
|
callable and terminal.
|
|
1256
1313
|
|
|
@@ -1406,7 +1463,7 @@ runtime's emission-failure channel to surface from the next public boundary
|
|
|
1406
1463
|
that drains.
|
|
1407
1464
|
|
|
1408
1465
|
The recorded receipts and the recorded last classified event are
|
|
1409
|
-
process-local: the
|
|
1466
|
+
process-local: the durable runtime snapshot persists neither, and a
|
|
1410
1467
|
restored runtime advertises a retry again only after its next classified
|
|
1411
1468
|
event.
|
|
1412
1469
|
|
|
@@ -1544,6 +1601,11 @@ The thin emitted module:
|
|
|
1544
1601
|
and the canonical `<#>` → `irNumber` special case; the
|
|
1545
1602
|
transition-event payload fields the FSM's Boss union declares; a
|
|
1546
1603
|
non-default player binding where the linker inputs supplied one; the
|
|
1604
|
+
complete `playerStates` status map derived from every FSM state that invokes
|
|
1605
|
+
the typed `player` actor, with each `player` copied from that state's
|
|
1606
|
+
source-derived `meta.playbook.player` (an empty map when there is no such
|
|
1607
|
+
state); the
|
|
1608
|
+
`verbatimPayloadFields` set derived from annotated result fields above; the
|
|
1547
1609
|
`controlContextFields` projection of §Control surface; and any
|
|
1548
1610
|
per-playbook strategy override (classifier, prompt composers,
|
|
1549
1611
|
required-field extraction, status formatting) an earlier section of this
|
|
@@ -1579,7 +1641,13 @@ The thin emitted module:
|
|
|
1579
1641
|
fields?: Readonly<Record<string, XStateBossEventFieldSpec>>;
|
|
1580
1642
|
}
|
|
1581
1643
|
|
|
1644
|
+
interface XStatePlayerStateStatus {
|
|
1645
|
+
player: string;
|
|
1646
|
+
label: string;
|
|
1647
|
+
}
|
|
1648
|
+
|
|
1582
1649
|
bossEvents?: readonly XStateBossEventSpec[];
|
|
1650
|
+
playerStates?: Readonly<Record<string, XStatePlayerStateStatus>>;
|
|
1583
1651
|
placeholderFields?: Readonly<Record<string, string>>;
|
|
1584
1652
|
```
|
|
1585
1653
|
|
|
@@ -1629,6 +1697,7 @@ The thin emitted module:
|
|
|
1629
1697
|
top-of-file header comment so the file is reproducible from the same
|
|
1630
1698
|
inputs.
|
|
1631
1699
|
- Sources the contract types (`PlayerResult`, `PlayerCallOptions`,
|
|
1700
|
+
`PlayerSessionStore`,
|
|
1632
1701
|
`CaptainResult`, `CaptainCallOptions`, `PlaybookPorts`, `PlaybookSession`,
|
|
1633
1702
|
`PlaybookTraceEvent`,
|
|
1634
1703
|
`PlaybookCallRequest`, `PlaybookCallResult`, `PlaybookCallStart`,
|
package/slc/text2gears.md
CHANGED
|
@@ -65,6 +65,20 @@ Those requirements remain in the item's condition or `Results:` metadata.
|
|
|
65
65
|
Adding control-oriented prompt lines merely to restate them changes the
|
|
66
66
|
Boss-visible contract and is nonconformant.
|
|
67
67
|
|
|
68
|
+
### Authored prompt fragments
|
|
69
|
+
|
|
70
|
+
Source may compose one acting prompt from authored Markdown instruction blocks and runtime context that it explicitly says to relay in quotes (`>`).
|
|
71
|
+
A fenced `markdown` block introduced as an instruction or prompt is an authored static prompt fragment: its fence delimiters are Source syntax, while every interior line and blank line is prompt content preserved after documented Markdown unescaping.
|
|
72
|
+
|
|
73
|
+
An instruction fence and a relayed-context fragment that apply to one behavior shall appear in the target blockquote in their Source order.
|
|
74
|
+
Distinct non-empty fragments shall be separated by one blank prompt line unless Source explicitly supplies a different boundary.
|
|
75
|
+
text2gears shall not move a shared instruction ahead of behavior-specific context, move quoted evidence after an instruction that Source says follows the evidence, or otherwise regroup fragments for convenience.
|
|
76
|
+
|
|
77
|
+
Where Source says that a runtime value is relayed in quotes, the leading `>` is prompt content rather than Source-only blockquote syntax.
|
|
78
|
+
If Source supplies a blockquoted template for that relay, text2gears shall keep one literal leading `>` on every quoted line; the target GEARS line therefore uses its outer blockquote marker followed by the literal marker, such as `> > Coder output: <coder-output>`.
|
|
79
|
+
If Source names the relayed value but supplies no template, text2gears shall emit its canonical typed placeholder on a line beginning with literal `> ` and shall not summarize, paraphrase, or invent a value in its place.
|
|
80
|
+
An ordinary Source blockquote that specifies a complete acting prompt without requiring quoted relay retains the existing rule above: its one leading marker is Source syntax and is not prompt content.
|
|
81
|
+
|
|
68
82
|
Source statements that assign active-leaf routing, call identity, suspension,
|
|
69
83
|
or return matching to the host describe execution preconditions rather than
|
|
70
84
|
behaviors for Captain to perform. text2gears shall use such a statement only as
|
|
@@ -139,6 +153,11 @@ A single-outcome producer then declares exactly one bullet naming the
|
|
|
139
153
|
property; this consumed-output case is the sole one in which a
|
|
140
154
|
single-outcome behavior carries a `Results:` label.
|
|
141
155
|
|
|
156
|
+
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>` ``.
|
|
157
|
+
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.
|
|
158
|
+
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.
|
|
159
|
+
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.
|
|
160
|
+
|
|
142
161
|
Result metadata is compiler control data, not part of the acting agent's
|
|
143
162
|
prompt.
|
|
144
163
|
text2gears shall not put guard names, result-property schema, JSON control
|
|
@@ -202,11 +221,11 @@ next phase cannot compile.
|
|
|
202
221
|
Example:
|
|
203
222
|
|
|
204
223
|
```markdown
|
|
205
|
-
###
|
|
224
|
+
### DECIDE-1
|
|
206
225
|
|
|
207
226
|
Parallel group: initial-proposals
|
|
208
227
|
|
|
209
|
-
When Boss gives a topic, Captain shall prompt
|
|
228
|
+
When Boss gives a topic, Captain shall prompt Coder:
|
|
210
229
|
|
|
211
230
|
> Propose your design independently.
|
|
212
231
|
```
|
|
@@ -306,6 +325,7 @@ Prompts shall carry the specification's normative requirements as instructions t
|
|
|
306
325
|
|
|
307
326
|
Source snippets may overlap or duplicate.
|
|
308
327
|
When composing them into a spec item, text2gears shall deduplicate identical prompt lines.
|
|
328
|
+
It shall not deduplicate across distinct authored fragments when doing so would erase a fragment boundary or change the Source-ordered prompt.
|
|
309
329
|
|
|
310
330
|
Each spec item addresses one state behavior and carries its full final prompt (the static part).
|
|
311
331
|
Cross-item duplication is acceptable: spec items are compiled artifacts; Source is what users maintain.
|
package/src/runtime.d.ts
CHANGED
|
@@ -7,6 +7,12 @@ export interface PlayerResult {
|
|
|
7
7
|
export interface PlayerCallOptions {
|
|
8
8
|
resume: string | false;
|
|
9
9
|
}
|
|
10
|
+
export interface PlayerSessionStore {
|
|
11
|
+
select(playerId: string): string | false;
|
|
12
|
+
update(playerId: string, resumeToken?: string): void;
|
|
13
|
+
snapshot(): Readonly<Record<string, string>>;
|
|
14
|
+
restore(tokens: Readonly<Record<string, string>>): void;
|
|
15
|
+
}
|
|
10
16
|
export interface CaptainCallOptions {
|
|
11
17
|
visibility: 'visible' | 'hidden';
|
|
12
18
|
resume: string | false;
|
|
@@ -41,6 +47,11 @@ export interface PlaybookPendingCall {
|
|
|
41
47
|
playbookId: string;
|
|
42
48
|
childSessionId: string;
|
|
43
49
|
}
|
|
50
|
+
export interface PlaybookSuspendedCall extends PlaybookPendingCall {
|
|
51
|
+
stateId: string;
|
|
52
|
+
text: string;
|
|
53
|
+
turnId?: number;
|
|
54
|
+
}
|
|
44
55
|
export interface PlaybookCallRequest {
|
|
45
56
|
callId: string;
|
|
46
57
|
playbookId: string;
|
|
@@ -106,6 +117,7 @@ export interface PlaybookSession {
|
|
|
106
117
|
parentSessionId?: string;
|
|
107
118
|
parentCallId?: string;
|
|
108
119
|
depth: number;
|
|
120
|
+
playerSessions?: PlayerSessionStore;
|
|
109
121
|
ports: PlaybookPorts;
|
|
110
122
|
}
|
|
111
123
|
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' | 'apply.started' | 'apply.finished' | 'fsm.transition' | 'status.emitted' | 'boss.input.settled' | 'session.disposed';
|
|
@@ -130,8 +142,7 @@ export interface PlaybookPendingBossQuestion {
|
|
|
130
142
|
question: string;
|
|
131
143
|
sourceItem?: string;
|
|
132
144
|
}
|
|
133
|
-
|
|
134
|
-
schemaVersion: 1;
|
|
145
|
+
interface PlaybookRuntimeSnapshotFields {
|
|
135
146
|
playbookId: string;
|
|
136
147
|
machine: JsonValue;
|
|
137
148
|
playerResumeTokens: {
|
|
@@ -148,6 +159,13 @@ export interface PlaybookRuntimeSnapshot {
|
|
|
148
159
|
state: PlaybookState;
|
|
149
160
|
pendingBossQuestions: readonly PlaybookPendingBossQuestion[];
|
|
150
161
|
}
|
|
162
|
+
export type PlaybookRuntimeSnapshot = PlaybookRuntimeSnapshotFields & ({
|
|
163
|
+
schemaVersion: 1;
|
|
164
|
+
suspendedCall?: never;
|
|
165
|
+
} | {
|
|
166
|
+
schemaVersion: 2;
|
|
167
|
+
suspendedCall?: PlaybookSuspendedCall;
|
|
168
|
+
});
|
|
151
169
|
export interface PlaybookControlAction {
|
|
152
170
|
id: string;
|
|
153
171
|
label: string;
|
|
@@ -192,3 +210,4 @@ export interface PlaybookRuntime {
|
|
|
192
210
|
dispose(): Promise<void>;
|
|
193
211
|
}
|
|
194
212
|
export type PlaybookRuntimeFactory<Options = unknown> = (options: Options) => PlaybookRuntime;
|
|
213
|
+
export {};
|
package/src/runtime.ts
CHANGED
|
@@ -19,6 +19,17 @@ export interface PlayerCallOptions {
|
|
|
19
19
|
resume: string | false;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
// DR-030: a composing host may supply one frame-local view of the root
|
|
23
|
+
// engagement's player continuation. The runtime selects through this store
|
|
24
|
+
// before tracing/calling and updates it from the validated result. Hosts that
|
|
25
|
+
// omit it retain the runtime's private per-session store.
|
|
26
|
+
export interface PlayerSessionStore {
|
|
27
|
+
select(playerId: string): string | false;
|
|
28
|
+
update(playerId: string, resumeToken?: string): void;
|
|
29
|
+
snapshot(): Readonly<Record<string, string>>;
|
|
30
|
+
restore(tokens: Readonly<Record<string, string>>): void;
|
|
31
|
+
}
|
|
32
|
+
|
|
22
33
|
export interface CaptainCallOptions {
|
|
23
34
|
visibility: 'visible' | 'hidden';
|
|
24
35
|
resume: string | false;
|
|
@@ -64,6 +75,15 @@ export interface PlaybookPendingCall {
|
|
|
64
75
|
childSessionId: string;
|
|
65
76
|
}
|
|
66
77
|
|
|
78
|
+
// DR-031 §5: complete durable identity for one nested call whose start
|
|
79
|
+
// boundary has already been published and whose child remains suspended.
|
|
80
|
+
// `turnId` is absent when the call was opened outside a Boss-turn boundary.
|
|
81
|
+
export interface PlaybookSuspendedCall extends PlaybookPendingCall {
|
|
82
|
+
stateId: string;
|
|
83
|
+
text: string;
|
|
84
|
+
turnId?: number;
|
|
85
|
+
}
|
|
86
|
+
|
|
67
87
|
export interface PlaybookCallRequest {
|
|
68
88
|
callId: string;
|
|
69
89
|
playbookId: string;
|
|
@@ -143,6 +163,7 @@ export interface PlaybookSession {
|
|
|
143
163
|
parentSessionId?: string;
|
|
144
164
|
parentCallId?: string;
|
|
145
165
|
depth: number;
|
|
166
|
+
playerSessions?: PlayerSessionStore;
|
|
146
167
|
ports: PlaybookPorts;
|
|
147
168
|
}
|
|
148
169
|
|
|
@@ -187,12 +208,11 @@ export interface PlaybookPendingBossQuestion {
|
|
|
187
208
|
sourceItem?: string;
|
|
188
209
|
}
|
|
189
210
|
|
|
190
|
-
// DR-014 §1: JSON-safe capture of a parked
|
|
191
|
-
//
|
|
192
|
-
// questions are first-class so a
|
|
193
|
-
//
|
|
194
|
-
|
|
195
|
-
schemaVersion: 1;
|
|
211
|
+
// DR-014 §1 / DR-031 §5: JSON-safe capture of a parked or nested-call
|
|
212
|
+
// suspended session. `machine` is the opaque XState persisted snapshot;
|
|
213
|
+
// pending Boss questions and a schema-2 suspended call are first-class so a
|
|
214
|
+
// host never has to reconstruct durable ownership from presentation records.
|
|
215
|
+
interface PlaybookRuntimeSnapshotFields {
|
|
196
216
|
playbookId: string;
|
|
197
217
|
machine: JsonValue;
|
|
198
218
|
playerResumeTokens: { readonly [playerId: string]: string };
|
|
@@ -208,6 +228,18 @@ export interface PlaybookRuntimeSnapshot {
|
|
|
208
228
|
pendingBossQuestions: readonly PlaybookPendingBossQuestion[];
|
|
209
229
|
}
|
|
210
230
|
|
|
231
|
+
export type PlaybookRuntimeSnapshot = PlaybookRuntimeSnapshotFields &
|
|
232
|
+
(
|
|
233
|
+
| {
|
|
234
|
+
schemaVersion: 1;
|
|
235
|
+
suspendedCall?: never;
|
|
236
|
+
}
|
|
237
|
+
| {
|
|
238
|
+
schemaVersion: 2;
|
|
239
|
+
suspendedCall?: PlaybookSuspendedCall;
|
|
240
|
+
}
|
|
241
|
+
);
|
|
242
|
+
|
|
211
243
|
// DR-029: one currently valid, runtime-advertised control action. The id
|
|
212
244
|
// is stable within the returned view; the label is runtime-written,
|
|
213
245
|
// Boss-appropriate text derived from source state descriptions.
|
|
@@ -67,6 +67,11 @@ export interface ScheduledStatus {
|
|
|
67
67
|
message: string;
|
|
68
68
|
data?: JsonValue;
|
|
69
69
|
}
|
|
70
|
+
/** Boss-facing identity for one FSM state whose invoked actor is `player`. */
|
|
71
|
+
export interface XStatePlayerStateStatus {
|
|
72
|
+
player: string;
|
|
73
|
+
label: string;
|
|
74
|
+
}
|
|
70
75
|
export interface XStateBossEventFieldSpec {
|
|
71
76
|
/** The judge supplies routing data; the runtime supplies exact Boss text. */
|
|
72
77
|
source: 'judge' | 'text';
|
|
@@ -177,8 +182,10 @@ export interface XStatePlaybookRuntimeSpec<TOptions> {
|
|
|
177
182
|
* recoverable FSM-result failures instead.
|
|
178
183
|
*/
|
|
179
184
|
captainStrategy?: XStateCaptainStrategy<TOptions>;
|
|
180
|
-
/** Status line emitted after classification
|
|
185
|
+
/** Status line emitted after classification; canonical metadata defaults to the event type, legacy artifacts to none. */
|
|
181
186
|
classificationStatus?: (event: EventObject) => string | undefined;
|
|
187
|
+
/** Complete FSM-derived Boss-facing metadata for every `player` state; its presence selects the canonical status profile. */
|
|
188
|
+
playerStates?: Readonly<Record<string, XStatePlayerStateStatus>>;
|
|
182
189
|
/** Map a player-invoking state's input to the host player id. Default: lowercased player name. */
|
|
183
190
|
resolvePlayerId?: (input: PlaybookPlayerInput, options: TOptions) => string;
|
|
184
191
|
/** Compose the player prompt. Default: continuation blocks + `<field>` placeholder substitution. */
|
|
@@ -207,7 +214,7 @@ export interface XStatePlaybookRuntimeSpec<TOptions> {
|
|
|
207
214
|
controlContextFields?: readonly string[];
|
|
208
215
|
/** States that may suspend for a Boss reply. Default: targets of the FSM's `awaitBossReply` BOSS_REPLY transitions. */
|
|
209
216
|
resumableStateIds?: ReadonlySet<string>;
|
|
210
|
-
/** Human status lines for a root transition. Default:
|
|
217
|
+
/** Human status lines for a root transition. Default: guard, declared-player, question, and failure lines. */
|
|
211
218
|
statusesForState?: (state: PlaybookState, context: Record<string, unknown>, event: unknown) => readonly ScheduledStatus[];
|
|
212
219
|
/** Detached JSON-safe transition-event descriptor. Default: `type` + `transitionEventFields` strings + validated output + normalized error. */
|
|
213
220
|
normalizeTransitionEvent?: (event: unknown) => JsonValue | undefined;
|