@sublang/playbook 11.0.0 → 12.1.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 (49) hide show
  1. package/docs/cli.md +9 -6
  2. package/docs/configuration.md +15 -1
  3. package/docs/embedding.md +83 -1
  4. package/package.json +28 -3
  5. package/reference/sdlc/code.playbook/bin/repository-effects.js +501 -170
  6. package/reference/sdlc/code.playbook/bin/session-store.js +4 -1
  7. package/reference/sdlc/code.playbook/code.fsm.d.ts +22 -19
  8. package/reference/sdlc/code.playbook/code.fsm.js +116 -52
  9. package/reference/sdlc/code.playbook/code.fsm.ts +149 -64
  10. package/reference/sdlc/code.playbook/code.gears.md +40 -20
  11. package/reference/sdlc/code.playbook/code.playbook.js +23 -2
  12. package/reference/sdlc/code.playbook/code.playbook.ts +23 -2
  13. package/reference/sdlc/code.playbook/host-capabilities.d.ts +291 -0
  14. package/reference/sdlc/code.playbook/host-capabilities.js +40 -0
  15. package/reference/sdlc/code.playbook/playbook.config.template.yaml +18 -2
  16. package/reference/sdlc/decide.playbook/decide.fsm.d.ts +13 -6
  17. package/reference/sdlc/decide.playbook/decide.fsm.js +54 -27
  18. package/reference/sdlc/decide.playbook/decide.fsm.ts +68 -29
  19. package/reference/sdlc/decide.playbook/decide.gears.md +25 -19
  20. package/reference/sdlc/decide.playbook/decide.playbook.js +11 -3
  21. package/reference/sdlc/decide.playbook/decide.playbook.ts +11 -3
  22. package/reference/sdlc/decide.playbook/decide.registry.js +1 -1
  23. package/reference/sdlc/decide.playbook/decide.registry.ts +1 -1
  24. package/reference/sdlc/dev.md +52 -0
  25. package/reference/sdlc/dev.playbook/dev.fsm.d.ts +261 -0
  26. package/reference/sdlc/dev.playbook/dev.fsm.js +723 -0
  27. package/reference/sdlc/dev.playbook/dev.fsm.ts +988 -0
  28. package/reference/sdlc/dev.playbook/dev.gears.md +91 -0
  29. package/reference/sdlc/dev.playbook/dev.playbook.d.ts +21 -0
  30. package/reference/sdlc/dev.playbook/dev.playbook.js +143 -0
  31. package/reference/sdlc/dev.playbook/dev.playbook.ts +246 -0
  32. package/reference/sdlc/dev.playbook/dev.registry.d.ts +40 -0
  33. package/reference/sdlc/dev.playbook/dev.registry.js +64 -0
  34. package/reference/sdlc/dev.playbook/dev.registry.ts +120 -0
  35. package/reference/sdlc/review.playbook/review.fsm.d.ts +15 -2
  36. package/reference/sdlc/review.playbook/review.fsm.js +77 -27
  37. package/reference/sdlc/review.playbook/review.fsm.ts +96 -30
  38. package/reference/sdlc/review.playbook/review.gears.md +52 -26
  39. package/reference/sdlc/review.playbook/review.playbook.js +17 -7
  40. package/reference/sdlc/review.playbook/review.playbook.ts +17 -7
  41. package/reference/sdlc/review.playbook/review.registry.js +1 -1
  42. package/reference/sdlc/review.playbook/review.registry.ts +1 -1
  43. package/slc/gears2fsm.md +20 -0
  44. package/slc/link.md +28 -5
  45. package/slc/text2gears.md +21 -1
  46. package/src/xstate-playbook-runtime.js +5 -2
  47. package/src/xstate-playbook-runtime.ts +5 -2
  48. package/src/xstate-runtime.js +13 -1
  49. package/src/xstate-runtime.ts +13 -1
@@ -25,8 +25,14 @@ export interface PendingBossQuestion {
25
25
  }
26
26
 
27
27
  export interface ReviewOutput {
28
- approvedCommit: 'latest';
29
28
  noUnsettledFindings: true;
29
+ /**
30
+ * Exact receipt-derived repository revision at which the review scope was
31
+ * evaluated: the closing clean round's `unchanged` receipt observes it as
32
+ * HEAD — the last review-fix commit when one landed, or the caller-supplied
33
+ * scope revision when none did (DR-045).
34
+ */
35
+ evaluatedRevision: string;
30
36
  }
31
37
 
32
38
  export type ReviewInput = Readonly<Record<string, never>>;
@@ -35,6 +41,10 @@ export interface ReviewContext {
35
41
  callerInput?: string;
36
42
  reviewerOutput?: string;
37
43
  coderOutput?: string;
44
+ /** Receipt-derived OID of the latest review-fix commit (never player prose). */
45
+ latestCommit?: string;
46
+ /** Observed HEAD of the closing clean round's unchanged receipt (DR-045). */
47
+ evaluatedRevision?: string;
38
48
  lastError?: unknown;
39
49
  pendingBossQuestion?: PendingBossQuestion;
40
50
  bossReply?: string;
@@ -62,14 +72,15 @@ export interface PlayerInput {
62
72
  callerInput?: string;
63
73
  reviewerOutput?: string;
64
74
  coderOutput?: string;
75
+ latestCommit?: string;
65
76
  pendingBossQuestion?: PendingBossQuestion;
66
77
  bossReply?: string;
67
78
  }
68
79
 
69
80
  export type PlayerOutput =
70
81
  | { guard: 'hasFindings'; reviewerOutput: string }
71
- | { guard: 'noFindings' }
72
- | { guard: 'committed'; coderOutput: string }
82
+ | { guard: 'noFindings'; evaluatedRevision: string }
83
+ | { guard: 'committed'; coderOutput: string; latestCommit: string }
73
84
  | { guard: 'rejectedAll'; coderOutput: string }
74
85
  | { guard: 'needsBossReply'; question: string };
75
86
 
@@ -80,13 +91,16 @@ const NEEDS_BOSS_REPLY_DESCRIPTION =
80
91
 
81
92
  const SHARED_REVIEW_INSTRUCTION = [
82
93
  'Understand the full picture and think systematically about the underlying design.',
83
- 'Continue to identify issues or improvements, if any (numbered; no duplication).',
84
- 'For any rebuttal, accept or challenge it.',
85
- 'Treat as settled, and do not raise again, any finding in this review rejected twice with reasoning.',
94
+ 'Continue to identify issues or improvements, if any, without duplication.',
95
+ 'Number the findings consistently across rounds.',
86
96
  'Flag only what materially affects correctness, behavior, or spec quality — not style, equally valid alternatives, or theoretical threats.',
87
- 'For specs, flag stale, missing, over-specified, or under-specified ones.',
97
+ 'For specs, flag stale, missing, over-specified, or under-specified ones, if any.',
88
98
  'Avoid unnecessary complexity in code or tests, but flag any fundamental design flaw when leaving it would cost more in later patches than fixing it now.',
89
99
  '',
100
+ 'If an issue represents a class of defect, find every instance within the review scope worth fixing rather than surfacing one or two per round, which drags out the review.',
101
+ 'For any rebuttal, accept or challenge it.',
102
+ 'Treat as settled, and do not raise again, any finding in this review rejected twice with reasoning.',
103
+ '',
90
104
  'Do not re-run tests or builds whose inputs have not changed since any previous reported run.',
91
105
  'Do not edit files or commit; report findings only.',
92
106
  '',
@@ -95,8 +109,9 @@ const SHARED_REVIEW_INSTRUCTION = [
95
109
  ].join('\n');
96
110
 
97
111
  const INITIAL_REVIEW_PROMPT = [
98
- 'A new review begins on the latest commit.',
99
- 'Review the latest commit and resulting repository state; read the commit message first for its intent, scope, and rationale.',
112
+ 'A new review begins for the review scope.',
113
+ 'Keep to the original intent and follow what it asks.',
114
+ '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.',
100
115
  '',
101
116
  '> <caller-input>',
102
117
  '',
@@ -104,8 +119,12 @@ const INITIAL_REVIEW_PROMPT = [
104
119
  ].join('\n');
105
120
 
106
121
  const POST_COMMIT_REVIEW_PROMPT = [
107
- 'Review the latest commit and resulting repository state; read the commit message first for its intent, scope, and rationale.',
122
+ 'A new review round begins for the review scope in the cumulative committed state, with particular attention to the latest review-fix commit.',
123
+ 'Keep to the original intent and follow what it asks.',
124
+ "Read the latest review-fix commit's message and see Coder's feedback below.",
108
125
  '',
126
+ '> <caller-input>',
127
+ '> <latest-commit>',
109
128
  '> <coder-output>',
110
129
  '',
111
130
  SHARED_REVIEW_INSTRUCTION,
@@ -113,26 +132,31 @@ const POST_COMMIT_REVIEW_PROMPT = [
113
132
 
114
133
  const REBUTTAL_REVIEW_PROMPT = [
115
134
  'No new commit was made because Coder rejected every finding.',
135
+ "See Coder's feedback below.",
116
136
  '',
137
+ '> <caller-input>',
117
138
  '> <coder-output>',
118
139
  '',
119
140
  SHARED_REVIEW_INSTRUCTION,
120
141
  ].join('\n');
121
142
 
122
143
  const CODER_DISPOSITION_PROMPT = [
144
+ '> <caller-input>',
123
145
  '> <reviewer-output>',
124
146
  '',
125
147
  'For each review item, accept or reject it.',
126
148
  'Before deciding, understand the full picture and think systematically about the underlying design.',
149
+ 'Keep to the original intent and follow what it asks.',
127
150
  'Reject anything that is not essential or is not worth fixing now.',
128
- 'If you accept an item, fix its root cause, including any fundamental design flaw - do not patch around it.',
151
+ 'If you accept an item, fix its root cause, including any fundamental design flaw do not patch around it; if it represents a class of defect, find every instance within the review scope worth fixing rather than addressing one or two per round, which drags out the review.',
129
152
  'If you reject an item, give the reasoning and cite code or test output that supports it.',
130
153
  'Do not re-run tests or builds whose inputs have not changed since any previous reported run.',
131
154
  '',
132
- 'If you accept any item, make minimal changes and commit them as one new commit; never amend the reviewed commit.',
155
+ 'If you accept any item, make minimal changes and add one new review-fix commit; never rewrite any existing commit.',
133
156
  'Follow @specs/packages/git.md.',
134
157
  'Make the commit message explain concisely what changed and why, including relevant verification.',
135
- 'Coder is <coder-llm>; Reviewer is <reviewer-llm>; format model tokens in conventional human form.',
158
+ 'Identify every new commit you make.',
159
+ 'Coder is <coder-llm>; Reviewer is <reviewer-llm>.',
136
160
  '',
137
161
  'If you reject every item, change nothing and make no commit.',
138
162
  'Report every disposition, all relevant run results, and every rebuttal.',
@@ -141,7 +165,8 @@ const CODER_DISPOSITION_PROMPT = [
141
165
  const REVIEW_RESULTS = {
142
166
  hasFindings:
143
167
  'Reviewer raised one or more unsettled findings. Output shall include `reviewerOutput: <verbatim final text>`.',
144
- noFindings: 'Reviewer raised no unsettled findings.',
168
+ noFindings:
169
+ '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>`.',
145
170
  needsBossReply: NEEDS_BOSS_REPLY_DESCRIPTION,
146
171
  } as const;
147
172
 
@@ -149,31 +174,31 @@ const REBUTTAL_RESULTS = {
149
174
  hasFindings:
150
175
  'Reviewer kept one or more unsettled findings. Output shall include `reviewerOutput: <verbatim final text>`.',
151
176
  noFindings:
152
- 'Reviewer accepted the rebuttals and no unsettled findings remain.',
177
+ '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>`.',
153
178
  needsBossReply: NEEDS_BOSS_REPLY_DESCRIPTION,
154
179
  } as const;
155
180
 
156
181
  const CODER_RESULTS = {
157
182
  committed:
158
- 'Coder accepted at least one item and made one new commit. Output shall include `coderOutput: <verbatim final text>`.',
183
+ 'Coder accepted at least one item and added one new review-fix commit. Output shall include `coderOutput: <verbatim final text>` and `latestCommit: <commit identity>`.',
159
184
  rejectedAll:
160
185
  'Coder rejected every item and made no commit. Output shall include `coderOutput: <verbatim final text>`.',
161
186
  needsBossReply: NEEDS_BOSS_REPLY_DESCRIPTION,
162
187
  } as const;
163
188
 
164
189
  const stateDescriptions = {
165
- ready: 'Waits for a caller to start a committed-work review.',
190
+ ready: 'Waits for a caller to start a scoped committed-work review.',
166
191
  reviewInitial:
167
- 'REVIEW-1: Reviewer examines the latest commit against the caller input.',
192
+ "REVIEW-1: Reviewer reviews the caller's review scope against the original intent.",
168
193
  addressFindings:
169
194
  'REVIEW-2: Coder accepts or rejects every current review finding.',
170
195
  reviewAfterCommit:
171
- 'REVIEW-3: Reviewer examines the new review-fix commit and repository state.',
196
+ 'REVIEW-3: Reviewer reviews the cumulative committed state after a review-fix commit.',
172
197
  reviewAfterRebuttal:
173
198
  'REVIEW-4: Reviewer adjudicates an all-rejected Coder disposition.',
174
199
  awaitBossReply: 'Waits for Boss to answer the active player question.',
175
200
  failed: 'Retains a recoverable REVIEW failure for the caller.',
176
- done: 'The latest commit is approved with no unsettled findings.',
201
+ done: 'The requested review is complete: no unsettled findings remain within the review scope.',
177
202
  } as const;
178
203
 
179
204
  const playbookMeta = <StateId extends keyof typeof stateDescriptions>(
@@ -240,11 +265,19 @@ export const reviewMachine = setup({
240
265
  isNonEmptyString(output.reviewerOutput)
241
266
  );
242
267
  },
243
- noFindings: ({ event }) => outputOf(event).guard === 'noFindings',
268
+ noFindings: ({ event }) => {
269
+ const output = outputOf(event);
270
+ return (
271
+ output.guard === 'noFindings' &&
272
+ isNonEmptyString(output.evaluatedRevision)
273
+ );
274
+ },
244
275
  committed: ({ event }) => {
245
276
  const output = outputOf(event);
246
277
  return (
247
- output.guard === 'committed' && isNonEmptyString(output.coderOutput)
278
+ output.guard === 'committed' &&
279
+ isNonEmptyString(output.coderOutput) &&
280
+ isNonEmptyString(output.latestCommit)
248
281
  );
249
282
  },
250
283
  rejectedAll: ({ event }) => {
@@ -305,6 +338,8 @@ export const reviewMachine = setup({
305
338
  event.type === 'START_REVIEW' ? event.callerInput : undefined,
306
339
  reviewerOutput: undefined,
307
340
  coderOutput: undefined,
341
+ latestCommit: undefined,
342
+ evaluatedRevision: undefined,
308
343
  lastError: undefined,
309
344
  pendingBossQuestion: undefined,
310
345
  bossReply: undefined,
@@ -314,6 +349,8 @@ export const reviewMachine = setup({
314
349
  event.type === 'BOSS_INTERRUPT' ? event.bossIntent : undefined,
315
350
  reviewerOutput: undefined,
316
351
  coderOutput: undefined,
352
+ latestCommit: undefined,
353
+ evaluatedRevision: undefined,
317
354
  lastError: undefined,
318
355
  pendingBossQuestion: undefined,
319
356
  bossReply: undefined,
@@ -336,11 +373,29 @@ export const reviewMachine = setup({
336
373
  ? output.coderOutput
337
374
  : undefined;
338
375
  },
376
+ // The receipt-derived review-fix commit identity replaces the prior one
377
+ // only when Coder committed; an all-rejected round leaves the evaluated
378
+ // revision unchanged.
379
+ latestCommit: ({ context, event }) => {
380
+ const output = outputOf(event);
381
+ return output.guard === 'committed'
382
+ ? output.latestCommit
383
+ : context.latestCommit;
384
+ },
339
385
  lastError: undefined,
340
386
  pendingBossQuestion: undefined,
341
387
  bossReply: undefined,
342
388
  }),
343
- clearBossReplyContext: assign({
389
+ rememberEvaluatedRevision: assign({
390
+ // DR-045: the closing clean round's unchanged receipt observes the
391
+ // exact revision the review scope was evaluated at.
392
+ evaluatedRevision: ({ context, event }) => {
393
+ const output = outputOf(event);
394
+ return output.guard === 'noFindings'
395
+ ? output.evaluatedRevision
396
+ : context.evaluatedRevision;
397
+ },
398
+ lastError: undefined,
344
399
  pendingBossQuestion: undefined,
345
400
  bossReply: undefined,
346
401
  }),
@@ -478,7 +533,7 @@ export const reviewMachine = setup({
478
533
  acceptedOutcome: 'noFindings',
479
534
  },
480
535
  },
481
- 'clearBossReplyContext',
536
+ 'rememberEvaluatedRevision',
482
537
  ],
483
538
  },
484
539
  {
@@ -516,6 +571,7 @@ export const reviewMachine = setup({
516
571
  role: 'coder',
517
572
  prompt: CODER_DISPOSITION_PROMPT,
518
573
  result: CODER_RESULTS,
574
+ callerInput: context.callerInput,
519
575
  reviewerOutput: context.reviewerOutput,
520
576
  pendingBossQuestion: context.pendingBossQuestion,
521
577
  bossReply: context.bossReply,
@@ -586,6 +642,8 @@ export const reviewMachine = setup({
586
642
  role: 'reviewer',
587
643
  prompt: POST_COMMIT_REVIEW_PROMPT,
588
644
  result: REVIEW_RESULTS,
645
+ callerInput: context.callerInput,
646
+ latestCommit: context.latestCommit,
589
647
  coderOutput: context.coderOutput,
590
648
  pendingBossQuestion: context.pendingBossQuestion,
591
649
  bossReply: context.bossReply,
@@ -618,7 +676,7 @@ export const reviewMachine = setup({
618
676
  acceptedOutcome: 'noFindings',
619
677
  },
620
678
  },
621
- 'clearBossReplyContext',
679
+ 'rememberEvaluatedRevision',
622
680
  ],
623
681
  },
624
682
  {
@@ -656,6 +714,7 @@ export const reviewMachine = setup({
656
714
  role: 'reviewer',
657
715
  prompt: REBUTTAL_REVIEW_PROMPT,
658
716
  result: REBUTTAL_RESULTS,
717
+ callerInput: context.callerInput,
659
718
  coderOutput: context.coderOutput,
660
719
  pendingBossQuestion: context.pendingBossQuestion,
661
720
  bossReply: context.bossReply,
@@ -688,7 +747,7 @@ export const reviewMachine = setup({
688
747
  acceptedOutcome: 'noFindings',
689
748
  },
690
749
  },
691
- 'clearBossReplyContext',
750
+ 'rememberEvaluatedRevision',
692
751
  ],
693
752
  },
694
753
  {
@@ -777,8 +836,15 @@ export const reviewMachine = setup({
777
836
  type: 'final',
778
837
  },
779
838
  },
780
- output: (): ReviewOutput => ({
781
- approvedCommit: 'latest',
782
- noUnsettledFindings: true,
783
- }),
839
+ output: ({ context }): ReviewOutput => {
840
+ if (!isNonEmptyString(context.evaluatedRevision)) {
841
+ throw new Error(
842
+ 'REVIEW reached done without a receipt-observed evaluated revision',
843
+ );
844
+ }
845
+ return {
846
+ noUnsettledFindings: true,
847
+ evaluatedRevision: context.evaluatedRevision,
848
+ };
849
+ },
784
850
  });
@@ -1,30 +1,41 @@
1
1
  <!-- SPDX-License-Identifier: Apache-2.0 -->
2
2
  <!-- SPDX-FileCopyrightText: 2026 SubLang International <https://sublang.ai> -->
3
3
 
4
- # REVIEW: Commit Review Workflow
4
+ # REVIEW: Scoped Committed-Work Review Workflow
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.
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
+ `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.
17
+
11
18
  ### REVIEW-1
12
19
 
13
20
  When the caller starts a review, Captain shall relay the complete caller input to Reviewer with the first-round and shared review instructions:
14
21
 
15
- > A new review begins on the latest commit.
16
- > Review the latest commit and resulting repository state; read the commit message first for its intent, scope, and rationale.
22
+ > A new review begins for the review scope.
23
+ > Keep to the original intent and follow what it asks.
24
+ > 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.
17
25
  >
18
26
  > > <caller-input>
19
27
  >
20
28
  > Understand the full picture and think systematically about the underlying design.
21
- > Continue to identify issues or improvements, if any (numbered; no duplication).
22
- > For any rebuttal, accept or challenge it.
23
- > Treat as settled, and do not raise again, any finding in this review rejected twice with reasoning.
29
+ > Continue to identify issues or improvements, if any, without duplication.
30
+ > Number the findings consistently across rounds.
24
31
  > Flag only what materially affects correctness, behavior, or spec quality — not style, equally valid alternatives, or theoretical threats.
25
- > For specs, flag stale, missing, over-specified, or under-specified ones.
32
+ > For specs, flag stale, missing, over-specified, or under-specified ones, if any.
26
33
  > Avoid unnecessary complexity in code or tests, but flag any fundamental design flaw when leaving it would cost more in later patches than fixing it now.
27
34
  >
35
+ > If an issue represents a class of defect, find every instance within the review scope worth fixing rather than surfacing one or two per round, which drags out the review.
36
+ > For any rebuttal, accept or challenge it.
37
+ > Treat as settled, and do not raise again, any finding in this review rejected twice with reasoning.
38
+ >
28
39
  > Do not re-run tests or builds whose inputs have not changed since any previous reported run.
29
40
  > Do not edit files or commit; report findings only.
30
41
  >
@@ -33,49 +44,59 @@ When the caller starts a review, Captain shall relay the complete caller input t
33
44
 
34
45
  Results:
35
46
  - `hasFindings`: Reviewer raised one or more unsettled findings. Output shall include `reviewerOutput: <verbatim final text>`.
36
- - `noFindings`: Reviewer raised no unsettled findings.
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>`.
37
48
 
38
49
  ### REVIEW-2
39
50
 
40
- When Reviewer raises or keeps any finding, Captain shall relay Reviewer's output to Coder with the disposition instruction:
51
+ When Reviewer raises or keeps any finding, Captain shall relay the caller input and Reviewer's findings to Coder with the disposition prompt:
41
52
 
53
+ > > <caller-input>
42
54
  > > <reviewer-output>
43
55
  >
44
56
  > For each review item, accept or reject it.
45
57
  > Before deciding, understand the full picture and think systematically about the underlying design.
58
+ > Keep to the original intent and follow what it asks.
46
59
  > Reject anything that is not essential or is not worth fixing now.
47
- > If you accept an item, fix its root cause, including any fundamental design flaw - do not patch around it.
60
+ > If you accept an item, fix its root cause, including any fundamental design flaw do not patch around it; if it represents a class of defect, find every instance within the review scope worth fixing rather than addressing one or two per round, which drags out the review.
48
61
  > If you reject an item, give the reasoning and cite code or test output that supports it.
49
62
  > Do not re-run tests or builds whose inputs have not changed since any previous reported run.
50
63
  >
51
- > If you accept any item, make minimal changes and commit them as one new commit; never amend the reviewed commit.
64
+ > If you accept any item, make minimal changes and add one new review-fix commit; never rewrite any existing commit.
52
65
  > Follow @specs/packages/git.md.
53
66
  > Make the commit message explain concisely what changed and why, including relevant verification.
54
- > Coder is <coder-llm>; Reviewer is <reviewer-llm>; format model tokens in conventional human form.
67
+ > Identify every new commit you make.
68
+ > Coder is <coder-llm>; Reviewer is <reviewer-llm>.
55
69
  >
56
70
  > If you reject every item, change nothing and make no commit.
57
71
  > Report every disposition, all relevant run results, and every rebuttal.
58
72
 
59
73
  Results:
60
- - `committed`: Coder accepted at least one item and made one new commit. Output shall include `coderOutput: <verbatim final text>`.
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>`.
61
75
  - `rejectedAll`: Coder rejected every item and made no commit. Output shall include `coderOutput: <verbatim final text>`.
62
76
 
63
77
  ### REVIEW-3
64
78
 
65
- When Coder makes a review-fix commit, Captain shall relay Coder's output to Reviewer with the next-round and shared review instructions:
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:
66
80
 
67
- > Review the latest commit and resulting repository state; read the commit message first for its intent, scope, and rationale.
81
+ > A new review round begins for the review scope in the cumulative committed state, with particular attention to the latest review-fix commit.
82
+ > Keep to the original intent and follow what it asks.
83
+ > Read the latest review-fix commit's message and see Coder's feedback below.
68
84
  >
85
+ > > <caller-input>
86
+ > > <latest-commit>
69
87
  > > <coder-output>
70
88
  >
71
89
  > Understand the full picture and think systematically about the underlying design.
72
- > Continue to identify issues or improvements, if any (numbered; no duplication).
73
- > For any rebuttal, accept or challenge it.
74
- > Treat as settled, and do not raise again, any finding in this review rejected twice with reasoning.
90
+ > Continue to identify issues or improvements, if any, without duplication.
91
+ > Number the findings consistently across rounds.
75
92
  > Flag only what materially affects correctness, behavior, or spec quality — not style, equally valid alternatives, or theoretical threats.
76
- > For specs, flag stale, missing, over-specified, or under-specified ones.
93
+ > For specs, flag stale, missing, over-specified, or under-specified ones, if any.
77
94
  > Avoid unnecessary complexity in code or tests, but flag any fundamental design flaw when leaving it would cost more in later patches than fixing it now.
78
95
  >
96
+ > If an issue represents a class of defect, find every instance within the review scope worth fixing rather than surfacing one or two per round, which drags out the review.
97
+ > For any rebuttal, accept or challenge it.
98
+ > Treat as settled, and do not raise again, any finding in this review rejected twice with reasoning.
99
+ >
79
100
  > Do not re-run tests or builds whose inputs have not changed since any previous reported run.
80
101
  > Do not edit files or commit; report findings only.
81
102
  >
@@ -84,24 +105,29 @@ When Coder makes a review-fix commit, Captain shall relay Coder's output to Revi
84
105
 
85
106
  Results:
86
107
  - `hasFindings`: Reviewer raised one or more unsettled findings. Output shall include `reviewerOutput: <verbatim final text>`.
87
- - `noFindings`: Reviewer raised no unsettled findings.
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>`.
88
109
 
89
110
  ### REVIEW-4
90
111
 
91
- When Coder rejects every finding and makes no commit, Captain shall relay Coder's output to Reviewer with the rebuttal and shared review instructions:
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:
92
113
 
93
114
  > No new commit was made because Coder rejected every finding.
115
+ > See Coder's feedback below.
94
116
  >
117
+ > > <caller-input>
95
118
  > > <coder-output>
96
119
  >
97
120
  > Understand the full picture and think systematically about the underlying design.
98
- > Continue to identify issues or improvements, if any (numbered; no duplication).
99
- > For any rebuttal, accept or challenge it.
100
- > Treat as settled, and do not raise again, any finding in this review rejected twice with reasoning.
121
+ > Continue to identify issues or improvements, if any, without duplication.
122
+ > Number the findings consistently across rounds.
101
123
  > Flag only what materially affects correctness, behavior, or spec quality — not style, equally valid alternatives, or theoretical threats.
102
- > For specs, flag stale, missing, over-specified, or under-specified ones.
124
+ > For specs, flag stale, missing, over-specified, or under-specified ones, if any.
103
125
  > Avoid unnecessary complexity in code or tests, but flag any fundamental design flaw when leaving it would cost more in later patches than fixing it now.
104
126
  >
127
+ > If an issue represents a class of defect, find every instance within the review scope worth fixing rather than surfacing one or two per round, which drags out the review.
128
+ > For any rebuttal, accept or challenge it.
129
+ > Treat as settled, and do not raise again, any finding in this review rejected twice with reasoning.
130
+ >
105
131
  > Do not re-run tests or builds whose inputs have not changed since any previous reported run.
106
132
  > Do not edit files or commit; report findings only.
107
133
  >
@@ -110,4 +136,4 @@ When Coder rejects every finding and makes no commit, Captain shall relay Coder'
110
136
 
111
137
  Results:
112
138
  - `hasFindings`: Reviewer kept one or more unsettled findings. Output shall include `reviewerOutput: <verbatim final text>`.
113
- - `noFindings`: Reviewer accepted the rebuttals and no unsettled findings remain.
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>`.
@@ -7,7 +7,8 @@
7
7
  // Boss event: deterministic START_REVIEW entry; exact Boss text becomes
8
8
  // callerInput; pending player questions retain BOSS_REPLY
9
9
  // Adjudication: LLM judge per state; coderOutput and reviewerOutput are
10
- // carried verbatim
10
+ // carried verbatim; latestCommit is receipt-owned effect
11
+ // evidence, never taken from either player's prose
11
12
  // Compat: artifact schema 3 / runtime ABI 1
12
13
  import { createXStatePlaybookRuntime, snapshotJsonValue, } from '@sublang/playbook/xstate-runtime';
13
14
  import { reviewMachine, } from './review.fsm.js';
@@ -90,7 +91,7 @@ const runtimeSpec = {
90
91
  roleStates: {
91
92
  reviewInitial: {
92
93
  role: 'reviewer',
93
- label: 'REVIEW-1: Reviewer examines the latest commit against the caller input.',
94
+ label: "REVIEW-1: Reviewer reviews the caller's review scope against the original intent.",
94
95
  },
95
96
  addressFindings: {
96
97
  role: 'coder',
@@ -98,7 +99,7 @@ const runtimeSpec = {
98
99
  },
99
100
  reviewAfterCommit: {
100
101
  role: 'reviewer',
101
- label: 'REVIEW-3: Reviewer examines the new review-fix commit and repository state.',
102
+ label: 'REVIEW-3: Reviewer reviews the cumulative committed state after a review-fix commit.',
102
103
  },
103
104
  reviewAfterRebuttal: {
104
105
  role: 'reviewer',
@@ -113,7 +114,9 @@ const runtimeSpec = {
113
114
  repositoryDisposition: 'unchanged',
114
115
  },
115
116
  noFindings: {
116
- fields: {},
117
+ // DR-045: the clean round's unchanged receipt observes the exact
118
+ // evaluated revision as HEAD; the reconciler injects it here.
119
+ fields: { evaluatedRevision: 'effect' },
117
120
  repositoryDisposition: 'unchanged',
118
121
  },
119
122
  needsBossReply: {
@@ -123,7 +126,10 @@ const runtimeSpec = {
123
126
  },
124
127
  addressFindings: {
125
128
  committed: {
126
- fields: { coderOutput: 'presentation' },
129
+ fields: {
130
+ coderOutput: 'presentation',
131
+ latestCommit: 'effect',
132
+ },
127
133
  repositoryDisposition: 'one-descendant-commit',
128
134
  },
129
135
  rejectedAll: {
@@ -141,7 +147,9 @@ const runtimeSpec = {
141
147
  repositoryDisposition: 'unchanged',
142
148
  },
143
149
  noFindings: {
144
- fields: {},
150
+ // DR-045: the clean round's unchanged receipt observes the exact
151
+ // evaluated revision as HEAD; the reconciler injects it here.
152
+ fields: { evaluatedRevision: 'effect' },
145
153
  repositoryDisposition: 'unchanged',
146
154
  },
147
155
  needsBossReply: {
@@ -155,7 +163,9 @@ const runtimeSpec = {
155
163
  repositoryDisposition: 'unchanged',
156
164
  },
157
165
  noFindings: {
158
- fields: {},
166
+ // DR-045: the clean round's unchanged receipt observes the exact
167
+ // evaluated revision as HEAD; the reconciler injects it here.
168
+ fields: { evaluatedRevision: 'effect' },
159
169
  repositoryDisposition: 'unchanged',
160
170
  },
161
171
  needsBossReply: {
@@ -7,7 +7,8 @@
7
7
  // Boss event: deterministic START_REVIEW entry; exact Boss text becomes
8
8
  // callerInput; pending player questions retain BOSS_REPLY
9
9
  // Adjudication: LLM judge per state; coderOutput and reviewerOutput are
10
- // carried verbatim
10
+ // carried verbatim; latestCommit is receipt-owned effect
11
+ // evidence, never taken from either player's prose
11
12
  // Compat: artifact schema 3 / runtime ABI 1
12
13
 
13
14
  import {
@@ -181,7 +182,7 @@ const runtimeSpec = {
181
182
  reviewInitial: {
182
183
  role: 'reviewer',
183
184
  label:
184
- 'REVIEW-1: Reviewer examines the latest commit against the caller input.',
185
+ "REVIEW-1: Reviewer reviews the caller's review scope against the original intent.",
185
186
  },
186
187
  addressFindings: {
187
188
  role: 'coder',
@@ -190,7 +191,7 @@ const runtimeSpec = {
190
191
  reviewAfterCommit: {
191
192
  role: 'reviewer',
192
193
  label:
193
- 'REVIEW-3: Reviewer examines the new review-fix commit and repository state.',
194
+ 'REVIEW-3: Reviewer reviews the cumulative committed state after a review-fix commit.',
194
195
  },
195
196
  reviewAfterRebuttal: {
196
197
  role: 'reviewer',
@@ -206,7 +207,9 @@ const runtimeSpec = {
206
207
  repositoryDisposition: 'unchanged',
207
208
  },
208
209
  noFindings: {
209
- fields: {},
210
+ // DR-045: the clean round's unchanged receipt observes the exact
211
+ // evaluated revision as HEAD; the reconciler injects it here.
212
+ fields: { evaluatedRevision: 'effect' },
210
213
  repositoryDisposition: 'unchanged',
211
214
  },
212
215
  needsBossReply: {
@@ -216,7 +219,10 @@ const runtimeSpec = {
216
219
  },
217
220
  addressFindings: {
218
221
  committed: {
219
- fields: { coderOutput: 'presentation' },
222
+ fields: {
223
+ coderOutput: 'presentation',
224
+ latestCommit: 'effect',
225
+ },
220
226
  repositoryDisposition: 'one-descendant-commit',
221
227
  },
222
228
  rejectedAll: {
@@ -234,7 +240,9 @@ const runtimeSpec = {
234
240
  repositoryDisposition: 'unchanged',
235
241
  },
236
242
  noFindings: {
237
- fields: {},
243
+ // DR-045: the clean round's unchanged receipt observes the exact
244
+ // evaluated revision as HEAD; the reconciler injects it here.
245
+ fields: { evaluatedRevision: 'effect' },
238
246
  repositoryDisposition: 'unchanged',
239
247
  },
240
248
  needsBossReply: {
@@ -248,7 +256,9 @@ const runtimeSpec = {
248
256
  repositoryDisposition: 'unchanged',
249
257
  },
250
258
  noFindings: {
251
- fields: {},
259
+ // DR-045: the clean round's unchanged receipt observes the exact
260
+ // evaluated revision as HEAD; the reconciler injects it here.
261
+ fields: { evaluatedRevision: 'effect' },
252
262
  repositoryDisposition: 'unchanged',
253
263
  },
254
264
  needsBossReply: {
@@ -47,7 +47,7 @@ export function validateReviewOptions(optionSlice) {
47
47
  export const reviewPlaybookRegistryEntry = {
48
48
  id: 'review',
49
49
  command: 'review',
50
- intent: 'review the latest commit until no material correctness or spec findings remain',
50
+ intent: 'review a supplied scope of committed work until no unsettled findings remain',
51
51
  artifactSchema: 3,
52
52
  runtimeProfile: Object.freeze({
53
53
  kind: 'shared-factory',
@@ -104,7 +104,7 @@ export const reviewPlaybookRegistryEntry: ReviewPlaybookRegistryEntry = {
104
104
  id: 'review',
105
105
  command: 'review',
106
106
  intent:
107
- 'review the latest commit until no material correctness or spec findings remain',
107
+ 'review a supplied scope of committed work until no unsettled findings remain',
108
108
  artifactSchema: 3,
109
109
  runtimeProfile: Object.freeze({
110
110
  kind: 'shared-factory',