@sublang/playbook 14.0.0 → 15.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 +14 -14
- package/docs/configuration.md +15 -9
- package/package.json +1 -1
- package/reference/sdlc/branch.playbook/branch.fsm.d.ts +1 -1
- package/reference/sdlc/code.md +1 -1
- package/reference/sdlc/code.playbook/bin/launch-config.js +55 -16
- package/reference/sdlc/code.playbook/bin/playbook.js +14 -9
- package/reference/sdlc/code.playbook/bin/repository-effects.js +187 -14
- package/reference/sdlc/code.playbook/bin/run.js +12 -8
- package/reference/sdlc/code.playbook/code.fsm.d.ts +1 -1
- package/reference/sdlc/code.playbook/code.fsm.js +1 -1
- package/reference/sdlc/code.playbook/code.fsm.ts +1 -1
- package/reference/sdlc/code.playbook/code.gears.md +2 -2
- package/reference/sdlc/code.playbook/host-capabilities.d.ts +6 -0
- package/reference/sdlc/code.playbook/playbook-captain.d.ts +3 -1
- package/reference/sdlc/code.playbook/playbook-captain.js +357 -16
- package/reference/sdlc/code.playbook/playbook-captain.ts +459 -34
- package/reference/sdlc/code.playbook/session-host.d.ts +6 -3
- package/reference/sdlc/decide.md +1 -1
- package/reference/sdlc/decide.playbook/decide.fsm.d.ts +1 -1
- package/reference/sdlc/decide.playbook/decide.fsm.js +1 -1
- package/reference/sdlc/decide.playbook/decide.fsm.ts +1 -1
- package/reference/sdlc/decide.playbook/decide.gears.md +1 -1
- package/reference/sdlc/decide.playbook/decide.playbook.js +25 -1
- package/reference/sdlc/decide.playbook/decide.playbook.ts +35 -2
- package/reference/sdlc/dev.md +15 -8
- package/reference/sdlc/dev.playbook/dev.fsm.d.ts +1 -1
- package/reference/sdlc/dev.playbook/dev.fsm.js +18 -12
- package/reference/sdlc/dev.playbook/dev.fsm.ts +18 -13
- package/reference/sdlc/dev.playbook/dev.gears.md +19 -12
- package/reference/sdlc/dev.playbook/dev.playbook.js +1 -1
- package/reference/sdlc/dev.playbook/dev.playbook.ts +1 -2
- package/reference/sdlc/dev.playbook/dev.registry.js +1 -1
- package/reference/sdlc/dev.playbook/dev.registry.ts +1 -1
- package/reference/sdlc/pr.playbook/pr.fsm.d.ts +1 -1
- package/reference/sdlc/review.md +1 -1
- package/reference/sdlc/review.playbook/review.fsm.d.ts +1 -1
- package/reference/sdlc/review.playbook/review.fsm.js +1 -1
- package/reference/sdlc/review.playbook/review.fsm.ts +1 -1
- package/reference/sdlc/review.playbook/review.gears.md +1 -1
- package/slc/link.md +32 -0
- package/src/runtime.d.ts +70 -0
- package/src/runtime.js +232 -1
- package/src/runtime.ts +358 -1
- package/src/xstate-playbook-runtime.d.ts +9 -10
- package/src/xstate-playbook-runtime.js +372 -20
- package/src/xstate-playbook-runtime.ts +460 -19
- package/src/xstate-runtime.d.ts +9 -1
- package/src/xstate-runtime.js +299 -19
- package/src/xstate-runtime.ts +362 -21
|
@@ -214,7 +214,7 @@ export declare const decideMachine: import("xstate").StateMachine<DecideContext,
|
|
|
214
214
|
} | {
|
|
215
215
|
type: "validReviewSuccess";
|
|
216
216
|
params: unknown;
|
|
217
|
-
}, never, "done" | "failed" | "
|
|
217
|
+
}, never, "done" | "failed" | "ready" | "awaitBossReply" | "reportedReviewFailure" | "commitCoderProposal" | "reviewCommit" | {
|
|
218
218
|
independentProposals: {
|
|
219
219
|
coder: "complete" | "working" | "waiting";
|
|
220
220
|
reviewer: "complete" | "working" | "waiting";
|
|
@@ -26,7 +26,7 @@ const SYNTHESIZE_COMMIT_PROMPT = [
|
|
|
26
26
|
'Commit the result as one new commit, following @specs/packages/git.md.',
|
|
27
27
|
'Make the commit message explain concisely what changed and why.',
|
|
28
28
|
'Identify every new commit you make.',
|
|
29
|
-
'Coder
|
|
29
|
+
'Credit every AI that contributed to this commit: Coder <coder-llm> and Reviewer <reviewer-llm>, whose proposal it carries.',
|
|
30
30
|
'',
|
|
31
31
|
'> Original topic: <caller-topic>',
|
|
32
32
|
"> Reviewer's independent proposal: <reviewer-proposal>",
|
|
@@ -168,7 +168,7 @@ const SYNTHESIZE_COMMIT_PROMPT = [
|
|
|
168
168
|
'Commit the result as one new commit, following @specs/packages/git.md.',
|
|
169
169
|
'Make the commit message explain concisely what changed and why.',
|
|
170
170
|
'Identify every new commit you make.',
|
|
171
|
-
'Coder
|
|
171
|
+
'Credit every AI that contributed to this commit: Coder <coder-llm> and Reviewer <reviewer-llm>, whose proposal it carries.',
|
|
172
172
|
'',
|
|
173
173
|
'> Original topic: <caller-topic>',
|
|
174
174
|
"> Reviewer's independent proposal: <reviewer-proposal>",
|
|
@@ -66,7 +66,7 @@ When both independent proposals are complete, Captain shall relay the complete t
|
|
|
66
66
|
> Commit the result as one new commit, following @specs/packages/git.md.
|
|
67
67
|
> Make the commit message explain concisely what changed and why.
|
|
68
68
|
> Identify every new commit you make.
|
|
69
|
-
> Coder
|
|
69
|
+
> Credit every AI that contributed to this commit: Coder <coder-llm> and Reviewer <reviewer-llm>, whose proposal it carries.
|
|
70
70
|
>
|
|
71
71
|
> > Original topic: <caller-topic>
|
|
72
72
|
> > Reviewer's independent proposal: <reviewer-proposal>
|
|
@@ -2481,20 +2481,42 @@ function createDecidePlaybookRuntime(options, deferredEffects) {
|
|
|
2481
2481
|
}
|
|
2482
2482
|
return 'restored';
|
|
2483
2483
|
};
|
|
2484
|
+
/**
|
|
2485
|
+
* DR-063 §3: reconciliation re-reads the host's ledger, which the control
|
|
2486
|
+
* view has just done. With no eligible checkpoint restoration and a complete
|
|
2487
|
+
* receipt on every unresolved boundary, re-reading resolves nothing.
|
|
2488
|
+
*/
|
|
2489
|
+
const reconciliationStanding = (restorationEligible) => {
|
|
2490
|
+
if (restorationEligible)
|
|
2491
|
+
return { standing: 'ready' };
|
|
2492
|
+
const envelopes = unresolvedEffectEnvelopeIdentities();
|
|
2493
|
+
if (envelopes.length === 0)
|
|
2494
|
+
return { standing: 'ready' };
|
|
2495
|
+
const boundaryIds = envelopes.flatMap((envelope) => envelope.kind === 'boundary'
|
|
2496
|
+
? [envelope.boundaryId]
|
|
2497
|
+
: (effectLedgerMirror.logicalOperations.find(({ operationId }) => operationId === envelope.operationId)?.boundaryIds ?? []));
|
|
2498
|
+
if (boundaryIds.length === 0)
|
|
2499
|
+
return { standing: 'ready' };
|
|
2500
|
+
return boundaryIds.every((boundaryId) => effectLedgerMirror.boundaries.find((candidate) => candidate.boundaryId === boundaryId)?.physicalReceipt !== undefined)
|
|
2501
|
+
? { standing: 'no-op', reason: 'receipt-complete' }
|
|
2502
|
+
: { standing: 'ready' };
|
|
2503
|
+
};
|
|
2484
2504
|
const unresolvedControlCandidates = () => {
|
|
2485
2505
|
if (!hasUnresolvedReconciliation())
|
|
2486
2506
|
return [];
|
|
2487
2507
|
const operation = hiddenDeferredOperationId === undefined
|
|
2488
2508
|
? undefined
|
|
2489
2509
|
: effectLedgerMirror.logicalOperations.find(({ operationId }) => operationId === hiddenDeferredOperationId);
|
|
2510
|
+
const restorationEligible = operation?.checkpointRestorationEligible === true;
|
|
2490
2511
|
return [
|
|
2491
2512
|
{
|
|
2492
2513
|
action: {
|
|
2493
2514
|
id: UNRESOLVED_EFFECT_RECONCILIATION_ACTION_ID,
|
|
2494
2515
|
label: 'Retry unresolved effect reconciliation',
|
|
2516
|
+
...reconciliationStanding(restorationEligible),
|
|
2495
2517
|
},
|
|
2496
2518
|
kind: 'reconcile',
|
|
2497
|
-
...(
|
|
2519
|
+
...(restorationEligible
|
|
2498
2520
|
? { deferredRestoreOperationId: operation.operationId }
|
|
2499
2521
|
: {}),
|
|
2500
2522
|
},
|
|
@@ -2502,6 +2524,8 @@ function createDecidePlaybookRuntime(options, deferredEffects) {
|
|
|
2502
2524
|
action: {
|
|
2503
2525
|
id: UNRESOLVED_EFFECT_ABANDONMENT_ACTION_ID,
|
|
2504
2526
|
label: 'Abandon unresolved workflow attempt',
|
|
2527
|
+
// DR-063 §3: abandonment always changes the session's standing.
|
|
2528
|
+
standing: 'ready',
|
|
2505
2529
|
},
|
|
2506
2530
|
kind: 'abandon',
|
|
2507
2531
|
},
|
|
@@ -3850,6 +3850,35 @@ function createDecidePlaybookRuntime(
|
|
|
3850
3850
|
};
|
|
3851
3851
|
type UnresolvedControlCandidates = readonly UnresolvedControlCandidate[];
|
|
3852
3852
|
|
|
3853
|
+
/**
|
|
3854
|
+
* DR-063 §3: reconciliation re-reads the host's ledger, which the control
|
|
3855
|
+
* view has just done. With no eligible checkpoint restoration and a complete
|
|
3856
|
+
* receipt on every unresolved boundary, re-reading resolves nothing.
|
|
3857
|
+
*/
|
|
3858
|
+
const reconciliationStanding = (
|
|
3859
|
+
restorationEligible: boolean,
|
|
3860
|
+
): Pick<PlaybookControlAction, 'standing' | 'reason'> => {
|
|
3861
|
+
if (restorationEligible) return { standing: 'ready' };
|
|
3862
|
+
const envelopes = unresolvedEffectEnvelopeIdentities();
|
|
3863
|
+
if (envelopes.length === 0) return { standing: 'ready' };
|
|
3864
|
+
const boundaryIds = envelopes.flatMap((envelope) =>
|
|
3865
|
+
envelope.kind === 'boundary'
|
|
3866
|
+
? [envelope.boundaryId]
|
|
3867
|
+
: (effectLedgerMirror.logicalOperations.find(
|
|
3868
|
+
({ operationId }) => operationId === envelope.operationId,
|
|
3869
|
+
)?.boundaryIds ?? []),
|
|
3870
|
+
);
|
|
3871
|
+
if (boundaryIds.length === 0) return { standing: 'ready' };
|
|
3872
|
+
return boundaryIds.every(
|
|
3873
|
+
(boundaryId) =>
|
|
3874
|
+
effectLedgerMirror.boundaries.find(
|
|
3875
|
+
(candidate) => candidate.boundaryId === boundaryId,
|
|
3876
|
+
)?.physicalReceipt !== undefined,
|
|
3877
|
+
)
|
|
3878
|
+
? { standing: 'no-op', reason: 'receipt-complete' }
|
|
3879
|
+
: { standing: 'ready' };
|
|
3880
|
+
};
|
|
3881
|
+
|
|
3853
3882
|
const unresolvedControlCandidates = (): UnresolvedControlCandidates => {
|
|
3854
3883
|
if (!hasUnresolvedReconciliation()) return [];
|
|
3855
3884
|
const operation =
|
|
@@ -3859,21 +3888,25 @@ function createDecidePlaybookRuntime(
|
|
|
3859
3888
|
({ operationId }) =>
|
|
3860
3889
|
operationId === hiddenDeferredOperationId,
|
|
3861
3890
|
);
|
|
3891
|
+
const restorationEligible = operation?.checkpointRestorationEligible === true;
|
|
3862
3892
|
return [
|
|
3863
3893
|
{
|
|
3864
3894
|
action: {
|
|
3865
3895
|
id: UNRESOLVED_EFFECT_RECONCILIATION_ACTION_ID,
|
|
3866
3896
|
label: 'Retry unresolved effect reconciliation',
|
|
3897
|
+
...reconciliationStanding(restorationEligible),
|
|
3867
3898
|
},
|
|
3868
3899
|
kind: 'reconcile',
|
|
3869
|
-
...(
|
|
3870
|
-
? { deferredRestoreOperationId: operation
|
|
3900
|
+
...(restorationEligible
|
|
3901
|
+
? { deferredRestoreOperationId: operation!.operationId }
|
|
3871
3902
|
: {}),
|
|
3872
3903
|
},
|
|
3873
3904
|
{
|
|
3874
3905
|
action: {
|
|
3875
3906
|
id: UNRESOLVED_EFFECT_ABANDONMENT_ACTION_ID,
|
|
3876
3907
|
label: 'Abandon unresolved workflow attempt',
|
|
3908
|
+
// DR-063 §3: abandonment always changes the session's standing.
|
|
3909
|
+
standing: 'ready',
|
|
3877
3910
|
},
|
|
3878
3911
|
kind: 'abandon',
|
|
3879
3912
|
},
|
package/reference/sdlc/dev.md
CHANGED
|
@@ -12,6 +12,7 @@ The caller supplies a development request including any desired outcome, scope,
|
|
|
12
12
|
|
|
13
13
|
`dev` is an optional repository-aware planner for a development request that needs more analysis before choosing a development path.
|
|
14
14
|
It coordinates existing playbooks and owns no repository commit itself.
|
|
15
|
+
Analyst chooses the path and states why in a short planning note; analysis, design, and implementation belong to the playbooks `dev` calls, and a question to Boss serves only the choice of path.
|
|
15
16
|
|
|
16
17
|
At the start of `dev` and after each Boss reply, Captain shall relay the development request, relevant discussion context, and any relevant run results to Analyst in quotes (`>`), along with the following instruction:
|
|
17
18
|
|
|
@@ -20,17 +21,23 @@ At the start of `dev` and after each Boss reply, Captain shall relay the develop
|
|
|
20
21
|
> Run results: <run-results>
|
|
21
22
|
|
|
22
23
|
```markdown
|
|
23
|
-
|
|
24
|
+
Plan which playbooks run for this request; the playbooks do the work.
|
|
25
|
+
Read the request, then the specs and the repository only as far as choosing the path requires.
|
|
24
26
|
Do not change files or commit while planning or discussing the request.
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
- If the discussion has concluded after a Boss reply and no repository work should follow, choose `discussion complete`.
|
|
28
|
-
- If implementation can proceed under the existing decisions, choose `code`.
|
|
29
|
-
- If implementation first requires a new or amended durable decision that the existing specs do not settle, choose `decide then code`.
|
|
30
|
-
- If the request names a GitHub issue (number or URL) or explicitly asks for pull-request delivery, read the issue and its comments as part of the analysis (`gh issue view --comments` with the issue number) and choose `code via pull request` or `decide then code via pull request` in place of `code` or `decide then code`.
|
|
28
|
+
Choose exactly one:
|
|
31
29
|
|
|
30
|
+
- `code`: the existing decisions and spec items settle how the work is done.
|
|
31
|
+
- `decide then code`: the work turns on a rule, concept, term, shape, or trade-off the specs leave open or contradict; name what is open, do not settle it.
|
|
32
|
+
- `code via pull request` or `decide then code via pull request`, in place of the two above, when the request names a GitHub issue (number or URL) or explicitly asks for pull-request delivery; read the issue and its comments (`gh issue view --comments` with the issue number) while choosing.
|
|
33
|
+
- A question to Boss, only when the answer would change which path runs or whether any work is wanted: one short question naming the alternatives it decides between, and nothing else. When every answer leads to the same path, choose it; the playbook settles the open point.
|
|
34
|
+
- `discussion complete`, after a Boss reply, when no repository work should follow.
|
|
35
|
+
|
|
36
|
+
Your reply is the planning note the chosen playbook receives. It holds only the path and, in at most ten lines, why — the decisions and spec items that settle the work, or the open point a decision must settle — plus the scope the request implies and any fact from the issue the playbooks need.
|
|
37
|
+
It holds no design, proposal, implementation instruction, or file-level finding: the playbooks own those.
|
|
38
|
+
A reply that chooses a path asks Boss nothing; a reply that asks Boss chooses no path.
|
|
32
39
|
A question or exploratory discussion is not by itself authorization to create a durable decision or implement changes.
|
|
33
|
-
Do not choose `decide then code` merely because the work is large.
|
|
40
|
+
Do not choose `decide then code` merely because the work is large, nor `code` merely because it is small.
|
|
34
41
|
Consult @specs/map.md for relevant context and @specs/meta.md for spec requirements, if needed.
|
|
35
42
|
```
|
|
36
43
|
|
|
@@ -42,7 +49,7 @@ No outcome depends on a fixed presentation format of Analyst's reply.
|
|
|
42
49
|
For needs Boss reply, `dev` shall use the standard Boss-question suspension with Analyst's complete response.
|
|
43
50
|
The session Captain shall present that response to Boss and, after Boss replies, resume `dev` with the answer in the same Analyst conversation; include the previous question only when that conversation must start fresh.
|
|
44
51
|
|
|
45
|
-
Discussion complete is available only after a Boss reply, when
|
|
52
|
+
Discussion complete is available only after a Boss reply, when that reply settles that no repository work should follow.
|
|
46
53
|
It completes `dev` without a child call or repository change.
|
|
47
54
|
|
|
48
55
|
For code, `dev` shall directly call playbook `code` with the development request, relevant discussion context, and planning result in quotes (`>`).
|
|
@@ -296,7 +296,7 @@ export declare const devMachine: import("xstate").StateMachine<DevContext, {
|
|
|
296
296
|
} | {
|
|
297
297
|
type: "resumesPlanAnalysis";
|
|
298
298
|
params: unknown;
|
|
299
|
-
}, never, "done" | "failed" | "
|
|
299
|
+
}, never, "done" | "failed" | "ready" | "awaitBossReply" | "planAnalysis" | "createBranch" | "callCode" | "callDecide" | "callCodeAfterDecide" | "openPullRequest" | "discussionComplete" | "reportedChildFailure", string, DevInput, {
|
|
300
300
|
readonly status: "discussion-complete";
|
|
301
301
|
} | {
|
|
302
302
|
readonly status: "complete";
|
|
@@ -8,30 +8,36 @@ const PLAN_ANALYSIS_PROMPT = [
|
|
|
8
8
|
'> Prior discussion: <discussion-context>',
|
|
9
9
|
'> Run results: <run-results>',
|
|
10
10
|
'',
|
|
11
|
-
'
|
|
11
|
+
'Plan which playbooks run for this request; the playbooks do the work.',
|
|
12
|
+
'Read the request, then the specs and the repository only as far as choosing the path requires.',
|
|
12
13
|
'Do not change files or commit while planning or discussing the request.',
|
|
13
14
|
'',
|
|
14
|
-
'
|
|
15
|
-
'- If the discussion has concluded after a Boss reply and no repository work should follow, choose `discussion complete`.',
|
|
16
|
-
'- If implementation can proceed under the existing decisions, choose `code`.',
|
|
17
|
-
'- If implementation first requires a new or amended durable decision that the existing specs do not settle, choose `decide then code`.',
|
|
18
|
-
'- If the request names a GitHub issue (number or URL) or explicitly asks for pull-request delivery, read the issue and its comments as part of the analysis (`gh issue view --comments` with the issue number) and choose `code via pull request` or `decide then code via pull request` in place of `code` or `decide then code`.',
|
|
15
|
+
'Choose exactly one:',
|
|
19
16
|
'',
|
|
17
|
+
'- `code`: the existing decisions and spec items settle how the work is done.',
|
|
18
|
+
'- `decide then code`: the work turns on a rule, concept, term, shape, or trade-off the specs leave open or contradict; name what is open, do not settle it.',
|
|
19
|
+
'- `code via pull request` or `decide then code via pull request`, in place of the two above, when the request names a GitHub issue (number or URL) or explicitly asks for pull-request delivery; read the issue and its comments (`gh issue view --comments` with the issue number) while choosing.',
|
|
20
|
+
'- A question to Boss, only when the answer would change which path runs or whether any work is wanted: one short question naming the alternatives it decides between, and nothing else. When every answer leads to the same path, choose it; the playbook settles the open point.',
|
|
21
|
+
'- `discussion complete`, after a Boss reply, when no repository work should follow.',
|
|
22
|
+
'',
|
|
23
|
+
'Your reply is the planning note the chosen playbook receives. It holds only the path and, in at most ten lines, why — the decisions and spec items that settle the work, or the open point a decision must settle — plus the scope the request implies and any fact from the issue the playbooks need.',
|
|
24
|
+
'It holds no design, proposal, implementation instruction, or file-level finding: the playbooks own those.',
|
|
25
|
+
'A reply that chooses a path asks Boss nothing; a reply that asks Boss chooses no path.',
|
|
20
26
|
'A question or exploratory discussion is not by itself authorization to create a durable decision or implement changes.',
|
|
21
|
-
'Do not choose `decide then code` merely because the work is large.',
|
|
27
|
+
'Do not choose `decide then code` merely because the work is large, nor `code` merely because it is small.',
|
|
22
28
|
'Consult @specs/map.md for relevant context and @specs/meta.md for spec requirements, if needed.',
|
|
23
29
|
].join('\n');
|
|
24
30
|
const PLAN_ANALYSIS_RESULTS = {
|
|
25
31
|
discussionComplete: 'Analyst concluded the discussion after a Boss reply, with no repository work to follow.',
|
|
26
|
-
code: 'Analyst
|
|
27
|
-
decideThenCode: 'Analyst
|
|
28
|
-
codeViaPullRequest: 'Analyst
|
|
29
|
-
decideThenCodeViaPullRequest: 'Analyst
|
|
32
|
+
code: 'Analyst chose `code`: the existing decisions and spec items settle how the work is done. Output shall include `planningResult: <verbatim final text>`.',
|
|
33
|
+
decideThenCode: 'Analyst chose `decide then code`: the work turns on a point the specs leave open or contradict. Output shall include `planningResult: <verbatim final text>`.',
|
|
34
|
+
codeViaPullRequest: 'Analyst chose `code via pull request`: the existing decisions settle the work, and the request names a GitHub issue or explicitly asks for pull-request delivery. Output shall include `planningResult: <verbatim final text>`.',
|
|
35
|
+
decideThenCodeViaPullRequest: 'Analyst chose `decide then code via pull request`: the work turns on a point the specs leave open or contradict, and the request names a GitHub issue or explicitly asks for pull-request delivery. Output shall include `planningResult: <verbatim final text>`.',
|
|
30
36
|
needsBossReply: "The acting agent's prose surfaces a clarifying question for Boss that the agent cannot answer alone. Output shall include `question: <verbatim question text from the acting agent's prose>`.",
|
|
31
37
|
};
|
|
32
38
|
const STATE_DESCRIPTIONS = {
|
|
33
39
|
ready: 'Waiting for a development request.',
|
|
34
|
-
planAnalysis: 'Analyst is
|
|
40
|
+
planAnalysis: 'Analyst is choosing the development path.',
|
|
35
41
|
createBranch: 'The BRANCH playbook is preparing the pull-request branch for the planned development path.',
|
|
36
42
|
callCode: 'The CODE playbook is implementing the planned development path.',
|
|
37
43
|
callDecide: 'The DECIDE playbook is settling the durable decision the planned path requires.',
|
|
@@ -198,17 +198,23 @@ const PLAN_ANALYSIS_PROMPT = [
|
|
|
198
198
|
'> Prior discussion: <discussion-context>',
|
|
199
199
|
'> Run results: <run-results>',
|
|
200
200
|
'',
|
|
201
|
-
'
|
|
201
|
+
'Plan which playbooks run for this request; the playbooks do the work.',
|
|
202
|
+
'Read the request, then the specs and the repository only as far as choosing the path requires.',
|
|
202
203
|
'Do not change files or commit while planning or discussing the request.',
|
|
203
204
|
'',
|
|
204
|
-
'
|
|
205
|
-
'- If the discussion has concluded after a Boss reply and no repository work should follow, choose `discussion complete`.',
|
|
206
|
-
'- If implementation can proceed under the existing decisions, choose `code`.',
|
|
207
|
-
'- If implementation first requires a new or amended durable decision that the existing specs do not settle, choose `decide then code`.',
|
|
208
|
-
'- If the request names a GitHub issue (number or URL) or explicitly asks for pull-request delivery, read the issue and its comments as part of the analysis (`gh issue view --comments` with the issue number) and choose `code via pull request` or `decide then code via pull request` in place of `code` or `decide then code`.',
|
|
205
|
+
'Choose exactly one:',
|
|
209
206
|
'',
|
|
207
|
+
'- `code`: the existing decisions and spec items settle how the work is done.',
|
|
208
|
+
'- `decide then code`: the work turns on a rule, concept, term, shape, or trade-off the specs leave open or contradict; name what is open, do not settle it.',
|
|
209
|
+
'- `code via pull request` or `decide then code via pull request`, in place of the two above, when the request names a GitHub issue (number or URL) or explicitly asks for pull-request delivery; read the issue and its comments (`gh issue view --comments` with the issue number) while choosing.',
|
|
210
|
+
'- A question to Boss, only when the answer would change which path runs or whether any work is wanted: one short question naming the alternatives it decides between, and nothing else. When every answer leads to the same path, choose it; the playbook settles the open point.',
|
|
211
|
+
'- `discussion complete`, after a Boss reply, when no repository work should follow.',
|
|
212
|
+
'',
|
|
213
|
+
'Your reply is the planning note the chosen playbook receives. It holds only the path and, in at most ten lines, why — the decisions and spec items that settle the work, or the open point a decision must settle — plus the scope the request implies and any fact from the issue the playbooks need.',
|
|
214
|
+
'It holds no design, proposal, implementation instruction, or file-level finding: the playbooks own those.',
|
|
215
|
+
'A reply that chooses a path asks Boss nothing; a reply that asks Boss chooses no path.',
|
|
210
216
|
'A question or exploratory discussion is not by itself authorization to create a durable decision or implement changes.',
|
|
211
|
-
'Do not choose `decide then code` merely because the work is large.',
|
|
217
|
+
'Do not choose `decide then code` merely because the work is large, nor `code` merely because it is small.',
|
|
212
218
|
'Consult @specs/map.md for relevant context and @specs/meta.md for spec requirements, if needed.',
|
|
213
219
|
].join('\n');
|
|
214
220
|
|
|
@@ -216,21 +222,20 @@ const PLAN_ANALYSIS_RESULTS = {
|
|
|
216
222
|
discussionComplete:
|
|
217
223
|
'Analyst concluded the discussion after a Boss reply, with no repository work to follow.',
|
|
218
224
|
code:
|
|
219
|
-
'Analyst
|
|
225
|
+
'Analyst chose `code`: the existing decisions and spec items settle how the work is done. Output shall include `planningResult: <verbatim final text>`.',
|
|
220
226
|
decideThenCode:
|
|
221
|
-
'Analyst
|
|
227
|
+
'Analyst chose `decide then code`: the work turns on a point the specs leave open or contradict. Output shall include `planningResult: <verbatim final text>`.',
|
|
222
228
|
codeViaPullRequest:
|
|
223
|
-
'Analyst
|
|
229
|
+
'Analyst chose `code via pull request`: the existing decisions settle the work, and the request names a GitHub issue or explicitly asks for pull-request delivery. Output shall include `planningResult: <verbatim final text>`.',
|
|
224
230
|
decideThenCodeViaPullRequest:
|
|
225
|
-
'Analyst
|
|
231
|
+
'Analyst chose `decide then code via pull request`: the work turns on a point the specs leave open or contradict, and the request names a GitHub issue or explicitly asks for pull-request delivery. Output shall include `planningResult: <verbatim final text>`.',
|
|
226
232
|
needsBossReply:
|
|
227
233
|
"The acting agent's prose surfaces a clarifying question for Boss that the agent cannot answer alone. Output shall include `question: <verbatim question text from the acting agent's prose>`.",
|
|
228
234
|
} as const;
|
|
229
235
|
|
|
230
236
|
const STATE_DESCRIPTIONS = {
|
|
231
237
|
ready: 'Waiting for a development request.',
|
|
232
|
-
planAnalysis:
|
|
233
|
-
'Analyst is analyzing the development request to choose the smallest sound next step.',
|
|
238
|
+
planAnalysis: 'Analyst is choosing the development path.',
|
|
234
239
|
createBranch:
|
|
235
240
|
'The BRANCH playbook is preparing the pull-request branch for the planned development path.',
|
|
236
241
|
callCode: 'The CODE playbook is implementing the planned development path.',
|
|
@@ -9,6 +9,7 @@ Roles:
|
|
|
9
9
|
|
|
10
10
|
`dev` is an optional repository-aware planner for a development request that needs more analysis before choosing a development path.
|
|
11
11
|
It coordinates existing playbooks and owns no repository commit itself.
|
|
12
|
+
Analyst chooses the path and states why in a short planning note; analysis, design, and implementation belong to the playbooks `dev` calls, and a question to Boss serves only the choice of path.
|
|
12
13
|
|
|
13
14
|
## Analyst
|
|
14
15
|
|
|
@@ -20,31 +21,37 @@ At the start of `dev` and after each Boss reply, Captain shall relay the develop
|
|
|
20
21
|
> > Prior discussion: <discussion-context>
|
|
21
22
|
> > Run results: <run-results>
|
|
22
23
|
>
|
|
23
|
-
>
|
|
24
|
+
> Plan which playbooks run for this request; the playbooks do the work.
|
|
25
|
+
> Read the request, then the specs and the repository only as far as choosing the path requires.
|
|
24
26
|
> Do not change files or commit while planning or discussing the request.
|
|
25
27
|
>
|
|
26
|
-
>
|
|
27
|
-
> - If the discussion has concluded after a Boss reply and no repository work should follow, choose `discussion complete`.
|
|
28
|
-
> - If implementation can proceed under the existing decisions, choose `code`.
|
|
29
|
-
> - If implementation first requires a new or amended durable decision that the existing specs do not settle, choose `decide then code`.
|
|
30
|
-
> - If the request names a GitHub issue (number or URL) or explicitly asks for pull-request delivery, read the issue and its comments as part of the analysis (`gh issue view --comments` with the issue number) and choose `code via pull request` or `decide then code via pull request` in place of `code` or `decide then code`.
|
|
28
|
+
> Choose exactly one:
|
|
31
29
|
>
|
|
30
|
+
> - `code`: the existing decisions and spec items settle how the work is done.
|
|
31
|
+
> - `decide then code`: the work turns on a rule, concept, term, shape, or trade-off the specs leave open or contradict; name what is open, do not settle it.
|
|
32
|
+
> - `code via pull request` or `decide then code via pull request`, in place of the two above, when the request names a GitHub issue (number or URL) or explicitly asks for pull-request delivery; read the issue and its comments (`gh issue view --comments` with the issue number) while choosing.
|
|
33
|
+
> - A question to Boss, only when the answer would change which path runs or whether any work is wanted: one short question naming the alternatives it decides between, and nothing else. When every answer leads to the same path, choose it; the playbook settles the open point.
|
|
34
|
+
> - `discussion complete`, after a Boss reply, when no repository work should follow.
|
|
35
|
+
>
|
|
36
|
+
> Your reply is the planning note the chosen playbook receives. It holds only the path and, in at most ten lines, why — the decisions and spec items that settle the work, or the open point a decision must settle — plus the scope the request implies and any fact from the issue the playbooks need.
|
|
37
|
+
> It holds no design, proposal, implementation instruction, or file-level finding: the playbooks own those.
|
|
38
|
+
> A reply that chooses a path asks Boss nothing; a reply that asks Boss chooses no path.
|
|
32
39
|
> A question or exploratory discussion is not by itself authorization to create a durable decision or implement changes.
|
|
33
|
-
> Do not choose `decide then code` merely because the work is large.
|
|
40
|
+
> Do not choose `decide then code` merely because the work is large, nor `code` merely because it is small.
|
|
34
41
|
> Consult @specs/map.md for relevant context and @specs/meta.md for spec requirements, if needed.
|
|
35
42
|
|
|
36
43
|
Results:
|
|
37
44
|
- `discussionComplete`: Analyst concluded the discussion after a Boss reply, with no repository work to follow.
|
|
38
|
-
- `code`: Analyst
|
|
39
|
-
- `decideThenCode`: Analyst
|
|
40
|
-
- `codeViaPullRequest`: Analyst
|
|
41
|
-
- `decideThenCodeViaPullRequest`: Analyst
|
|
45
|
+
- `code`: Analyst chose `code`: the existing decisions and spec items settle how the work is done. Output shall include `planningResult: <verbatim final text>`.
|
|
46
|
+
- `decideThenCode`: Analyst chose `decide then code`: the work turns on a point the specs leave open or contradict. Output shall include `planningResult: <verbatim final text>`.
|
|
47
|
+
- `codeViaPullRequest`: Analyst chose `code via pull request`: the existing decisions settle the work, and the request names a GitHub issue or explicitly asks for pull-request delivery. Output shall include `planningResult: <verbatim final text>`.
|
|
48
|
+
- `decideThenCodeViaPullRequest`: Analyst chose `decide then code via pull request`: the work turns on a point the specs leave open or contradict, and the request names a GitHub issue or explicitly asks for pull-request delivery. Output shall include `planningResult: <verbatim final text>`.
|
|
42
49
|
|
|
43
50
|
Workflow outcomes:
|
|
44
51
|
- The planning result has six semantic outcomes: needs Boss reply, discussion complete, code, decide then code, code via pull request, and decide then code via pull request.
|
|
45
52
|
- Each outcome requires affirmative support in Analyst's result; absence of a reason to choose another outcome is not support, and no outcome depends on a fixed presentation format of Analyst's reply.
|
|
46
53
|
- Needs Boss reply uses the standard Boss-question suspension with Analyst's complete response; after Boss replies, `dev` resumes with the answer in the same Analyst conversation; the previous question is included only when that conversation must start fresh.
|
|
47
|
-
- Discussion complete is available only after a Boss reply, when
|
|
54
|
+
- Discussion complete is available only after a Boss reply, when that reply settles that no repository work should follow; it completes `dev` without a child call or repository change.
|
|
48
55
|
- `dev` acts on the accepted outcome itself and does not return to the session Captain for another routing decision.
|
|
49
56
|
|
|
50
57
|
## Nested development paths
|
|
@@ -92,7 +92,7 @@ const runtimeSpec = {
|
|
|
92
92
|
roleStates: {
|
|
93
93
|
planAnalysis: {
|
|
94
94
|
role: 'analyst',
|
|
95
|
-
label: 'Analyst is
|
|
95
|
+
label: 'Analyst is choosing the development path.',
|
|
96
96
|
},
|
|
97
97
|
},
|
|
98
98
|
// DR-044: DEV owns no repository commit — every Analyst outcome is
|
|
@@ -179,8 +179,7 @@ const runtimeSpec = {
|
|
|
179
179
|
roleStates: {
|
|
180
180
|
planAnalysis: {
|
|
181
181
|
role: 'analyst',
|
|
182
|
-
label:
|
|
183
|
-
'Analyst is analyzing the development request to choose the smallest sound next step.',
|
|
182
|
+
label: 'Analyst is choosing the development path.',
|
|
184
183
|
},
|
|
185
184
|
},
|
|
186
185
|
// DR-044: DEV owns no repository commit — every Analyst outcome is
|
|
@@ -49,7 +49,7 @@ export function validateDevOptions(optionSlice) {
|
|
|
49
49
|
export const devPlaybookRegistryEntry = {
|
|
50
50
|
id: 'dev',
|
|
51
51
|
command: 'dev',
|
|
52
|
-
intent: '
|
|
52
|
+
intent: 'plan the development path for a request: direct implementation, or a durable decision first, delivered through a pull request when the request names a GitHub issue or asks for one',
|
|
53
53
|
artifactSchema: 3,
|
|
54
54
|
runtimeProfile: Object.freeze({
|
|
55
55
|
kind: 'shared-factory',
|
|
@@ -104,7 +104,7 @@ export const devPlaybookRegistryEntry: DevPlaybookRegistryEntry = {
|
|
|
104
104
|
id: 'dev',
|
|
105
105
|
command: 'dev',
|
|
106
106
|
intent:
|
|
107
|
-
'
|
|
107
|
+
'plan the development path for a request: direct implementation, or a durable decision first, delivered through a pull request when the request names a GitHub issue or asks for one',
|
|
108
108
|
artifactSchema: 3,
|
|
109
109
|
runtimeProfile: Object.freeze({
|
|
110
110
|
kind: 'shared-factory',
|
|
@@ -278,7 +278,7 @@ export declare const prMachine: import("xstate").StateMachine<PrContext, {
|
|
|
278
278
|
} | {
|
|
279
279
|
type: "resumesOpenPullRequest";
|
|
280
280
|
params: unknown;
|
|
281
|
-
}, never, "failed" | "
|
|
281
|
+
}, never, "failed" | "ready" | "awaitBossReply" | "openPullRequest" | "waitForChecks" | "fixChecks" | "publishFix" | "waitForChecksAfterFix" | "mergePullRequest" | "updateLocalDefault" | "notPublished" | "fixNotPublished" | "checksStillFailing" | "merged" | "mergeRefused" | "mergedLocalBehind" | "fixFailed", string, Readonly<Record<never, never>>, {
|
|
282
282
|
readonly status: "merged";
|
|
283
283
|
/** The pull request number, exactly as Coder reported it. */
|
|
284
284
|
readonly pullRequest: string;
|
package/reference/sdlc/review.md
CHANGED
|
@@ -101,7 +101,7 @@ If you accept any item, make minimal changes and add one new review-fix commit;
|
|
|
101
101
|
Follow @specs/packages/git.md.
|
|
102
102
|
Make the commit message explain concisely what changed and why, including relevant verification.
|
|
103
103
|
Identify every new commit you make.
|
|
104
|
-
Coder
|
|
104
|
+
Credit every AI that contributed to this commit: Coder <coder-llm> and Reviewer <reviewer-llm>, whose findings it answers.
|
|
105
105
|
|
|
106
106
|
If you reject every item, change nothing and make no commit.
|
|
107
107
|
Report every disposition, all relevant run results, and every rebuttal.
|
|
@@ -169,7 +169,7 @@ export declare const reviewMachine: import("xstate").StateMachine<ReviewContext,
|
|
|
169
169
|
} | {
|
|
170
170
|
type: "restartInitialReview";
|
|
171
171
|
params: unknown;
|
|
172
|
-
}, never, "done" | "failed" | "
|
|
172
|
+
}, never, "done" | "failed" | "ready" | "awaitBossReply" | "reviewInitial" | "addressFindings" | "reviewAfterCommit" | "reviewAfterRebuttal", string, Readonly<Record<string, never>>, ReviewOutput, import("xstate").EventObject, import("xstate").MetaObject, {
|
|
173
173
|
id: "review";
|
|
174
174
|
states: {
|
|
175
175
|
readonly ready: {
|
|
@@ -67,7 +67,7 @@ const CODER_DISPOSITION_PROMPT = [
|
|
|
67
67
|
'Follow @specs/packages/git.md.',
|
|
68
68
|
'Make the commit message explain concisely what changed and why, including relevant verification.',
|
|
69
69
|
'Identify every new commit you make.',
|
|
70
|
-
'Coder
|
|
70
|
+
'Credit every AI that contributed to this commit: Coder <coder-llm> and Reviewer <reviewer-llm>, whose findings it answers.',
|
|
71
71
|
'',
|
|
72
72
|
'If you reject every item, change nothing and make no commit.',
|
|
73
73
|
'Report every disposition, all relevant run results, and every rebuttal.',
|
|
@@ -156,7 +156,7 @@ const CODER_DISPOSITION_PROMPT = [
|
|
|
156
156
|
'Follow @specs/packages/git.md.',
|
|
157
157
|
'Make the commit message explain concisely what changed and why, including relevant verification.',
|
|
158
158
|
'Identify every new commit you make.',
|
|
159
|
-
'Coder
|
|
159
|
+
'Credit every AI that contributed to this commit: Coder <coder-llm> and Reviewer <reviewer-llm>, whose findings it answers.',
|
|
160
160
|
'',
|
|
161
161
|
'If you reject every item, change nothing and make no commit.',
|
|
162
162
|
'Report every disposition, all relevant run results, and every rebuttal.',
|
|
@@ -65,7 +65,7 @@ When Reviewer raises or keeps any finding, Captain shall relay the caller input
|
|
|
65
65
|
> Follow @specs/packages/git.md.
|
|
66
66
|
> Make the commit message explain concisely what changed and why, including relevant verification.
|
|
67
67
|
> Identify every new commit you make.
|
|
68
|
-
> Coder
|
|
68
|
+
> Credit every AI that contributed to this commit: Coder <coder-llm> and Reviewer <reviewer-llm>, whose findings it answers.
|
|
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.
|
package/slc/link.md
CHANGED
|
@@ -247,10 +247,36 @@ type JsonValue =
|
|
|
247
247
|
| readonly JsonValue[]
|
|
248
248
|
| { readonly [key: string]: JsonValue };
|
|
249
249
|
|
|
250
|
+
// DR-063: the closed failure-cause contract. `code` is one of
|
|
251
|
+
// PLAYBOOK_FAILURE_CODES and `evidence` holds exactly the members that code
|
|
252
|
+
// names — repository paths, dispositions, classifications, and revisions, never
|
|
253
|
+
// content or internal identity.
|
|
254
|
+
type PlaybookFailureCode =
|
|
255
|
+
| 'commit-missing'
|
|
256
|
+
| 'commit-residual'
|
|
257
|
+
| 'pre-existing-lost'
|
|
258
|
+
| 'commits-more-than-one'
|
|
259
|
+
| 'history-rewritten'
|
|
260
|
+
| 'foreign-change'
|
|
261
|
+
| 'observation-unstable'
|
|
262
|
+
| 'attribution-ambiguous'
|
|
263
|
+
| 'receipt-missing'
|
|
264
|
+
| 'judge-failed'
|
|
265
|
+
| 'player-failed'
|
|
266
|
+
| 'aborted'
|
|
267
|
+
| 'child-failed'
|
|
268
|
+
| 'runtime-defect';
|
|
269
|
+
|
|
270
|
+
interface PlaybookFailureCause {
|
|
271
|
+
readonly code: PlaybookFailureCode;
|
|
272
|
+
readonly evidence: PlaybookFailureEvidence;
|
|
273
|
+
}
|
|
274
|
+
|
|
250
275
|
interface NormalizedError {
|
|
251
276
|
name: string;
|
|
252
277
|
message: string;
|
|
253
278
|
stack?: string;
|
|
279
|
+
cause?: PlaybookFailureCause; // present when the error carried a valid one
|
|
254
280
|
}
|
|
255
281
|
|
|
256
282
|
type PlaybookStateValue =
|
|
@@ -2045,9 +2071,15 @@ parked-session snapshot capability; the pair changes no runtime ABI and no
|
|
|
2045
2071
|
artifact or snapshot schema.
|
|
2046
2072
|
|
|
2047
2073
|
```typescript
|
|
2074
|
+
type PlaybookControlStanding = 'ready' | 'no-op' | 'blocked';
|
|
2075
|
+
type PlaybookControlActionReason = 'receipt-complete';
|
|
2076
|
+
|
|
2048
2077
|
interface PlaybookControlAction {
|
|
2049
2078
|
id: string; // stable within the returned view
|
|
2050
2079
|
label: string; // runtime-written, Boss-appropriate
|
|
2080
|
+
standing?: PlaybookControlStanding; // what running it would do (DR-063);
|
|
2081
|
+
// absent reads as `ready`
|
|
2082
|
+
reason?: PlaybookControlActionReason; // why it is not `ready`
|
|
2051
2083
|
}
|
|
2052
2084
|
|
|
2053
2085
|
interface PlaybookControlView {
|