@sublang/playbook 10.0.0 → 12.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.
- package/README.md +1 -1
- package/docs/cli.md +67 -19
- package/docs/configuration.md +103 -40
- package/docs/embedding.md +88 -0
- package/package.json +30 -4
- package/reference/sdlc/code.md +35 -15
- package/reference/sdlc/code.playbook/bin/interactive-session.js +58 -6
- package/reference/sdlc/code.playbook/bin/launch-config.js +499 -241
- package/reference/sdlc/code.playbook/bin/playbook.js +236 -187
- package/reference/sdlc/code.playbook/bin/replay-observer.js +221 -0
- package/reference/sdlc/code.playbook/bin/run.js +355 -203
- package/reference/sdlc/code.playbook/bin/session-store.js +1512 -136
- package/reference/sdlc/code.playbook/code.fsm.d.ts +22 -19
- package/reference/sdlc/code.playbook/code.fsm.js +116 -52
- package/reference/sdlc/code.playbook/code.fsm.ts +149 -64
- package/reference/sdlc/code.playbook/code.gears.md +40 -20
- package/reference/sdlc/code.playbook/code.playbook.js +23 -2
- package/reference/sdlc/code.playbook/code.playbook.ts +23 -2
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +4 -1
- package/reference/sdlc/code.playbook/playbook-captain.js +21 -3
- package/reference/sdlc/code.playbook/playbook-captain.ts +42 -6
- package/reference/sdlc/code.playbook/playbook.config.template.yaml +31 -11
- package/reference/sdlc/code.playbook/session-store.d.ts +82 -0
- package/reference/sdlc/code.playbook/session-store.js +113 -0
- package/reference/sdlc/decide.md +24 -15
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +13 -6
- package/reference/sdlc/decide.playbook/decide.fsm.js +54 -27
- package/reference/sdlc/decide.playbook/decide.fsm.ts +68 -29
- package/reference/sdlc/decide.playbook/decide.gears.md +25 -19
- package/reference/sdlc/decide.playbook/decide.playbook.js +11 -3
- package/reference/sdlc/decide.playbook/decide.playbook.ts +11 -3
- package/reference/sdlc/decide.playbook/decide.registry.js +1 -1
- package/reference/sdlc/decide.playbook/decide.registry.ts +1 -1
- package/reference/sdlc/dev.md +52 -0
- package/reference/sdlc/dev.playbook/dev.fsm.d.ts +261 -0
- package/reference/sdlc/dev.playbook/dev.fsm.js +723 -0
- package/reference/sdlc/dev.playbook/dev.fsm.ts +988 -0
- package/reference/sdlc/dev.playbook/dev.gears.md +91 -0
- package/reference/sdlc/dev.playbook/dev.playbook.d.ts +21 -0
- package/reference/sdlc/dev.playbook/dev.playbook.js +143 -0
- package/reference/sdlc/dev.playbook/dev.playbook.ts +246 -0
- package/reference/sdlc/dev.playbook/dev.registry.d.ts +40 -0
- package/reference/sdlc/dev.playbook/dev.registry.js +64 -0
- package/reference/sdlc/dev.playbook/dev.registry.ts +120 -0
- package/reference/sdlc/review.md +36 -18
- package/reference/sdlc/review.playbook/review.fsm.d.ts +15 -2
- package/reference/sdlc/review.playbook/review.fsm.js +77 -27
- package/reference/sdlc/review.playbook/review.fsm.ts +96 -30
- package/reference/sdlc/review.playbook/review.gears.md +52 -26
- package/reference/sdlc/review.playbook/review.playbook.js +17 -7
- package/reference/sdlc/review.playbook/review.playbook.ts +17 -7
- package/reference/sdlc/review.playbook/review.registry.js +1 -1
- package/reference/sdlc/review.playbook/review.registry.ts +1 -1
- package/slc/link.md +12 -5
- package/slc/text2gears.md +3 -0
- package/src/xstate-playbook-runtime.js +5 -2
- package/src/xstate-playbook-runtime.ts +5 -2
- package/src/xstate-runtime.js +13 -1
- package/src/xstate-runtime.ts +13 -1
package/reference/sdlc/code.md
CHANGED
|
@@ -8,35 +8,44 @@ Roles:
|
|
|
8
8
|
|
|
9
9
|
- Coder
|
|
10
10
|
|
|
11
|
-
The caller supplies
|
|
11
|
+
The caller supplies a coding request together with any relevant context.
|
|
12
12
|
|
|
13
|
-
A coding intent follows either one direct implementation phase or an IR sequence consisting of a new-IR phase
|
|
13
|
+
A new coding intent follows either one direct implementation phase or an IR sequence consisting of a new-IR phase followed by one phase for each IR task.
|
|
14
|
+
An existing IR follows one IR-task phase for each remaining unfinished task, starting with its next unfinished task.
|
|
14
15
|
Each phase ends with one new Coder commit (owned by `code`).
|
|
15
16
|
After each `code`-owned commit, Captain shall call the `review` playbook and wait until it passes with no unsettled findings.
|
|
16
17
|
Playbook `review` owns every review round and every review-fix commit.
|
|
17
|
-
Do not
|
|
18
|
+
Do not rewrite any existing commit.
|
|
18
19
|
|
|
19
20
|
When `review` passes a direct implementation phase, `code` is complete.
|
|
20
21
|
When `review` passes a new IR or a nonfinal IR-task phase, Captain shall continue with the next unfinished IR-task phase.
|
|
21
22
|
When `review` passes the final IR-task phase, `code` is complete.
|
|
22
|
-
When `review` returns an authored abort or failure, or a terminal result that does not
|
|
23
|
+
When `review` returns an authored abort or failure, or a terminal result that does not establish that the supplied scope was evaluated with no unsettled findings, `code` shall start no further phase and shall report the failure and the last `code`-owned commit to its caller.
|
|
23
24
|
When the nested `review` call fails outside that authored result contract, `code` shall park as failed and retain the control-plane error instead of reporting an authored review outcome.
|
|
24
25
|
|
|
25
26
|
At the start of the first phase, Captain shall relay to Coder the complete caller input and any relevant run results in quotes (`>`), along with the following instruction:
|
|
26
27
|
|
|
27
28
|
```markdown
|
|
28
|
-
|
|
29
|
-
If
|
|
30
|
-
|
|
29
|
+
First determine whether the coding request starts a new coding intent or continues an existing IR with unfinished work.
|
|
30
|
+
If the request may continue an existing IR but does not identify it unambiguously, ask Boss before changing files.
|
|
31
|
+
|
|
32
|
+
For a new coding intent, assess whether it can be completed well in one commit.
|
|
33
|
+
If it can, implement and test it, update the affected specs, and ensure @specs/map.md remains accurate.
|
|
34
|
+
If it cannot, decompose it into tasks sized to exactly one commit each, add a new IR under @specs/intents, and do not implement any IR task in this phase.
|
|
31
35
|
Plan affected spec updates before, with, or after their corresponding code changes, either as standalone IR tasks or as explicit work within related tasks.
|
|
32
36
|
|
|
37
|
+
For an existing IR, read the identified IR and implement exactly its next unfinished task, including corresponding tests or specs if any.
|
|
38
|
+
Do not implement a later task in this phase.
|
|
39
|
+
Mark the IR's progress and deliverables when relevant.
|
|
40
|
+
If the IR will be finished after this phase, double-check that all acceptance criteria are met.
|
|
41
|
+
|
|
33
42
|
Consult @specs/map.md for relevant context and @specs/meta.md for spec requirements, if needed.
|
|
34
43
|
```
|
|
35
44
|
|
|
36
|
-
At the start of every IR-task phase, Captain shall relay to Coder the
|
|
45
|
+
At the start of every later IR-task phase, Captain shall relay to Coder the original caller input, the IR identity, and any relevant run results in quotes (`>`), along with the following instruction:
|
|
37
46
|
|
|
38
47
|
```markdown
|
|
39
|
-
Read IR
|
|
48
|
+
Read the identified IR and implement exactly its next unfinished task, including corresponding tests or specs if any.
|
|
40
49
|
Do not implement a later task in this phase.
|
|
41
50
|
Mark the IR's progress and deliverables when relevant.
|
|
42
51
|
If the IR will be finished after this phase, double-check that all acceptance criteria are met.
|
|
@@ -45,18 +54,29 @@ If the IR will be finished after this phase, double-check that all acceptance cr
|
|
|
45
54
|
At the start of *every* phase, Captain shall append the following instruction:
|
|
46
55
|
|
|
47
56
|
```markdown
|
|
57
|
+
Keep to the original intent and follow what it asks.
|
|
48
58
|
Do not re-run tests or builds whose inputs have not changed since any previous reported run.
|
|
49
59
|
Make the phase's minimal changes and then one new commit, following @specs/packages/git.md; never amend an existing commit.
|
|
50
60
|
Make the commit message explain concisely what changed and why, including relevant verification.
|
|
51
|
-
|
|
61
|
+
Identify every new commit you make.
|
|
62
|
+
Coder is <coder-llm>.
|
|
52
63
|
```
|
|
53
64
|
|
|
54
|
-
|
|
65
|
+
Every new-intent phase has two semantic outcomes: direct implementation and new IR; the new-IR outcome identifies the created IR.
|
|
66
|
+
Every IR-task phase, including the first phase for an existing IR, identifies the IR and the implemented task, and has two semantic outcomes: more tasks and final task.
|
|
67
|
+
The first phase therefore has four semantic outcomes — direct implementation, new IR, more tasks, and final task — plus the Boss question when the continued IR is ambiguous.
|
|
68
|
+
Each semantic outcome requires affirmative support in Coder's result, but no phase transition shall depend on a fixed presentation format of Coder's reply.
|
|
69
|
+
Captain shall use the repository-effect receipt as the authoritative identity of the phase's new commit.
|
|
70
|
+
|
|
71
|
+
At the end of every phase, Captain shall call playbook `review` and input the following in quotes (`>`):
|
|
55
72
|
|
|
56
|
-
>
|
|
73
|
+
> Original intent: \<caller-input\>
|
|
74
|
+
> Review scope: the commit \<code-commit\> from this coding phase and its resulting repository state.
|
|
57
75
|
> Coder output: \<coder-output\>
|
|
58
76
|
|
|
59
|
-
|
|
77
|
+
For an IR-task phase, Captain shall additionally input the following in quotes (`>`):
|
|
60
78
|
|
|
61
|
-
> IR task: \<ir-task\>
|
|
62
|
-
|
|
79
|
+
> Current IR task: \<ir-task\>
|
|
80
|
+
|
|
81
|
+
A nested `review` passes the phase only when its result applies to that supplied review scope, returns the exact evaluated repository revision, and affirmatively establishes that no unsettled findings remain.
|
|
82
|
+
On successful completion, `code` returns the exact last `code`-owned commit, the exact final evaluated repository revision, and the fact that every phase's review passed with no unsettled findings.
|
|
@@ -35,6 +35,10 @@ import {
|
|
|
35
35
|
validateFrozenExecutionConfig,
|
|
36
36
|
} from './run.js';
|
|
37
37
|
import { prepareConfiguredRegistries } from './provision.js';
|
|
38
|
+
import {
|
|
39
|
+
createReplayRecordObserver,
|
|
40
|
+
replayIncompleteMessage,
|
|
41
|
+
} from './replay-observer.js';
|
|
38
42
|
import {
|
|
39
43
|
assertCaptainSessionExecutionCompatible,
|
|
40
44
|
createCaptainSessionStore,
|
|
@@ -86,10 +90,7 @@ export function validateManagedInteractivePayload(value) {
|
|
|
86
90
|
}
|
|
87
91
|
assertUuid(value.sessionId, 'managed interactive session id');
|
|
88
92
|
assertCanonicalAbsolutePath(value.cwd, 'managed interactive working directory');
|
|
89
|
-
|
|
90
|
-
value.sessionsDir,
|
|
91
|
-
'managed interactive sessions directory',
|
|
92
|
-
);
|
|
93
|
+
assertAbsolutePath(value.sessionsDir, 'managed interactive sessions directory');
|
|
93
94
|
if (typeof value.noProvision !== 'boolean') {
|
|
94
95
|
throw new Error('managed interactive noProvision must be a boolean');
|
|
95
96
|
}
|
|
@@ -317,11 +318,19 @@ export function createManagedInteractiveLifecycle(payloadValue, options = {}) {
|
|
|
317
318
|
let activeTurn;
|
|
318
319
|
let executionProjection;
|
|
319
320
|
let freshLaunchRecord;
|
|
321
|
+
let replayChannel;
|
|
320
322
|
|
|
321
323
|
const release = async () => {
|
|
322
324
|
if (released || lease === undefined) return;
|
|
323
325
|
const owned = lease;
|
|
324
|
-
|
|
326
|
+
let status;
|
|
327
|
+
try {
|
|
328
|
+
status = await owned.release();
|
|
329
|
+
} catch (error) {
|
|
330
|
+
await replayChannel?.reportIfIncomplete();
|
|
331
|
+
throw error;
|
|
332
|
+
}
|
|
333
|
+
await replayChannel?.reportIfIncomplete(status);
|
|
325
334
|
if (lease === owned) lease = undefined;
|
|
326
335
|
released = true;
|
|
327
336
|
};
|
|
@@ -369,6 +378,11 @@ export function createManagedInteractiveLifecycle(payloadValue, options = {}) {
|
|
|
369
378
|
let host;
|
|
370
379
|
try {
|
|
371
380
|
lease = await store.acquire(payload.sessionId);
|
|
381
|
+
replayChannel = createManagedReplayChannel({
|
|
382
|
+
lease,
|
|
383
|
+
sessionId: payload.sessionId,
|
|
384
|
+
presentationGate: context.observers[0],
|
|
385
|
+
});
|
|
372
386
|
const authoritative =
|
|
373
387
|
typeof lease.recoverUnresolvedEffectAbandonment === 'function'
|
|
374
388
|
? await lease.recoverUnresolvedEffectAbandonment()
|
|
@@ -435,7 +449,12 @@ export function createManagedInteractiveLifecycle(payloadValue, options = {}) {
|
|
|
435
449
|
cwd: payload.cwd,
|
|
436
450
|
sessionLease: lease,
|
|
437
451
|
loadModule,
|
|
438
|
-
observers:
|
|
452
|
+
observers: [
|
|
453
|
+
...context.observers,
|
|
454
|
+
...(replayChannel === undefined
|
|
455
|
+
? []
|
|
456
|
+
: [replayChannel.observer]),
|
|
457
|
+
],
|
|
439
458
|
...(options.adapterImports
|
|
440
459
|
? { adapterImports: options.adapterImports }
|
|
441
460
|
: {}),
|
|
@@ -491,6 +510,7 @@ export function createManagedInteractiveLifecycle(payloadValue, options = {}) {
|
|
|
491
510
|
retainedGenerations,
|
|
492
511
|
reconcileRepositoryEffects: created.reconcileRepositoryEffects,
|
|
493
512
|
});
|
|
513
|
+
await replayChannel?.reportIfIncomplete();
|
|
494
514
|
initialized = true;
|
|
495
515
|
return {
|
|
496
516
|
abortActiveTurn: (...args) => host.abortActiveTurn(...args),
|
|
@@ -600,6 +620,7 @@ export function createManagedInteractiveLifecycle(payloadValue, options = {}) {
|
|
|
600
620
|
unresolvedEffects: settlement.unresolvedEffects,
|
|
601
621
|
retentionUpdates: settlement.retentionUpdates,
|
|
602
622
|
});
|
|
623
|
+
await replayChannel?.reportIfIncomplete();
|
|
603
624
|
activeTurn = undefined;
|
|
604
625
|
},
|
|
605
626
|
|
|
@@ -631,6 +652,31 @@ export function createManagedInteractiveLifecycle(payloadValue, options = {}) {
|
|
|
631
652
|
});
|
|
632
653
|
}
|
|
633
654
|
|
|
655
|
+
function createManagedReplayChannel({
|
|
656
|
+
lease,
|
|
657
|
+
sessionId,
|
|
658
|
+
presentationGate,
|
|
659
|
+
}) {
|
|
660
|
+
if (
|
|
661
|
+
typeof lease?.append !== 'function' ||
|
|
662
|
+
typeof lease?.streamStatus !== 'function'
|
|
663
|
+
) {
|
|
664
|
+
return undefined;
|
|
665
|
+
}
|
|
666
|
+
return createReplayRecordObserver({
|
|
667
|
+
lease,
|
|
668
|
+
async onIncomplete() {
|
|
669
|
+
if (typeof presentationGate?.onRecord !== 'function') return;
|
|
670
|
+
await presentationGate.onRecord({
|
|
671
|
+
type: 'captain_status',
|
|
672
|
+
turnId: null,
|
|
673
|
+
timestamp: Date.now(),
|
|
674
|
+
message: replayIncompleteMessage(sessionId),
|
|
675
|
+
});
|
|
676
|
+
},
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
|
|
634
680
|
async function writeManagedInteractiveReadinessClaim({
|
|
635
681
|
workDir,
|
|
636
682
|
sessionId,
|
|
@@ -912,6 +958,12 @@ function assertCanonicalAbsolutePath(value, path) {
|
|
|
912
958
|
}
|
|
913
959
|
}
|
|
914
960
|
|
|
961
|
+
function assertAbsolutePath(value, path) {
|
|
962
|
+
if (typeof value !== 'string' || !isAbsolute(value)) {
|
|
963
|
+
throw new Error(`${path} must be an absolute path`);
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
|
|
915
967
|
function assertManagedDescriptorPath(path) {
|
|
916
968
|
if (basename(path) !== MANAGED_INTERACTIVE_PAYLOAD_FILE) {
|
|
917
969
|
throw new Error(
|