guild-cli 0.1.0__tar.gz → 0.2.0__tar.gz
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.
- guild_cli-0.2.0/.claude/skills/assign-to-workforce/SKILL.md +242 -0
- guild_cli-0.2.0/.claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh +212 -0
- guild_cli-0.2.0/.claude/skills/spec-to-plan/SKILL.md +230 -0
- guild_cli-0.2.0/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +102 -0
- guild_cli-0.2.0/.claude/skills/think/SKILL.md +201 -0
- guild_cli-0.2.0/.claude/skills/think/scripts/think.sh +101 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/CHANGELOG.md +29 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/PKG-INFO +1 -1
- guild_cli-0.2.0/docs/skill-sources.md +77 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/pyproject.toml +1 -1
- {guild_cli-0.1.0 → guild_cli-0.2.0}/uv.lock +1 -1
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/cicd/SKILL.md +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/communicate/SKILL.md +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/communicate/scripts/templates/skill-new-brief.md +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/pypi-maintainer/SKILL.md +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/pypi-maintainer/scripts/switch-source.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/version-bump/SKILL.md +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.claude/skills.local.yaml.example +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.flake8 +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.github/workflows/publish.yml +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.github/workflows/tests.yml +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.gitignore +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/.markdownlint-cli2.yaml +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/CLAUDE.md +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/LICENSE +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/README.md +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/culture.yaml +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/guild/__init__.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/guild/__main__.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/guild/cli/__init__.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/guild/cli/_commands/__init__.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/guild/cli/_commands/explain.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/guild/cli/_commands/learn.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/guild/cli/_commands/whoami.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/guild/cli/_errors.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/guild/cli/_output.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/guild/cli/_repo.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/tests/__init__.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/tests/test_cli.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/tests/test_cli_explain.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/tests/test_cli_learn.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/tests/test_cli_whoami.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/tests/test_skills_convention.py +0 -0
- {guild_cli-0.1.0 → guild_cli-0.2.0}/tests/test_version_fallback.py +0 -0
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: assign-to-workforce
|
|
3
|
+
type: command
|
|
4
|
+
description: >
|
|
5
|
+
Fan out a converged devague plan's dependency waves to parallel agents in
|
|
6
|
+
isolated git worktrees, one agent per task per wave, with TDD-gated merges
|
|
7
|
+
by the main agent. Human gates: the exported spec, the implementation split
|
|
8
|
+
plan (task map + per-task agent/model proposal + go/no-go), and the final PR.
|
|
9
|
+
The devague CLI stays deterministic and non-orchestrating (#20) — it only
|
|
10
|
+
*describes* the graph via `devague plan waves`; the operator (main agent)
|
|
11
|
+
performs the fan-out. Use when the user says "assign to workforce",
|
|
12
|
+
"fan out the plan", "parallel subagents", or after /spec-to-plan exports a
|
|
13
|
+
plan. Authored and maintained in agentculture/devague (origin = devague);
|
|
14
|
+
steward pulls this skill from here and broadcasts it to the AgentCulture
|
|
15
|
+
mesh — it is NOT vendored from steward like the other skills here.
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# assign-to-workforce — fan out a converged plan's waves to parallel agents
|
|
19
|
+
|
|
20
|
+
The skill is named **`assign-to-workforce`**; the product/CLI it reads is the
|
|
21
|
+
**`devague plan waves`** command. (The prior leg — turning a spec into a plan —
|
|
22
|
+
is the sibling **`/spec-to-plan`** skill.)
|
|
23
|
+
|
|
24
|
+
`assign-to-workforce` takes a **converged devague plan** and fans out its
|
|
25
|
+
dependency waves to parallel agents (subagents, teammate agents, or generalist
|
|
26
|
+
agents) — one agent per task per wave — each working in an **isolated git
|
|
27
|
+
worktree**. The main agent merges each completed worktree gated by TDD. The
|
|
28
|
+
human owns exactly three gates: the exported spec, the implementation split
|
|
29
|
+
plan, and the final PR.
|
|
30
|
+
|
|
31
|
+
The devague CLI is **never orchestrated by devague itself** — `devague plan
|
|
32
|
+
waves` describes the dependency graph (#20); it does not spawn agents, manage
|
|
33
|
+
worktrees, mark tasks done, or pick a backend. The fan-out is the *operator's*
|
|
34
|
+
job — this skill and the main agent perform it.
|
|
35
|
+
|
|
36
|
+
## How to run
|
|
37
|
+
|
|
38
|
+
The entry point is `scripts/assign-to-workforce.sh`. Invoke it from the
|
|
39
|
+
repository whose plan you are implementing (plans persist under `.devague/`
|
|
40
|
+
in the current directory):
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
bash .claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh split-plan [--plan <slug>]
|
|
44
|
+
bash .claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh waves [--plan <slug>] [--json]
|
|
45
|
+
bash .claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh help
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
It resolves the CLI portably — an installed `devague` on `PATH` (the normal
|
|
49
|
+
case), falling back to `uv run devague` when you are inside the devague
|
|
50
|
+
checkout, else an install hint. The `split-plan` subcommand reads
|
|
51
|
+
`devague plan waves --json` and renders the human-facing implementation split
|
|
52
|
+
plan: task map, proposed per-task agent + model assignment, and the go/no-go
|
|
53
|
+
question. The `waves` subcommand forwards to `devague plan waves` verbatim.
|
|
54
|
+
|
|
55
|
+
### Usage
|
|
56
|
+
|
|
57
|
+
| Subcommand | What it does |
|
|
58
|
+
|------------|--------------|
|
|
59
|
+
| `split-plan [--plan S]` | Read `devague plan waves` and print the implementation split plan — task map with per-task agent + model proposal — ready for human go/no-go review. |
|
|
60
|
+
| `waves [--plan S] [--json]` | Forward to `devague plan waves [--json]`. Read-only; lists wave batches. On a converged plan exits 0 listing the waves. |
|
|
61
|
+
| `help` | Print usage. |
|
|
62
|
+
|
|
63
|
+
## The full flow
|
|
64
|
+
|
|
65
|
+
The flow has three human gates and one automated TDD merge loop.
|
|
66
|
+
|
|
67
|
+
### Human gate 1 — the exported spec
|
|
68
|
+
|
|
69
|
+
The plan is seeded from a converged frame (`devague plan new --frame <slug>`).
|
|
70
|
+
The human reviewed and approved the spec when it was exported by the `/think`
|
|
71
|
+
skill. No re-approval needed here — the spec gate is already closed.
|
|
72
|
+
|
|
73
|
+
### Human gate 2 — the implementation split plan
|
|
74
|
+
|
|
75
|
+
Before any task is assigned, the main agent presents the **implementation split
|
|
76
|
+
plan** for human go/no-go. This is the only gate the human owns at the
|
|
77
|
+
implementation stage (per task, the TDD gate is the main agent's).
|
|
78
|
+
|
|
79
|
+
The split plan contains:
|
|
80
|
+
|
|
81
|
+
1. **Task map** — every task id, its one-line summary, acceptance criteria, and
|
|
82
|
+
the wave it belongs to (from `devague plan waves`).
|
|
83
|
+
2. **Per-task agent + model proposal** — for each task: the proposed agent type
|
|
84
|
+
(subagent / teammate / generalist), the proposed model (e.g. a cheaper/faster
|
|
85
|
+
model for a well-scoped task), and the scope justification (why this task is
|
|
86
|
+
safe to delegate).
|
|
87
|
+
3. **Go/no-go question** — explicit human decision: "Approve this split and
|
|
88
|
+
assign the plan to the workforce, or edit it first?"
|
|
89
|
+
|
|
90
|
+
The human may edit any row (agent type, model, scope) before approving. The
|
|
91
|
+
plan is model-agnostic — devague does not pick a backend (#20).
|
|
92
|
+
|
|
93
|
+
Run `split-plan` to print the proposed table:
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
bash .claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh split-plan
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Do not proceed to fan-out until the human approves the split plan.
|
|
100
|
+
|
|
101
|
+
### Fan-out — one agent per task per wave in isolated worktrees
|
|
102
|
+
|
|
103
|
+
Once the human approves, the main agent fans out each wave in order:
|
|
104
|
+
|
|
105
|
+
1. **Create an isolated git worktree** for each task in the current wave:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
git worktree add ../worktrees/agent-<task-id> -b agent/<task-id>
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
2. **Spawn a task agent** inside that worktree (using the approved model from
|
|
112
|
+
the split plan), with:
|
|
113
|
+
- The task id, summary, and acceptance criteria as its brief.
|
|
114
|
+
- Instruction to work **test-first** (TDD): write the failing test(s) that
|
|
115
|
+
match the acceptance criteria before implementing.
|
|
116
|
+
- Instruction to commit its work to the worktree branch.
|
|
117
|
+
|
|
118
|
+
3. **Same-wave tasks run in parallel** (within-wave tasks have no
|
|
119
|
+
inter-task dependency; the dependency graph guarantees this). Same-file
|
|
120
|
+
overlap surfaces as a merge conflict at reconcile time, not a live race —
|
|
121
|
+
isolated worktrees prevent clobbering.
|
|
122
|
+
|
|
123
|
+
4. **Wait for all tasks in the wave to complete** before starting the next wave.
|
|
124
|
+
|
|
125
|
+
### TDD-gated merge — main agent, no human per task
|
|
126
|
+
|
|
127
|
+
For each completed task worktree, the main agent:
|
|
128
|
+
|
|
129
|
+
1. **Runs the task's tests before merge** (on the main branch): baseline must
|
|
130
|
+
pass (or the relevant tests must be absent — the task adds them).
|
|
131
|
+
2. **Merges the worktree branch** into the main branch:
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
git merge --no-ff agent/<task-id>
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
3. **Runs the task's tests after merge**: they must pass. If they do not, the
|
|
138
|
+
merge is reverted and the task agent is given the failure output to fix.
|
|
139
|
+
4. **Removes the worktree** once the merge is accepted:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
git worktree remove ../worktrees/agent-<task-id>
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The human does **not** review individual task merges. Per-task acceptance is
|
|
146
|
+
the main agent's responsibility — the TDD gate (tests pass before AND after
|
|
147
|
+
merge) plus the task's acceptance criteria. This mirrors the non-authoritative
|
|
148
|
+
working state pattern of the Human Review Loop (#17): per-task merge records
|
|
149
|
+
are uncommitted working state; the authoritative human gate is the final PR.
|
|
150
|
+
|
|
151
|
+
Advance to the next wave only after all tasks in the current wave are merged
|
|
152
|
+
and their tests pass.
|
|
153
|
+
|
|
154
|
+
### Human gate 3 — the final PR
|
|
155
|
+
|
|
156
|
+
Once all waves are merged and the full test suite passes, the main agent opens
|
|
157
|
+
a PR via the `cicd` skill (`agex pr open`). The human reviews and merges. This
|
|
158
|
+
is the last and only remaining human gate.
|
|
159
|
+
|
|
160
|
+
## Hard rules (do not violate)
|
|
161
|
+
|
|
162
|
+
These protect the human-gate contract and the TDD guarantee.
|
|
163
|
+
|
|
164
|
+
- **Present the split plan before any fan-out.** Never spawn a task agent
|
|
165
|
+
without prior human approval of the implementation split plan (gate 2). The
|
|
166
|
+
split plan is the human's only implementation-stage decision.
|
|
167
|
+
- **One worktree per task.** Never run two tasks in the same worktree — file
|
|
168
|
+
contention is managed by isolation, not by trust in the dependency graph.
|
|
169
|
+
The dependency graph guarantees *logical* independence within a wave, not
|
|
170
|
+
*file* disjointness. Conflicts surface at merge time.
|
|
171
|
+
- **Tests before AND after merge — no exceptions.** The TDD gate must pass on
|
|
172
|
+
both sides. A merge that makes tests pass only after (not before) means the
|
|
173
|
+
baseline was already broken — fix the baseline first.
|
|
174
|
+
- **Human does not gate per-task merges.** The TDD contract replaces the
|
|
175
|
+
human here. Do not pause for human approval between wave tasks.
|
|
176
|
+
- **devague CLI is not orchestrated.** `devague plan waves` is read-only
|
|
177
|
+
scheduling metadata (#20). Never run `devague plan` commands inside a task
|
|
178
|
+
worktree to "mark a task done" or modify plan state from a subagent.
|
|
179
|
+
- **Three gates only.** The human's gates are: (1) the exported spec, (2) the
|
|
180
|
+
implementation split plan, (3) the final PR. No silent fourth gate.
|
|
181
|
+
- **No LLM calls in the devague CLI.** The CLI is deterministic. This skill
|
|
182
|
+
adds orchestration convention, not CLI behavior.
|
|
183
|
+
|
|
184
|
+
## Output contract
|
|
185
|
+
|
|
186
|
+
The `split-plan` subcommand prints to **stdout** and exits 0 when a converged
|
|
187
|
+
plan is found. On error (no plan, cyclic graph) it exits non-zero with a
|
|
188
|
+
`hint:` line on stderr. The `waves` subcommand forwards the CLI's own output
|
|
189
|
+
contract (stdout, `--json` for structured output, exit 0 on success).
|
|
190
|
+
|
|
191
|
+
## Worked example
|
|
192
|
+
|
|
193
|
+
Picking up after `/spec-to-plan` exported a plan for the frame `my-feature`:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
a() { bash .claude/skills/assign-to-workforce/scripts/assign-to-workforce.sh "$@"; }
|
|
197
|
+
|
|
198
|
+
# 1. Inspect the waves
|
|
199
|
+
a waves
|
|
200
|
+
|
|
201
|
+
# 2. Present the implementation split plan for human review
|
|
202
|
+
a split-plan
|
|
203
|
+
|
|
204
|
+
# --- HUMAN: review the table, edit agent/model assignments if needed,
|
|
205
|
+
# then say "approved" to proceed ---
|
|
206
|
+
|
|
207
|
+
# 3. Fan out wave 1 (t1, t2, t3 are independent — run in parallel)
|
|
208
|
+
git worktree add ../worktrees/agent-t1 -b agent/t1
|
|
209
|
+
git worktree add ../worktrees/agent-t2 -b agent/t2
|
|
210
|
+
git worktree add ../worktrees/agent-t3 -b agent/t3
|
|
211
|
+
# ... spawn task agents in each worktree, await completion ...
|
|
212
|
+
|
|
213
|
+
# 4. TDD-gated merge for each wave-1 task (no human per task)
|
|
214
|
+
git merge --no-ff agent/t1 # tests pass before + after
|
|
215
|
+
git worktree remove ../worktrees/agent-t1
|
|
216
|
+
git merge --no-ff agent/t2
|
|
217
|
+
git worktree remove ../worktrees/agent-t2
|
|
218
|
+
git merge --no-ff agent/t3
|
|
219
|
+
git worktree remove ../worktrees/agent-t3
|
|
220
|
+
|
|
221
|
+
# 5. Advance to wave 2 (t4 depends on t1–t3 being merged)
|
|
222
|
+
git worktree add ../worktrees/agent-t4 -b agent/t4
|
|
223
|
+
# ... spawn, await, merge with TDD gate, remove worktree ...
|
|
224
|
+
|
|
225
|
+
# 6. Open the final PR (human gate 3)
|
|
226
|
+
bash .claude/skills/cicd/scripts/workflow.sh open
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
The exported plan-md from `devague plan export` is the standing brief for
|
|
230
|
+
each task agent — its task id, summary, acceptance criteria, and the targets
|
|
231
|
+
it covers are already in that file.
|
|
232
|
+
|
|
233
|
+
## Provenance
|
|
234
|
+
|
|
235
|
+
This is a **first-party** skill — its origin is `agentculture/devague`, where
|
|
236
|
+
the devague agent maintains it alongside the tools it operates (dogfooding),
|
|
237
|
+
next to its siblings `/think` and `/spec-to-plan`. It is the *third* skill in
|
|
238
|
+
that outbound family, covering the implementation leg after a plan converges.
|
|
239
|
+
The flow runs the *opposite* direction of the vendored steward skills: steward
|
|
240
|
+
pulls this **from** devague and broadcasts it to the rest of the AgentCulture
|
|
241
|
+
mesh. The `cite, don't import` policy still holds: downstream repos copy it,
|
|
242
|
+
they don't symlink or depend on it. See `docs/skill-sources.md`.
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# assign-to-workforce.sh — fan out devague plan waves to parallel agents.
|
|
3
|
+
#
|
|
4
|
+
# The skill is named `assign-to-workforce`; it reads `devague plan waves`
|
|
5
|
+
# (scheduling metadata produced by the /spec-to-plan skill) and renders the
|
|
6
|
+
# implementation split plan: task map + per-task agent/model proposal + a
|
|
7
|
+
# go/no-go prompt for the human. The actual fan-out (worktree creation,
|
|
8
|
+
# spawning, TDD-gated merges) is performed by the operator/main agent once
|
|
9
|
+
# the human approves the split plan.
|
|
10
|
+
#
|
|
11
|
+
# The devague CLI is non-orchestrating (#20): `devague plan waves` describes
|
|
12
|
+
# the dependency graph; it does not spawn agents, manage worktrees, or pick
|
|
13
|
+
# a backend. This wrapper is the operator-facing helper.
|
|
14
|
+
#
|
|
15
|
+
# Origin: authored and maintained in agentculture/devague. steward pulls this
|
|
16
|
+
# skill from here and broadcasts it to the rest of the AgentCulture mesh, so
|
|
17
|
+
# it is written to run anywhere — portable bash, no devague-checkout assumptions.
|
|
18
|
+
#
|
|
19
|
+
# Plans persist under .devague/ in the current directory, so run from the repo
|
|
20
|
+
# you are implementing.
|
|
21
|
+
|
|
22
|
+
set -euo pipefail
|
|
23
|
+
|
|
24
|
+
# ── resolve the devague CLI (mesh-first, then local-dev fallback) ───────────
|
|
25
|
+
DEVAGUE=()
|
|
26
|
+
resolve_devague() {
|
|
27
|
+
if command -v devague >/dev/null 2>&1; then
|
|
28
|
+
DEVAGUE=(devague) # installed tool — the normal mesh case
|
|
29
|
+
return 0
|
|
30
|
+
fi
|
|
31
|
+
# Local-dev fallback: inside the devague checkout, run via uv.
|
|
32
|
+
local dir="$PWD"
|
|
33
|
+
while [ -n "$dir" ] && [ "$dir" != "/" ]; do
|
|
34
|
+
if [ -f "$dir/pyproject.toml" ] \
|
|
35
|
+
&& grep -q '^name = "devague"' "$dir/pyproject.toml" 2>/dev/null; then
|
|
36
|
+
if command -v uv >/dev/null 2>&1; then
|
|
37
|
+
DEVAGUE=(uv run devague)
|
|
38
|
+
return 0
|
|
39
|
+
fi
|
|
40
|
+
break
|
|
41
|
+
fi
|
|
42
|
+
dir=$(dirname "$dir")
|
|
43
|
+
done
|
|
44
|
+
cat >&2 <<'EOF'
|
|
45
|
+
error: devague CLI not found.
|
|
46
|
+
hint: install it with `uv tool install devague` (or `pipx install devague`),
|
|
47
|
+
or run from inside the devague checkout with `uv` available.
|
|
48
|
+
https://github.com/agentculture/devague
|
|
49
|
+
EOF
|
|
50
|
+
return 1
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
usage() {
|
|
54
|
+
cat <<'EOF'
|
|
55
|
+
assign-to-workforce.sh — fan out devague plan waves to parallel agents.
|
|
56
|
+
|
|
57
|
+
Usage:
|
|
58
|
+
assign-to-workforce.sh split-plan [--plan <slug>] print the implementation split plan
|
|
59
|
+
assign-to-workforce.sh waves [--plan <slug>] [--json] list dependency waves
|
|
60
|
+
assign-to-workforce.sh help this help
|
|
61
|
+
|
|
62
|
+
Commands:
|
|
63
|
+
split-plan Read `devague plan waves --json` and render the human-facing
|
|
64
|
+
implementation split plan: task map + per-task agent/model
|
|
65
|
+
proposal + go/no-go. Present this to the human before any
|
|
66
|
+
fan-out; do not proceed without approval.
|
|
67
|
+
waves Forward `devague plan waves` (and any extra flags) verbatim.
|
|
68
|
+
On a converged plan exits 0 and lists the dependency waves.
|
|
69
|
+
|
|
70
|
+
Plans persist under .devague/ in the current directory — run from the repo
|
|
71
|
+
you are implementing. Results go to stdout, diagnostics to stderr.
|
|
72
|
+
|
|
73
|
+
Human gates (three only):
|
|
74
|
+
1. The exported spec (already closed by the /think leg).
|
|
75
|
+
2. This implementation split plan (go/no-go to assign to workforce).
|
|
76
|
+
3. The final PR (opened by the main agent via `cicd` / `agex pr open`).
|
|
77
|
+
|
|
78
|
+
The devague CLI is non-orchestrating (#20): `devague plan waves` describes
|
|
79
|
+
the graph; the operator performs the fan-out. One worktree per task; TDD
|
|
80
|
+
gates every merge (tests pass before AND after merge); no human per task.
|
|
81
|
+
EOF
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
# ── split-plan: render the implementation split plan for human review ────────
|
|
85
|
+
cmd_split_plan() {
|
|
86
|
+
local extra_args=()
|
|
87
|
+
# Forward any --plan flag so waves targets the right plan.
|
|
88
|
+
while [ $# -gt 0 ]; do
|
|
89
|
+
extra_args+=("$1")
|
|
90
|
+
shift
|
|
91
|
+
done
|
|
92
|
+
|
|
93
|
+
local waves_json tmp_err waves_rc old_exit_trap
|
|
94
|
+
# Clean up the temp file on any exit path — including a signal after its
|
|
95
|
+
# creation — WITHOUT permanently changing the script's process-global EXIT
|
|
96
|
+
# handling. Capture any prior EXIT trap BEFORE mktemp (that capture forks a
|
|
97
|
+
# subshell, so doing it first keeps it out of the untracked-file window),
|
|
98
|
+
# then install our cleanup trap on the line immediately after mktemp, and
|
|
99
|
+
# restore the prior trap once the file is safely gone (#30; PR #31 review;
|
|
100
|
+
# devague#32).
|
|
101
|
+
old_exit_trap="$(trap -p EXIT)"
|
|
102
|
+
tmp_err="$(mktemp)"
|
|
103
|
+
trap 'rm -f "$tmp_err"' EXIT
|
|
104
|
+
set +e
|
|
105
|
+
waves_json="$("${DEVAGUE[@]}" plan waves --json "${extra_args[@]}" 2>"$tmp_err")"
|
|
106
|
+
waves_rc=$?
|
|
107
|
+
set -e
|
|
108
|
+
local waves_err
|
|
109
|
+
waves_err="$(cat "$tmp_err")"
|
|
110
|
+
rm -f "$tmp_err"
|
|
111
|
+
trap - EXIT
|
|
112
|
+
eval "${old_exit_trap}" # empty string is a no-op; re-installs a prior trap if any
|
|
113
|
+
|
|
114
|
+
if [ "$waves_rc" -ne 0 ]; then
|
|
115
|
+
printf '%s\n' "$waves_err" >&2
|
|
116
|
+
return "$waves_rc"
|
|
117
|
+
fi
|
|
118
|
+
|
|
119
|
+
DEVAGUE_WAVES_JSON="$waves_json" python3 - <<'PY'
|
|
120
|
+
import json
|
|
121
|
+
import os
|
|
122
|
+
import sys
|
|
123
|
+
|
|
124
|
+
raw = os.environ.get("DEVAGUE_WAVES_JSON", "").strip()
|
|
125
|
+
if not raw:
|
|
126
|
+
print("error: no waves output from devague plan waves", file=sys.stderr)
|
|
127
|
+
print("hint: ensure a converged plan exists (devague plan converge)", file=sys.stderr)
|
|
128
|
+
sys.exit(1)
|
|
129
|
+
|
|
130
|
+
try:
|
|
131
|
+
data = json.loads(raw)
|
|
132
|
+
except json.JSONDecodeError as exc:
|
|
133
|
+
print(f"error: could not parse waves JSON: {exc}", file=sys.stderr)
|
|
134
|
+
sys.exit(1)
|
|
135
|
+
|
|
136
|
+
plan_slug = data.get("plan", "(unknown)")
|
|
137
|
+
waves = data.get("waves") or []
|
|
138
|
+
|
|
139
|
+
print(f"Implementation split plan — plan: {plan_slug}")
|
|
140
|
+
print()
|
|
141
|
+
print("Dependency waves (from `devague plan waves`):")
|
|
142
|
+
for i, wave in enumerate(waves, 1):
|
|
143
|
+
tasks = ", ".join(wave)
|
|
144
|
+
print(f" Wave {i}: [{tasks}]")
|
|
145
|
+
|
|
146
|
+
print()
|
|
147
|
+
print("Task assignments (proposed — edit before approving):")
|
|
148
|
+
print()
|
|
149
|
+
|
|
150
|
+
headers = ("Task", "Wave", "Summary", "Agent type", "Model", "Scope note")
|
|
151
|
+
rows = []
|
|
152
|
+
for i, wave in enumerate(waves, 1):
|
|
153
|
+
for task_id in wave:
|
|
154
|
+
rows.append((
|
|
155
|
+
task_id,
|
|
156
|
+
str(i),
|
|
157
|
+
"(see plan export for summary + acceptance criteria)",
|
|
158
|
+
"subagent",
|
|
159
|
+
"cheaper/faster",
|
|
160
|
+
"TDD-scoped task; isolated worktree; tests gate merge",
|
|
161
|
+
))
|
|
162
|
+
|
|
163
|
+
col_widths = [max(len(h), max((len(r[j]) for r in rows), default=0))
|
|
164
|
+
for j, h in enumerate(headers)]
|
|
165
|
+
|
|
166
|
+
def row_str(cells):
|
|
167
|
+
return "| " + " | ".join(c.ljust(w) for c, w in zip(cells, col_widths)) + " |"
|
|
168
|
+
|
|
169
|
+
sep = "| " + " | ".join("-" * w for w in col_widths) + " |"
|
|
170
|
+
print(row_str(headers))
|
|
171
|
+
print(sep)
|
|
172
|
+
for row in rows:
|
|
173
|
+
print(row_str(row))
|
|
174
|
+
|
|
175
|
+
print()
|
|
176
|
+
print("Go/no-go: review the table above, edit agent type / model / scope as needed,")
|
|
177
|
+
print("then confirm: \"Approved — assign to workforce\" or \"Edit first\".")
|
|
178
|
+
print()
|
|
179
|
+
print("Once approved, fan out wave by wave:")
|
|
180
|
+
print(" 1. Create one git worktree per task in the wave.")
|
|
181
|
+
print(" 2. Spawn a task agent per worktree (brief = task summary + acceptance criteria).")
|
|
182
|
+
print(" 3. Await all tasks in the wave; then TDD-gate each merge (tests before + after).")
|
|
183
|
+
print(" 4. Advance to the next wave.")
|
|
184
|
+
print(" 5. Open the final PR (human gate 3) after all waves merge and tests pass.")
|
|
185
|
+
PY
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
main() {
|
|
189
|
+
case "${1:-help}" in
|
|
190
|
+
help | -h | --help)
|
|
191
|
+
usage
|
|
192
|
+
return 0
|
|
193
|
+
;;
|
|
194
|
+
split-plan)
|
|
195
|
+
shift
|
|
196
|
+
resolve_devague
|
|
197
|
+
cmd_split_plan "$@"
|
|
198
|
+
;;
|
|
199
|
+
waves)
|
|
200
|
+
shift
|
|
201
|
+
resolve_devague
|
|
202
|
+
exec "${DEVAGUE[@]}" plan waves "$@"
|
|
203
|
+
;;
|
|
204
|
+
*)
|
|
205
|
+
printf 'error: unknown subcommand: %s\n' "$1" >&2
|
|
206
|
+
printf 'hint: run `assign-to-workforce.sh help` for usage\n' >&2
|
|
207
|
+
return 1
|
|
208
|
+
;;
|
|
209
|
+
esac
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
main "$@"
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-to-plan
|
|
3
|
+
type: command
|
|
4
|
+
description: >
|
|
5
|
+
Turn a converged devague spec into a buildable plan by working forwards (the
|
|
6
|
+
spec→plan leg; drives the `devague plan` CLI group). Seed a plan from a
|
|
7
|
+
converged frame, add tasks that collectively cover every coverage target (the
|
|
8
|
+
frame's confirmed claims + honesty conditions), give each task acceptance
|
|
9
|
+
criteria and an honest dependency order, park genuine unknowns as first-class
|
|
10
|
+
risks, and export a plan only once it *converges*. Use when the user says
|
|
11
|
+
"spec to plan", "stp", "turn this spec into a plan", "plan this spec", "make a
|
|
12
|
+
build plan", or after the /think skill exports a spec. Authored and maintained
|
|
13
|
+
in agentculture/devague (origin = devague); steward pulls this skill from here
|
|
14
|
+
and broadcasts it to the AgentCulture mesh — it is NOT vendored from steward
|
|
15
|
+
like the other skills here.
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
# spec-to-plan — work a converged spec forwards into a buildable plan
|
|
19
|
+
|
|
20
|
+
The skill is named **`spec-to-plan`**; the product/CLI it drives is the
|
|
21
|
+
**`devague plan`** command group. (The prior leg — turning a vague idea into a
|
|
22
|
+
spec — is the sibling **`/think`** skill.) It is the **forward** peer of the
|
|
23
|
+
working-backwards spec engine: where `/think` converges on *what* to build,
|
|
24
|
+
`/spec-to-plan` converges on *how* to build it.
|
|
25
|
+
|
|
26
|
+
A plan is seeded from a **converged frame** and tracks **tasks** against the
|
|
27
|
+
spec's **coverage targets**. The CLI is **deterministic and move-driven** — you
|
|
28
|
+
(the agent) choose the next move; the CLI tracks state and tells you what's still
|
|
29
|
+
missing. Run `devague plan learn` for the method and `devague plan explain
|
|
30
|
+
<move>` for any single move.
|
|
31
|
+
|
|
32
|
+
## How to run
|
|
33
|
+
|
|
34
|
+
The entry point is `scripts/spec-to-plan.sh`. Invoke it from the repository you
|
|
35
|
+
are speccing (plans persist under `.devague/` in the current directory, alongside
|
|
36
|
+
the frames they derive from):
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
bash .claude/skills/spec-to-plan/scripts/spec-to-plan.sh <move> [args...]
|
|
40
|
+
bash .claude/skills/spec-to-plan/scripts/spec-to-plan.sh status
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
It resolves the CLI portably — an installed `devague` on `PATH` (the normal
|
|
44
|
+
case), falling back to `uv run devague` inside the devague checkout, else an
|
|
45
|
+
install hint. Every move — including `status` — is forwarded verbatim as
|
|
46
|
+
`devague plan <move>`, so you can equally call the CLI directly
|
|
47
|
+
(`devague plan <move> …`).
|
|
48
|
+
|
|
49
|
+
### Moves
|
|
50
|
+
|
|
51
|
+
| Move | What it does |
|
|
52
|
+
|------|--------------|
|
|
53
|
+
| `new --frame <slug>` | Seed a plan from a **converged** frame. Derives the coverage targets (`c*`/`h*`) the plan must satisfy. Refuses an unconverged frame. |
|
|
54
|
+
| `task "<summary>"` | Add a task. `--accept "<crit>"`, `--dep <tN>`, `--covers <c*/h*>` (each repeatable); `--origin llm` lands it `proposed`. |
|
|
55
|
+
| `accept <tN> "<crit>"` | Add an acceptance criterion to a task. |
|
|
56
|
+
| `depend <tN> --on <tM>` | Record that task `tN` depends on `tM`. |
|
|
57
|
+
| `cover <tN> --target <c*/h*>` | Mark a task as covering a coverage target. |
|
|
58
|
+
| `confirm <tN>` / `reject <tN>` | Resolve a task. **User-only decision.** |
|
|
59
|
+
| `risk "<text>" --kind <kind>` | Record a first-class plan risk (`--task <tN>` to attach). |
|
|
60
|
+
| `converge` | Evaluate the gate against the **live** source frame; list remaining gaps. |
|
|
61
|
+
| `export` | Write the buildable plan to `docs/plans/` — only after `converge` passes. |
|
|
62
|
+
| `waves` | Emit deterministic dependency waves (`{plan, waves}`) — scheduling metadata only, *not* orchestration. Read-only, works on an in-progress plan; refuses a cyclic/dangling graph. Devague describes the graph; an operator decides how to run it (#20). |
|
|
63
|
+
| `status` | Read-only: where the plan stands + the recommended next move, re-checked against the live frame (`--json` too). |
|
|
64
|
+
| `show` / `list` | Render a plan / list plans (`--json` for raw state). |
|
|
65
|
+
| `learn` / `explain <move>` | Teach the method / explain one move. |
|
|
66
|
+
|
|
67
|
+
Risk kinds (shared with the frame engine): `unknown_nonblocking`,
|
|
68
|
+
`unknown_blocking`, `out_of_scope`, `follow_up`.
|
|
69
|
+
|
|
70
|
+
### `status` — the next-move verb
|
|
71
|
+
|
|
72
|
+
`status` is a first-class, **read-only** CLI verb (`devague plan status`,
|
|
73
|
+
internalised from this wrapper in 0.11.0 — issue
|
|
74
|
+
[#30](https://github.com/agentculture/devague/issues/30)). It composes
|
|
75
|
+
`devague plan list` + `devague plan converge` and prints where the current plan
|
|
76
|
+
stands, the remaining gaps, and the recommended next move derived from the first
|
|
77
|
+
gap. Like `converge`/`export` it re-checks the **live** source frame (so frame
|
|
78
|
+
drift surfaces as an error), but it never mutates state. Pass `--json` for the
|
|
79
|
+
structured payload (`{plan, total, ready_for_plan, blockers, warnings,
|
|
80
|
+
parked_items, required_next_moves}`).
|
|
81
|
+
|
|
82
|
+
```text
|
|
83
|
+
plan: my-feature (1 plan total)
|
|
84
|
+
convergence: NOT passed — 2 gap(s):
|
|
85
|
+
- coverage target c5 (boundary) has no confirmed task
|
|
86
|
+
- task t2 has no acceptance criteria
|
|
87
|
+
|
|
88
|
+
recommended next move (first gap):
|
|
89
|
+
cover c5: devague plan task "<summary>" --covers c5 --accept "<...>"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
Run it whenever you're unsure what to do next.
|
|
93
|
+
|
|
94
|
+
## Hard rules (do not violate)
|
|
95
|
+
|
|
96
|
+
These are the point of the method — convergence must mean something.
|
|
97
|
+
|
|
98
|
+
- **Seed from a converged spec only.** `plan new` refuses a frame that hasn't
|
|
99
|
+
converged. The plan's coverage targets *are* the spec's confirmed claims and
|
|
100
|
+
honesty conditions — there is nothing honest to plan against until the spec
|
|
101
|
+
converges.
|
|
102
|
+
- **LLM proposals stay proposed.** A task captured with `--origin llm` lands as
|
|
103
|
+
`proposed`. **Never `confirm` your own proposal.** Confirmation is a user-only
|
|
104
|
+
decision — surface the proposed task and let the user confirm or reject it.
|
|
105
|
+
- **Cover every target; criteria on every task.** The gate requires every
|
|
106
|
+
coverage target to be covered by a confirmed task, and every confirmed task to
|
|
107
|
+
carry at least one acceptance criterion. Don't hand-wave a task as "done-ish."
|
|
108
|
+
- **Keep the graph honest.** Dependencies must reference real tasks and form an
|
|
109
|
+
acyclic graph; the gate rejects dangling deps and cycles.
|
|
110
|
+
- **Park real unknowns as risks; don't paper over them.** A genuinely unknown
|
|
111
|
+
decision is an `unknown_blocking` risk — it holds back convergence, by design.
|
|
112
|
+
- **Converge against the live frame.** `converge`/`export` re-load the source
|
|
113
|
+
frame every time. If the frame was deleted or has regressed below convergence,
|
|
114
|
+
they refuse — re-converge the spec (in `/think`) first.
|
|
115
|
+
|
|
116
|
+
## Coaching toward small, file-disjoint, TDD-gated tasks
|
|
117
|
+
|
|
118
|
+
When authoring a plan that will be built via parallel execution (fanned out to
|
|
119
|
+
multiple agents via the downstream `/assign-to-workforce` skill), prefer the
|
|
120
|
+
following discipline to maximize parallelism and minimize merge friction:
|
|
121
|
+
|
|
122
|
+
### Small and crisply scoped
|
|
123
|
+
|
|
124
|
+
Each task should be **small enough for a simpler or cheaper model to build
|
|
125
|
+
test-first** without re-deriving the full design. If a task spans multiple files
|
|
126
|
+
or architectural layers, split it — narrow scope forces you to write sharp
|
|
127
|
+
acceptance criteria and keeps waves wide.
|
|
128
|
+
|
|
129
|
+
### File disjoint
|
|
130
|
+
|
|
131
|
+
**Prefer tasks that touch non-overlapping files.** When two same-wave tasks
|
|
132
|
+
modify the same file, merge collision becomes inevitable. The dependency graph
|
|
133
|
+
alone *does not* guarantee file disjointness — it only sequences task *content*
|
|
134
|
+
dependencies; same-wave tasks with overlapping file-writes must be split across
|
|
135
|
+
waves or given explicit dependencies.
|
|
136
|
+
|
|
137
|
+
Check `devague plan waves` output: if a wave is wide but all tasks touch
|
|
138
|
+
`src/core.py`, the wave is *formally* parallel but *operationally* serialized at
|
|
139
|
+
merge. Reorder task boundaries so wide waves operate on disjoint file sets.
|
|
140
|
+
|
|
141
|
+
### TDD acceptance criteria on every task
|
|
142
|
+
|
|
143
|
+
Every confirmed task must carry **at least one acceptance criterion**, phrased as
|
|
144
|
+
a testable condition (not a vague outcome). For example:
|
|
145
|
+
|
|
146
|
+
- Bad: "Implement the parser"
|
|
147
|
+
- Better: "Parser accepts a valid spec file and rejects malformed YAML without
|
|
148
|
+
data loss"
|
|
149
|
+
|
|
150
|
+
Acceptance criteria are **the contract** between the main agent (who merges) and
|
|
151
|
+
the subagent (who builds). A test suite derived from these criteria validates
|
|
152
|
+
each task's output *before* merge, independent of model capability. This is not
|
|
153
|
+
optional: `devague plan converge` warns (non-blocking) when a confirmed task
|
|
154
|
+
lacks criteria.
|
|
155
|
+
|
|
156
|
+
### The key invariant: parallel = serial
|
|
157
|
+
|
|
158
|
+
**A plan built in parallel must yield identical results to building it serially.**
|
|
159
|
+
This is guaranteed only if:
|
|
160
|
+
|
|
161
|
+
1. Same-wave tasks have no inter-task dependencies (checked by `waves`).
|
|
162
|
+
2. Same-wave tasks touch disjoint files (you must verify; the CLI does not).
|
|
163
|
+
3. Each task's acceptance criteria are sharp enough that a subagent's output
|
|
164
|
+
passes them independent of whether it was built in isolation or alongside
|
|
165
|
+
other tasks.
|
|
166
|
+
|
|
167
|
+
The TDD gate — tests pass before *and* after the merge — is the main agent's
|
|
168
|
+
proof that parallelism didn't break correctness.
|
|
169
|
+
|
|
170
|
+
### How to route tasks to the workforce
|
|
171
|
+
|
|
172
|
+
Once your plan converges, `devague plan waves` emits the dependency-graph as
|
|
173
|
+
**scheduling metadata** (ordered batches of task IDs). This feeds directly into
|
|
174
|
+
the `/assign-to-workforce` skill, which:
|
|
175
|
+
|
|
176
|
+
1. Displays the plan, waves, and suggested per-task subagent/model pairing.
|
|
177
|
+
2. Waits for the human to approve the implementation split plan (or edit
|
|
178
|
+
assignments).
|
|
179
|
+
3. Fans out approved waves to isolated subagent worktrees (one per task per
|
|
180
|
+
wave).
|
|
181
|
+
4. Returns control to the main agent, which TDD-gates each merge before moving
|
|
182
|
+
to the next wave.
|
|
183
|
+
|
|
184
|
+
Plan for workforce execution early: narrow task scope, write crisp acceptance
|
|
185
|
+
criteria, and strive for wide waves with disjoint files.
|
|
186
|
+
|
|
187
|
+
## Output contract
|
|
188
|
+
|
|
189
|
+
Results go to **stdout**, diagnostics and errors to **stderr** — a strict split
|
|
190
|
+
you can rely on when parsing. Pass `--json` to any move for a structured payload.
|
|
191
|
+
Exit code `0` on success, non-zero on user error (with a `hint:` line). Plans
|
|
192
|
+
live under `.devague/plans/` in the current directory; the exported plan-md lands
|
|
193
|
+
in `docs/plans/`.
|
|
194
|
+
|
|
195
|
+
## Worked example
|
|
196
|
+
|
|
197
|
+
Picking up after `/think` exported a spec for the frame `my-feature`:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
p() { bash .claude/skills/spec-to-plan/scripts/spec-to-plan.sh "$@"; }
|
|
201
|
+
|
|
202
|
+
p new --frame my-feature # seeds the plan + its coverage targets
|
|
203
|
+
p show # see the c*/h* targets you must cover
|
|
204
|
+
|
|
205
|
+
p task "Build the core engine" --accept "engine has a convergence gate" \
|
|
206
|
+
--covers c1 --covers c3
|
|
207
|
+
p task "Pressure-test honesty conditions" --dep t1 --covers h1 --covers h2 \
|
|
208
|
+
--accept "every honesty condition maps to a test"
|
|
209
|
+
|
|
210
|
+
# Park a genuine unknown instead of guessing:
|
|
211
|
+
p risk "exact rollout sequencing" --kind unknown_nonblocking
|
|
212
|
+
|
|
213
|
+
p status # what's left + the next move
|
|
214
|
+
p converge # gate; resolve any listed gaps
|
|
215
|
+
p export # writes docs/plans/my-feature.md once converged
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
The exported plan-md is a buildable artifact: topologically ordered tasks, each
|
|
219
|
+
with acceptance criteria and the spec targets it covers. It feeds directly into
|
|
220
|
+
implementation (or `superpowers:writing-plans`).
|
|
221
|
+
|
|
222
|
+
## Provenance
|
|
223
|
+
|
|
224
|
+
This is a **first-party** skill — its origin is `agentculture/devague`, where the
|
|
225
|
+
devague agent maintains it alongside the tool it operates (dogfooding), next to
|
|
226
|
+
its sibling `/think`. It is the *inverse* of the other skills under
|
|
227
|
+
`.claude/skills/`, which devague vendors **from** steward. When ready, steward
|
|
228
|
+
pulls it **from** devague and broadcasts it to the rest of the AgentCulture mesh.
|
|
229
|
+
The `cite, don't import` policy still holds: downstream repos copy it, they don't
|
|
230
|
+
symlink or depend on it. See `docs/skill-sources.md`.
|