@sublang/playbook 15.0.0 → 16.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 (81) hide show
  1. package/README.md +1 -1
  2. package/docs/embedding.md +9 -7
  3. package/package.json +3 -1
  4. package/reference/sdlc/branch.playbook/branch.fsm.d.ts +63 -33
  5. package/reference/sdlc/branch.playbook/branch.fsm.js +190 -108
  6. package/reference/sdlc/branch.playbook/branch.fsm.ts +269 -147
  7. package/reference/sdlc/branch.playbook/branch.gears.md +7 -17
  8. package/reference/sdlc/branch.playbook/branch.playbook.d.ts +12 -16
  9. package/reference/sdlc/branch.playbook/branch.playbook.js +112 -101
  10. package/reference/sdlc/branch.playbook/branch.playbook.ts +128 -171
  11. package/reference/sdlc/branch.playbook/branch.registry.d.ts +3 -2
  12. package/reference/sdlc/branch.playbook/branch.registry.ts +6 -2
  13. package/reference/sdlc/code.playbook/bin/repository-effects.js +54 -13
  14. package/reference/sdlc/code.playbook/code.fsm.d.ts +143 -90
  15. package/reference/sdlc/code.playbook/code.fsm.introspect.d.ts +8 -8
  16. package/reference/sdlc/code.playbook/code.fsm.introspect.ts +13 -13
  17. package/reference/sdlc/code.playbook/code.fsm.js +609 -649
  18. package/reference/sdlc/code.playbook/code.fsm.ts +890 -821
  19. package/reference/sdlc/code.playbook/code.gears.md +39 -29
  20. package/reference/sdlc/code.playbook/code.playbook.d.ts +13 -16
  21. package/reference/sdlc/code.playbook/code.playbook.js +166 -147
  22. package/reference/sdlc/code.playbook/code.playbook.ts +180 -229
  23. package/reference/sdlc/code.playbook/code.registry.d.ts +3 -2
  24. package/reference/sdlc/code.playbook/code.registry.ts +6 -2
  25. package/reference/sdlc/code.playbook/playbook-captain.d.ts +42 -0
  26. package/reference/sdlc/code.playbook/playbook-captain.js +829 -194
  27. package/reference/sdlc/code.playbook/playbook-captain.ts +1227 -220
  28. package/reference/sdlc/decide.md +1 -0
  29. package/reference/sdlc/decide.playbook/decide.fsm.d.ts +270 -154
  30. package/reference/sdlc/decide.playbook/decide.fsm.js +765 -732
  31. package/reference/sdlc/decide.playbook/decide.fsm.ts +1167 -945
  32. package/reference/sdlc/decide.playbook/decide.gears.md +28 -21
  33. package/reference/sdlc/decide.playbook/decide.playbook.d.ts +11 -67
  34. package/reference/sdlc/decide.playbook/decide.playbook.js +155 -3570
  35. package/reference/sdlc/decide.playbook/decide.playbook.ts +186 -5061
  36. package/reference/sdlc/decide.playbook/decide.registry.d.ts +8 -4
  37. package/reference/sdlc/decide.playbook/decide.registry.js +2 -2
  38. package/reference/sdlc/decide.playbook/decide.registry.ts +13 -6
  39. package/reference/sdlc/dev.playbook/dev.fsm.d.ts +113 -131
  40. package/reference/sdlc/dev.playbook/dev.fsm.js +517 -575
  41. package/reference/sdlc/dev.playbook/dev.fsm.ts +667 -787
  42. package/reference/sdlc/dev.playbook/dev.gears.md +52 -54
  43. package/reference/sdlc/dev.playbook/dev.playbook.d.ts +13 -10
  44. package/reference/sdlc/dev.playbook/dev.playbook.js +128 -120
  45. package/reference/sdlc/dev.playbook/dev.playbook.ts +143 -193
  46. package/reference/sdlc/dev.playbook/dev.registry.d.ts +3 -2
  47. package/reference/sdlc/dev.playbook/dev.registry.ts +6 -2
  48. package/reference/sdlc/pr.playbook/pr.fsm.d.ts +92 -85
  49. package/reference/sdlc/pr.playbook/pr.fsm.js +461 -518
  50. package/reference/sdlc/pr.playbook/pr.fsm.ts +533 -663
  51. package/reference/sdlc/pr.playbook/pr.gears.md +47 -63
  52. package/reference/sdlc/pr.playbook/pr.playbook.d.ts +13 -23
  53. package/reference/sdlc/pr.playbook/pr.playbook.js +118 -112
  54. package/reference/sdlc/pr.playbook/pr.playbook.ts +136 -190
  55. package/reference/sdlc/pr.playbook/pr.registry.d.ts +3 -2
  56. package/reference/sdlc/pr.playbook/pr.registry.ts +4 -2
  57. package/reference/sdlc/review.md +3 -3
  58. package/reference/sdlc/review.playbook/review.fsm.d.ts +150 -116
  59. package/reference/sdlc/review.playbook/review.fsm.js +479 -550
  60. package/reference/sdlc/review.playbook/review.fsm.ts +717 -662
  61. package/reference/sdlc/review.playbook/review.gears.md +32 -29
  62. package/reference/sdlc/review.playbook/review.playbook.d.ts +12 -12
  63. package/reference/sdlc/review.playbook/review.playbook.js +180 -155
  64. package/reference/sdlc/review.playbook/review.playbook.ts +190 -230
  65. package/reference/sdlc/review.playbook/review.registry.d.ts +6 -5
  66. package/reference/sdlc/review.playbook/review.registry.js +3 -3
  67. package/reference/sdlc/review.playbook/review.registry.ts +9 -5
  68. package/slc/gears2fsm.md +72 -3
  69. package/slc/link.md +50 -27
  70. package/slc/materialize-link.mjs +51 -13
  71. package/slc/optimize.md +4 -1
  72. package/slc/prefix-prompts.mjs +191 -0
  73. package/slc/prefix.md +203 -0
  74. package/slc/slc.pin-inputs.json +11 -1
  75. package/slc/text2gears.md +71 -11
  76. package/src/xstate-playbook-runtime.d.ts +82 -9
  77. package/src/xstate-playbook-runtime.js +1224 -283
  78. package/src/xstate-playbook-runtime.ts +1671 -338
  79. package/src/xstate-runtime.d.ts +3 -1
  80. package/src/xstate-runtime.js +9 -2
  81. package/src/xstate-runtime.ts +12 -2
@@ -1,30 +1,31 @@
1
1
  <!-- SPDX-License-Identifier: Apache-2.0 -->
2
2
  <!-- SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai> -->
3
3
 
4
- # REVIEW: Scoped Committed-Work Review Workflow
4
+ # Review
5
5
 
6
6
  Roles:
7
7
 
8
8
  - Coder
9
9
  - Reviewer
10
10
 
11
- The caller supplies one caller input carrying the original intent, the review scope in the caller's own words, and optional relevant context and run results.
11
+ The caller supplies, as one caller input, the original intent; the review scope in the caller's own words; and optional relevant context and run results.
12
12
  The caller's review scope is the baseline for every round, and each review-fix commit joins that scope as it lands, so every later round reviews the cumulative committed state.
13
13
  `review` examines committed work only.
14
- Captain takes the evaluated repository revision from repository authority, not from either player's prose: the repository-effect receipt is the authoritative identity of any review-fix commit, and a clean round's `unchanged` receipt proves the observed revision it evaluated.
15
- Finding numbers are references within this review only; no review transition depends on numbering or any fixed presentation format of either player's reply.
16
- Rounds continue until Reviewer affirmatively reports that the requested review is complete and no unsettled findings remain; `review` then returns the exact repository revision at which the review scope was evaluated and the fact that no unsettled findings remain within that scope.
14
+ Captain takes the evaluated repository revision from repository authority, not from either player's prose, and uses the repository-effect receipt as the authoritative identity of any review-fix commit.
15
+ Finding numbers are references within this review only.
16
+ No review transition depends on numbering or any fixed presentation format of either player's reply.
17
+ Reviewer reads the relayed context information and follows the corresponding instructions.
18
+ Rounds continue until Reviewer affirmatively reports that the requested review is complete and no unsettled findings remain; a progress report, status update, or promise of a later result supports no review outcome.
19
+ `review` then returns the exact repository revision at which the review scope was evaluated and the fact that no unsettled findings remain within that scope.
17
20
 
18
21
  ### REVIEW-1
19
22
 
20
- When the caller starts a review, Captain shall relay the complete caller input to Reviewer with the first-round and shared review instructions:
23
+ When the caller starts a review with its input, at the first review round, Captain shall prompt Reviewer:
21
24
 
22
25
  > A new review begins for the review scope.
23
26
  > Keep to the original intent and follow what it asks.
24
27
  > When the scope names commits, read each commit message for its context and rationale; otherwise use repository history and commit messages wherever they help establish that context.
25
28
  >
26
- > > Original request: <caller-input>
27
- >
28
29
  > Understand the full picture and think systematically about the underlying design.
29
30
  > Continue to identify issues or improvements, if any, without duplication.
30
31
  > Number the findings consistently across rounds.
@@ -41,18 +42,17 @@ When the caller starts a review, Captain shall relay the complete caller input t
41
42
  >
42
43
  > Consult @specs/map.md for context if needed; verify it remains accurate.
43
44
  > Consult @specs/meta.md for spec requirements if needed; verify affected specs follow it.
45
+ >
46
+ > > Original request: <caller-input>
44
47
 
45
48
  Results:
46
- - `hasFindings`: Reviewer raised one or more unsettled findings. Output shall include `reviewerOutput: <verbatim final text>`.
47
- - `noFindings`: Reviewer affirmatively reported the requested review complete with no unsettled findings remaining; a progress report, status update, or promise of a later result supports no review outcome. Output shall include `evaluatedRevision: <repository revision>`.
49
+ - `hasFindings`: Reviewer raised one or more unsettled findings; a progress report, status update, or promise of a later result supports no review outcome, and the outcome does not depend on finding numbering or any fixed presentation format of Reviewer's reply. Output shall include `reviewerOutput: <verbatim final text>`.
50
+ - `noFindings`: Reviewer affirmatively reported that the requested review is complete and no unsettled findings remain; a progress report, status update, or promise of a later result supports no review outcome, and the outcome does not depend on finding numbering or any fixed presentation format of Reviewer's reply. On this outcome the workflow returns the exact repository revision at which the review scope was evaluated, taken from repository authority and not from either player's prose, as evaluatedRevision, and the fact that no unsettled findings remain within that scope, as noUnsettledFindings true. Output shall include `evaluatedRevision: <repository revision>`.
48
51
 
49
52
  ### REVIEW-2
50
53
 
51
- When Reviewer raises or keeps any finding, Captain shall relay the caller input and Reviewer's findings to Coder with the disposition prompt:
54
+ When Reviewer raises or keeps any finding, with the repository-effect receipt as the authoritative identity of any review-fix commit, Captain shall prompt Coder:
52
55
 
53
- > > Original request: <caller-input>
54
- > > Reviewer findings: <reviewer-output>
55
- >
56
56
  > For each review item, accept or reject it.
57
57
  > Before deciding, understand the full picture and think systematically about the underlying design.
58
58
  > Keep to the original intent and follow what it asks.
@@ -69,23 +69,22 @@ When Reviewer raises or keeps any finding, Captain shall relay the caller input
69
69
  >
70
70
  > If you reject every item, change nothing and make no commit.
71
71
  > Report every disposition, all relevant run results, and every rebuttal.
72
+ >
73
+ > > Original request: <caller-input>
74
+ > > Reviewer findings: <reviewer-output>
72
75
 
73
76
  Results:
74
- - `committed`: Coder accepted at least one item and added one new review-fix commit. Output shall include `coderOutput: <verbatim final text>` and `latestCommit: <commit identity>`.
75
- - `rejectedAll`: Coder rejected every item and made no commit. Output shall include `coderOutput: <verbatim final text>`.
77
+ - `committed`: Coder made one new review-fix commit; the outcome does not depend on finding numbering or any fixed presentation format of Coder's reply. Output shall include `coderOutput: <verbatim final text>` and `latestCommit: <commit identity>`.
78
+ - `rejectedAll`: Coder rejected every finding, changed nothing, and made no commit; the outcome does not depend on finding numbering or any fixed presentation format of Coder's reply. Output shall include `coderOutput: <verbatim final text>`.
76
79
 
77
80
  ### REVIEW-3
78
81
 
79
- When Coder makes a review-fix commit, Captain shall relay the caller input, the review-fix commit, and Coder's feedback to Reviewer with the next-round and shared review instructions:
82
+ When Coder makes a new review-fix commit, at the start of the next review round, Captain shall prompt Reviewer:
80
83
 
81
84
  > A new review round begins for the review scope in the cumulative committed state, with particular attention to the latest review-fix commit.
82
85
  > Keep to the original intent and follow what it asks.
83
86
  > Read the latest review-fix commit's message and see Coder's feedback below.
84
87
  >
85
- > > Original request: <caller-input>
86
- > > Latest commit: <latest-commit>
87
- > > Coder output: <coder-output>
88
- >
89
88
  > Understand the full picture and think systematically about the underlying design.
90
89
  > Continue to identify issues or improvements, if any, without duplication.
91
90
  > Number the findings consistently across rounds.
@@ -102,21 +101,22 @@ When Coder makes a review-fix commit, Captain shall relay the caller input, the
102
101
  >
103
102
  > Consult @specs/map.md for context if needed; verify it remains accurate.
104
103
  > Consult @specs/meta.md for spec requirements if needed; verify affected specs follow it.
104
+ >
105
+ > > Original request: <caller-input>
106
+ > > Latest commit: <latest-commit>
107
+ > > Coder output: <coder-output>
105
108
 
106
109
  Results:
107
- - `hasFindings`: Reviewer raised one or more unsettled findings. Output shall include `reviewerOutput: <verbatim final text>`.
108
- - `noFindings`: Reviewer affirmatively reported the requested review complete with no unsettled findings remaining; a progress report, status update, or promise of a later result supports no review outcome. Output shall include `evaluatedRevision: <repository revision>`.
110
+ - `hasFindings`: Reviewer raised or kept one or more unsettled findings; a progress report, status update, or promise of a later result supports no review outcome, and the outcome does not depend on finding numbering or any fixed presentation format of Reviewer's reply. Output shall include `reviewerOutput: <verbatim final text>`.
111
+ - `noFindings`: Reviewer affirmatively reported that the requested review is complete and no unsettled findings remain; a progress report, status update, or promise of a later result supports no review outcome, and the outcome does not depend on finding numbering or any fixed presentation format of Reviewer's reply. On this outcome the workflow returns the exact repository revision at which the review scope was evaluated, taken from repository authority and not from either player's prose, as evaluatedRevision, and the fact that no unsettled findings remain within that scope, as noUnsettledFindings true. Output shall include `evaluatedRevision: <repository revision>`.
109
112
 
110
113
  ### REVIEW-4
111
114
 
112
- When Coder rejects every finding and makes no commit, Captain shall relay the caller input and Coder's feedback to Reviewer with the rebuttal and shared review instructions:
115
+ When Coder rejects every finding and makes no commit, at the start of the next review round, Captain shall prompt Reviewer:
113
116
 
114
117
  > No new commit was made because Coder rejected every finding.
115
118
  > See Coder's feedback below.
116
119
  >
117
- > > Original request: <caller-input>
118
- > > Coder output: <coder-output>
119
- >
120
120
  > Understand the full picture and think systematically about the underlying design.
121
121
  > Continue to identify issues or improvements, if any, without duplication.
122
122
  > Number the findings consistently across rounds.
@@ -133,7 +133,10 @@ When Coder rejects every finding and makes no commit, Captain shall relay the ca
133
133
  >
134
134
  > Consult @specs/map.md for context if needed; verify it remains accurate.
135
135
  > Consult @specs/meta.md for spec requirements if needed; verify affected specs follow it.
136
+ >
137
+ > > Original request: <caller-input>
138
+ > > Coder output: <coder-output>
136
139
 
137
140
  Results:
138
- - `hasFindings`: Reviewer kept one or more unsettled findings. Output shall include `reviewerOutput: <verbatim final text>`.
139
- - `noFindings`: Reviewer accepted the rebuttals and affirmatively reported the requested review complete with no unsettled findings remaining; a progress report, status update, or promise of a later result supports no review outcome. Output shall include `evaluatedRevision: <repository revision>`.
141
+ - `hasFindings`: Reviewer raised or kept one or more unsettled findings; a progress report, status update, or promise of a later result supports no review outcome, and the outcome does not depend on finding numbering or any fixed presentation format of Reviewer's reply. Output shall include `reviewerOutput: <verbatim final text>`.
142
+ - `noFindings`: Reviewer affirmatively reported that the requested review is complete and no unsettled findings remain; a progress report, status update, or promise of a later result supports no review outcome, and the outcome does not depend on finding numbering or any fixed presentation format of Reviewer's reply. On this outcome the workflow returns the exact repository revision at which the review scope was evaluated, taken from repository authority and not from either player's prose, as evaluatedRevision, and the fact that no unsettled findings remain within that scope, as noUnsettledFindings true. Output shall include `evaluatedRevision: <repository revision>`.
@@ -1,16 +1,16 @@
1
- import { type XStatePlaybookRuntimeFactory, type XStatePlaybookRuntimeConstruction, type XStatePromptIdentity } from '@sublang/playbook/xstate-runtime';
2
- import { type PlayerInput, type ReviewInput } from './review.fsm.js';
3
- import type { PlaybookHostConstructionCapabilities } from '../code.playbook/playbook-captain.js';
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';
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, };
6
- export type ReviewPlaybookOptions = ReviewInput;
7
- export type ReviewPlaybookHostCapabilities = PlaybookHostConstructionCapabilities & XStatePlaybookRuntimeConstruction<ReviewPlaybookOptions, object>['hostCapabilities'];
8
- /** Keep every line of a relayed runtime value inside its authored quote. */
9
- declare function composePlayerPrompt(input: PlayerInput, promptIdentity: XStatePromptIdentity, resuming?: boolean): string;
1
+ import { type XStatePromptIdentity, type PlaybookPlayerInput, type XStatePlaybookRuntimeConstruction, type XStatePlaybookRuntimeFactory } from '@sublang/playbook/xstate-runtime';
2
+ export type { PlayerResult, PlayerCallOptions, PlayerSessionStore, CaptainResult, CaptainCallOptions, JsonValue, NormalizedError, PlaybookCallRequest, PlaybookCallResult, PlaybookCallStart, PlaybookStateValue, PlaybookState, PlaybookPendingCall, PlaybookRunResult, PlaybookRuntime, PlaybookRuntimeFactory, PlaybookRuntimeSnapshot, PlaybookSession, PlaybookPorts, PlaybookTraceEvent, PlaybookTraceType, PlaybookControlReceipt, PlaybookControlView, } from '@sublang/playbook/runtime';
3
+ export interface PlaybookRuntimeOptions {
4
+ }
5
+ export type PlaybookHostCapabilities = XStatePlaybookRuntimeConstruction<PlaybookRuntimeOptions, {
6
+ readonly authority: object;
7
+ }>['hostCapabilities'];
8
+ export declare function validateOptions(value: unknown): PlaybookRuntimeOptions;
10
9
  export declare const _internal: {
11
- composePlayerPrompt: typeof composePlayerPrompt;
12
- VERBATIM_PAYLOAD_FIELDS: ReadonlySet<string>;
10
+ composePlayerPrompt: (input: PlaybookPlayerInput, promptIdentity: XStatePromptIdentity, resuming?: boolean) => string;
11
+ RESUMABLE_STATE_IDS: ReadonlySet<string>;
13
12
  UNFINISHED_FINAL_STATE_IDS: ReadonlySet<string>;
13
+ VERBATIM_PAYLOAD_FIELDS: ReadonlySet<string>;
14
14
  };
15
- declare const createPlaybookRuntime: XStatePlaybookRuntimeFactory<XStatePlaybookRuntimeConstruction<ReviewPlaybookOptions, ReviewPlaybookHostCapabilities>, 3>;
15
+ declare const createPlaybookRuntime: XStatePlaybookRuntimeFactory<XStatePlaybookRuntimeConstruction<PlaybookRuntimeOptions, PlaybookHostCapabilities>, 3>;
16
16
  export default createPlaybookRuntime;
@@ -1,181 +1,206 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai>
3
- //
4
- // Generated by slc/link.md (FSM-to-Runtime linker).
5
- // Source FSM: ./review.fsm.ts
6
- // Role metadata: Coder→coder, Reviewer→reviewer (canonical local roles)
7
- // Boss event: deterministic START_REVIEW entry; exact Boss text becomes
8
- // callerInput; pending player questions retain BOSS_REPLY
9
- // Adjudication: LLM judge per state; coderOutput and reviewerOutput are
10
- // carried verbatim; latestCommit is receipt-owned effect
11
- // evidence, never taken from either player's prose
12
- // Compat: artifact schema 3 / runtime ABI 1
13
- import { createXStatePlaybookRuntime, composePlayerContinuation, snapshotJsonValue, } from '@sublang/playbook/xstate-runtime';
14
- import { reviewMachine, } from './review.fsm.js';
15
- const PLACEHOLDER = /<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>/g;
3
+ // Generated by slc/materialize-link.mjs; governed by the complete slc/link.md.
4
+ // FSM: "./review.fsm.js"; export: reviewMachine; strategies: shared defaults with labelled string relays and nested actors.
5
+ import { reviewMachine as machine } from "./review.fsm.js";
6
+ import { createXStatePlaybookRuntime, snapshotJsonValue, composePlayerContinuation, } from '@sublang/playbook/xstate-runtime';
7
+ const OPTION_SCHEMA = {};
8
+ const INPUT_MAPPING = {};
9
+ const RESUMABLE_STATE_IDS = new Set([
10
+ "firstReview",
11
+ "fixFindings",
12
+ "reviewAfterFix",
13
+ "reviewAfterRejection"
14
+ ]);
15
+ const UNFINISHED_FINAL_STATE_IDS = new Set([]);
16
16
  const VERBATIM_PAYLOAD_FIELDS = new Set([
17
- 'reviewerOutput',
18
- 'coderOutput',
17
+ "reviewerOutput",
18
+ "coderOutput"
19
19
  ]);
20
- const UNFINISHED_FINAL_STATE_IDS = new Set();
21
- function snapshotReviewOptions(value) {
22
- const captured = snapshotJsonValue(value, 'REVIEW runtime options');
23
- if (captured === null ||
24
- typeof captured !== 'object' ||
25
- Array.isArray(captured)) {
26
- throw new TypeError('REVIEW runtime options must be an object');
20
+ export function validateOptions(value) {
21
+ const captured = snapshotJsonValue(value === undefined ? {} : value, "REVIEW runtime options");
22
+ if (captured === null || typeof captured !== 'object' || Array.isArray(captured)) {
23
+ throw new TypeError("REVIEW runtime options must be an object");
24
+ }
25
+ const fields = captured;
26
+ for (const key of Object.keys(captured)) {
27
+ if (!Object.hasOwn(OPTION_SCHEMA, key))
28
+ throw new TypeError("REVIEW runtime options." + key + ' is not declared');
27
29
  }
28
- const record = captured;
29
- for (const key of Object.keys(record)) {
30
- throw new TypeError(`REVIEW runtime options.${key} is not declared`);
30
+ for (const [key, schema] of Object.entries(OPTION_SCHEMA)) {
31
+ if (!Object.hasOwn(captured, key)) {
32
+ if (schema.required)
33
+ throw new TypeError("REVIEW runtime options." + key + ' is required');
34
+ }
35
+ else if (typeof fields[key] !== schema.type || (schema.type === 'number' && !Number.isFinite(fields[key]))) {
36
+ throw new TypeError("REVIEW runtime options." + key + ' must be a ' + schema.type);
37
+ }
31
38
  }
32
39
  return captured;
33
40
  }
34
- function placeholderField(token) {
35
- if (token === '#')
36
- return 'irNumber';
37
- return token.replace(/-([A-Za-z0-9_$])/g, (_match, next) => next.toUpperCase());
38
- }
39
- function quotedContinuation(value) {
40
- return value.replaceAll('\n', '\n> ');
41
- }
42
- /** Keep every line of a relayed runtime value inside its authored quote. */
43
- function composePlayerPrompt(input, promptIdentity, resuming = false) {
41
+ function renderPlayerPrompt(input, promptIdentity, resuming = false) {
44
42
  const fields = input;
45
- const body = input.prompt.replace(PLACEHOLDER, (match, token, offset, source) => {
46
- const value = token === 'coder-llm'
47
- ? promptIdentity('coder')
48
- : token === 'reviewer-llm'
49
- ? promptIdentity('reviewer')
50
- : fields[placeholderField(token)];
51
- if (typeof value !== 'string')
52
- return match;
53
- const lineStart = source.lastIndexOf('\n', offset - 1) + 1;
54
- return source.slice(lineStart, offset).startsWith('> ')
55
- ? quotedContinuation(value)
56
- : value;
57
- });
43
+ const mapping = {};
44
+ const identities = { "coder-llm": "coder", "reviewer-llm": "reviewer" };
45
+ const omitted = new Set([]);
46
+ const fieldFor = (token) => Object.hasOwn(mapping, token) ? mapping[token] : (token === '#' ? 'irNumber' : token.replace(/-([A-Za-z0-9_$])/g, (_match, next) => next.toUpperCase()));
47
+ const parts = input.prompt.split(/(\r?\n)/);
48
+ let body = '';
49
+ for (let index = 0; index < parts.length; index += 2) {
50
+ const line = parts[index];
51
+ if (omitted.has(line)) {
52
+ const token = /<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>$/.exec(line)[1];
53
+ if (fields[fieldFor(token)] === '')
54
+ continue;
55
+ }
56
+ body += line.replace(/<(#|[A-Za-z_$][A-Za-z0-9_$-]*)>/g, (match, token) => {
57
+ const value = Object.hasOwn(identities, token) ? promptIdentity(identities[token]) : fields[fieldFor(token)];
58
+ if (typeof value !== 'string')
59
+ return match;
60
+ return line.startsWith('> ') ? value.replace(/\r?\n/g, (ending) => ending + '> ') : value;
61
+ }) + (parts[index + 1] ?? '');
62
+ }
58
63
  return composePlayerContinuation(input, body, resuming);
59
64
  }
60
- export const _internal = {
61
- composePlayerPrompt,
62
- VERBATIM_PAYLOAD_FIELDS,
63
- UNFINISHED_FINAL_STATE_IDS,
64
- };
65
+ const composePlayerPrompt = (input, promptIdentity, resuming) => renderPlayerPrompt(input, promptIdentity, resuming);
65
66
  const runtimeSpec = {
66
- label: 'REVIEW',
67
- // DR-022 / slc/link.md: the declaration carries the value current at link
68
- // time — a literal, never the loading engine's RUNTIME_ABI self-report,
69
- // which would follow whatever engine loads the module and make the
70
- // factory's skew check compare that engine with itself.
71
- compat: { artifactSchema: 3, runtimeAbi: 1 },
72
- snapshotOptions: snapshotReviewOptions,
73
- entryEvent: {
74
- type: 'START_REVIEW',
75
- textField: 'callerInput',
76
- // `copyStartInput` copies the entry text here, so the failure-state
77
- // retry reads it back from the persisted machine snapshot and survives
78
- // a continued session (DR-034).
79
- contextField: 'callerInput',
80
- },
81
- roleStates: {
82
- reviewInitial: {
83
- role: 'reviewer',
84
- label: "REVIEW-1: Reviewer reviews the caller's review scope against the original intent.",
85
- },
86
- addressFindings: {
87
- role: 'coder',
88
- label: 'REVIEW-2: Coder accepts or rejects every current review finding.',
89
- },
90
- reviewAfterCommit: {
91
- role: 'reviewer',
92
- label: 'REVIEW-3: Reviewer reviews the cumulative committed state after a review-fix commit.',
67
+ composePlayerPrompt,
68
+ ...{
69
+ "label": "REVIEW",
70
+ "compat": {
71
+ "artifactSchema": 3,
72
+ "runtimeAbi": 1
93
73
  },
94
- reviewAfterRebuttal: {
95
- role: 'reviewer',
96
- label: 'REVIEW-4: Reviewer adjudicates an all-rejected Coder disposition.',
74
+ "entryEvent": {
75
+ "type": "START_REVIEW",
76
+ "textField": "callerInput",
77
+ "contextField": "callerInput"
97
78
  },
98
- },
99
- outcomeAuthority: {
100
- governedPlayerStates: {
101
- reviewInitial: {
102
- hasFindings: {
103
- fields: { reviewerOutput: 'presentation' },
104
- repositoryDisposition: 'unchanged',
105
- },
106
- noFindings: {
107
- // DR-045: the clean round's unchanged receipt observes the exact
108
- // evaluated revision as HEAD; the reconciler injects it here.
109
- fields: { evaluatedRevision: 'effect' },
110
- repositoryDisposition: 'unchanged',
111
- },
112
- needsBossReply: {
113
- fields: { question: 'presentation' },
114
- repositoryDisposition: 'unchanged',
115
- },
79
+ "bossEvents": [],
80
+ "roleStates": {
81
+ "firstReview": {
82
+ "role": "reviewer",
83
+ "label": "Reviewer runs the first review round over the review scope."
116
84
  },
117
- addressFindings: {
118
- committed: {
119
- fields: {
120
- coderOutput: 'presentation',
121
- latestCommit: 'effect',
122
- },
123
- repositoryDisposition: 'one-descendant-commit',
124
- },
125
- rejectedAll: {
126
- fields: { coderOutput: 'presentation' },
127
- repositoryDisposition: 'unchanged',
128
- },
129
- needsBossReply: {
130
- fields: { question: 'presentation' },
131
- repositoryDisposition: 'deferred',
132
- },
85
+ "fixFindings": {
86
+ "role": "coder",
87
+ "label": "Coder accepts or rejects each of Reviewer's findings and commits any accepted fixes."
133
88
  },
134
- reviewAfterCommit: {
135
- hasFindings: {
136
- fields: { reviewerOutput: 'presentation' },
137
- repositoryDisposition: 'unchanged',
138
- },
139
- noFindings: {
140
- // DR-045: the clean round's unchanged receipt observes the exact
141
- // evaluated revision as HEAD; the reconciler injects it here.
142
- fields: { evaluatedRevision: 'effect' },
143
- repositoryDisposition: 'unchanged',
144
- },
145
- needsBossReply: {
146
- fields: { question: 'presentation' },
147
- repositoryDisposition: 'unchanged',
148
- },
89
+ "reviewAfterFix": {
90
+ "role": "reviewer",
91
+ "label": "Reviewer runs the next review round over the cumulative committed state after a review-fix commit."
149
92
  },
150
- reviewAfterRebuttal: {
151
- hasFindings: {
152
- fields: { reviewerOutput: 'presentation' },
153
- repositoryDisposition: 'unchanged',
93
+ "reviewAfterRejection": {
94
+ "role": "reviewer",
95
+ "label": "Reviewer runs the next review round after Coder rejected every finding without a commit."
96
+ }
97
+ },
98
+ "outcomeAuthority": {
99
+ "governedPlayerStates": {
100
+ "firstReview": {
101
+ "hasFindings": {
102
+ "fields": {
103
+ "reviewerOutput": "presentation"
104
+ },
105
+ "repositoryDisposition": "unchanged"
106
+ },
107
+ "noFindings": {
108
+ "fields": {
109
+ "evaluatedRevision": "effect"
110
+ },
111
+ "repositoryDisposition": "unchanged"
112
+ },
113
+ "needsBossReply": {
114
+ "fields": {
115
+ "question": "presentation"
116
+ },
117
+ "repositoryDisposition": "unchanged"
118
+ }
154
119
  },
155
- noFindings: {
156
- // DR-045: the clean round's unchanged receipt observes the exact
157
- // evaluated revision as HEAD; the reconciler injects it here.
158
- fields: { evaluatedRevision: 'effect' },
159
- repositoryDisposition: 'unchanged',
120
+ "fixFindings": {
121
+ "committed": {
122
+ "fields": {
123
+ "coderOutput": "presentation",
124
+ "latestCommit": "effect"
125
+ },
126
+ "repositoryDisposition": "one-descendant-commit"
127
+ },
128
+ "rejectedAll": {
129
+ "fields": {
130
+ "coderOutput": "presentation"
131
+ },
132
+ "repositoryDisposition": "unchanged"
133
+ },
134
+ "needsBossReply": {
135
+ "fields": {
136
+ "question": "presentation"
137
+ },
138
+ "repositoryDisposition": "deferred"
139
+ }
160
140
  },
161
- needsBossReply: {
162
- fields: { question: 'presentation' },
163
- repositoryDisposition: 'unchanged',
141
+ "reviewAfterFix": {
142
+ "hasFindings": {
143
+ "fields": {
144
+ "reviewerOutput": "presentation"
145
+ },
146
+ "repositoryDisposition": "unchanged"
147
+ },
148
+ "noFindings": {
149
+ "fields": {
150
+ "evaluatedRevision": "effect"
151
+ },
152
+ "repositoryDisposition": "unchanged"
153
+ },
154
+ "needsBossReply": {
155
+ "fields": {
156
+ "question": "presentation"
157
+ },
158
+ "repositoryDisposition": "unchanged"
159
+ }
164
160
  },
165
- },
161
+ "reviewAfterRejection": {
162
+ "hasFindings": {
163
+ "fields": {
164
+ "reviewerOutput": "presentation"
165
+ },
166
+ "repositoryDisposition": "unchanged"
167
+ },
168
+ "noFindings": {
169
+ "fields": {
170
+ "evaluatedRevision": "effect"
171
+ },
172
+ "repositoryDisposition": "unchanged"
173
+ },
174
+ "needsBossReply": {
175
+ "fields": {
176
+ "question": "presentation"
177
+ },
178
+ "repositoryDisposition": "unchanged"
179
+ }
180
+ }
181
+ }
166
182
  },
183
+ "placeholderFields": {},
184
+ "transitionEventFields": [
185
+ "callerInput",
186
+ "targetId",
187
+ "answer",
188
+ "questionId"
189
+ ],
190
+ "controlContextFields": []
167
191
  },
168
- composePlayerPrompt: (input, promptIdentity, resuming) => composePlayerPrompt(input, promptIdentity, resuming),
192
+ snapshotOptions: validateOptions,
193
+ machineInput: (options) => Object.fromEntries(Object.entries(INPUT_MAPPING).filter(([, key]) => options[key] !== undefined)
194
+ .map(([field, key]) => [field, options[key]])),
169
195
  verbatimPayloadFields: VERBATIM_PAYLOAD_FIELDS,
170
- controlContextFields: [],
196
+ resumableStateIds: RESUMABLE_STATE_IDS,
171
197
  unfinishedFinalStateIds: UNFINISHED_FINAL_STATE_IDS,
172
- transitionEventFields: [
173
- 'callerInput',
174
- 'bossIntent',
175
- 'targetId',
176
- 'answer',
177
- 'questionId',
178
- ],
179
198
  };
180
- const createPlaybookRuntime = createXStatePlaybookRuntime(reviewMachine, runtimeSpec);
199
+ export const _internal = {
200
+ composePlayerPrompt,
201
+ RESUMABLE_STATE_IDS,
202
+ UNFINISHED_FINAL_STATE_IDS,
203
+ VERBATIM_PAYLOAD_FIELDS,
204
+ };
205
+ const createPlaybookRuntime = createXStatePlaybookRuntime(machine, runtimeSpec);
181
206
  export default createPlaybookRuntime;