@sublang/playbook 0.8.0 → 1.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 +243 -193
- package/package.json +52 -17
- package/reference/sdlc/captain.md +102 -0
- package/reference/sdlc/captain.playbook/captain.fsm.d.ts +227 -0
- package/reference/sdlc/captain.playbook/captain.fsm.js +628 -0
- package/reference/sdlc/captain.playbook/captain.fsm.ts +851 -0
- package/reference/sdlc/captain.playbook/captain.gears.md +60 -0
- package/reference/sdlc/captain.playbook/captain.playbook.d.ts +23 -0
- package/reference/sdlc/captain.playbook/captain.playbook.js +1053 -0
- package/reference/sdlc/captain.playbook/captain.playbook.ts +1144 -0
- package/reference/sdlc/code.playbook/bin/playbook.js +580 -0
- package/reference/sdlc/code.playbook/bin/run.js +893 -0
- package/reference/sdlc/code.playbook/code.fsm.d.ts +11 -4
- package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +2 -2
- package/reference/sdlc/code.playbook/code.fsm.introspect.js +1 -1
- package/reference/sdlc/code.playbook/code.fsm.introspect.ts +6 -6
- package/reference/sdlc/code.playbook/code.fsm.js +334 -102
- package/reference/sdlc/code.playbook/code.fsm.ts +470 -182
- package/reference/sdlc/code.playbook/code.gears.md +11 -10
- package/reference/sdlc/code.playbook/code.playbook.d.ts +18 -9
- package/reference/sdlc/code.playbook/code.playbook.js +1098 -202
- package/reference/sdlc/code.playbook/code.playbook.ts +1440 -258
- package/reference/sdlc/code.playbook/code.registry.d.ts +17 -5
- package/reference/sdlc/code.playbook/code.registry.js +49 -34
- package/reference/sdlc/code.playbook/code.registry.ts +75 -41
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +16 -8
- package/reference/sdlc/code.playbook/playbook-captain.js +1005 -240
- package/reference/sdlc/code.playbook/playbook-captain.ts +1310 -301
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +68 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.d.ts +396 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.js +2066 -0
- package/reference/sdlc/discuss.playbook/discuss.fsm.ts +2464 -0
- package/reference/sdlc/discuss.playbook/discuss.gears.md +251 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.d.ts +113 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.js +1514 -0
- package/reference/sdlc/discuss.playbook/discuss.playbook.ts +1926 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.d.ts +58 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.js +97 -0
- package/reference/sdlc/discuss.playbook/discuss.registry.ts +153 -0
- package/slc/gears2fsm.md +557 -57
- package/slc/link.md +1097 -80
- package/slc/optimize.md +88 -0
- package/slc/text2gears.md +247 -5
- package/src/runtime.d.ts +145 -3
- package/src/runtime.ts +200 -2
- package/src/xstate-runtime.d.ts +94 -0
- package/src/xstate-runtime.js +1247 -0
- package/src/xstate-runtime.ts +1802 -0
- package/reference/sdlc/code.playbook/bin/playbook-code.js +0 -487
- package/reference/sdlc/code.playbook/code.tmux-play.d.ts +0 -4
- package/reference/sdlc/code.playbook/code.tmux-play.js +0 -11
- package/reference/sdlc/code.playbook/code.tmux-play.ts +0 -29
- package/reference/sdlc/code.playbook/playbook-code.config.template.yaml +0 -72
- package/reference/sdlc/code.playbook/tmux-play.config.yaml +0 -55
- package/reference/sdlc/code.playbook/tmux-play.production.config.yaml +0 -38
package/src/runtime.ts
CHANGED
|
@@ -10,24 +10,222 @@
|
|
|
10
10
|
|
|
11
11
|
export interface PlayerResult {
|
|
12
12
|
status: 'ok' | 'aborted' | 'error';
|
|
13
|
+
resumeToken?: string;
|
|
13
14
|
finalText?: string;
|
|
14
15
|
error?: string;
|
|
15
16
|
}
|
|
16
17
|
|
|
18
|
+
export interface PlayerCallOptions {
|
|
19
|
+
resume: string | false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface CaptainCallOptions {
|
|
23
|
+
visibility: 'visible' | 'hidden';
|
|
24
|
+
resume: string | false;
|
|
25
|
+
allowedTools?: readonly string[];
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface CaptainResult {
|
|
29
|
+
status: 'ok' | 'aborted' | 'error';
|
|
30
|
+
finalText?: string;
|
|
31
|
+
error?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type JsonValue =
|
|
35
|
+
| null
|
|
36
|
+
| boolean
|
|
37
|
+
| number
|
|
38
|
+
| string
|
|
39
|
+
| readonly JsonValue[]
|
|
40
|
+
| { readonly [key: string]: JsonValue };
|
|
41
|
+
|
|
42
|
+
export interface NormalizedError {
|
|
43
|
+
name: string;
|
|
44
|
+
message: string;
|
|
45
|
+
stack?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type PlaybookStateValue =
|
|
49
|
+
| string
|
|
50
|
+
| { readonly [key: string]: PlaybookStateValue };
|
|
51
|
+
|
|
52
|
+
export interface PlaybookState {
|
|
53
|
+
value: PlaybookStateValue;
|
|
54
|
+
activeStateIds: readonly string[];
|
|
55
|
+
tags: readonly string[];
|
|
56
|
+
status: 'active' | 'done' | 'error' | 'stopped';
|
|
57
|
+
quiescent: boolean;
|
|
58
|
+
stateId?: string;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export interface PlaybookPendingCall {
|
|
62
|
+
callId: string;
|
|
63
|
+
playbookId: string;
|
|
64
|
+
childSessionId: string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface PlaybookCallRequest {
|
|
68
|
+
callId: string;
|
|
69
|
+
playbookId: string;
|
|
70
|
+
text: string;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export type PlaybookCallResult =
|
|
74
|
+
| {
|
|
75
|
+
status: 'ok';
|
|
76
|
+
playbookId: string;
|
|
77
|
+
childSessionId: string;
|
|
78
|
+
state?: PlaybookState;
|
|
79
|
+
output?: JsonValue;
|
|
80
|
+
}
|
|
81
|
+
| {
|
|
82
|
+
status: 'aborted';
|
|
83
|
+
playbookId: string;
|
|
84
|
+
childSessionId?: string;
|
|
85
|
+
state?: PlaybookState;
|
|
86
|
+
error?: NormalizedError;
|
|
87
|
+
}
|
|
88
|
+
| {
|
|
89
|
+
status: 'error';
|
|
90
|
+
playbookId: string;
|
|
91
|
+
childSessionId?: string;
|
|
92
|
+
state?: PlaybookState;
|
|
93
|
+
error: NormalizedError;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export type PlaybookCallStart =
|
|
97
|
+
| { state: 'settled'; result: PlaybookCallResult }
|
|
98
|
+
| { state: 'suspended'; childSessionId: string };
|
|
99
|
+
|
|
100
|
+
export type PlaybookRunResult =
|
|
101
|
+
| { outcome: 'quiescent' | 'no-action'; state: PlaybookState }
|
|
102
|
+
| {
|
|
103
|
+
outcome: 'failed' | 'aborted';
|
|
104
|
+
state: PlaybookState;
|
|
105
|
+
error?: NormalizedError;
|
|
106
|
+
}
|
|
107
|
+
| {
|
|
108
|
+
outcome: 'terminal';
|
|
109
|
+
state: PlaybookState;
|
|
110
|
+
output?: JsonValue;
|
|
111
|
+
}
|
|
112
|
+
| {
|
|
113
|
+
outcome: 'suspended';
|
|
114
|
+
state: PlaybookState;
|
|
115
|
+
pendingCall: PlaybookPendingCall;
|
|
116
|
+
};
|
|
117
|
+
|
|
17
118
|
export interface PlaybookPorts {
|
|
18
119
|
callPlayer(
|
|
19
120
|
playerId: string,
|
|
20
121
|
prompt: string,
|
|
21
122
|
signal: AbortSignal,
|
|
123
|
+
options: PlayerCallOptions,
|
|
22
124
|
): Promise<PlayerResult>;
|
|
125
|
+
callCaptain(
|
|
126
|
+
prompt: string,
|
|
127
|
+
signal: AbortSignal,
|
|
128
|
+
options: CaptainCallOptions,
|
|
129
|
+
): Promise<CaptainResult>;
|
|
23
130
|
callJudge(prompt: string, signal: AbortSignal): Promise<string>;
|
|
131
|
+
callPlaybook(
|
|
132
|
+
request: PlaybookCallRequest,
|
|
133
|
+
signal: AbortSignal,
|
|
134
|
+
): Promise<PlaybookCallStart>;
|
|
24
135
|
emitStatus(message: string, data?: unknown): Promise<void>;
|
|
25
136
|
emitTelemetry(event: { topic: string; payload: unknown }): Promise<void>;
|
|
26
137
|
}
|
|
27
138
|
|
|
139
|
+
export interface PlaybookSession {
|
|
140
|
+
sessionId: string;
|
|
141
|
+
playbookId: string;
|
|
142
|
+
rootSessionId: string;
|
|
143
|
+
parentSessionId?: string;
|
|
144
|
+
parentCallId?: string;
|
|
145
|
+
depth: number;
|
|
146
|
+
ports: PlaybookPorts;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export type PlaybookTraceType =
|
|
150
|
+
| 'session.started'
|
|
151
|
+
| 'boss.input.received'
|
|
152
|
+
| 'judge.call.started'
|
|
153
|
+
| 'judge.call.finished'
|
|
154
|
+
| 'player.call.started'
|
|
155
|
+
| 'player.call.finished'
|
|
156
|
+
| 'captain.call.started'
|
|
157
|
+
| 'captain.call.finished'
|
|
158
|
+
| 'playbook.call.started'
|
|
159
|
+
| 'playbook.call.finished'
|
|
160
|
+
| 'fsm.transition'
|
|
161
|
+
| 'status.emitted'
|
|
162
|
+
| 'boss.input.settled'
|
|
163
|
+
| 'session.disposed';
|
|
164
|
+
|
|
165
|
+
export interface PlaybookTraceEvent {
|
|
166
|
+
schemaVersion: 2;
|
|
167
|
+
sessionId: string;
|
|
168
|
+
playbookId: string;
|
|
169
|
+
rootSessionId: string;
|
|
170
|
+
parentSessionId?: string;
|
|
171
|
+
parentCallId?: string;
|
|
172
|
+
depth: number;
|
|
173
|
+
sequence: number;
|
|
174
|
+
timestamp: number;
|
|
175
|
+
type: PlaybookTraceType;
|
|
176
|
+
turnId?: number;
|
|
177
|
+
callId?: string;
|
|
178
|
+
payload: JsonValue;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export interface PlaybookPendingBossQuestion {
|
|
182
|
+
questionId: string;
|
|
183
|
+
player: string;
|
|
184
|
+
question: string;
|
|
185
|
+
sourceItem?: string;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// DR-014 §1: JSON-safe capture of a parked session. `machine` is the
|
|
189
|
+
// XState persisted snapshot and is opaque to hosts; the pending Boss
|
|
190
|
+
// questions are first-class so a host can surface what was asked
|
|
191
|
+
// without parsing status lines or telemetry.
|
|
192
|
+
export interface PlaybookRuntimeSnapshot {
|
|
193
|
+
schemaVersion: 1;
|
|
194
|
+
playbookId: string;
|
|
195
|
+
machine: JsonValue;
|
|
196
|
+
playerResumeTokens: { readonly [playerId: string]: string };
|
|
197
|
+
sequences: {
|
|
198
|
+
trace: number;
|
|
199
|
+
turn: number;
|
|
200
|
+
judgeCall: number;
|
|
201
|
+
playerCall: number;
|
|
202
|
+
playbookCall: number;
|
|
203
|
+
};
|
|
204
|
+
state: PlaybookState;
|
|
205
|
+
pendingBossQuestions: readonly PlaybookPendingBossQuestion[];
|
|
206
|
+
}
|
|
207
|
+
|
|
28
208
|
export interface PlaybookRuntime {
|
|
29
|
-
init(
|
|
30
|
-
|
|
209
|
+
init(session: PlaybookSession): Promise<void>;
|
|
210
|
+
// DR-014 §1 optional durable-session capability: a runtime implements
|
|
211
|
+
// both members or neither. `exportSnapshot` returns undefined outside
|
|
212
|
+
// a safe capture point (parked quiescence between public boundaries);
|
|
213
|
+
// `restore` is an alternative to `init` that rehydrates the exported
|
|
214
|
+
// snapshot under the same immutable session identity.
|
|
215
|
+
exportSnapshot?(): PlaybookRuntimeSnapshot | undefined;
|
|
216
|
+
restore?(
|
|
217
|
+
session: PlaybookSession,
|
|
218
|
+
snapshot: PlaybookRuntimeSnapshot,
|
|
219
|
+
): Promise<void>;
|
|
220
|
+
handleBossInput(turn: {
|
|
221
|
+
text: string;
|
|
222
|
+
signal: AbortSignal;
|
|
223
|
+
}): Promise<PlaybookRunResult>;
|
|
224
|
+
resumePlaybookCall(input: {
|
|
225
|
+
callId: string;
|
|
226
|
+
result: PlaybookCallResult;
|
|
227
|
+
signal: AbortSignal;
|
|
228
|
+
}): Promise<PlaybookRunResult>;
|
|
31
229
|
dispose(): Promise<void>;
|
|
32
230
|
}
|
|
33
231
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { type AnyActorRef, type PromiseActorLogic, type SnapshotFrom } from 'xstate';
|
|
2
|
+
import type { CaptainResult, JsonValue, NormalizedError, PlaybookCallRequest, PlaybookCallResult, PlaybookCallStart, PlaybookPendingCall, PlaybookRuntimeSnapshot, PlaybookSession, PlaybookState, PlayerResult } from './runtime.js';
|
|
3
|
+
/**
|
|
4
|
+
* Compose invocation-lifetime and imperative-boundary cancellation without
|
|
5
|
+
* installing a second forwarding listener in each generated runtime.
|
|
6
|
+
*/
|
|
7
|
+
export declare function combineAbortSignals(...signals: readonly (AbortSignal | undefined)[]): AbortSignal;
|
|
8
|
+
/**
|
|
9
|
+
* Register host cleanup started synchronously by an invocation abort.
|
|
10
|
+
* The nested bridge drains these promises before it publishes the matching
|
|
11
|
+
* call-finish boundary, without widening the public six-port contract.
|
|
12
|
+
*/
|
|
13
|
+
export declare function registerPlaybookAbortCleanup(signal: AbortSignal, cleanup: Promise<unknown>): void;
|
|
14
|
+
/** Reject values that would be changed, omitted, or rejected by JSON. */
|
|
15
|
+
export declare function assertJsonSafe(value: unknown, path?: string, ancestors?: ReadonlySet<object>): asserts value is JsonValue;
|
|
16
|
+
/** Validate, detach, and recursively freeze host-owned JSON input. */
|
|
17
|
+
export declare function snapshotJsonValue(value: unknown, path?: string): JsonValue;
|
|
18
|
+
/** Validate session causality and detach its immutable identity from the host. */
|
|
19
|
+
export declare function snapshotPlaybookSession(session: PlaybookSession): PlaybookSession;
|
|
20
|
+
export declare function normalizeError(error: unknown): NormalizedError;
|
|
21
|
+
export interface PlaybookStateMetadata {
|
|
22
|
+
stateId: string;
|
|
23
|
+
description: string;
|
|
24
|
+
}
|
|
25
|
+
/** Read stable state identity without consulting XState's private `_nodes`. */
|
|
26
|
+
export declare function activePlaybookStateMetadata(snapshot: unknown): readonly PlaybookStateMetadata[];
|
|
27
|
+
export interface SnapshotNormalizationOptions {
|
|
28
|
+
pendingCall?: PlaybookPendingCall;
|
|
29
|
+
}
|
|
30
|
+
export declare function normalizePlaybookSnapshot(snapshot: unknown, options?: SnapshotNormalizationOptions): PlaybookState;
|
|
31
|
+
export declare function detachPersistedMachineSnapshot(persisted: unknown): JsonValue;
|
|
32
|
+
export declare function assertPlaybookRuntimeSnapshot(value: unknown, expectedPlaybookId: string): PlaybookRuntimeSnapshot;
|
|
33
|
+
export interface NestedPlaybookInput {
|
|
34
|
+
stateId: string;
|
|
35
|
+
playbookId: string;
|
|
36
|
+
text: string;
|
|
37
|
+
}
|
|
38
|
+
export interface PlaybookCallStarted {
|
|
39
|
+
callId: string;
|
|
40
|
+
stateId: string;
|
|
41
|
+
playbookId: string;
|
|
42
|
+
text: string;
|
|
43
|
+
}
|
|
44
|
+
export interface PlaybookCallFinished extends PlaybookCallStarted {
|
|
45
|
+
result: PlaybookCallResult;
|
|
46
|
+
}
|
|
47
|
+
export interface NestedPlaybookBridgeOptions {
|
|
48
|
+
nextCallId(): string;
|
|
49
|
+
/** Active public runtime boundary whose abort also owns a new child call. */
|
|
50
|
+
getBoundarySignal?(): AbortSignal | undefined;
|
|
51
|
+
callPlaybook(request: PlaybookCallRequest, signal: AbortSignal): Promise<PlaybookCallStart>;
|
|
52
|
+
emitStarted(event: PlaybookCallStarted): Promise<void>;
|
|
53
|
+
emitFinished(event: PlaybookCallFinished): Promise<void>;
|
|
54
|
+
drain(): Promise<void>;
|
|
55
|
+
bindResumeSignal?(signal: AbortSignal): void;
|
|
56
|
+
onControlPlaneError?(error: unknown): void;
|
|
57
|
+
onBackgroundError?(error: unknown): void;
|
|
58
|
+
}
|
|
59
|
+
export declare class NestedPlaybookCallError extends Error {
|
|
60
|
+
readonly result: PlaybookCallResult;
|
|
61
|
+
constructor(result: PlaybookCallResult);
|
|
62
|
+
}
|
|
63
|
+
export interface PendingCallObserver {
|
|
64
|
+
getPendingCall(): PlaybookPendingCall | undefined;
|
|
65
|
+
subscribePendingCall(listener: (pendingCall: PlaybookPendingCall) => void): () => void;
|
|
66
|
+
}
|
|
67
|
+
export interface NestedPlaybookBridge<TInput extends NestedPlaybookInput = NestedPlaybookInput> extends PendingCallObserver {
|
|
68
|
+
actorLogic: PromiseActorLogic<JsonValue | undefined, TInput>;
|
|
69
|
+
resume(input: {
|
|
70
|
+
callId: string;
|
|
71
|
+
result: PlaybookCallResult;
|
|
72
|
+
signal: AbortSignal;
|
|
73
|
+
}): Promise<void>;
|
|
74
|
+
abortPending(error?: unknown): Promise<void>;
|
|
75
|
+
dispose(): Promise<void>;
|
|
76
|
+
}
|
|
77
|
+
/** Validate, detach, and freeze a host direct-Captain result. */
|
|
78
|
+
export declare function validateCaptainResult(value: unknown, path?: string): CaptainResult;
|
|
79
|
+
/** Validate, detach, and freeze a host delegated-player result. */
|
|
80
|
+
export declare function validatePlayerResult(value: unknown, path?: string): PlayerResult;
|
|
81
|
+
export declare function validatePlaybookCallResult(result: unknown, expectedPlaybookId: string, expectedChildSessionId?: string): PlaybookCallResult;
|
|
82
|
+
export declare function validatePlaybookCallStart(start: unknown, expectedPlaybookId: string): PlaybookCallStart;
|
|
83
|
+
export declare function createNestedPlaybookBridge<TInput extends NestedPlaybookInput = NestedPlaybookInput>(options: NestedPlaybookBridgeOptions): NestedPlaybookBridge<TInput>;
|
|
84
|
+
export interface WaitForPlaybookQuiescenceOptions {
|
|
85
|
+
signal?: AbortSignal;
|
|
86
|
+
timeout?: number;
|
|
87
|
+
pendingCalls?: PendingCallObserver;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Wait at the imperative runtime boundary; workflow waiting remains in XState.
|
|
91
|
+
* A pending-call notification covers the case where the suspended state was
|
|
92
|
+
* entered before its host returned the child session id.
|
|
93
|
+
*/
|
|
94
|
+
export declare function waitForPlaybookQuiescence<TActorRef extends AnyActorRef>(actor: TActorRef, options?: WaitForPlaybookQuiescenceOptions): Promise<SnapshotFrom<TActorRef>>;
|