@sublang/playbook 0.2.0 → 0.4.1

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.
@@ -255,7 +255,7 @@ const planAndImplementInput: CaptainInputFactory = (context) => ({
255
255
  prompt: [
256
256
  'Assess whether this can be completed in a single commit, following best practices.',
257
257
  'If yes, implement and test, updating both code and specs; otherwise, decompose into tasks as a new IR under @specs/iterations.',
258
- 'Consult @specs/map.md for relevant context if needed; ensure it reflects the changes.',
258
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; ensure @specs/map.md reflects the changes.',
259
259
  'Do not commit.',
260
260
  ].join('\n'),
261
261
  result: withNeedsBossReply({
@@ -708,7 +708,7 @@ export const codingMachine = setup({
708
708
  '- Minimal: essential and concise; every item earns its place; also check with other items.',
709
709
  '',
710
710
  'Flag anything missing, redundant, over-specified, or under-specified.',
711
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
711
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
712
712
  "If the change is ready to commit or push, don't raise nitpicks.",
713
713
  ].join('\n'),
714
714
  result: {
@@ -748,7 +748,7 @@ export const codingMachine = setup({
748
748
  'Refer to the commit message.',
749
749
  'Flag any issues or improvements (numbered; no duplication).',
750
750
  "Think thoroughly — don't just approve or reject.",
751
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
751
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
752
752
  "If the change is ready to commit or push, don't raise nitpicks.",
753
753
  ].join('\n'),
754
754
  result: {
@@ -795,7 +795,7 @@ export const codingMachine = setup({
795
795
  'Flag anything missing, redundant, over-specified, or under-specified.',
796
796
  'Flag any issues or improvements (numbered; no duplication).',
797
797
  "Think thoroughly — don't just approve or reject.",
798
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
798
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
799
799
  "If the change is ready to commit or push, don't raise nitpicks.",
800
800
  ].join('\n'),
801
801
  result: {
@@ -841,7 +841,7 @@ export const codingMachine = setup({
841
841
  '- Minimal: essential and concise; every item earns its place; also check with other items.',
842
842
  '',
843
843
  'Flag anything missing, redundant, over-specified, or under-specified.',
844
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
844
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
845
845
  "If the change is ready to commit or push, don't raise nitpicks.",
846
846
  ].join('\n'),
847
847
  result: {
@@ -882,7 +882,7 @@ export const codingMachine = setup({
882
882
  'Refer to the commit message.',
883
883
  'Flag any issues or improvements (numbered; no duplication).',
884
884
  "Think thoroughly — don't just approve or reject.",
885
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
885
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
886
886
  "If the change is ready to commit or push, don't raise nitpicks.",
887
887
  ].join('\n'),
888
888
  result: {
@@ -930,7 +930,7 @@ export const codingMachine = setup({
930
930
  'Flag anything missing, redundant, over-specified, or under-specified.',
931
931
  'Flag any issues or improvements (numbered; no duplication).',
932
932
  "Think thoroughly — don't just approve or reject.",
933
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
933
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
934
934
  "If the change is ready to commit or push, don't raise nitpicks.",
935
935
  ].join('\n'),
936
936
  result: {
@@ -974,7 +974,7 @@ export const codingMachine = setup({
974
974
  '- Minimal: essential and concise; every item earns its place; also check with other items.',
975
975
  '',
976
976
  'Flag anything missing, redundant, over-specified, or under-specified.',
977
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
977
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
978
978
  "If the change is ready to commit or push, don't raise nitpicks.",
979
979
  ].join('\n'),
980
980
  result: {
@@ -1015,7 +1015,7 @@ export const codingMachine = setup({
1015
1015
  'Understand the intent.',
1016
1016
  'Flag any issues or improvements (numbered; no duplication).',
1017
1017
  "Think thoroughly — don't just approve or reject.",
1018
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
1018
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
1019
1019
  "If the change is ready to commit or push, don't raise nitpicks.",
1020
1020
  ].join('\n'),
1021
1021
  result: {
@@ -1063,7 +1063,7 @@ export const codingMachine = setup({
1063
1063
  'Flag anything missing, redundant, over-specified, or under-specified.',
1064
1064
  'Flag any issues or improvements (numbered; no duplication).',
1065
1065
  "Think thoroughly — don't just approve or reject.",
1066
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
1066
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
1067
1067
  "If the change is ready to commit or push, don't raise nitpicks.",
1068
1068
  ].join('\n'),
1069
1069
  result: {
@@ -1111,7 +1111,7 @@ export const codingMachine = setup({
1111
1111
  '- Minimal: essential and concise; every item earns its place; also check with other items.',
1112
1112
  '',
1113
1113
  'Flag anything missing, redundant, over-specified, or under-specified.',
1114
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
1114
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
1115
1115
  "If the change is ready to commit or push, don't raise nitpicks.",
1116
1116
  'For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.',
1117
1117
  ].join('\n'),
@@ -1156,7 +1156,7 @@ export const codingMachine = setup({
1156
1156
  'Understand the intent.',
1157
1157
  'Flag any issues or improvements (numbered; no duplication).',
1158
1158
  "Think thoroughly — don't just approve or reject.",
1159
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
1159
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
1160
1160
  "If the change is ready to commit or push, don't raise nitpicks.",
1161
1161
  'For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.',
1162
1162
  ].join('\n'),
@@ -1208,7 +1208,7 @@ export const codingMachine = setup({
1208
1208
  'Flag anything missing, redundant, over-specified, or under-specified.',
1209
1209
  'Flag any issues or improvements (numbered; no duplication).',
1210
1210
  "Think thoroughly — don't just approve or reject.",
1211
- 'Consult @specs/map.md for relevant context if needed; verify it reflects the changes.',
1211
+ 'Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.',
1212
1212
  "If the change is ready to commit or push, don't raise nitpicks.",
1213
1213
  'For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.',
1214
1214
  ].join('\n'),
@@ -1319,6 +1319,7 @@ export const codingMachine = setup({
1319
1319
  prompt: [
1320
1320
  'Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).',
1321
1321
  'Coder is <coder-llm>.',
1322
+ 'Format the `Co-authored-by` `<model>` token as the conventional human form of the substituted id (e.g., `claude-opus-4-7` → `Claude-Opus-4.7`, `gpt-5.5` → `GPT-5.5`).',
1322
1323
  ].join('\n'),
1323
1324
  result: {
1324
1325
  committedSpecs: 'Committed changes that touch only @specs/{user,dev,test}/.',
@@ -1382,6 +1383,7 @@ export const codingMachine = setup({
1382
1383
  prompt: [
1383
1384
  'Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).',
1384
1385
  'Coder is <coder-llm>; Reviewer is <reviewer-llm>.',
1386
+ 'Format the `Co-authored-by` `<model>` token as the conventional human form of the substituted id (e.g., `claude-opus-4-7` → `Claude-Opus-4.7`, `gpt-5.5` → `GPT-5.5`).',
1385
1387
  ].join('\n'),
1386
1388
  result: {
1387
1389
  committed: 'Relevant changes were committed.',
@@ -16,7 +16,7 @@ Players:
16
16
  When Boss gives a coding intent, Captain shall relay it to Coder along with the following prompt:
17
17
  > Assess whether this can be completed in a single commit, following best practices.
18
18
  > If yes, implement and test, updating both code and specs; otherwise, decompose into tasks as a new IR under @specs/iterations.
19
- > Consult @specs/map.md for relevant context if needed; ensure it reflects the changes.
19
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; ensure @specs/map.md reflects the changes.
20
20
  > Do not commit.
21
21
  The resulting changes are Initial Changes.
22
22
 
@@ -68,7 +68,7 @@ When Committer commits Initial Changes from a Boss coding intent involving chang
68
68
  > - Minimal: essential and concise; every item earns its place; also check with other items.
69
69
  >
70
70
  > Flag anything missing, redundant, over-specified, or under-specified.
71
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
71
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
72
72
  > If the change is ready to commit or push, don't raise nitpicks.
73
73
 
74
74
  ### CODE-6
@@ -78,7 +78,7 @@ When Committer commits Initial Changes from a Boss coding intent involving chang
78
78
  > Refer to the commit message.
79
79
  > Flag any issues or improvements (numbered; no duplication).
80
80
  > Think thoroughly — don't just approve or reject.
81
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
81
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
82
82
  > If the change is ready to commit or push, don't raise nitpicks.
83
83
 
84
84
  ### CODE-7
@@ -95,7 +95,7 @@ When Committer commits Initial Changes from a Boss coding intent involving chang
95
95
  > Flag anything missing, redundant, over-specified, or under-specified.
96
96
  > Flag any issues or improvements (numbered; no duplication).
97
97
  > Think thoroughly — don't just approve or reject.
98
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
98
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
99
99
  > If the change is ready to commit or push, don't raise nitpicks.
100
100
 
101
101
  ### CODE-8
@@ -110,7 +110,7 @@ When Committer commits Initial Changes from an IR task involving changes only in
110
110
  > - Minimal: essential and concise; every item earns its place; also check with other items.
111
111
  >
112
112
  > Flag anything missing, redundant, over-specified, or under-specified.
113
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
113
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
114
114
  > If the change is ready to commit or push, don't raise nitpicks.
115
115
 
116
116
  ### CODE-9
@@ -120,7 +120,7 @@ When Committer commits Initial Changes from an IR task involving changes only ou
120
120
  > Refer to the commit message.
121
121
  > Flag any issues or improvements (numbered; no duplication).
122
122
  > Think thoroughly — don't just approve or reject.
123
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
123
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
124
124
  > If the change is ready to commit or push, don't raise nitpicks.
125
125
 
126
126
  ### CODE-10
@@ -137,7 +137,7 @@ When Committer commits Initial Changes from an IR task involving changes both in
137
137
  > Flag anything missing, redundant, over-specified, or under-specified.
138
138
  > Flag any issues or improvements (numbered; no duplication).
139
139
  > Think thoroughly — don't just approve or reject.
140
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
140
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
141
141
  > If the change is ready to commit or push, don't raise nitpicks.
142
142
 
143
143
  ### CODE-11
@@ -152,7 +152,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
152
152
  > - Minimal: essential and concise; every item earns its place; also check with other items.
153
153
  >
154
154
  > Flag anything missing, redundant, over-specified, or under-specified.
155
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
155
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
156
156
  > If the change is ready to commit or push, don't raise nitpicks.
157
157
 
158
158
  ### CODE-12
@@ -162,7 +162,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
162
162
  > Understand the intent.
163
163
  > Flag any issues or improvements (numbered; no duplication).
164
164
  > Think thoroughly — don't just approve or reject.
165
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
165
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
166
166
  > If the change is ready to commit or push, don't raise nitpicks.
167
167
 
168
168
  ### CODE-13
@@ -179,7 +179,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
179
179
  > Flag anything missing, redundant, over-specified, or under-specified.
180
180
  > Flag any issues or improvements (numbered; no duplication).
181
181
  > Think thoroughly — don't just approve or reject.
182
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
182
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
183
183
  > If the change is ready to commit or push, don't raise nitpicks.
184
184
 
185
185
  ### CODE-14
@@ -199,7 +199,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
199
199
  > - Minimal: essential and concise; every item earns its place; also check with other items.
200
200
  >
201
201
  > Flag anything missing, redundant, over-specified, or under-specified.
202
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
202
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
203
203
  > If the change is ready to commit or push, don't raise nitpicks.
204
204
  > For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.
205
205
 
@@ -210,7 +210,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
210
210
  > Understand the intent.
211
211
  > Flag any issues or improvements (numbered; no duplication).
212
212
  > Think thoroughly — don't just approve or reject.
213
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
213
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
214
214
  > If the change is ready to commit or push, don't raise nitpicks.
215
215
  > For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.
216
216
 
@@ -228,7 +228,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
228
228
  > Flag anything missing, redundant, over-specified, or under-specified.
229
229
  > Flag any issues or improvements (numbered; no duplication).
230
230
  > Think thoroughly — don't just approve or reject.
231
- > Consult @specs/map.md for relevant context if needed; verify it reflects the changes.
231
+ > Consult @specs/map.md or @specs/meta.md for relevant context if needed; verify @specs/map.md reflects the changes.
232
232
  > If the change is ready to commit or push, don't raise nitpicks.
233
233
  > For each rebuttal below, challenge or accept it, with strong reasoning, solid evidence, and comprehensive thinking.
234
234
 
@@ -239,6 +239,7 @@ When Coder makes unreviewed changes (outside of any Initial Changes) involving c
239
239
  When Coder makes any Initial Changes and Reviewer has not played since the last commit, Captain shall prompt Committer:
240
240
  > Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).
241
241
  > Coder is <coder-llm>.
242
+ > Format the `Co-authored-by` `<model>` token as the conventional human form of the substituted id (e.g., `claude-opus-4-7` → `Claude-Opus-4.7`, `gpt-5.5` → `GPT-5.5`).
242
243
 
243
244
  Result guard: `needsBossInput` — Committing requires additional Boss input or rescoping rather than a specific answer to resume this same state.
244
245
 
@@ -247,5 +248,6 @@ Result guard: `needsBossInput` — Committing requires additional Boss input or
247
248
  When Coder makes any Initial Changes and Reviewer has played since the last commit, or Reviewer raises no findings on uncommitted changes and Coder has played since the last commit, Captain shall prompt Committer:
248
249
  > Make a commit of the changes that belong in the repo, following @specs/dev/git.md (reread if necessary).
249
250
  > Coder is <coder-llm>; Reviewer is <reviewer-llm>.
251
+ > Format the `Co-authored-by` `<model>` token as the conventional human form of the substituted id (e.g., `claude-opus-4-7` → `Claude-Opus-4.7`, `gpt-5.5` → `GPT-5.5`).
250
252
 
251
253
  Result guard: `needsBossInput` — Committing requires additional Boss input or rescoping rather than a specific answer to resume this same state.
@@ -40,10 +40,9 @@ interface PendingBossQuestionForStatus {
40
40
  }
41
41
  declare function pendingBossQuestionFromContext(context: Record<string, unknown>): PendingBossQuestionForStatus | undefined;
42
42
  declare function formatAwaitBossReplyEntry(context: Record<string, unknown>): string;
43
- declare function formatStateEntry(stateId: string, context?: Record<string, unknown>): string;
43
+ declare function formatStateEntry(stateId: string, context?: Record<string, unknown>): string | undefined;
44
44
  declare function formatTransition(event: unknown): string | undefined;
45
- declare function formatBossEcho(text: string, eventType?: string): string;
46
- declare function formatRiders(context: Record<string, unknown>): string;
45
+ declare function formatClassification(eventType: string): string;
47
46
  declare function stateTelemetryPayload(from: unknown, to: string, event: unknown, context: Record<string, unknown>): Record<string, unknown>;
48
47
  export declare const _internal: {
49
48
  composePlayerPrompt: typeof composePlayerPrompt;
@@ -57,8 +56,7 @@ export declare const _internal: {
57
56
  formatAwaitBossReplyEntry: typeof formatAwaitBossReplyEntry;
58
57
  formatStateEntry: typeof formatStateEntry;
59
58
  formatTransition: typeof formatTransition;
60
- formatBossEcho: typeof formatBossEcho;
61
- formatRiders: typeof formatRiders;
59
+ formatClassification: typeof formatClassification;
62
60
  stateTelemetryPayload: typeof stateTelemetryPayload;
63
61
  };
64
62
  export default function createPlaybookRuntime(options: CodePlaybookOptions): PlaybookRuntime;
@@ -21,10 +21,15 @@ const BOSS_REPLY_ERRORS = {
21
21
  // TODO marker.
22
22
  // Player-prompt composer — DR-004 §6.
23
23
  // Substitutes the three placeholder tokens in `input.prompt` (literal
24
- // string replace, no escaping) and prepends labelled blocks for any
25
- // populated structured field. When a state resumes from a Boss reply,
26
- // the continuation preamble and Q/A blocks precede the ordinary
27
- // labelled blocks. The FSM's prompt body is never re-flowed.
24
+ // string replace, no escaping) and arranges labelled blocks around
25
+ // the prompt body. Context blocks the body refers to as prior
26
+ // material (`Boss intent:`, `Task description:`) are prepended;
27
+ // action blocks the body refers to as material below
28
+ // (`Review items:`, `Rebuttals:`) are appended after the body so the
29
+ // CODE-N prompts' "review item below" / "rebuttal below" phrasing
30
+ // matches the rendered layout. When a state resumes from a Boss
31
+ // reply, the continuation preamble and Q/A blocks precede every
32
+ // ordinary block. The FSM's prompt body is never re-flowed.
28
33
  function composePlayerPrompt(input) {
29
34
  const blocks = [];
30
35
  if (input.pendingBossQuestion !== undefined &&
@@ -36,12 +41,6 @@ function composePlayerPrompt(input) {
36
41
  if (input.intent !== undefined) {
37
42
  blocks.push(`Boss intent:\n${input.intent}`);
38
43
  }
39
- if (input.reviews !== undefined) {
40
- blocks.push(`Review items:\n${input.reviews}`);
41
- }
42
- if (input.challenges !== undefined) {
43
- blocks.push(`Rebuttals:\n${input.challenges}`);
44
- }
45
44
  if (input.taskDescription !== undefined) {
46
45
  blocks.push(`Task description:\n${input.taskDescription}`);
47
46
  }
@@ -56,6 +55,12 @@ function composePlayerPrompt(input) {
56
55
  body = body.replaceAll('<reviewer-llm>', input.reviewerPlayer);
57
56
  }
58
57
  blocks.push(body);
58
+ if (input.reviews !== undefined) {
59
+ blocks.push(`Review items:\n${input.reviews}`);
60
+ }
61
+ if (input.challenges !== undefined) {
62
+ blocks.push(`Rebuttals:\n${input.challenges}`);
63
+ }
59
64
  return blocks.join('\n\n');
60
65
  }
61
66
  // Player-id resolver — DR-004 §2.
@@ -331,14 +336,22 @@ function captainBridge(ports, getActiveSignal) {
331
336
  });
332
337
  }
333
338
  // Captain pane display — PBRT-3 / PBRT-14.
334
- // The Captain pane is a stream keyed on four glyphs so a reader can
335
- // parse each line at a glance:
336
- // ◆ basic idle entry (ready / done / failed)
337
- // Boss input echo
338
- // ⮕ captain-invoking state entry (label + player + CODE-N)
339
- // ⤷ transition (guard fired by the just-finished captain call)
340
- // Prompts and full player output ride the player panes; the Captain
341
- // pane keeps to the state-machine shape.
339
+ // The Captain pane is a stream of three glyphs plus one bare
340
+ // captain-speech act, designed so a reader can parse each line at a
341
+ // glance:
342
+ // (no glyph) bare FSM event type — host renders as captain speech
343
+ // (e.g., `captain> START_CODING`)
344
+ // ⤷ captain-invoking state entry: `<Player>: <label>`
345
+ // → transition guard outcome (`· field=N` tallies
346
+ // appended); the host presenter owns any visual
347
+ // nesting under the preceding ⤷ entry
348
+ // ◆ failure state (with `lastError` data) and the
349
+ // `awaitBossReply` suspension state (custom payload)
350
+ // The runtime emits no status line on entry to the idle state
351
+ // (`ready`) or the terminal state (`done`); the next `boss>` prompt
352
+ // is the implicit "turn over" signal. Prompts and full player output
353
+ // ride the player panes; the Captain pane keeps to the state-machine
354
+ // shape.
342
355
  const STATE_LABELS = {
343
356
  planAndImplement: 'plan & implement',
344
357
  respondToReview: 'respond to review',
@@ -394,13 +407,20 @@ const QUIESCENT_STATES = new Set([
394
407
  'done',
395
408
  'failed',
396
409
  ]);
397
- // awaitBossReply is quiescent too, but uses a custom single-line
398
- // status frame rather than the plain `◆ <state>` entry.
399
- const BASIC_IDLE_GLYPH_STATES = new Set([...QUIESCENT_STATES].filter((stateId) => stateId !== 'awaitBossReply'));
410
+ // States whose entry the runtime does not surface on the Captain
411
+ // pane per PBRT-3: the readline returning to its `boss>` prompt is
412
+ // the implicit "turn over" signal, so a `◆ ready` / `◆ done`
413
+ // tombstone is redundant.
414
+ const SUPPRESSED_ENTRY_STATES = new Set([
415
+ 'ready',
416
+ 'done',
417
+ ]);
400
418
  // Captain-pane surface (PBRT-3): every captain-invoking state plus
401
- // the quiescent states. Wider than the prior
402
- // "Boss-relevant" set per slc/link.md's default "emit on every
403
- // transition; let the host filter."
419
+ // the quiescent states whose entry still carries information
420
+ // (failure with `lastError`, awaitBossReply with the pending
421
+ // question). `ready` and `done` flow through the inspect handler
422
+ // but their entries are dropped before emitStatus per
423
+ // SUPPRESSED_ENTRY_STATES above.
404
424
  const CAPTAIN_PANE_STATES = new Set([
405
425
  ...stateMetadata.keys(),
406
426
  ...QUIESCENT_STATES,
@@ -438,12 +458,14 @@ function formatAwaitBossReplyEntry(context) {
438
458
  function formatStateEntry(stateId, context = {}) {
439
459
  if (stateId === 'awaitBossReply')
440
460
  return formatAwaitBossReplyEntry(context);
441
- if (BASIC_IDLE_GLYPH_STATES.has(stateId))
442
- return `◆ ${stateId}`;
461
+ if (SUPPRESSED_ENTRY_STATES.has(stateId))
462
+ return undefined;
463
+ if (stateId === 'failed')
464
+ return '◆ failed';
443
465
  const meta = stateMetadata.get(stateId);
444
466
  if (!meta)
445
- return `⮕ ${stateId}`;
446
- return `⮕ ${meta.label} ${meta.player} per ${meta.sourceItem}`;
467
+ return `⤷ ${stateId}`;
468
+ return `⤷ ${meta.player}: ${meta.label}`;
447
469
  }
448
470
  function formatTransition(event) {
449
471
  const output = event?.output;
@@ -457,29 +479,15 @@ function formatTransition(event) {
457
479
  tallies.push(`${field}=${items ? items.length : 1}`);
458
480
  }
459
481
  }
460
- const suffix = tallies.length > 0 ? ` ${tallies.join(' ')}` : '';
461
- return `⤷ ${output.guard}${suffix}`;
482
+ const suffix = tallies.length > 0 ? ` · ${tallies.join(' · ')}` : '';
483
+ // No leading whitespace: visual nesting under the preceding ⤷
484
+ // entry is the host presenter's concern (cligent's writeStatusLine
485
+ // emits status messages verbatim, with its own chrome but no
486
+ // continuation indent; layout is its job, not ours).
487
+ return `→ ${output.guard}${suffix}`;
462
488
  }
463
- function formatBossEcho(text, eventType) {
464
- return eventType !== undefined
465
- ? `▸ BOSS ${text} → ${eventType}`
466
- : `▸ BOSS ${text}`;
467
- }
468
- // Rider fields PBRT-14 names — surfaced inline on a state entry
469
- // whenever the FSM context populates them, regardless of which
470
- // captain-invoking state is being entered. Routing-only context
471
- // (reviewSubject, afterReview, etc.) stays out of the pane and is
472
- // visible via emitTelemetry instead.
473
- const RIDER_FIELDS = ['intent', 'irNumber', 'taskDescription'];
474
- function formatRiders(context) {
475
- const parts = [];
476
- for (const f of RIDER_FIELDS) {
477
- const v = context[f];
478
- if (typeof v === 'string' && v.length > 0) {
479
- parts.push(`${f}=${JSON.stringify(v)}`);
480
- }
481
- }
482
- return parts.length > 0 ? ` ${parts.join(' ')}` : '';
489
+ function formatClassification(eventType) {
490
+ return eventType;
483
491
  }
484
492
  function stateTelemetryPayload(from, to, event, context) {
485
493
  const payload = { from, to, event };
@@ -507,8 +515,7 @@ export const _internal = {
507
515
  formatAwaitBossReplyEntry,
508
516
  formatStateEntry,
509
517
  formatTransition,
510
- formatBossEcho,
511
- formatRiders,
518
+ formatClassification,
512
519
  stateTelemetryPayload,
513
520
  };
514
521
  export default function createPlaybookRuntime(options) {
@@ -584,17 +591,15 @@ export default function createPlaybookRuntime(options) {
584
591
  enqueueEmit(() => ports.emitStatus(transitionLine));
585
592
  }
586
593
  const entryLine = formatStateEntry(to, context);
587
- const riderSuffix = stateMetadata.has(to)
588
- ? formatRiders(context)
589
- : '';
590
- const message = entryLine + riderSuffix;
594
+ if (entryLine === undefined)
595
+ return;
591
596
  if (to === 'failed') {
592
597
  const lastError = snap.context
593
598
  ?.lastError;
594
- enqueueEmit(() => ports.emitStatus(message, { lastError }));
599
+ enqueueEmit(() => ports.emitStatus(entryLine, { lastError }));
595
600
  }
596
601
  else {
597
- enqueueEmit(() => ports.emitStatus(message));
602
+ enqueueEmit(() => ports.emitStatus(entryLine));
598
603
  }
599
604
  },
600
605
  });
@@ -620,12 +625,13 @@ export default function createPlaybookRuntime(options) {
620
625
  await drainEmissions();
621
626
  return;
622
627
  }
623
- // 2. Captain-pane Boss-input echo (PBRT-14): the verbatim
624
- // Boss text and the FSM event it classified to, before
625
- // the FSM advances. Enqueued so it interleaves cleanly
626
- // with the inspect-driven transition emissions.
628
+ // 2. Captain-pane classification line (PBRT-14): the bare
629
+ // FSM event type, emitted before the FSM advances so the
630
+ // host can render it as captain speech (e.g.,
631
+ // `captain> START_CODING`). Enqueued so it interleaves
632
+ // cleanly with the inspect-driven transition emissions.
627
633
  const echoPorts = savedPorts;
628
- enqueueEmit(() => echoPorts.emitStatus(formatBossEcho(text, event.type)));
634
+ enqueueEmit(() => echoPorts.emitStatus(formatClassification(event.type)));
629
635
  // 3. final state ('done') cannot accept new events — dispose
630
636
  // and reconstruct per DR-004 §5.
631
637
  if (actor.getSnapshot().status === 'done') {