@sublang/playbook 9.0.0 → 10.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 (64) hide show
  1. package/docs/cli.md +51 -8
  2. package/docs/embedding.md +38 -12
  3. package/package.json +7 -3
  4. package/reference/sdlc/captain.md +14 -10
  5. package/reference/sdlc/captain.playbook/captain.fsm.d.ts +33 -13
  6. package/reference/sdlc/captain.playbook/captain.fsm.js +80 -9
  7. package/reference/sdlc/captain.playbook/captain.fsm.ts +137 -18
  8. package/reference/sdlc/captain.playbook/captain.gears.md +10 -6
  9. package/reference/sdlc/captain.playbook/captain.playbook.d.ts +5 -1
  10. package/reference/sdlc/captain.playbook/captain.playbook.js +140 -10
  11. package/reference/sdlc/captain.playbook/captain.playbook.ts +188 -16
  12. package/reference/sdlc/code.md +0 -1
  13. package/reference/sdlc/code.playbook/bin/interactive-session.js +170 -17
  14. package/reference/sdlc/code.playbook/bin/launch-config.js +136 -4
  15. package/reference/sdlc/code.playbook/bin/playbook.js +81 -4
  16. package/reference/sdlc/code.playbook/bin/repository-effects.js +2930 -0
  17. package/reference/sdlc/code.playbook/bin/run.js +365 -63
  18. package/reference/sdlc/code.playbook/bin/session-store.js +2877 -209
  19. package/reference/sdlc/code.playbook/code.fsm.d.ts +7 -0
  20. package/reference/sdlc/code.playbook/code.fsm.js +74 -25
  21. package/reference/sdlc/code.playbook/code.fsm.ts +83 -29
  22. package/reference/sdlc/code.playbook/code.gears.md +0 -2
  23. package/reference/sdlc/code.playbook/code.playbook.d.ts +5 -2
  24. package/reference/sdlc/code.playbook/code.playbook.js +54 -2
  25. package/reference/sdlc/code.playbook/code.playbook.ts +75 -6
  26. package/reference/sdlc/code.playbook/code.registry.d.ts +10 -3
  27. package/reference/sdlc/code.playbook/code.registry.js +10 -3
  28. package/reference/sdlc/code.playbook/code.registry.ts +23 -5
  29. package/reference/sdlc/code.playbook/playbook-captain.d.ts +99 -7
  30. package/reference/sdlc/code.playbook/playbook-captain.js +1850 -72
  31. package/reference/sdlc/code.playbook/playbook-captain.ts +2759 -96
  32. package/reference/sdlc/decide.md +0 -1
  33. package/reference/sdlc/decide.playbook/decide.fsm.d.ts +7 -0
  34. package/reference/sdlc/decide.playbook/decide.fsm.js +80 -29
  35. package/reference/sdlc/decide.playbook/decide.fsm.ts +89 -31
  36. package/reference/sdlc/decide.playbook/decide.gears.md +0 -1
  37. package/reference/sdlc/decide.playbook/decide.playbook.d.ts +13 -5
  38. package/reference/sdlc/decide.playbook/decide.playbook.js +1712 -91
  39. package/reference/sdlc/decide.playbook/decide.playbook.ts +2677 -136
  40. package/reference/sdlc/decide.playbook/decide.registry.d.ts +7 -3
  41. package/reference/sdlc/decide.playbook/decide.registry.js +10 -3
  42. package/reference/sdlc/decide.playbook/decide.registry.ts +20 -5
  43. package/reference/sdlc/review.playbook/review.fsm.d.ts +7 -0
  44. package/reference/sdlc/review.playbook/review.fsm.js +133 -12
  45. package/reference/sdlc/review.playbook/review.fsm.ts +140 -12
  46. package/reference/sdlc/review.playbook/review.playbook.d.ts +5 -2
  47. package/reference/sdlc/review.playbook/review.playbook.js +65 -2
  48. package/reference/sdlc/review.playbook/review.playbook.ts +83 -6
  49. package/reference/sdlc/review.playbook/review.registry.d.ts +10 -3
  50. package/reference/sdlc/review.playbook/review.registry.js +10 -3
  51. package/reference/sdlc/review.playbook/review.registry.ts +23 -5
  52. package/slc/gears2fsm.md +6 -5
  53. package/slc/link.md +544 -41
  54. package/src/accepted-outcome.d.ts +18 -0
  55. package/src/accepted-outcome.js +94 -0
  56. package/src/accepted-outcome.ts +140 -0
  57. package/src/runtime.d.ts +164 -3
  58. package/src/runtime.ts +213 -2
  59. package/src/xstate-playbook-runtime.d.ts +149 -10
  60. package/src/xstate-playbook-runtime.js +2569 -270
  61. package/src/xstate-playbook-runtime.ts +4133 -490
  62. package/src/xstate-runtime.d.ts +59 -1
  63. package/src/xstate-runtime.js +866 -7
  64. package/src/xstate-runtime.ts +1397 -7
@@ -1,4 +1,4 @@
1
- import { type PlaybookRuntime } from './decide.playbook.js';
1
+ import { type DecidePlaybookHostCapabilities, type PlaybookRuntime } from './decide.playbook.js';
2
2
  export interface PlaybookSummaryPolicy {
3
3
  stateCountLabels: Readonly<Record<string, string>>;
4
4
  copyPasteGuardNames: readonly string[];
@@ -12,12 +12,16 @@ export interface DecidePlaybookRegistryEntry {
12
12
  id: 'decide';
13
13
  command: 'decide';
14
14
  intent: string;
15
- artifactSchema: 2;
15
+ artifactSchema: 3;
16
+ runtimeProfile: {
17
+ readonly kind: 'bespoke';
18
+ readonly artifactSchema: 3;
19
+ };
16
20
  requiredRoleIds: readonly ['coder', 'reviewer'];
17
21
  concurrentRoleSets: readonly [readonly ['coder', 'reviewer']];
18
22
  summaryPolicy: PlaybookSummaryPolicy;
19
23
  validateOptions(optionSlice: unknown): DecideOptions;
20
- createRuntime(options: DecideOptions): PlaybookRuntime;
24
+ createRuntime(options: DecideOptions, hostCapabilities: DecidePlaybookHostCapabilities): PlaybookRuntime;
21
25
  }
22
26
  export declare const decideStateCountLabels: {
23
27
  readonly independentProposals: "proposal round";
@@ -42,13 +42,20 @@ export const decidePlaybookRegistryEntry = {
42
42
  id: 'decide',
43
43
  command: 'decide',
44
44
  intent: 'turn independent Coder and Reviewer proposals into an approved spec-design commit',
45
- artifactSchema: 2,
45
+ artifactSchema: 3,
46
+ runtimeProfile: Object.freeze({
47
+ kind: 'bespoke',
48
+ artifactSchema: 3,
49
+ }),
46
50
  requiredRoleIds: ['coder', 'reviewer'],
47
51
  concurrentRoleSets: [['coder', 'reviewer']],
48
52
  summaryPolicy: decideSummaryPolicy,
49
53
  validateOptions: validateDecideOptions,
50
- createRuntime(options) {
51
- return createPlaybookRuntime(options);
54
+ createRuntime(options, hostCapabilities) {
55
+ return createPlaybookRuntime({
56
+ configuredOptions: options,
57
+ hostCapabilities,
58
+ });
52
59
  },
53
60
  };
54
61
  export default decidePlaybookRegistryEntry;
@@ -2,6 +2,7 @@
2
2
  // SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
3
3
 
4
4
  import createPlaybookRuntime, {
5
+ type DecidePlaybookHostCapabilities,
5
6
  type PlaybookRuntime,
6
7
  } from './decide.playbook.js';
7
8
 
@@ -20,12 +21,19 @@ export interface DecidePlaybookRegistryEntry {
20
21
  id: 'decide';
21
22
  command: 'decide';
22
23
  intent: string;
23
- artifactSchema: 2;
24
+ artifactSchema: 3;
25
+ runtimeProfile: {
26
+ readonly kind: 'bespoke';
27
+ readonly artifactSchema: 3;
28
+ };
24
29
  requiredRoleIds: readonly ['coder', 'reviewer'];
25
30
  concurrentRoleSets: readonly [readonly ['coder', 'reviewer']];
26
31
  summaryPolicy: PlaybookSummaryPolicy;
27
32
  validateOptions(optionSlice: unknown): DecideOptions;
28
- createRuntime(options: DecideOptions): PlaybookRuntime;
33
+ createRuntime(
34
+ options: DecideOptions,
35
+ hostCapabilities: DecidePlaybookHostCapabilities,
36
+ ): PlaybookRuntime;
29
37
  }
30
38
 
31
39
  export const decideStateCountLabels = {
@@ -88,13 +96,20 @@ export const decidePlaybookRegistryEntry: DecidePlaybookRegistryEntry = {
88
96
  command: 'decide',
89
97
  intent:
90
98
  'turn independent Coder and Reviewer proposals into an approved spec-design commit',
91
- artifactSchema: 2,
99
+ artifactSchema: 3,
100
+ runtimeProfile: Object.freeze({
101
+ kind: 'bespoke',
102
+ artifactSchema: 3,
103
+ }),
92
104
  requiredRoleIds: ['coder', 'reviewer'],
93
105
  concurrentRoleSets: [['coder', 'reviewer']],
94
106
  summaryPolicy: decideSummaryPolicy,
95
107
  validateOptions: validateDecideOptions,
96
- createRuntime(options) {
97
- return createPlaybookRuntime(options);
108
+ createRuntime(options, hostCapabilities) {
109
+ return createPlaybookRuntime({
110
+ configuredOptions: options,
111
+ hostCapabilities,
112
+ });
98
113
  },
99
114
  };
100
115
 
@@ -81,6 +81,13 @@ export declare const reviewMachine: import("xstate").StateMachine<ReviewContext,
81
81
  logic: import("xstate").PromiseActorLogic<PlayerOutput, PlayerInput, import("xstate").EventObject>;
82
82
  id: string | undefined;
83
83
  }, {
84
+ type: "playbook.acceptedOutcome";
85
+ params: {
86
+ readonly source: string;
87
+ readonly target: string;
88
+ readonly acceptedOutcome: string;
89
+ };
90
+ } | {
84
91
  type: "rememberActorError";
85
92
  params: import("xstate").NonReducibleUnknown;
86
93
  } | {
@@ -170,6 +170,7 @@ export const reviewMachine = setup({
170
170
  event.bossIntent.trim().length > 0,
171
171
  },
172
172
  actions: {
173
+ 'playbook.acceptedOutcome': (_args, _params) => undefined,
173
174
  copyStartInput: assign({
174
175
  callerInput: ({ event }) => event.type === 'START_REVIEW' ? event.callerInput : undefined,
175
176
  reviewerOutput: undefined,
@@ -320,17 +321,47 @@ export const reviewMachine = setup({
320
321
  {
321
322
  guard: 'hasFindings',
322
323
  target: '#addressFindings',
323
- actions: 'rememberReviewerOutput',
324
+ actions: [
325
+ {
326
+ type: 'playbook.acceptedOutcome',
327
+ params: {
328
+ source: 'reviewInitial',
329
+ target: 'addressFindings',
330
+ acceptedOutcome: 'hasFindings',
331
+ },
332
+ },
333
+ 'rememberReviewerOutput',
334
+ ],
324
335
  },
325
336
  {
326
337
  guard: 'noFindings',
327
338
  target: '#done',
328
- actions: 'clearBossReplyContext',
339
+ actions: [
340
+ {
341
+ type: 'playbook.acceptedOutcome',
342
+ params: {
343
+ source: 'reviewInitial',
344
+ target: 'done',
345
+ acceptedOutcome: 'noFindings',
346
+ },
347
+ },
348
+ 'clearBossReplyContext',
349
+ ],
329
350
  },
330
351
  {
331
352
  guard: 'needsBossReply',
332
353
  target: '#awaitBossReply',
333
- actions: 'setPendingReviewInitial',
354
+ actions: [
355
+ {
356
+ type: 'playbook.acceptedOutcome',
357
+ params: {
358
+ source: 'reviewInitial',
359
+ target: 'awaitBossReply',
360
+ acceptedOutcome: 'needsBossReply',
361
+ },
362
+ },
363
+ 'setPendingReviewInitial',
364
+ ],
334
365
  },
335
366
  ],
336
367
  onError: {
@@ -360,17 +391,47 @@ export const reviewMachine = setup({
360
391
  {
361
392
  guard: 'committed',
362
393
  target: '#reviewAfterCommit',
363
- actions: 'rememberCoderOutput',
394
+ actions: [
395
+ {
396
+ type: 'playbook.acceptedOutcome',
397
+ params: {
398
+ source: 'addressFindings',
399
+ target: 'reviewAfterCommit',
400
+ acceptedOutcome: 'committed',
401
+ },
402
+ },
403
+ 'rememberCoderOutput',
404
+ ],
364
405
  },
365
406
  {
366
407
  guard: 'rejectedAll',
367
408
  target: '#reviewAfterRebuttal',
368
- actions: 'rememberCoderOutput',
409
+ actions: [
410
+ {
411
+ type: 'playbook.acceptedOutcome',
412
+ params: {
413
+ source: 'addressFindings',
414
+ target: 'reviewAfterRebuttal',
415
+ acceptedOutcome: 'rejectedAll',
416
+ },
417
+ },
418
+ 'rememberCoderOutput',
419
+ ],
369
420
  },
370
421
  {
371
422
  guard: 'needsBossReply',
372
423
  target: '#awaitBossReply',
373
- actions: 'setPendingAddressFindings',
424
+ actions: [
425
+ {
426
+ type: 'playbook.acceptedOutcome',
427
+ params: {
428
+ source: 'addressFindings',
429
+ target: 'awaitBossReply',
430
+ acceptedOutcome: 'needsBossReply',
431
+ },
432
+ },
433
+ 'setPendingAddressFindings',
434
+ ],
374
435
  },
375
436
  ],
376
437
  onError: {
@@ -400,17 +461,47 @@ export const reviewMachine = setup({
400
461
  {
401
462
  guard: 'hasFindings',
402
463
  target: '#addressFindings',
403
- actions: 'rememberReviewerOutput',
464
+ actions: [
465
+ {
466
+ type: 'playbook.acceptedOutcome',
467
+ params: {
468
+ source: 'reviewAfterCommit',
469
+ target: 'addressFindings',
470
+ acceptedOutcome: 'hasFindings',
471
+ },
472
+ },
473
+ 'rememberReviewerOutput',
474
+ ],
404
475
  },
405
476
  {
406
477
  guard: 'noFindings',
407
478
  target: '#done',
408
- actions: 'clearBossReplyContext',
479
+ actions: [
480
+ {
481
+ type: 'playbook.acceptedOutcome',
482
+ params: {
483
+ source: 'reviewAfterCommit',
484
+ target: 'done',
485
+ acceptedOutcome: 'noFindings',
486
+ },
487
+ },
488
+ 'clearBossReplyContext',
489
+ ],
409
490
  },
410
491
  {
411
492
  guard: 'needsBossReply',
412
493
  target: '#awaitBossReply',
413
- actions: 'setPendingReviewAfterCommit',
494
+ actions: [
495
+ {
496
+ type: 'playbook.acceptedOutcome',
497
+ params: {
498
+ source: 'reviewAfterCommit',
499
+ target: 'awaitBossReply',
500
+ acceptedOutcome: 'needsBossReply',
501
+ },
502
+ },
503
+ 'setPendingReviewAfterCommit',
504
+ ],
414
505
  },
415
506
  ],
416
507
  onError: {
@@ -440,17 +531,47 @@ export const reviewMachine = setup({
440
531
  {
441
532
  guard: 'hasFindings',
442
533
  target: '#addressFindings',
443
- actions: 'rememberReviewerOutput',
534
+ actions: [
535
+ {
536
+ type: 'playbook.acceptedOutcome',
537
+ params: {
538
+ source: 'reviewAfterRebuttal',
539
+ target: 'addressFindings',
540
+ acceptedOutcome: 'hasFindings',
541
+ },
542
+ },
543
+ 'rememberReviewerOutput',
544
+ ],
444
545
  },
445
546
  {
446
547
  guard: 'noFindings',
447
548
  target: '#done',
448
- actions: 'clearBossReplyContext',
549
+ actions: [
550
+ {
551
+ type: 'playbook.acceptedOutcome',
552
+ params: {
553
+ source: 'reviewAfterRebuttal',
554
+ target: 'done',
555
+ acceptedOutcome: 'noFindings',
556
+ },
557
+ },
558
+ 'clearBossReplyContext',
559
+ ],
449
560
  },
450
561
  {
451
562
  guard: 'needsBossReply',
452
563
  target: '#awaitBossReply',
453
- actions: 'setPendingReviewAfterRebuttal',
564
+ actions: [
565
+ {
566
+ type: 'playbook.acceptedOutcome',
567
+ params: {
568
+ source: 'reviewAfterRebuttal',
569
+ target: 'awaitBossReply',
570
+ acceptedOutcome: 'needsBossReply',
571
+ },
572
+ },
573
+ 'setPendingReviewAfterRebuttal',
574
+ ],
454
575
  },
455
576
  ],
456
577
  onError: {
@@ -292,6 +292,14 @@ export const reviewMachine = setup({
292
292
  event.bossIntent.trim().length > 0,
293
293
  },
294
294
  actions: {
295
+ 'playbook.acceptedOutcome': (
296
+ _args,
297
+ _params: {
298
+ readonly source: string;
299
+ readonly target: string;
300
+ readonly acceptedOutcome: string;
301
+ },
302
+ ) => undefined,
295
303
  copyStartInput: assign({
296
304
  callerInput: ({ event }) =>
297
305
  event.type === 'START_REVIEW' ? event.callerInput : undefined,
@@ -446,17 +454,47 @@ export const reviewMachine = setup({
446
454
  {
447
455
  guard: 'hasFindings',
448
456
  target: '#addressFindings',
449
- actions: 'rememberReviewerOutput',
457
+ actions: [
458
+ {
459
+ type: 'playbook.acceptedOutcome',
460
+ params: {
461
+ source: 'reviewInitial',
462
+ target: 'addressFindings',
463
+ acceptedOutcome: 'hasFindings',
464
+ },
465
+ },
466
+ 'rememberReviewerOutput',
467
+ ],
450
468
  },
451
469
  {
452
470
  guard: 'noFindings',
453
471
  target: '#done',
454
- actions: 'clearBossReplyContext',
472
+ actions: [
473
+ {
474
+ type: 'playbook.acceptedOutcome',
475
+ params: {
476
+ source: 'reviewInitial',
477
+ target: 'done',
478
+ acceptedOutcome: 'noFindings',
479
+ },
480
+ },
481
+ 'clearBossReplyContext',
482
+ ],
455
483
  },
456
484
  {
457
485
  guard: 'needsBossReply',
458
486
  target: '#awaitBossReply',
459
- actions: 'setPendingReviewInitial',
487
+ actions: [
488
+ {
489
+ type: 'playbook.acceptedOutcome',
490
+ params: {
491
+ source: 'reviewInitial',
492
+ target: 'awaitBossReply',
493
+ acceptedOutcome: 'needsBossReply',
494
+ },
495
+ },
496
+ 'setPendingReviewInitial',
497
+ ],
460
498
  },
461
499
  ],
462
500
  onError: {
@@ -486,17 +524,47 @@ export const reviewMachine = setup({
486
524
  {
487
525
  guard: 'committed',
488
526
  target: '#reviewAfterCommit',
489
- actions: 'rememberCoderOutput',
527
+ actions: [
528
+ {
529
+ type: 'playbook.acceptedOutcome',
530
+ params: {
531
+ source: 'addressFindings',
532
+ target: 'reviewAfterCommit',
533
+ acceptedOutcome: 'committed',
534
+ },
535
+ },
536
+ 'rememberCoderOutput',
537
+ ],
490
538
  },
491
539
  {
492
540
  guard: 'rejectedAll',
493
541
  target: '#reviewAfterRebuttal',
494
- actions: 'rememberCoderOutput',
542
+ actions: [
543
+ {
544
+ type: 'playbook.acceptedOutcome',
545
+ params: {
546
+ source: 'addressFindings',
547
+ target: 'reviewAfterRebuttal',
548
+ acceptedOutcome: 'rejectedAll',
549
+ },
550
+ },
551
+ 'rememberCoderOutput',
552
+ ],
495
553
  },
496
554
  {
497
555
  guard: 'needsBossReply',
498
556
  target: '#awaitBossReply',
499
- actions: 'setPendingAddressFindings',
557
+ actions: [
558
+ {
559
+ type: 'playbook.acceptedOutcome',
560
+ params: {
561
+ source: 'addressFindings',
562
+ target: 'awaitBossReply',
563
+ acceptedOutcome: 'needsBossReply',
564
+ },
565
+ },
566
+ 'setPendingAddressFindings',
567
+ ],
500
568
  },
501
569
  ],
502
570
  onError: {
@@ -526,17 +594,47 @@ export const reviewMachine = setup({
526
594
  {
527
595
  guard: 'hasFindings',
528
596
  target: '#addressFindings',
529
- actions: 'rememberReviewerOutput',
597
+ actions: [
598
+ {
599
+ type: 'playbook.acceptedOutcome',
600
+ params: {
601
+ source: 'reviewAfterCommit',
602
+ target: 'addressFindings',
603
+ acceptedOutcome: 'hasFindings',
604
+ },
605
+ },
606
+ 'rememberReviewerOutput',
607
+ ],
530
608
  },
531
609
  {
532
610
  guard: 'noFindings',
533
611
  target: '#done',
534
- actions: 'clearBossReplyContext',
612
+ actions: [
613
+ {
614
+ type: 'playbook.acceptedOutcome',
615
+ params: {
616
+ source: 'reviewAfterCommit',
617
+ target: 'done',
618
+ acceptedOutcome: 'noFindings',
619
+ },
620
+ },
621
+ 'clearBossReplyContext',
622
+ ],
535
623
  },
536
624
  {
537
625
  guard: 'needsBossReply',
538
626
  target: '#awaitBossReply',
539
- actions: 'setPendingReviewAfterCommit',
627
+ actions: [
628
+ {
629
+ type: 'playbook.acceptedOutcome',
630
+ params: {
631
+ source: 'reviewAfterCommit',
632
+ target: 'awaitBossReply',
633
+ acceptedOutcome: 'needsBossReply',
634
+ },
635
+ },
636
+ 'setPendingReviewAfterCommit',
637
+ ],
540
638
  },
541
639
  ],
542
640
  onError: {
@@ -566,17 +664,47 @@ export const reviewMachine = setup({
566
664
  {
567
665
  guard: 'hasFindings',
568
666
  target: '#addressFindings',
569
- actions: 'rememberReviewerOutput',
667
+ actions: [
668
+ {
669
+ type: 'playbook.acceptedOutcome',
670
+ params: {
671
+ source: 'reviewAfterRebuttal',
672
+ target: 'addressFindings',
673
+ acceptedOutcome: 'hasFindings',
674
+ },
675
+ },
676
+ 'rememberReviewerOutput',
677
+ ],
570
678
  },
571
679
  {
572
680
  guard: 'noFindings',
573
681
  target: '#done',
574
- actions: 'clearBossReplyContext',
682
+ actions: [
683
+ {
684
+ type: 'playbook.acceptedOutcome',
685
+ params: {
686
+ source: 'reviewAfterRebuttal',
687
+ target: 'done',
688
+ acceptedOutcome: 'noFindings',
689
+ },
690
+ },
691
+ 'clearBossReplyContext',
692
+ ],
575
693
  },
576
694
  {
577
695
  guard: 'needsBossReply',
578
696
  target: '#awaitBossReply',
579
- actions: 'setPendingReviewAfterRebuttal',
697
+ actions: [
698
+ {
699
+ type: 'playbook.acceptedOutcome',
700
+ params: {
701
+ source: 'reviewAfterRebuttal',
702
+ target: 'awaitBossReply',
703
+ acceptedOutcome: 'needsBossReply',
704
+ },
705
+ },
706
+ 'setPendingReviewAfterRebuttal',
707
+ ],
580
708
  },
581
709
  ],
582
710
  onError: {
@@ -1,13 +1,16 @@
1
- import { type XStatePromptIdentity } from '@sublang/playbook/xstate-runtime';
1
+ import { type XStatePlaybookRuntimeFactory, type XStatePlaybookRuntimeConstruction, type XStatePromptIdentity } from '@sublang/playbook/xstate-runtime';
2
2
  import { type PlayerInput, type ReviewInput } from './review.fsm.js';
3
+ import type { PlaybookHostConstructionCapabilities } from '../code.playbook/playbook-captain.js';
3
4
  import type { CaptainCallOptions, CaptainResult, JsonValue, NormalizedError, PlayerCallOptions, PlaybookCallRequest, PlaybookCallResult, PlaybookCallStart, PlaybookControlReceipt, PlaybookControlView, PlaybookPendingCall, PlaybookPorts, PlaybookRunResult, PlaybookRuntime, PlaybookRuntimeFactory, PlaybookRuntimeSnapshot, PlaybookSession, PlaybookState, PlaybookStateValue, PlaybookTraceEvent, PlaybookTraceType, PlayerResult, PlayerSessionStore } from '@sublang/playbook/runtime';
4
5
  export type { CaptainCallOptions, CaptainResult, JsonValue, NormalizedError, PlayerCallOptions, PlaybookCallRequest, PlaybookCallResult, PlaybookCallStart, PlaybookControlReceipt, PlaybookControlView, PlaybookPendingCall, PlaybookPorts, PlaybookRunResult, PlaybookRuntime, PlaybookRuntimeFactory, PlaybookRuntimeSnapshot, PlaybookSession, PlaybookState, PlaybookStateValue, PlaybookTraceEvent, PlaybookTraceType, PlayerResult, PlayerSessionStore, };
5
6
  export type ReviewPlaybookOptions = ReviewInput;
7
+ export type ReviewPlaybookHostCapabilities = PlaybookHostConstructionCapabilities & XStatePlaybookRuntimeConstruction<ReviewPlaybookOptions, object>['hostCapabilities'];
6
8
  /** Keep every line of a relayed runtime value inside its authored quote. */
7
9
  declare function composePlayerPrompt(input: PlayerInput, promptIdentity: XStatePromptIdentity): string;
8
10
  export declare const _internal: {
9
11
  composePlayerPrompt: typeof composePlayerPrompt;
10
12
  VERBATIM_PAYLOAD_FIELDS: ReadonlySet<string>;
13
+ UNFINISHED_FINAL_STATE_IDS: ReadonlySet<string>;
11
14
  };
12
- declare const createPlaybookRuntime: PlaybookRuntimeFactory<ReviewPlaybookOptions>;
15
+ declare const createPlaybookRuntime: XStatePlaybookRuntimeFactory<XStatePlaybookRuntimeConstruction<ReviewPlaybookOptions, ReviewPlaybookHostCapabilities>, 3>;
13
16
  export default createPlaybookRuntime;
@@ -8,7 +8,7 @@
8
8
  // callerInput; pending player questions retain BOSS_REPLY
9
9
  // Adjudication: LLM judge per state; coderOutput and reviewerOutput are
10
10
  // carried verbatim
11
- // Compat: artifact schema 2 / runtime ABI 1
11
+ // Compat: artifact schema 3 / runtime ABI 1
12
12
  import { createXStatePlaybookRuntime, snapshotJsonValue, } from '@sublang/playbook/xstate-runtime';
13
13
  import { reviewMachine, } from './review.fsm.js';
14
14
  const PLACEHOLDER = /<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>/g;
@@ -17,6 +17,7 @@ const VERBATIM_PAYLOAD_FIELDS = new Set([
17
17
  'reviewerOutput',
18
18
  'coderOutput',
19
19
  ]);
20
+ const UNFINISHED_FINAL_STATE_IDS = new Set();
20
21
  function snapshotReviewOptions(value) {
21
22
  const captured = snapshotJsonValue(value, 'REVIEW runtime options');
22
23
  if (captured === null ||
@@ -68,6 +69,7 @@ function composePlayerPrompt(input, promptIdentity) {
68
69
  export const _internal = {
69
70
  composePlayerPrompt,
70
71
  VERBATIM_PAYLOAD_FIELDS,
72
+ UNFINISHED_FINAL_STATE_IDS,
71
73
  };
72
74
  const runtimeSpec = {
73
75
  label: 'REVIEW',
@@ -75,7 +77,7 @@ const runtimeSpec = {
75
77
  // time — a literal, never the loading engine's RUNTIME_ABI self-report,
76
78
  // which would follow whatever engine loads the module and make the
77
79
  // factory's skew check compare that engine with itself.
78
- compat: { artifactSchema: 2, runtimeAbi: 1 },
80
+ compat: { artifactSchema: 3, runtimeAbi: 1 },
79
81
  snapshotOptions: snapshotReviewOptions,
80
82
  entryEvent: {
81
83
  type: 'START_REVIEW',
@@ -103,9 +105,70 @@ const runtimeSpec = {
103
105
  label: 'REVIEW-4: Reviewer adjudicates an all-rejected Coder disposition.',
104
106
  },
105
107
  },
108
+ outcomeAuthority: {
109
+ governedPlayerStates: {
110
+ reviewInitial: {
111
+ hasFindings: {
112
+ fields: { reviewerOutput: 'presentation' },
113
+ repositoryDisposition: 'unchanged',
114
+ },
115
+ noFindings: {
116
+ fields: {},
117
+ repositoryDisposition: 'unchanged',
118
+ },
119
+ needsBossReply: {
120
+ fields: { question: 'presentation' },
121
+ repositoryDisposition: 'unchanged',
122
+ },
123
+ },
124
+ addressFindings: {
125
+ committed: {
126
+ fields: { coderOutput: 'presentation' },
127
+ repositoryDisposition: 'one-descendant-commit',
128
+ },
129
+ rejectedAll: {
130
+ fields: { coderOutput: 'presentation' },
131
+ repositoryDisposition: 'unchanged',
132
+ },
133
+ needsBossReply: {
134
+ fields: { question: 'presentation' },
135
+ repositoryDisposition: 'deferred',
136
+ },
137
+ },
138
+ reviewAfterCommit: {
139
+ hasFindings: {
140
+ fields: { reviewerOutput: 'presentation' },
141
+ repositoryDisposition: 'unchanged',
142
+ },
143
+ noFindings: {
144
+ fields: {},
145
+ repositoryDisposition: 'unchanged',
146
+ },
147
+ needsBossReply: {
148
+ fields: { question: 'presentation' },
149
+ repositoryDisposition: 'unchanged',
150
+ },
151
+ },
152
+ reviewAfterRebuttal: {
153
+ hasFindings: {
154
+ fields: { reviewerOutput: 'presentation' },
155
+ repositoryDisposition: 'unchanged',
156
+ },
157
+ noFindings: {
158
+ fields: {},
159
+ repositoryDisposition: 'unchanged',
160
+ },
161
+ needsBossReply: {
162
+ fields: { question: 'presentation' },
163
+ repositoryDisposition: 'unchanged',
164
+ },
165
+ },
166
+ },
167
+ },
106
168
  composePlayerPrompt: (input, promptIdentity) => composePlayerPrompt(input, promptIdentity),
107
169
  verbatimPayloadFields: VERBATIM_PAYLOAD_FIELDS,
108
170
  controlContextFields: [],
171
+ unfinishedFinalStateIds: UNFINISHED_FINAL_STATE_IDS,
109
172
  transitionEventFields: [
110
173
  'callerInput',
111
174
  'bossIntent',