@tcanaud/playbook 1.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/LICENSE +21 -0
- package/README.md +69 -0
- package/bin/cli.js +60 -0
- package/package.json +31 -0
- package/src/detect.js +118 -0
- package/src/installer.js +142 -0
- package/src/session.js +493 -0
- package/src/updater.js +85 -0
- package/src/validator.js +289 -0
- package/src/worktree.js +120 -0
- package/src/yaml-parser.js +682 -0
- package/templates/commands/playbook.resume.md +143 -0
- package/templates/commands/playbook.run.md +214 -0
- package/templates/core/_index.yaml +15 -0
- package/templates/core/playbook.tpl.yaml +88 -0
- package/templates/playbooks/auto-feature.yaml +100 -0
- package/templates/playbooks/auto-validate.yaml +31 -0
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# /playbook.resume — Resume Interrupted Playbook Session
|
|
2
|
+
|
|
3
|
+
**Input**: None — this command takes no arguments. It auto-detects the active session.
|
|
4
|
+
|
|
5
|
+
You are the **Playbook Supervisor** resuming an interrupted session. Your job is to find the last active session, determine where it left off, and continue execution from the correct step.
|
|
6
|
+
|
|
7
|
+
## 1. Find Repository Root
|
|
8
|
+
|
|
9
|
+
Run `git rev-parse --show-toplevel` to find the repository root. All paths are relative to this root.
|
|
10
|
+
|
|
11
|
+
## 2. Scan for In-Progress Sessions
|
|
12
|
+
|
|
13
|
+
Scan `.playbooks/sessions/*/session.yaml` for sessions with `status: "in_progress"`.
|
|
14
|
+
|
|
15
|
+
Read each `session.yaml` and check the `status` field.
|
|
16
|
+
|
|
17
|
+
**If no in-progress sessions found**:
|
|
18
|
+
> No active playbook session found. Start a new one with `/playbook.run {playbook} {feature}`.
|
|
19
|
+
|
|
20
|
+
Stop execution.
|
|
21
|
+
|
|
22
|
+
**If multiple in-progress sessions found**:
|
|
23
|
+
- Pick the most recent by session ID (the timestamp prefix `YYYYMMDD` sorts chronologically, then the 3-char suffix breaks ties alphabetically)
|
|
24
|
+
- Report which session was selected
|
|
25
|
+
|
|
26
|
+
**If exactly one found**: Use that session.
|
|
27
|
+
|
|
28
|
+
## 3. Load Session Context
|
|
29
|
+
|
|
30
|
+
From the selected `session.yaml`, extract:
|
|
31
|
+
- `session_id` — the session identifier
|
|
32
|
+
- `playbook` — the playbook name
|
|
33
|
+
- `feature` — the feature branch name
|
|
34
|
+
- `args` — the resolved arguments
|
|
35
|
+
- `current_step` — the step that was in progress when interrupted
|
|
36
|
+
|
|
37
|
+
Report:
|
|
38
|
+
> Resuming session `{session_id}` — playbook `{playbook}`, feature `{feature}`
|
|
39
|
+
|
|
40
|
+
## 4. Read the Playbook
|
|
41
|
+
|
|
42
|
+
Read the playbook YAML from `.playbooks/playbooks/{playbook}.yaml`.
|
|
43
|
+
|
|
44
|
+
If the playbook file no longer exists, report error and stop:
|
|
45
|
+
> Playbook `{playbook}` not found. Cannot resume session `{session_id}`.
|
|
46
|
+
|
|
47
|
+
Parse the playbook to get the full step list. Resolve argument interpolation using the session's `args`.
|
|
48
|
+
|
|
49
|
+
## 5. Read the Journal
|
|
50
|
+
|
|
51
|
+
Read `.playbooks/sessions/{session_id}/journal.yaml` to determine execution state.
|
|
52
|
+
|
|
53
|
+
For each step in the playbook, check the journal:
|
|
54
|
+
- **Step has journal entry with `status: "done"`**: Skip — already completed
|
|
55
|
+
- **Step has journal entry with `status: "skipped"`**: Skip — was intentionally skipped
|
|
56
|
+
- **Step has journal entry with `status: "failed"`**: This is where we stopped — evaluate what to do
|
|
57
|
+
- **Step has journal entry with `status: "in_progress"`**: This step was interrupted — check postconditions
|
|
58
|
+
- **Step has no journal entry**: This step hasn't been attempted yet
|
|
59
|
+
|
|
60
|
+
## 6. Determine Resume Point
|
|
61
|
+
|
|
62
|
+
### If the last step has `status: "in_progress"`:
|
|
63
|
+
|
|
64
|
+
Check its **postconditions**:
|
|
65
|
+
|
|
66
|
+
| Condition | Check |
|
|
67
|
+
|-----------|-------|
|
|
68
|
+
| `spec_exists` | File exists: `specs/{feature}/spec.md` |
|
|
69
|
+
| `plan_exists` | File exists: `specs/{feature}/plan.md` |
|
|
70
|
+
| `tasks_exists` | File exists: `specs/{feature}/tasks.md` |
|
|
71
|
+
| `agreement_exists` | File exists: `.agreements/{feature}/agreement.yaml` |
|
|
72
|
+
| `agreement_pass` | File `.agreements/{feature}/check-report.md` contains `verdict: PASS` |
|
|
73
|
+
| `qa_plan_exists` | File exists: `.qa/{feature}/test-plan.md` OR `.qa/{feature}/_index.yaml` |
|
|
74
|
+
| `qa_verdict_pass` | File `.qa/{feature}/verdict.yaml` contains `verdict: PASS` |
|
|
75
|
+
| `pr_created` | Run `gh pr list --head "{feature}" --json number --jq 'length'` — result > 0 |
|
|
76
|
+
|
|
77
|
+
**If ALL postconditions pass**: The step actually completed before the crash. Update its journal entry to `done`, compute duration, and advance to the next step.
|
|
78
|
+
|
|
79
|
+
**If ANY postcondition fails**: The step did not complete. Re-run it from scratch.
|
|
80
|
+
|
|
81
|
+
### If the last step has `status: "failed"`:
|
|
82
|
+
|
|
83
|
+
Report the failure and ask the user:
|
|
84
|
+
> Step `{step_id}` previously failed with error: "{error}". Retry this step? (yes/skip/abort)
|
|
85
|
+
|
|
86
|
+
### If there's no in-progress or failed step:
|
|
87
|
+
|
|
88
|
+
Find the first step with no journal entry. That's the resume point.
|
|
89
|
+
|
|
90
|
+
## 7. Report Resume Status
|
|
91
|
+
|
|
92
|
+
Display a summary before continuing:
|
|
93
|
+
|
|
94
|
+
```
|
|
95
|
+
Session: {session_id}
|
|
96
|
+
Playbook: {playbook} ({description})
|
|
97
|
+
Feature: {feature}
|
|
98
|
+
|
|
99
|
+
Progress:
|
|
100
|
+
{step_id}: done (auto) — {duration}s
|
|
101
|
+
{step_id}: done (gate) — {duration}s
|
|
102
|
+
{step_id}: in_progress → resuming
|
|
103
|
+
{step_id}: pending
|
|
104
|
+
...
|
|
105
|
+
|
|
106
|
+
Resuming from step: {step_id}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## 8. Continue Execution
|
|
110
|
+
|
|
111
|
+
Resume the orchestration loop using the exact same logic as `/playbook.run`:
|
|
112
|
+
|
|
113
|
+
For each remaining step (from the resume point):
|
|
114
|
+
|
|
115
|
+
1. **Check preconditions** — evaluate each condition
|
|
116
|
+
2. **Evaluate autonomy level** — auto, gate_on_breaking, gate_always, skip
|
|
117
|
+
3. **Delegate via Task subagent** — fresh context per step
|
|
118
|
+
4. **Check postconditions** — verify artifacts exist
|
|
119
|
+
5. **Handle escalation triggers** — promote auto to gate if trigger fires
|
|
120
|
+
6. **Apply error policy** — stop, retry_once, gate
|
|
121
|
+
7. **Write journal entry** — record step outcome with all audit fields
|
|
122
|
+
8. **Advance** — move to next step
|
|
123
|
+
|
|
124
|
+
Update `session.yaml` `current_step` before each step execution.
|
|
125
|
+
|
|
126
|
+
## 9. Completion
|
|
127
|
+
|
|
128
|
+
When all remaining steps are done (or session is failed/aborted):
|
|
129
|
+
|
|
130
|
+
1. Update `session.yaml`:
|
|
131
|
+
- `status`: `completed` | `failed` | `aborted`
|
|
132
|
+
- `completed_at`: current ISO 8601 timestamp
|
|
133
|
+
- `current_step`: empty
|
|
134
|
+
|
|
135
|
+
2. Report final summary with full journal overview.
|
|
136
|
+
|
|
137
|
+
## Rules
|
|
138
|
+
|
|
139
|
+
- **No arguments required**: Auto-detect everything from the filesystem
|
|
140
|
+
- **No duplicate execution**: Never re-run a step that has `status: "done"` in the journal
|
|
141
|
+
- **Postcondition-based recovery**: Use postcondition checks to determine if an interrupted step actually completed
|
|
142
|
+
- **Same orchestration logic**: The execution loop is identical to `/playbook.run` — same conditions, same gates, same error policies
|
|
143
|
+
- **Journal continuity**: New journal entries are appended — never overwrite existing entries (except updating in_progress → done for recovered steps)
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
# /playbook.run — Playbook Supervisor
|
|
2
|
+
|
|
3
|
+
**Input**: `$ARGUMENTS` — `{playbook} {feature}` (e.g., `auto-feature 012-playbook-supervisor`)
|
|
4
|
+
|
|
5
|
+
You are the **Playbook Supervisor**. You orchestrate a sequence of workflow steps defined in a YAML playbook, delegating each step to a Task subagent with fresh context. You are NOT an executor — you are the orchestrator. You use the same slash commands as manual execution. No bypass, no shortcut.
|
|
6
|
+
|
|
7
|
+
## 1. Parse Arguments
|
|
8
|
+
|
|
9
|
+
Extract from `$ARGUMENTS`:
|
|
10
|
+
- `PLAYBOOK` — first word (playbook name, e.g., `auto-feature`)
|
|
11
|
+
- `FEATURE` — second word (feature branch name, e.g., `012-playbook-supervisor`)
|
|
12
|
+
|
|
13
|
+
If either is missing, ask the user: "Usage: /playbook.run {playbook} {feature}"
|
|
14
|
+
|
|
15
|
+
## 2. Read Playbook
|
|
16
|
+
|
|
17
|
+
Read the playbook YAML from `.playbooks/playbooks/{PLAYBOOK}.yaml`.
|
|
18
|
+
|
|
19
|
+
If the file does not exist, report error and stop:
|
|
20
|
+
> Playbook `{PLAYBOOK}` not found at `.playbooks/playbooks/{PLAYBOOK}.yaml`
|
|
21
|
+
|
|
22
|
+
Parse the playbook manually — extract:
|
|
23
|
+
- `name`, `description`, `version`
|
|
24
|
+
- `args[]` — declared arguments with names and required flags
|
|
25
|
+
- `steps[]` — ordered list of step definitions
|
|
26
|
+
|
|
27
|
+
Resolve argument interpolation: replace all `{{feature}}` references in step `args` with the actual `FEATURE` value. Do the same for any other declared args.
|
|
28
|
+
|
|
29
|
+
Validate that all required args are provided. If a required arg is missing, ask the user.
|
|
30
|
+
|
|
31
|
+
## 3. Session Management
|
|
32
|
+
|
|
33
|
+
### Check for existing session
|
|
34
|
+
|
|
35
|
+
Scan `.playbooks/sessions/*/session.yaml` for a session where:
|
|
36
|
+
- `playbook` matches `PLAYBOOK`
|
|
37
|
+
- `feature` matches `FEATURE`
|
|
38
|
+
- `status` is `in_progress`
|
|
39
|
+
|
|
40
|
+
**If found**: Resume that session (skip to step 5 with the existing session).
|
|
41
|
+
|
|
42
|
+
### Create new session
|
|
43
|
+
|
|
44
|
+
If no existing session found:
|
|
45
|
+
|
|
46
|
+
1. Generate session ID: `{YYYYMMDD}-{3char}` (e.g., `20260219-a7k`) where 3char is random lowercase alphanumeric
|
|
47
|
+
2. Create directory `.playbooks/sessions/{id}/`
|
|
48
|
+
3. Write `session.yaml`:
|
|
49
|
+
```yaml
|
|
50
|
+
session_id: "{id}"
|
|
51
|
+
playbook: "{PLAYBOOK}"
|
|
52
|
+
feature: "{FEATURE}"
|
|
53
|
+
args:
|
|
54
|
+
feature: "{FEATURE}"
|
|
55
|
+
status: "in_progress"
|
|
56
|
+
started_at: "{ISO 8601 now}"
|
|
57
|
+
completed_at: ""
|
|
58
|
+
current_step: ""
|
|
59
|
+
worktree: ""
|
|
60
|
+
```
|
|
61
|
+
4. Write `journal.yaml`:
|
|
62
|
+
```yaml
|
|
63
|
+
entries: []
|
|
64
|
+
```
|
|
65
|
+
5. Report: `Session {id} created for playbook {PLAYBOOK}`
|
|
66
|
+
|
|
67
|
+
## 4. Pre-flight Validation
|
|
68
|
+
|
|
69
|
+
Before executing any steps, verify:
|
|
70
|
+
- All slash commands referenced in steps exist (check `.claude/commands/` for the command files, or trust that they are available as skills)
|
|
71
|
+
- Report any missing commands and stop
|
|
72
|
+
|
|
73
|
+
## 5. Orchestration Loop
|
|
74
|
+
|
|
75
|
+
For each step in the playbook (in order):
|
|
76
|
+
|
|
77
|
+
### 5a. Check Preconditions
|
|
78
|
+
|
|
79
|
+
For each condition in the step's `preconditions[]`, evaluate:
|
|
80
|
+
|
|
81
|
+
| Condition | Check |
|
|
82
|
+
|-----------|-------|
|
|
83
|
+
| `spec_exists` | File exists: `specs/{FEATURE}/spec.md` |
|
|
84
|
+
| `plan_exists` | File exists: `specs/{FEATURE}/plan.md` |
|
|
85
|
+
| `tasks_exists` | File exists: `specs/{FEATURE}/tasks.md` |
|
|
86
|
+
| `agreement_exists` | File exists: `.agreements/{FEATURE}/agreement.yaml` |
|
|
87
|
+
| `agreement_pass` | File `.agreements/{FEATURE}/check-report.md` contains `verdict: PASS` |
|
|
88
|
+
| `qa_plan_exists` | File exists: `.qa/{FEATURE}/test-plan.md` OR `.qa/{FEATURE}/_index.yaml` |
|
|
89
|
+
| `qa_verdict_pass` | File `.qa/{FEATURE}/verdict.yaml` contains `verdict: PASS` |
|
|
90
|
+
| `pr_created` | Run `gh pr list --head "{FEATURE}" --json number --jq 'length'` — result > 0 |
|
|
91
|
+
|
|
92
|
+
If ANY precondition fails:
|
|
93
|
+
- Report which precondition failed and what artifact is missing
|
|
94
|
+
- **Do NOT proceed with this step** — halt and explain what needs to happen first
|
|
95
|
+
- If a previous step should have produced this artifact, investigate why it didn't
|
|
96
|
+
|
|
97
|
+
### 5b. Evaluate Autonomy Level
|
|
98
|
+
|
|
99
|
+
| Autonomy | Behavior |
|
|
100
|
+
|----------|----------|
|
|
101
|
+
| `auto` | Execute without asking. Proceed directly to delegation. |
|
|
102
|
+
| `gate_on_breaking` | Check if a breaking change is detected (for agreement checks). If breaking: halt and ask. If not: proceed like auto. |
|
|
103
|
+
| `gate_always` | Always halt. Present context and ask before proceeding. |
|
|
104
|
+
| `skip` | Do not execute. Log as skipped. Move to next step. |
|
|
105
|
+
|
|
106
|
+
**Gate Protocol** (when halting):
|
|
107
|
+
1. Present a clear summary: step name, command, what it will do
|
|
108
|
+
2. Ask: "Proceed with step '{id}' ({command})? (yes/no/abort)"
|
|
109
|
+
3. Wait for user response
|
|
110
|
+
4. If "yes" or "continue": proceed with delegation
|
|
111
|
+
5. If "no" or "skip": log as skipped, move to next step
|
|
112
|
+
6. If "abort": mark session as aborted, stop execution
|
|
113
|
+
|
|
114
|
+
### 5c. Delegate to Task Subagent
|
|
115
|
+
|
|
116
|
+
Record the step start time.
|
|
117
|
+
|
|
118
|
+
Update `session.yaml`: set `current_step` to the step ID.
|
|
119
|
+
|
|
120
|
+
Use the **Task tool** to delegate the step:
|
|
121
|
+
- Launch a subagent with `subagent_type: "general-purpose"`
|
|
122
|
+
- The prompt MUST include:
|
|
123
|
+
- The slash command to execute (e.g., "Execute /speckit.plan")
|
|
124
|
+
- The arguments (with resolved interpolation)
|
|
125
|
+
- The feature context
|
|
126
|
+
- Instruction to use the Skill tool to invoke the slash command
|
|
127
|
+
- Each subagent gets **fresh context** — no accumulated state from previous steps
|
|
128
|
+
|
|
129
|
+
**Parallel phases**: If multiple steps share the same `parallel_group`, launch ALL of them in a single message using multiple Task tool calls. Wait for all to complete before continuing.
|
|
130
|
+
|
|
131
|
+
### 5d. Check Postconditions
|
|
132
|
+
|
|
133
|
+
After the subagent completes, evaluate each condition in `postconditions[]` using the same checks as preconditions (table in 5a).
|
|
134
|
+
|
|
135
|
+
If ALL postconditions pass: mark step as **done**.
|
|
136
|
+
|
|
137
|
+
If ANY postcondition fails: check escalation triggers.
|
|
138
|
+
|
|
139
|
+
### 5e. Handle Escalation Triggers
|
|
140
|
+
|
|
141
|
+
If a postcondition failed AND the step has escalation triggers:
|
|
142
|
+
|
|
143
|
+
| Trigger | Fires When |
|
|
144
|
+
|---------|-----------|
|
|
145
|
+
| `postcondition_fail` | Any postcondition check fails |
|
|
146
|
+
| `verdict_fail` | QA verdict file contains FAIL |
|
|
147
|
+
| `agreement_breaking` | Agreement check found breaking changes |
|
|
148
|
+
| `subagent_error` | The Task subagent returned an error |
|
|
149
|
+
|
|
150
|
+
If a trigger fires on an `auto` step: **promote to gate**. Present the failure to the user and ask for a decision.
|
|
151
|
+
|
|
152
|
+
### 5f. Apply Error Policy
|
|
153
|
+
|
|
154
|
+
If the step failed (postcondition fail, subagent error):
|
|
155
|
+
|
|
156
|
+
| Policy | Behavior |
|
|
157
|
+
|--------|----------|
|
|
158
|
+
| `stop` | Mark session as failed. Stop all execution. Report the failure. |
|
|
159
|
+
| `retry_once` | Re-execute the step ONE time. If it fails again, apply `stop`. |
|
|
160
|
+
| `gate` | Escalate to the user. Present the failure context. Ask: "Fix and continue, or abort?" |
|
|
161
|
+
|
|
162
|
+
### 5g. Write Journal Entry
|
|
163
|
+
|
|
164
|
+
After each step (whether done, failed, or skipped), append a journal entry to `journal.yaml`:
|
|
165
|
+
|
|
166
|
+
```yaml
|
|
167
|
+
- step_id: "{id}"
|
|
168
|
+
status: "done" # done | failed | skipped
|
|
169
|
+
decision: "auto" # auto | gate | escalated | skipped
|
|
170
|
+
started_at: "{ISO 8601}"
|
|
171
|
+
completed_at: "{ISO 8601}"
|
|
172
|
+
duration_seconds: {N}
|
|
173
|
+
trigger: "" # escalation trigger if any
|
|
174
|
+
human_response: "" # user's response at gate if any
|
|
175
|
+
error: "" # error message if failed
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Only include `trigger`, `human_response`, and `error` fields when they have values.
|
|
179
|
+
|
|
180
|
+
### 5h. Advance to Next Step
|
|
181
|
+
|
|
182
|
+
Move to the next step in the playbook and repeat from 5a.
|
|
183
|
+
|
|
184
|
+
## 6. Completion
|
|
185
|
+
|
|
186
|
+
When all steps are done (or the session is failed/aborted):
|
|
187
|
+
|
|
188
|
+
1. Update `session.yaml`:
|
|
189
|
+
- `status`: `completed` (all done) | `failed` (step failed with stop) | `aborted` (user aborted)
|
|
190
|
+
- `completed_at`: current ISO 8601 timestamp
|
|
191
|
+
- `current_step`: empty
|
|
192
|
+
|
|
193
|
+
2. Report final summary:
|
|
194
|
+
```
|
|
195
|
+
Playbook {PLAYBOOK} — {status}
|
|
196
|
+
|
|
197
|
+
Steps: {done}/{total}
|
|
198
|
+
Duration: {total duration}
|
|
199
|
+
|
|
200
|
+
Journal: .playbooks/sessions/{id}/journal.yaml
|
|
201
|
+
|
|
202
|
+
Step results:
|
|
203
|
+
{step_id}: {status} ({decision}) — {duration}s
|
|
204
|
+
...
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
## Rules
|
|
208
|
+
|
|
209
|
+
- **Same commands as manual**: You execute the same slash commands a developer would type manually. No bypass.
|
|
210
|
+
- **Fresh context per step**: Each Task subagent starts clean. No state leaks between steps.
|
|
211
|
+
- **Journal is the truth**: Every decision, every gate response, every error is recorded in the journal.
|
|
212
|
+
- **Deterministic behavior**: Autonomy levels, conditions, error policies are a fixed vocabulary. Follow them exactly.
|
|
213
|
+
- **No invention**: Do not add steps, skip conditions, or modify the playbook at runtime.
|
|
214
|
+
- **Idempotent resume**: If this command is re-run with the same playbook and feature, it finds the existing session and resumes.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Playbook Index
|
|
2
|
+
# Auto-generated by @tcanaud/playbook init/update
|
|
3
|
+
# Lists all available playbooks in this project.
|
|
4
|
+
|
|
5
|
+
generated: "{{TIMESTAMP}}"
|
|
6
|
+
|
|
7
|
+
playbooks:
|
|
8
|
+
- name: "auto-feature"
|
|
9
|
+
file: "playbooks/auto-feature.yaml"
|
|
10
|
+
description: "Full feature workflow from plan to PR"
|
|
11
|
+
steps: 8
|
|
12
|
+
- name: "auto-validate"
|
|
13
|
+
file: "playbooks/auto-validate.yaml"
|
|
14
|
+
description: "QA validation: plan and run"
|
|
15
|
+
steps: 2
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Playbook Template
|
|
2
|
+
# Copy this file and customize it for your workflow.
|
|
3
|
+
# Validate with: npx @tcanaud/playbook check <file>
|
|
4
|
+
#
|
|
5
|
+
# ── Schema Reference ────────────────────────────────────
|
|
6
|
+
#
|
|
7
|
+
# Top-level fields (all required):
|
|
8
|
+
# name: Unique identifier [a-z0-9-]+
|
|
9
|
+
# description: Human-readable purpose
|
|
10
|
+
# version: Schema version (e.g., "1.0")
|
|
11
|
+
#
|
|
12
|
+
# args (required, may be empty array):
|
|
13
|
+
# - name: Argument name, referenced as {{name}} in step args
|
|
14
|
+
# description: Purpose of the argument
|
|
15
|
+
# required: true | false
|
|
16
|
+
#
|
|
17
|
+
# steps (required, min 1):
|
|
18
|
+
# - id: Unique within playbook [a-z0-9-]+
|
|
19
|
+
# command: Slash command to execute (e.g., "/speckit.plan")
|
|
20
|
+
# args: Optional — supports {{arg}} interpolation
|
|
21
|
+
# autonomy: Decision mode (see below)
|
|
22
|
+
# preconditions: Optional list of artifact checks (see below)
|
|
23
|
+
# postconditions: Optional list of artifact checks (see below)
|
|
24
|
+
# error_policy: Behavior on failure (see below)
|
|
25
|
+
# escalation_triggers: Optional list of triggers (see below)
|
|
26
|
+
# parallel_group: Optional — steps with same group run concurrently
|
|
27
|
+
#
|
|
28
|
+
# ── Autonomy Levels ─────────────────────────────────────
|
|
29
|
+
# auto Execute without human interaction
|
|
30
|
+
# gate_on_breaking Gate only when a breaking change is detected
|
|
31
|
+
# gate_always Always halt for human decision
|
|
32
|
+
# skip Skip execution, log as skipped
|
|
33
|
+
#
|
|
34
|
+
# ── Error Policies ──────────────────────────────────────
|
|
35
|
+
# stop Halt all execution, mark session as failed
|
|
36
|
+
# retry_once Re-execute once; if still fails, stop
|
|
37
|
+
# gate Escalate to human decision with failure context
|
|
38
|
+
#
|
|
39
|
+
# ── Escalation Triggers ────────────────────────────────
|
|
40
|
+
# postcondition_fail Any postcondition fails after step execution
|
|
41
|
+
# verdict_fail QA verdict file contains FAIL
|
|
42
|
+
# agreement_breaking Agreement check detects breaking changes
|
|
43
|
+
# subagent_error Task subagent returns error or crashes
|
|
44
|
+
#
|
|
45
|
+
# ── Conditions (Pre/Post) ──────────────────────────────
|
|
46
|
+
# spec_exists specs/{feature}/spec.md exists
|
|
47
|
+
# plan_exists specs/{feature}/plan.md exists
|
|
48
|
+
# tasks_exists specs/{feature}/tasks.md exists
|
|
49
|
+
# agreement_exists .agreements/{feature}/agreement.yaml exists
|
|
50
|
+
# agreement_pass .agreements/{feature}/check-report.md verdict: PASS
|
|
51
|
+
# qa_plan_exists .qa/{feature}/test-plan.md exists
|
|
52
|
+
# qa_verdict_pass .qa/{feature}/verdict.md verdict: PASS
|
|
53
|
+
# pr_created gh pr list --head {branch} returns non-empty
|
|
54
|
+
#
|
|
55
|
+
# ════════════════════════════════════════════════════════
|
|
56
|
+
|
|
57
|
+
name: "my-workflow"
|
|
58
|
+
description: "Describe your workflow here"
|
|
59
|
+
version: "1.0"
|
|
60
|
+
|
|
61
|
+
args:
|
|
62
|
+
- name: "feature"
|
|
63
|
+
description: "Feature branch name"
|
|
64
|
+
required: true
|
|
65
|
+
|
|
66
|
+
steps:
|
|
67
|
+
- id: "step-1"
|
|
68
|
+
command: "/speckit.plan"
|
|
69
|
+
args: ""
|
|
70
|
+
autonomy: "auto"
|
|
71
|
+
preconditions:
|
|
72
|
+
- "spec_exists"
|
|
73
|
+
postconditions:
|
|
74
|
+
- "plan_exists"
|
|
75
|
+
error_policy: "stop"
|
|
76
|
+
escalation_triggers: []
|
|
77
|
+
|
|
78
|
+
# Add more steps below following the same structure.
|
|
79
|
+
# Use parallel_group to run steps concurrently:
|
|
80
|
+
#
|
|
81
|
+
# - id: "step-a"
|
|
82
|
+
# command: "/some.command"
|
|
83
|
+
# parallel_group: "phase-2"
|
|
84
|
+
# ...
|
|
85
|
+
# - id: "step-b"
|
|
86
|
+
# command: "/other.command"
|
|
87
|
+
# parallel_group: "phase-2"
|
|
88
|
+
# ...
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
name: "auto-feature"
|
|
2
|
+
description: "Full feature workflow from plan to PR"
|
|
3
|
+
version: "1.0"
|
|
4
|
+
|
|
5
|
+
args:
|
|
6
|
+
- name: "feature"
|
|
7
|
+
description: "Feature branch name (e.g., 012-playbook-supervisor)"
|
|
8
|
+
required: true
|
|
9
|
+
|
|
10
|
+
steps:
|
|
11
|
+
- id: "plan"
|
|
12
|
+
command: "/speckit.plan"
|
|
13
|
+
args: ""
|
|
14
|
+
autonomy: "auto"
|
|
15
|
+
preconditions:
|
|
16
|
+
- "spec_exists"
|
|
17
|
+
postconditions:
|
|
18
|
+
- "plan_exists"
|
|
19
|
+
error_policy: "stop"
|
|
20
|
+
escalation_triggers: []
|
|
21
|
+
|
|
22
|
+
- id: "tasks"
|
|
23
|
+
command: "/speckit.tasks"
|
|
24
|
+
args: ""
|
|
25
|
+
autonomy: "auto"
|
|
26
|
+
preconditions:
|
|
27
|
+
- "plan_exists"
|
|
28
|
+
postconditions:
|
|
29
|
+
- "tasks_exists"
|
|
30
|
+
error_policy: "stop"
|
|
31
|
+
escalation_triggers: []
|
|
32
|
+
|
|
33
|
+
- id: "agreement"
|
|
34
|
+
command: "/agreement.create"
|
|
35
|
+
args: "{{feature}}"
|
|
36
|
+
autonomy: "auto"
|
|
37
|
+
preconditions:
|
|
38
|
+
- "tasks_exists"
|
|
39
|
+
postconditions:
|
|
40
|
+
- "agreement_exists"
|
|
41
|
+
error_policy: "gate"
|
|
42
|
+
escalation_triggers:
|
|
43
|
+
- "subagent_error"
|
|
44
|
+
|
|
45
|
+
- id: "implement"
|
|
46
|
+
command: "/speckit.implement"
|
|
47
|
+
args: ""
|
|
48
|
+
autonomy: "auto"
|
|
49
|
+
preconditions:
|
|
50
|
+
- "agreement_exists"
|
|
51
|
+
postconditions: []
|
|
52
|
+
error_policy: "retry_once"
|
|
53
|
+
escalation_triggers:
|
|
54
|
+
- "postcondition_fail"
|
|
55
|
+
- "subagent_error"
|
|
56
|
+
|
|
57
|
+
- id: "agreement-check"
|
|
58
|
+
command: "/agreement.check"
|
|
59
|
+
args: "{{feature}}"
|
|
60
|
+
autonomy: "gate_on_breaking"
|
|
61
|
+
preconditions: []
|
|
62
|
+
postconditions:
|
|
63
|
+
- "agreement_pass"
|
|
64
|
+
error_policy: "gate"
|
|
65
|
+
escalation_triggers:
|
|
66
|
+
- "agreement_breaking"
|
|
67
|
+
|
|
68
|
+
- id: "qa-plan"
|
|
69
|
+
command: "/qa.plan"
|
|
70
|
+
args: "{{feature}}"
|
|
71
|
+
autonomy: "auto"
|
|
72
|
+
preconditions:
|
|
73
|
+
- "agreement_pass"
|
|
74
|
+
postconditions:
|
|
75
|
+
- "qa_plan_exists"
|
|
76
|
+
error_policy: "stop"
|
|
77
|
+
escalation_triggers: []
|
|
78
|
+
|
|
79
|
+
- id: "qa-run"
|
|
80
|
+
command: "/qa.run"
|
|
81
|
+
args: "{{feature}}"
|
|
82
|
+
autonomy: "auto"
|
|
83
|
+
preconditions:
|
|
84
|
+
- "qa_plan_exists"
|
|
85
|
+
postconditions:
|
|
86
|
+
- "qa_verdict_pass"
|
|
87
|
+
error_policy: "gate"
|
|
88
|
+
escalation_triggers:
|
|
89
|
+
- "verdict_fail"
|
|
90
|
+
|
|
91
|
+
- id: "pr"
|
|
92
|
+
command: "/feature.pr"
|
|
93
|
+
args: "{{feature}}"
|
|
94
|
+
autonomy: "gate_always"
|
|
95
|
+
preconditions:
|
|
96
|
+
- "qa_verdict_pass"
|
|
97
|
+
postconditions:
|
|
98
|
+
- "pr_created"
|
|
99
|
+
error_policy: "stop"
|
|
100
|
+
escalation_triggers: []
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
name: "auto-validate"
|
|
2
|
+
description: "QA validation: plan and run"
|
|
3
|
+
version: "1.0"
|
|
4
|
+
|
|
5
|
+
args:
|
|
6
|
+
- name: "feature"
|
|
7
|
+
description: "Feature branch name (e.g., 012-playbook-supervisor)"
|
|
8
|
+
required: true
|
|
9
|
+
|
|
10
|
+
steps:
|
|
11
|
+
- id: "qa-plan"
|
|
12
|
+
command: "/qa.plan"
|
|
13
|
+
args: "{{feature}}"
|
|
14
|
+
autonomy: "auto"
|
|
15
|
+
preconditions:
|
|
16
|
+
- "spec_exists"
|
|
17
|
+
postconditions:
|
|
18
|
+
- "qa_plan_exists"
|
|
19
|
+
error_policy: "stop"
|
|
20
|
+
escalation_triggers: []
|
|
21
|
+
|
|
22
|
+
- id: "qa-run"
|
|
23
|
+
command: "/qa.run"
|
|
24
|
+
args: "{{feature}}"
|
|
25
|
+
autonomy: "auto"
|
|
26
|
+
preconditions:
|
|
27
|
+
- "qa_plan_exists"
|
|
28
|
+
postconditions:
|
|
29
|
+
- "qa_verdict_pass"
|
|
30
|
+
error_policy: "stop"
|
|
31
|
+
escalation_triggers: []
|