@sublang/playbook 7.0.0 → 9.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.
Files changed (62) hide show
  1. package/README.md +20 -7
  2. package/docs/cli.md +88 -43
  3. package/docs/configuration.md +221 -119
  4. package/docs/embedding.md +78 -27
  5. package/package.json +4 -3
  6. package/reference/sdlc/captain.playbook/captain.playbook.js +16 -5
  7. package/reference/sdlc/captain.playbook/captain.playbook.ts +20 -6
  8. package/reference/sdlc/code.md +1 -1
  9. package/reference/sdlc/code.playbook/bin/interactive-session.js +816 -0
  10. package/reference/sdlc/code.playbook/bin/launch-config.js +1078 -116
  11. package/reference/sdlc/code.playbook/bin/playbook.js +489 -34
  12. package/reference/sdlc/code.playbook/bin/run.js +283 -298
  13. package/reference/sdlc/code.playbook/bin/session-store.js +818 -26
  14. package/reference/sdlc/code.playbook/code.fsm.d.ts +9 -6
  15. package/reference/sdlc/code.playbook/code.fsm.introspect.js +2 -2
  16. package/reference/sdlc/code.playbook/code.fsm.introspect.ts +2 -2
  17. package/reference/sdlc/code.playbook/code.fsm.js +18 -15
  18. package/reference/sdlc/code.playbook/code.fsm.ts +21 -21
  19. package/reference/sdlc/code.playbook/code.gears.md +1 -1
  20. package/reference/sdlc/code.playbook/code.playbook.d.ts +2 -1
  21. package/reference/sdlc/code.playbook/code.playbook.js +25 -15
  22. package/reference/sdlc/code.playbook/code.playbook.ts +34 -17
  23. package/reference/sdlc/code.playbook/code.registry.d.ts +5 -13
  24. package/reference/sdlc/code.playbook/code.registry.js +3 -10
  25. package/reference/sdlc/code.playbook/code.registry.ts +7 -32
  26. package/reference/sdlc/code.playbook/playbook-captain.d.ts +39 -14
  27. package/reference/sdlc/code.playbook/playbook-captain.js +1014 -299
  28. package/reference/sdlc/code.playbook/playbook-captain.ts +1450 -406
  29. package/reference/sdlc/code.playbook/playbook.config.template.yaml +41 -49
  30. package/reference/sdlc/decide.md +4 -4
  31. package/reference/sdlc/decide.playbook/decide.fsm.d.ts +10 -10
  32. package/reference/sdlc/decide.playbook/decide.fsm.js +21 -14
  33. package/reference/sdlc/decide.playbook/decide.fsm.ts +27 -23
  34. package/reference/sdlc/decide.playbook/decide.gears.md +3 -5
  35. package/reference/sdlc/decide.playbook/decide.playbook.d.ts +11 -13
  36. package/reference/sdlc/decide.playbook/decide.playbook.js +465 -246
  37. package/reference/sdlc/decide.playbook/decide.playbook.ts +623 -283
  38. package/reference/sdlc/decide.playbook/decide.registry.d.ts +5 -13
  39. package/reference/sdlc/decide.playbook/decide.registry.js +3 -9
  40. package/reference/sdlc/decide.playbook/decide.registry.ts +7 -31
  41. package/reference/sdlc/review.md +4 -5
  42. package/reference/sdlc/review.playbook/review.fsm.d.ts +9 -11
  43. package/reference/sdlc/review.playbook/review.fsm.js +30 -24
  44. package/reference/sdlc/review.playbook/review.fsm.ts +39 -35
  45. package/reference/sdlc/review.playbook/review.gears.md +6 -5
  46. package/reference/sdlc/review.playbook/review.playbook.d.ts +2 -1
  47. package/reference/sdlc/review.playbook/review.playbook.js +29 -23
  48. package/reference/sdlc/review.playbook/review.playbook.ts +38 -28
  49. package/reference/sdlc/review.playbook/review.registry.d.ts +5 -13
  50. package/reference/sdlc/review.playbook/review.registry.js +3 -16
  51. package/reference/sdlc/review.playbook/review.registry.ts +7 -38
  52. package/slc/gears2fsm.md +45 -24
  53. package/slc/link.md +297 -135
  54. package/slc/text2gears.md +19 -18
  55. package/src/runtime.d.ts +21 -16
  56. package/src/runtime.ts +20 -23
  57. package/src/xstate-playbook-runtime.d.ts +34 -20
  58. package/src/xstate-playbook-runtime.js +973 -400
  59. package/src/xstate-playbook-runtime.ts +1203 -457
  60. package/src/xstate-runtime.d.ts +17 -7
  61. package/src/xstate-runtime.js +198 -81
  62. package/src/xstate-runtime.ts +339 -112
@@ -43,24 +43,17 @@ export function validateCodeOptions(optionSlice) {
43
43
  }
44
44
  return Object.freeze({});
45
45
  }
46
- function playerIdentity(players, id) {
47
- const player = players.find((entry) => entry.id === id);
48
- return player?.model ?? player?.adapter;
49
- }
50
- export function createCodeRuntimeOptions({ captainOptions, players, }) {
51
- validateCodeOptions(captainOptions);
52
- const coderPlayer = playerIdentity(players, 'coder');
53
- return coderPlayer === undefined ? {} : { coderPlayer };
54
- }
55
46
  export const codePlaybookRegistryEntry = {
56
47
  id: 'code',
57
48
  command: 'code',
58
49
  intent: 'implement a coding intent in reviewed, one-commit phases, using an intent record when needed',
50
+ artifactSchema: 2,
59
51
  requiredRoleIds: ['coder'],
52
+ concurrentRoleSets: [],
60
53
  summaryPolicy: codeSummaryPolicy,
61
54
  validateOptions: validateCodeOptions,
62
55
  createRuntime(options) {
63
- return createPlaybookRuntime(createCodeRuntimeOptions(options));
56
+ return createPlaybookRuntime(options);
64
57
  },
65
58
  };
66
59
  export default codePlaybookRegistryEntry;
@@ -2,7 +2,6 @@
2
2
  // SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
3
3
 
4
4
  import createPlaybookRuntime, {
5
- type CodePlaybookOptions,
6
5
  type PlaybookRuntime,
7
6
  } from './code.playbook.js';
8
7
 
@@ -15,27 +14,18 @@ export interface PlaybookSummaryPolicy {
15
14
  ): string;
16
15
  }
17
16
 
18
- export interface RegistryPlayer {
19
- id: string;
20
- adapter?: string;
21
- model?: string;
22
- }
23
-
24
- export interface CreateCodeRuntimeOptions {
25
- captainOptions: unknown;
26
- players: readonly RegistryPlayer[];
27
- }
28
-
29
17
  export type CodeOptions = Readonly<Record<string, never>>;
30
18
 
31
19
  export interface CodePlaybookRegistryEntry {
32
20
  id: 'code';
33
21
  command: 'code';
34
22
  intent: string;
23
+ artifactSchema: 2;
35
24
  requiredRoleIds: readonly ['coder'];
25
+ concurrentRoleSets: readonly [];
36
26
  summaryPolicy: PlaybookSummaryPolicy;
37
- validateOptions(captainOptions: unknown): CodeOptions;
38
- createRuntime(options: CreateCodeRuntimeOptions): PlaybookRuntime;
27
+ validateOptions(optionSlice: unknown): CodeOptions;
28
+ createRuntime(options: CodeOptions): PlaybookRuntime;
39
29
  }
40
30
 
41
31
  // REVIEW owns and labels its real review rounds. CODE's two suspended wrapper
@@ -96,33 +86,18 @@ export function validateCodeOptions(optionSlice: unknown): CodeOptions {
96
86
  return Object.freeze({});
97
87
  }
98
88
 
99
- function playerIdentity(
100
- players: readonly RegistryPlayer[],
101
- id: string,
102
- ): string | undefined {
103
- const player = players.find((entry) => entry.id === id);
104
- return player?.model ?? player?.adapter;
105
- }
106
-
107
- export function createCodeRuntimeOptions({
108
- captainOptions,
109
- players,
110
- }: CreateCodeRuntimeOptions): CodePlaybookOptions {
111
- validateCodeOptions(captainOptions);
112
- const coderPlayer = playerIdentity(players, 'coder');
113
- return coderPlayer === undefined ? {} : { coderPlayer };
114
- }
115
-
116
89
  export const codePlaybookRegistryEntry: CodePlaybookRegistryEntry = {
117
90
  id: 'code',
118
91
  command: 'code',
119
92
  intent:
120
93
  'implement a coding intent in reviewed, one-commit phases, using an intent record when needed',
94
+ artifactSchema: 2,
121
95
  requiredRoleIds: ['coder'],
96
+ concurrentRoleSets: [],
122
97
  summaryPolicy: codeSummaryPolicy,
123
98
  validateOptions: validateCodeOptions,
124
99
  createRuntime(options) {
125
- return createPlaybookRuntime(createCodeRuntimeOptions(options));
100
+ return createPlaybookRuntime(options);
126
101
  },
127
102
  };
128
103
 
@@ -1,11 +1,26 @@
1
- import type { Captain, CaptainSession } from '@sublang/cligent/tmux-play';
1
+ import { type Captain, type CaptainSession, type TuningSelection } from '@sublang/cligent/tmux-play';
2
+ import type { Effort, PermissionPolicy } from '@sublang/cligent';
2
3
  import type { JsonValue, PlaybookRuntime, PlaybookRuntimeSnapshot } from '@sublang/playbook/runtime';
3
4
  import { type CaptainControllerPort } from '../captain.playbook/captain.playbook.js';
4
- import type { PlaybookSummaryPolicy, RegistryPlayer } from './code.registry.js';
5
- export interface CreatePlaybookRuntimeOptions {
6
- captainOptions: unknown;
7
- players: readonly RegistryPlayer[];
5
+ import type { PlaybookSummaryPolicy } from './code.registry.js';
6
+ interface SessionAgent {
7
+ readonly adapter: string;
8
+ readonly model: TuningSelection;
9
+ readonly effort: TuningSelection<Effort>;
10
+ readonly instruction?: string;
11
+ readonly permissions?: PermissionPolicy;
8
12
  }
13
+ interface PlayerLedgerEntry {
14
+ readonly adapter: string;
15
+ readonly instruction?: string;
16
+ readonly permissions?: PermissionPolicy;
17
+ resumeToken?: string;
18
+ }
19
+ type DeepReadonly<T> = T extends (...args: never[]) => unknown ? T : T extends readonly (infer Element)[] ? readonly DeepReadonly<Element>[] : T extends object ? {
20
+ readonly [Key in keyof T]: DeepReadonly<T[Key]>;
21
+ } : T;
22
+ type SnapshotAgentEnvelope = DeepReadonly<Omit<SessionAgent, 'model' | 'effort'>>;
23
+ type PlayerLedgerSnapshotEntry = DeepReadonly<PlayerLedgerEntry>;
9
24
  export interface PlaybookCaptainDeps {
10
25
  loadModule?: (specifier: string) => Promise<unknown>;
11
26
  createSessionId?: () => string;
@@ -22,16 +37,22 @@ export interface PlaybookCaptainRegistryEntry {
22
37
  id: string;
23
38
  command: string;
24
39
  intent: string;
40
+ artifactSchema: 2;
25
41
  requiredRoleIds: readonly string[];
42
+ concurrentRoleSets: readonly (readonly string[])[];
26
43
  summaryPolicy?: PlaybookSummaryPolicy;
27
- validateOptions(captainOptions: unknown): unknown;
28
- createRuntime(options: CreatePlaybookRuntimeOptions): PlaybookRuntime;
44
+ validateOptions(optionSlice: unknown): unknown;
45
+ createRuntime(options: unknown): PlaybookRuntime;
29
46
  }
30
47
  type PlaybookCaptainConversationSnapshot = {
31
48
  readonly kind: 'unopened';
32
49
  } | {
33
50
  readonly kind: 'pinned';
34
51
  readonly token: string;
52
+ } | {
53
+ readonly kind: 'needsCatchUp';
54
+ readonly resume: string | false;
55
+ readonly afterJournalSeq: number;
35
56
  } | {
36
57
  readonly kind: 'needsSeeding';
37
58
  };
@@ -48,15 +69,19 @@ interface PlaybookCaptainFrameSnapshot {
48
69
  readonly depth: number;
49
70
  readonly parentSessionId?: string;
50
71
  readonly parentCallId?: string;
51
- readonly runtime: PlaybookRuntimeSnapshot;
72
+ readonly options: JsonValue;
73
+ readonly roleBindings: Readonly<Record<string, string>>;
74
+ readonly runtime: DeepReadonly<PlaybookRuntimeSnapshot>;
52
75
  }
53
76
  interface PlaybookCaptainShellSnapshotFields {
54
- readonly schemaVersion: 1;
77
+ readonly schemaVersion: 3;
55
78
  readonly captain: {
56
79
  readonly sessionId: string;
57
- readonly runtime: PlaybookRuntimeSnapshot;
80
+ readonly runtime: DeepReadonly<PlaybookRuntimeSnapshot>;
81
+ readonly agent: SnapshotAgentEnvelope;
58
82
  readonly conversation: PlaybookCaptainConversationSnapshot;
59
83
  };
84
+ readonly playerSessions: Readonly<Record<string, PlayerLedgerSnapshotEntry>>;
60
85
  /** Every Captain and engagement UUID issued during this logical session. */
61
86
  readonly issuedSessionIds: readonly string[];
62
87
  readonly sequences: {
@@ -71,28 +96,28 @@ interface PlaybookCaptainShellSnapshotFields {
71
96
  * Complete JSON-safe durable state for one Captain shell between Boss turns.
72
97
  * The discriminated mode keeps chat snapshots free of stale engagement data.
73
98
  */
74
- export type PlaybookCaptainShellSnapshot = PlaybookCaptainShellSnapshotFields & ({
99
+ type PlaybookCaptainShellSnapshotValue = PlaybookCaptainShellSnapshotFields & ({
75
100
  readonly mode: 'chat';
76
101
  readonly frames?: never;
77
- readonly rootPlayerResumeTokens?: never;
78
102
  readonly pendingBossQuestions?: never;
79
103
  readonly lastError?: never;
80
104
  } | {
81
105
  readonly mode: 'engaged.parked';
82
106
  /** Root-to-leaf engagement order. */
83
107
  readonly frames: readonly PlaybookCaptainFrameSnapshot[];
84
- /** Root-owned continuation, keyed by effective host-player id. */
85
- readonly rootPlayerResumeTokens: Readonly<Record<string, string>>;
86
108
  readonly pendingBossQuestions?: JsonValue;
87
109
  readonly lastError?: {
88
110
  readonly name: string;
89
111
  readonly message: string;
90
112
  };
91
113
  });
114
+ export type PlaybookCaptainShellSnapshot = DeepReadonly<PlaybookCaptainShellSnapshotValue>;
92
115
  /** tmux and headless front ends share this one durable Captain shell API. */
93
116
  export interface PlaybookCaptainShell extends Captain {
94
117
  exportSnapshot(): PlaybookCaptainShellSnapshot | undefined;
95
118
  restore(session: CaptainSession, snapshot: PlaybookCaptainShellSnapshot): Promise<void>;
96
119
  }
120
+ /** Validate, detach, and freeze one untrusted shell snapshot. */
121
+ export declare function assertPlaybookCaptainShellSnapshot(value: unknown): PlaybookCaptainShellSnapshot;
97
122
  export declare function createPlaybookCaptainShell(options: unknown, deps?: PlaybookCaptainDeps): PlaybookCaptainShell;
98
123
  export default createPlaybookCaptainShell;