devague 0.3.3__tar.gz → 0.4.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.
- devague-0.4.0/.claude/skills/spec-to-plan/SKILL.md +149 -0
- devague-0.4.0/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +226 -0
- {devague-0.3.3/.claude/skills/devague → devague-0.4.0/.claude/skills/think}/SKILL.md +25 -18
- devague-0.3.3/.claude/skills/devague/scripts/devague.sh → devague-0.4.0/.claude/skills/think/scripts/think.sh +10 -5
- {devague-0.3.3 → devague-0.4.0}/CHANGELOG.md +12 -0
- {devague-0.3.3 → devague-0.4.0}/CLAUDE.md +52 -14
- devague-0.4.0/PKG-INFO +58 -0
- devague-0.4.0/README.md +41 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/__init__.py +2 -0
- devague-0.4.0/devague/cli/_commands/plan.py +436 -0
- devague-0.4.0/devague/cli/_plans.py +29 -0
- devague-0.4.0/devague/plan.py +179 -0
- devague-0.4.0/devague/plan_convergence.py +142 -0
- devague-0.4.0/devague/plan_store.py +60 -0
- devague-0.4.0/devague/render/plan_md.py +91 -0
- {devague-0.3.3 → devague-0.4.0}/docs/skill-sources.md +13 -5
- devague-0.4.0/docs/superpowers/specs/2026-05-23-devague-spec-to-plan-design.md +198 -0
- {devague-0.3.3 → devague-0.4.0}/pyproject.toml +2 -2
- devague-0.4.0/tests/test_cli_plan.py +291 -0
- devague-0.4.0/tests/test_plan.py +102 -0
- devague-0.4.0/tests/test_plan_convergence.py +121 -0
- devague-0.4.0/tests/test_plan_store.py +67 -0
- devague-0.4.0/tests/test_render_plan.py +71 -0
- devague-0.4.0/tests/test_spec_to_plan_skill.py +124 -0
- devague-0.3.3/tests/test_devague_skill.py → devague-0.4.0/tests/test_think_skill.py +6 -5
- {devague-0.3.3 → devague-0.4.0}/uv.lock +1 -1
- devague-0.3.3/PKG-INFO +0 -23
- devague-0.3.3/README.md +0 -6
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/SKILL.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/SKILL.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/version-bump/SKILL.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/.claude/skills.local.yaml.example +0 -0
- {devague-0.3.3 → devague-0.4.0}/.flake8 +0 -0
- {devague-0.3.3 → devague-0.4.0}/.github/workflows/publish.yml +0 -0
- {devague-0.3.3 → devague-0.4.0}/.github/workflows/security-checks.yml +0 -0
- {devague-0.3.3 → devague-0.4.0}/.github/workflows/tests.yml +0 -0
- {devague-0.3.3 → devague-0.4.0}/.gitignore +0 -0
- {devague-0.3.3 → devague-0.4.0}/.markdownlint-cli2.yaml +0 -0
- {devague-0.3.3 → devague-0.4.0}/.pre-commit-config.yaml +0 -0
- {devague-0.3.3 → devague-0.4.0}/LICENSE +0 -0
- {devague-0.3.3 → devague-0.4.0}/culture.yaml +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/__init__.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/__main__.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/__init__.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/capture.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/confirm.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/converge.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/explain.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/export.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/interrogate.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/learn.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/list_frames.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/new.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/park.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/reject.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/show.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_errors.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_frames.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/cli/_output.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/convergence.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/frame.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/render/__init__.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/render/frame_md.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/render/spec_md.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/devague/store.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/docs/superpowers/plans/2026-05-22-specifix-onboarding.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/docs/superpowers/plans/2026-05-23-devague-rename.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/docs/superpowers/plans/2026-05-23-devague-working-backwards-engine.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/docs/superpowers/specs/2026-05-22-specifix-onboarding-design.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/docs/superpowers/specs/2026-05-23-devague-working-backwards-design.md +0 -0
- {devague-0.3.3 → devague-0.4.0}/sonar-project.properties +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/__init__.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/test_cli_affordances.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/test_cli_chassis.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/test_cli_converge_export.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/test_cli_errors.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/test_cli_moves.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/test_cli_output.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/test_convergence.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/test_frame.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/test_package.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/test_render.py +0 -0
- {devague-0.3.3 → devague-0.4.0}/tests/test_store.py +0 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: spec-to-plan
|
|
3
|
+
description: >
|
|
4
|
+
Turn a converged devague spec into a buildable plan by working forwards (the
|
|
5
|
+
spec→plan leg; drives the `devague plan` CLI group). Seed a plan from a
|
|
6
|
+
converged frame, add tasks that collectively cover every coverage target (the
|
|
7
|
+
frame's confirmed claims + honesty conditions), give each task acceptance
|
|
8
|
+
criteria and an honest dependency order, park genuine unknowns as first-class
|
|
9
|
+
risks, and export a plan only once it *converges*. Use when the user says
|
|
10
|
+
"spec to plan", "stp", "turn this spec into a plan", "plan this spec", "make a
|
|
11
|
+
build plan", or after the /think skill exports a spec. Authored and maintained
|
|
12
|
+
in agentculture/devague (origin = devague); steward pulls this skill from here
|
|
13
|
+
and broadcasts it to the AgentCulture mesh — it is NOT vendored from steward
|
|
14
|
+
like the other skills here.
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
# spec-to-plan — work a converged spec forwards into a buildable plan
|
|
18
|
+
|
|
19
|
+
The skill is named **`spec-to-plan`**; the product/CLI it drives is the
|
|
20
|
+
**`devague plan`** command group. (The prior leg — turning a vague idea into a
|
|
21
|
+
spec — is the sibling **`/think`** skill.) It is the **forward** peer of the
|
|
22
|
+
working-backwards spec engine: where `/think` converges on *what* to build,
|
|
23
|
+
`/spec-to-plan` converges on *how* to build it.
|
|
24
|
+
|
|
25
|
+
A plan is seeded from a **converged frame** and tracks **tasks** against the
|
|
26
|
+
spec's **coverage targets**. The CLI is **deterministic and move-driven** — you
|
|
27
|
+
(the agent) choose the next move; the CLI tracks state and tells you what's still
|
|
28
|
+
missing. Run `devague plan learn` for the method and `devague plan explain
|
|
29
|
+
<move>` for any single move.
|
|
30
|
+
|
|
31
|
+
## How to run
|
|
32
|
+
|
|
33
|
+
The entry point is `scripts/spec-to-plan.sh`. Invoke it from the repository you
|
|
34
|
+
are speccing (plans persist under `.devague/` in the current directory, alongside
|
|
35
|
+
the frames they derive from):
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
bash .claude/skills/spec-to-plan/scripts/spec-to-plan.sh <move> [args...]
|
|
39
|
+
bash .claude/skills/spec-to-plan/scripts/spec-to-plan.sh status
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
It resolves the CLI portably — an installed `devague` on `PATH` (the normal
|
|
43
|
+
case), falling back to `uv run devague` inside the devague checkout, else an
|
|
44
|
+
install hint. Every move except `status` is forwarded verbatim as `devague plan
|
|
45
|
+
<move>`, so you can equally call the CLI directly (`devague plan <move> …`).
|
|
46
|
+
|
|
47
|
+
### Moves
|
|
48
|
+
|
|
49
|
+
| Move | What it does |
|
|
50
|
+
|------|--------------|
|
|
51
|
+
| `new --frame <slug>` | Seed a plan from a **converged** frame. Derives the coverage targets (`c*`/`h*`) the plan must satisfy. Refuses an unconverged frame. |
|
|
52
|
+
| `task "<summary>"` | Add a task. `--accept "<crit>"`, `--dep <tN>`, `--covers <c*/h*>` (each repeatable); `--origin llm` lands it `proposed`. |
|
|
53
|
+
| `accept <tN> "<crit>"` | Add an acceptance criterion to a task. |
|
|
54
|
+
| `depend <tN> --on <tM>` | Record that task `tN` depends on `tM`. |
|
|
55
|
+
| `cover <tN> --target <c*/h*>` | Mark a task as covering a coverage target. |
|
|
56
|
+
| `confirm <tN>` / `reject <tN>` | Resolve a task. **User-only decision.** |
|
|
57
|
+
| `risk "<text>" --kind <kind>` | Record a first-class plan risk (`--task <tN>` to attach). |
|
|
58
|
+
| `converge` | Evaluate the gate against the **live** source frame; list remaining gaps. |
|
|
59
|
+
| `export` | Write the buildable plan to `docs/plans/` — only after `converge` passes. |
|
|
60
|
+
| `show` / `list` | Render a plan / list plans (`--json` for raw state). |
|
|
61
|
+
| `learn` / `explain <move>` | Teach the method / explain one move. |
|
|
62
|
+
|
|
63
|
+
Risk kinds (shared with the frame engine): `unknown_nonblocking`,
|
|
64
|
+
`unknown_blocking`, `out_of_scope`, `follow_up`.
|
|
65
|
+
|
|
66
|
+
### `status` — the next-move helper
|
|
67
|
+
|
|
68
|
+
`status` is a wrapper-only verb. It reads `devague plan converge --json` +
|
|
69
|
+
`devague plan list --json` and prints where the current plan stands, the
|
|
70
|
+
remaining gaps, and the recommended next move derived from the first gap.
|
|
71
|
+
|
|
72
|
+
```text
|
|
73
|
+
plan: my-feature (1 plan total)
|
|
74
|
+
convergence: NOT passed — 2 gap(s):
|
|
75
|
+
- coverage target c5 (boundary) has no confirmed task
|
|
76
|
+
- task t2 has no acceptance criteria
|
|
77
|
+
|
|
78
|
+
recommended next move (first gap):
|
|
79
|
+
cover c5: devague plan task "<summary>" --covers c5 --accept "<...>"
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Run it whenever you're unsure what to do next.
|
|
83
|
+
|
|
84
|
+
## Hard rules (do not violate)
|
|
85
|
+
|
|
86
|
+
These are the point of the method — convergence must mean something.
|
|
87
|
+
|
|
88
|
+
- **Seed from a converged spec only.** `plan new` refuses a frame that hasn't
|
|
89
|
+
converged. The plan's coverage targets *are* the spec's confirmed claims and
|
|
90
|
+
honesty conditions — there is nothing honest to plan against until the spec
|
|
91
|
+
converges.
|
|
92
|
+
- **LLM proposals stay proposed.** A task captured with `--origin llm` lands as
|
|
93
|
+
`proposed`. **Never `confirm` your own proposal.** Confirmation is a user-only
|
|
94
|
+
decision — surface the proposed task and let the user confirm or reject it.
|
|
95
|
+
- **Cover every target; criteria on every task.** The gate requires every
|
|
96
|
+
coverage target to be covered by a confirmed task, and every confirmed task to
|
|
97
|
+
carry at least one acceptance criterion. Don't hand-wave a task as "done-ish."
|
|
98
|
+
- **Keep the graph honest.** Dependencies must reference real tasks and form an
|
|
99
|
+
acyclic graph; the gate rejects dangling deps and cycles.
|
|
100
|
+
- **Park real unknowns as risks; don't paper over them.** A genuinely unknown
|
|
101
|
+
decision is an `unknown_blocking` risk — it holds back convergence, by design.
|
|
102
|
+
- **Converge against the live frame.** `converge`/`export` re-load the source
|
|
103
|
+
frame every time. If the frame was deleted or has regressed below convergence,
|
|
104
|
+
they refuse — re-converge the spec (in `/think`) first.
|
|
105
|
+
|
|
106
|
+
## Output contract
|
|
107
|
+
|
|
108
|
+
Results go to **stdout**, diagnostics and errors to **stderr** — a strict split
|
|
109
|
+
you can rely on when parsing. Pass `--json` to any move for a structured payload.
|
|
110
|
+
Exit code `0` on success, non-zero on user error (with a `hint:` line). Plans
|
|
111
|
+
live under `.devague/plans/` in the current directory; the exported plan-md lands
|
|
112
|
+
in `docs/plans/`.
|
|
113
|
+
|
|
114
|
+
## Worked example
|
|
115
|
+
|
|
116
|
+
Picking up after `/think` exported a spec for the frame `my-feature`:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
p() { bash .claude/skills/spec-to-plan/scripts/spec-to-plan.sh "$@"; }
|
|
120
|
+
|
|
121
|
+
p new --frame my-feature # seeds the plan + its coverage targets
|
|
122
|
+
p show # see the c*/h* targets you must cover
|
|
123
|
+
|
|
124
|
+
p task "Build the core engine" --accept "engine has a convergence gate" \
|
|
125
|
+
--covers c1 --covers c3
|
|
126
|
+
p task "Pressure-test honesty conditions" --dep t1 --covers h1 --covers h2 \
|
|
127
|
+
--accept "every honesty condition maps to a test"
|
|
128
|
+
|
|
129
|
+
# Park a genuine unknown instead of guessing:
|
|
130
|
+
p risk "exact rollout sequencing" --kind unknown_nonblocking
|
|
131
|
+
|
|
132
|
+
p status # what's left + the next move
|
|
133
|
+
p converge # gate; resolve any listed gaps
|
|
134
|
+
p export # writes docs/plans/my-feature.md once converged
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The exported plan-md is a buildable artifact: topologically ordered tasks, each
|
|
138
|
+
with acceptance criteria and the spec targets it covers. It feeds directly into
|
|
139
|
+
implementation (or `superpowers:writing-plans`).
|
|
140
|
+
|
|
141
|
+
## Provenance
|
|
142
|
+
|
|
143
|
+
This is a **first-party** skill — its origin is `agentculture/devague`, where the
|
|
144
|
+
devague agent maintains it alongside the tool it operates (dogfooding), next to
|
|
145
|
+
its sibling `/think`. It is the *inverse* of the other skills under
|
|
146
|
+
`.claude/skills/`, which devague vendors **from** steward. When ready, steward
|
|
147
|
+
pulls it **from** devague and broadcasts it to the rest of the AgentCulture mesh.
|
|
148
|
+
The `cite, don't import` policy still holds: downstream repos copy it, they don't
|
|
149
|
+
symlink or depend on it. See `docs/skill-sources.md`.
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# spec-to-plan.sh — drive devague's spec→plan engine (the /spec-to-plan skill).
|
|
3
|
+
#
|
|
4
|
+
# The skill is named `spec-to-plan`; the product/CLI it drives is `devague` (the
|
|
5
|
+
# idea→spec half lives in the sibling /think skill). This wrapper forwards every
|
|
6
|
+
# move to `devague plan <move>` verbatim, and adds one value-add subcommand —
|
|
7
|
+
# `status` — that reads the plan convergence gate and names the recommended next
|
|
8
|
+
# move. It is the forward leg: seed a plan from a *converged* frame, then work it
|
|
9
|
+
# into a buildable plan.
|
|
10
|
+
#
|
|
11
|
+
# Origin: authored and maintained in agentculture/devague. steward pulls this
|
|
12
|
+
# skill from here and broadcasts it to the rest of the AgentCulture mesh, so it
|
|
13
|
+
# is written to run anywhere — portable bash, no devague-checkout assumptions.
|
|
14
|
+
#
|
|
15
|
+
# Plans persist under .devague/ in the current directory (alongside frames), so
|
|
16
|
+
# run from the repo you are speccing.
|
|
17
|
+
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
# ── resolve the devague CLI (mesh-first, then local-dev fallback) ───────────
|
|
21
|
+
DEVAGUE=()
|
|
22
|
+
resolve_devague() {
|
|
23
|
+
if command -v devague >/dev/null 2>&1; then
|
|
24
|
+
DEVAGUE=(devague) # installed tool — the normal mesh case
|
|
25
|
+
return 0
|
|
26
|
+
fi
|
|
27
|
+
# Local-dev fallback: inside the devague checkout, run via uv.
|
|
28
|
+
local dir="$PWD"
|
|
29
|
+
while [ -n "$dir" ] && [ "$dir" != "/" ]; do
|
|
30
|
+
if [ -f "$dir/pyproject.toml" ] \
|
|
31
|
+
&& grep -q '^name = "devague"' "$dir/pyproject.toml" 2>/dev/null; then
|
|
32
|
+
if command -v uv >/dev/null 2>&1; then
|
|
33
|
+
DEVAGUE=(uv run devague)
|
|
34
|
+
return 0
|
|
35
|
+
fi
|
|
36
|
+
break
|
|
37
|
+
fi
|
|
38
|
+
dir=$(dirname "$dir")
|
|
39
|
+
done
|
|
40
|
+
cat >&2 <<'EOF'
|
|
41
|
+
error: devague CLI not found.
|
|
42
|
+
hint: install it with `uv tool install devague` (or `pipx install devague`),
|
|
43
|
+
or run from inside the devague checkout with `uv` available.
|
|
44
|
+
https://github.com/agentculture/devague
|
|
45
|
+
EOF
|
|
46
|
+
return 1
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
usage() {
|
|
50
|
+
cat <<'EOF'
|
|
51
|
+
spec-to-plan.sh — drive devague's spec→plan engine (the /spec-to-plan skill).
|
|
52
|
+
|
|
53
|
+
Usage:
|
|
54
|
+
spec-to-plan.sh <move> [args...] forward a `devague plan` move
|
|
55
|
+
spec-to-plan.sh status [--plan S] where the plan stands + the next move
|
|
56
|
+
spec-to-plan.sh help this help
|
|
57
|
+
|
|
58
|
+
Moves (forwarded to `devague plan`; run `devague plan learn` for the method):
|
|
59
|
+
new start a plan from a CONVERGED frame (--frame <slug>)
|
|
60
|
+
task add a task (--accept / --dep / --covers, --origin user|llm)
|
|
61
|
+
accept add an acceptance criterion to a task
|
|
62
|
+
depend record that a task depends on another (--on)
|
|
63
|
+
cover mark a task as covering a coverage target (c*/h*)
|
|
64
|
+
confirm confirm a task (USER-only decision)
|
|
65
|
+
reject reject a task
|
|
66
|
+
risk record a first-class plan risk
|
|
67
|
+
converge check whether the plan can export
|
|
68
|
+
export write the buildable plan (only after converge passes)
|
|
69
|
+
show / list render a plan / list plans
|
|
70
|
+
learn teach the method | explain <move> explain one move
|
|
71
|
+
|
|
72
|
+
Plans persist under .devague/ in the current directory — run from the repo you
|
|
73
|
+
are speccing. Results go to stdout, diagnostics to stderr; pass --json to any
|
|
74
|
+
move for structured output.
|
|
75
|
+
|
|
76
|
+
Note: `status` is a wrapper-only verb; everything else is forwarded verbatim as
|
|
77
|
+
`devague plan <move>`, so new plan moves work without editing this script.
|
|
78
|
+
|
|
79
|
+
Prior leg: a plan is seeded from a converged frame produced by the /think skill.
|
|
80
|
+
EOF
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
# ── status: read the plan convergence gate and recommend the next move ──────
|
|
84
|
+
cmd_status() {
|
|
85
|
+
local list_json conv_out conv_err conv_rc req_plan="" prev="" tmp_err
|
|
86
|
+
|
|
87
|
+
for arg in "$@"; do
|
|
88
|
+
case "$prev" in --plan) req_plan="$arg" ;; esac
|
|
89
|
+
case "$arg" in --plan=*) req_plan="${arg#--plan=}" ;; esac
|
|
90
|
+
prev="$arg"
|
|
91
|
+
done
|
|
92
|
+
|
|
93
|
+
list_json="$("${DEVAGUE[@]}" plan list --json 2>/dev/null || true)"
|
|
94
|
+
|
|
95
|
+
tmp_err="$(mktemp)"
|
|
96
|
+
set +e
|
|
97
|
+
conv_out="$("${DEVAGUE[@]}" plan converge --json "$@" 2>"$tmp_err")"
|
|
98
|
+
conv_rc=$?
|
|
99
|
+
set -e
|
|
100
|
+
conv_err="$(cat "$tmp_err")"
|
|
101
|
+
rm -f "$tmp_err"
|
|
102
|
+
|
|
103
|
+
DEVAGUE_LIST_JSON="$list_json" \
|
|
104
|
+
DEVAGUE_CONV_JSON="$conv_out" \
|
|
105
|
+
DEVAGUE_CONV_ERR="$conv_err" \
|
|
106
|
+
DEVAGUE_CONV_RC="$conv_rc" \
|
|
107
|
+
DEVAGUE_REQ_PLAN="$req_plan" \
|
|
108
|
+
python3 - <<'PY'
|
|
109
|
+
import json
|
|
110
|
+
import os
|
|
111
|
+
import re
|
|
112
|
+
import sys
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def load(name):
|
|
116
|
+
raw = os.environ.get(name, "").strip()
|
|
117
|
+
if not raw:
|
|
118
|
+
return None
|
|
119
|
+
try:
|
|
120
|
+
return json.loads(raw)
|
|
121
|
+
except json.JSONDecodeError:
|
|
122
|
+
return None
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
lst = load("DEVAGUE_LIST_JSON") or {}
|
|
126
|
+
conv = load("DEVAGUE_CONV_JSON")
|
|
127
|
+
conv_err = os.environ.get("DEVAGUE_CONV_ERR", "").strip()
|
|
128
|
+
req_plan = os.environ.get("DEVAGUE_REQ_PLAN", "").strip()
|
|
129
|
+
try:
|
|
130
|
+
conv_rc = int(os.environ.get("DEVAGUE_CONV_RC", "0") or "0")
|
|
131
|
+
except ValueError:
|
|
132
|
+
conv_rc = 0
|
|
133
|
+
|
|
134
|
+
plans = lst.get("plans") or []
|
|
135
|
+
current = lst.get("current")
|
|
136
|
+
|
|
137
|
+
if not plans:
|
|
138
|
+
print("no plans yet — seed one from a converged frame:")
|
|
139
|
+
print(' devague plan new --frame "<slug>"')
|
|
140
|
+
print(" (the frame must have converged in the /think skill first)")
|
|
141
|
+
sys.exit(0)
|
|
142
|
+
|
|
143
|
+
shown = req_plan or current or "(none selected)"
|
|
144
|
+
total = len(plans)
|
|
145
|
+
print(f"plan: {shown} ({total} plan{'s' if total != 1 else ''} total)")
|
|
146
|
+
|
|
147
|
+
if conv is None:
|
|
148
|
+
# A non-zero converge exit is a real error (deleted/regressed source frame,
|
|
149
|
+
# bad --plan) — relay devague's own error:/hint: lines instead of masking it.
|
|
150
|
+
if conv_rc != 0 and conv_err:
|
|
151
|
+
sys.stderr.write(conv_err + "\n")
|
|
152
|
+
sys.exit(conv_rc)
|
|
153
|
+
print("convergence: unknown (could not evaluate the plan)")
|
|
154
|
+
print("next move: devague plan show # inspect the plan")
|
|
155
|
+
sys.exit(0)
|
|
156
|
+
|
|
157
|
+
if conv.get("passed"):
|
|
158
|
+
print("convergence: PASSED ✓")
|
|
159
|
+
print("next move: devague plan export # write the buildable plan")
|
|
160
|
+
sys.exit(0)
|
|
161
|
+
|
|
162
|
+
missing = conv.get("missing") or []
|
|
163
|
+
print(f"convergence: NOT passed — {len(missing)} gap(s):")
|
|
164
|
+
for gap in missing:
|
|
165
|
+
print(f" - {gap}")
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def suggest(gap):
|
|
169
|
+
if "no tasks yet" in gap:
|
|
170
|
+
return 'devague plan task "<summary>" --covers <c*/h*> --accept "<criterion>"'
|
|
171
|
+
m = re.search(r"coverage target (\w+) ", gap)
|
|
172
|
+
if m:
|
|
173
|
+
tid = m.group(1)
|
|
174
|
+
return (
|
|
175
|
+
f'cover {tid}: devague plan task "<summary>" --covers {tid} --accept "<...>"'
|
|
176
|
+
f" (or: devague plan cover <tN> --target {tid})"
|
|
177
|
+
)
|
|
178
|
+
m = re.search(r"task (t\d+) has no acceptance", gap)
|
|
179
|
+
if m:
|
|
180
|
+
return f'devague plan accept {m.group(1)} "<acceptance criterion>"'
|
|
181
|
+
m = re.search(r"task (t\d+) still proposed", gap)
|
|
182
|
+
if m:
|
|
183
|
+
tid = m.group(1)
|
|
184
|
+
return (
|
|
185
|
+
f"this is an LLM proposal — the USER decides:"
|
|
186
|
+
f" devague plan confirm {tid} (or: devague plan reject {tid})"
|
|
187
|
+
)
|
|
188
|
+
m = re.search(r"task (t\d+) depends on unknown task (t\d+)", gap)
|
|
189
|
+
if m:
|
|
190
|
+
return f"fix {m.group(1)}'s dependency on missing {m.group(2)} (add it, or drop the dep)"
|
|
191
|
+
if "dependency cycle" in gap:
|
|
192
|
+
return "break the dependency cycle: re-point one task's --dep so the graph is acyclic"
|
|
193
|
+
m = re.search(r"blocking risk (r\d+)", gap)
|
|
194
|
+
if m:
|
|
195
|
+
return f"resolve {m.group(1)}: cover it with a task, or re-record it as non-blocking"
|
|
196
|
+
return "devague plan show # inspect and decide"
|
|
197
|
+
|
|
198
|
+
|
|
199
|
+
if missing:
|
|
200
|
+
print()
|
|
201
|
+
print("recommended next move (first gap):")
|
|
202
|
+
print(f" {suggest(missing[0])}")
|
|
203
|
+
PY
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
main() {
|
|
207
|
+
case "${1:-help}" in
|
|
208
|
+
help | -h | --help)
|
|
209
|
+
usage
|
|
210
|
+
return 0
|
|
211
|
+
;;
|
|
212
|
+
status)
|
|
213
|
+
shift
|
|
214
|
+
resolve_devague
|
|
215
|
+
cmd_status "$@"
|
|
216
|
+
;;
|
|
217
|
+
*)
|
|
218
|
+
# Forward everything else to `devague plan <move>` verbatim, so the
|
|
219
|
+
# CLI's own parser owns the plan surface.
|
|
220
|
+
resolve_devague
|
|
221
|
+
exec "${DEVAGUE[@]}" plan "$@"
|
|
222
|
+
;;
|
|
223
|
+
esac
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
main "$@"
|
|
@@ -1,21 +1,26 @@
|
|
|
1
1
|
---
|
|
2
|
-
name:
|
|
2
|
+
name: think
|
|
3
3
|
description: >
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
("pretend it shipped"),
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
spec", "announcement frame", or "devague", or when a feature request is too
|
|
11
|
-
vague to build yet.
|
|
12
|
-
|
|
4
|
+
Think a vague feature idea into a buildable spec by working backwards (the
|
|
5
|
+
idea→spec leg; drives the `devague` CLI). Start from the announcement
|
|
6
|
+
("pretend it shipped"), capture and classify claims, interrogate them with
|
|
7
|
+
honesty conditions and hard questions, park open vagueness as a first-class
|
|
8
|
+
object, and export a spec only once the frame *converges*. Use when the user
|
|
9
|
+
says "think this through", "spec this", "work backwards", "turn this idea into
|
|
10
|
+
a spec", "announcement frame", or "devague", or when a feature request is too
|
|
11
|
+
vague to build yet. Once a spec exports, hand off to the sibling /spec-to-plan
|
|
12
|
+
skill to turn it into a plan. Authored and maintained in agentculture/devague
|
|
13
|
+
(origin = devague); steward pulls this skill from here and broadcasts it to the
|
|
13
14
|
AgentCulture mesh — it is NOT vendored from steward like the other skills here.
|
|
14
15
|
---
|
|
15
16
|
|
|
16
|
-
#
|
|
17
|
+
# think — work an idea backwards into a buildable spec
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
The skill is named **`think`**; the product/CLI it drives is **`devague`**. (The
|
|
20
|
+
forward leg — turning a converged spec into a plan — is the sibling
|
|
21
|
+
**`/spec-to-plan`** skill, which drives `devague plan`.)
|
|
22
|
+
|
|
23
|
+
`think` turns a vague feature idea into a buildable spec by **working
|
|
19
24
|
backwards**: you start from the announcement you'd make if it had already
|
|
20
25
|
shipped, then build an **Announcement Frame** by capturing claims, pressure
|
|
21
26
|
-testing them, parking what's still genuinely unknown, and only exporting once
|
|
@@ -31,12 +36,12 @@ reads the convergence gate and tells you the recommended next move.
|
|
|
31
36
|
|
|
32
37
|
## How to run
|
|
33
38
|
|
|
34
|
-
The entry point is `scripts/
|
|
39
|
+
The entry point is `scripts/think.sh`. Invoke it from the repository you are
|
|
35
40
|
speccing (frames persist under `.devague/` in the current directory):
|
|
36
41
|
|
|
37
42
|
```bash
|
|
38
|
-
bash .claude/skills/
|
|
39
|
-
bash .claude/skills/
|
|
43
|
+
bash .claude/skills/think/scripts/think.sh <move> [args...]
|
|
44
|
+
bash .claude/skills/think/scripts/think.sh status
|
|
40
45
|
```
|
|
41
46
|
|
|
42
47
|
It resolves the CLI portably — an installed `devague` on `PATH` (the normal
|
|
@@ -129,7 +134,7 @@ A short end-to-end session (the kind you'd run to spec a feature like
|
|
|
129
134
|
[devague#5](https://github.com/agentculture/devague/issues/5)):
|
|
130
135
|
|
|
131
136
|
```bash
|
|
132
|
-
d() { bash .claude/skills/
|
|
137
|
+
d() { bash .claude/skills/think/scripts/think.sh "$@"; }
|
|
133
138
|
|
|
134
139
|
d new "Devague ships a documented spec contract"
|
|
135
140
|
d capture --kind audience "devague + the assisting LLM"
|
|
@@ -150,8 +155,10 @@ d converge # gate; resolve any listed gaps
|
|
|
150
155
|
d export # writes docs/specs/<slug>.md once converged
|
|
151
156
|
```
|
|
152
157
|
|
|
153
|
-
The exported spec-md is a buildable artifact
|
|
154
|
-
|
|
158
|
+
The exported spec-md is a buildable artifact. The next leg is the sibling
|
|
159
|
+
**`/spec-to-plan`** skill: `devague plan new --frame <slug>` seeds a plan from the
|
|
160
|
+
converged frame and works it forward into a buildable plan (it can equally feed
|
|
161
|
+
`superpowers:writing-plans` or a normal implementation PR).
|
|
155
162
|
|
|
156
163
|
## Provenance
|
|
157
164
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
-
#
|
|
2
|
+
# think.sh — drive devague's working-backwards idea→spec engine (the /think skill).
|
|
3
3
|
#
|
|
4
|
+
# The skill is named `think`; the product/CLI it drives is `devague` (the spec→plan
|
|
5
|
+
# half lives in the sibling /spec-to-plan skill, which drives `devague plan`).
|
|
4
6
|
# devague turns a vague feature idea into a buildable spec by working backwards.
|
|
5
7
|
# This wrapper is the agent-facing operator for the deterministic devague CLI:
|
|
6
8
|
# it resolves the CLI portably, forwards every move verbatim, and adds one
|
|
@@ -47,12 +49,12 @@ EOF
|
|
|
47
49
|
|
|
48
50
|
usage() {
|
|
49
51
|
cat <<'EOF'
|
|
50
|
-
|
|
52
|
+
think.sh — drive devague's working-backwards idea→spec engine (the /think skill).
|
|
51
53
|
|
|
52
54
|
Usage:
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
55
|
+
think.sh <move> [args...] forward a devague move
|
|
56
|
+
think.sh status [--frame S] where the frame stands + the next move
|
|
57
|
+
think.sh help this help
|
|
56
58
|
|
|
57
59
|
Moves (forwarded to the devague CLI; run `devague learn` for the full method):
|
|
58
60
|
new start a frame from the announcement ("pretend it shipped")
|
|
@@ -73,6 +75,9 @@ any move for structured output.
|
|
|
73
75
|
Note: `status` is a wrapper-only verb (the CLI has no `status`); everything
|
|
74
76
|
else is forwarded verbatim, so new devague moves work without editing this
|
|
75
77
|
script.
|
|
78
|
+
|
|
79
|
+
Next leg: once a frame exports a spec, hand off to the /spec-to-plan skill
|
|
80
|
+
(`devague plan ...`) to turn that spec into a buildable plan.
|
|
76
81
|
EOF
|
|
77
82
|
}
|
|
78
83
|
|
|
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
Format follows [Keep a Changelog](https://keepachangelog.com/). This project
|
|
6
6
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.0] - 2026-05-23
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Spec→plan engine** — a deterministic structural peer of the working-backwards frame engine that turns a converged spec into a buildable plan. New modules: `devague/plan.py` (Plan / Task / PlanRisk / CoverageTarget domain), `plan_convergence.py` (coverage + acceptance + acyclic-dependency + blocking-risk gate, reusing `ConvergenceResult`), `plan_store.py` (`.devague/plans/`), and `render/plan_md.py` (topologically-ordered buildable plan).
|
|
13
|
+
- Nested `devague plan` CLI group (`new` / `task` / `accept` / `depend` / `cover` / `confirm` / `reject` / `risk` / `converge` / `export` / `show` / `list` / `learn` / `explain`), all with `--json`. `plan new` requires a converged source frame; `converge`/`export` re-evaluate against the **live** frame and refuse on frame drift (deleted or regressed).
|
|
14
|
+
- New first-party **`/spec-to-plan`** skill (`.claude/skills/spec-to-plan/`): a portable wrapper (`scripts/spec-to-plan.sh`) forwarding to `devague plan` plus a `status` next-move helper over the plan gate.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **Renamed the `devague` skill to `think`** (`.claude/skills/think/`, `scripts/think.sh`) — clearer idea→spec framing and to pair with the new `/spec-to-plan` sibling. The product/CLI/repo name stays `devague`; only the skill identity changed. `docs/skill-sources.md` and downstream steward re-vendoring must relearn the new name. ("devague" remains a trigger keyword on `/think`.)
|
|
19
|
+
|
|
8
20
|
## [0.3.3] - 2026-05-23
|
|
9
21
|
|
|
10
22
|
### Added
|
|
@@ -4,12 +4,17 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|
|
4
4
|
|
|
5
5
|
## Status
|
|
6
6
|
|
|
7
|
-
**
|
|
8
|
-
engine
|
|
9
|
-
gate,
|
|
10
|
-
`
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
**Spec→plan engine landed (v0.4.0).** Both deterministic engines now ship.
|
|
8
|
+
The **frame engine** (idea→spec) — Frame domain model, JSON store, convergence
|
|
9
|
+
gate, renderer registry, and the flat moves `new` / `capture` / `interrogate` /
|
|
10
|
+
`confirm` / `reject` / `park` / `converge` / `export` / `show` / `list` /
|
|
11
|
+
`learn` / `explain`. The **plan engine** (spec→plan) is its structural peer:
|
|
12
|
+
`devague/plan.py`, `plan_convergence.py`, `plan_store.py`, `render/plan_md.py`,
|
|
13
|
+
and the nested group `devague plan <move>` (`new` / `task` / `accept` / `depend`
|
|
14
|
+
/ `cover` / `confirm` / `reject` / `risk` / `converge` / `export` / `show` /
|
|
15
|
+
`list` / `learn` / `explain`). The two operator skills are `/think` (idea→spec,
|
|
16
|
+
renamed from `/devague`) and `/spec-to-plan` (spec→plan). Coverage ≥ 95 %; all
|
|
17
|
+
linters pass. Run `git ls-files` to see the real surface.
|
|
13
18
|
|
|
14
19
|
Real commands: `uv sync`; `uv run devague --version`; `python -m devague`;
|
|
15
20
|
`uv run pytest -n auto` (single test: `uv run pytest tests/<file>::<node> -v`);
|
|
@@ -39,15 +44,44 @@ itself. The workflow:
|
|
|
39
44
|
|
|
40
45
|
Full design: `docs/superpowers/specs/2026-05-23-devague-working-backwards-design.md`.
|
|
41
46
|
|
|
47
|
+
## Spec→plan method (the forward leg)
|
|
48
|
+
|
|
49
|
+
The **plan engine** is the structural peer of the frame engine — same chassis,
|
|
50
|
+
same anti-fabrication rules, no LLM inside the CLI. It is namespaced under the
|
|
51
|
+
`devague plan` subcommand group (the *skill* is `/spec-to-plan`; the CLI verb is
|
|
52
|
+
`plan` — they intentionally differ, mirroring how `/think` drives the flat
|
|
53
|
+
verbs). The workflow:
|
|
54
|
+
|
|
55
|
+
1. `devague plan new --frame <slug>` — seed a plan from a **converged** frame.
|
|
56
|
+
Derives **coverage targets** (the frame's confirmed claims + honesty
|
|
57
|
+
conditions). Refuses an unconverged frame; refuses to clobber an existing plan.
|
|
58
|
+
2. `devague plan task "<summary>" [--accept … --dep … --covers … --origin]` —
|
|
59
|
+
add tasks; `--origin llm` lands `proposed` (user must `confirm`). Refine with
|
|
60
|
+
`accept` / `depend` / `cover`.
|
|
61
|
+
3. `devague plan risk "<text>" --kind <kind>` — park a genuine unknown as a
|
|
62
|
+
first-class plan risk instead of guessing.
|
|
63
|
+
4. `devague plan converge` — re-evaluates the gate **against the live frame**
|
|
64
|
+
(catches frame drift); lists gaps. A plan converges when every target is
|
|
65
|
+
covered by a confirmed task, every confirmed task has acceptance criteria, the
|
|
66
|
+
dependency graph is acyclic, and no blocking risk remains.
|
|
67
|
+
5. `devague plan export` — only after `converge` passes; writes a buildable
|
|
68
|
+
plan-md (topologically ordered) to `docs/plans/`.
|
|
69
|
+
|
|
70
|
+
Full design: `docs/superpowers/specs/2026-05-23-devague-spec-to-plan-design.md`.
|
|
71
|
+
|
|
42
72
|
## Project intent
|
|
43
73
|
|
|
44
74
|
**devague** — an AgentCulture agent that turns a vague feature idea into a
|
|
45
|
-
**buildable spec
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
frame *converges*.
|
|
75
|
+
**buildable spec**, then that spec into a **buildable plan**, by working
|
|
76
|
+
backwards then forwards. The spec method: start from the announcement ("pretend
|
|
77
|
+
it shipped — what would you announce?"), build an **Announcement Frame** by
|
|
78
|
+
capturing and classifying claims, pressure-testing them with honesty conditions
|
|
79
|
+
and hard questions, parking unresolved uncertainty as first-class "open
|
|
80
|
+
vagueness," and only exporting a buildable spec once the frame *converges*. The
|
|
81
|
+
plan method: seed a plan from that converged frame and converge it on coverage,
|
|
82
|
+
acceptance criteria, and an acyclic dependency order before exporting a plan.
|
|
83
|
+
Two operator skills cover the two legs: **`/think`** (idea→spec) and
|
|
84
|
+
**`/spec-to-plan`** (spec→plan); the product/CLI for both is **`devague`**.
|
|
51
85
|
|
|
52
86
|
This is a **state machine over claims, honesty conditions, open vagueness, and
|
|
53
87
|
convergence** driven by LLM-chosen moves — not a linear wizard. The CLI is
|
|
@@ -85,8 +119,12 @@ that unless the user asks otherwise. The established sibling shape is:
|
|
|
85
119
|
`DevagueError` + exit-code policy) and `_output.py` (strict stdout/stderr
|
|
86
120
|
split, `--json` support).
|
|
87
121
|
- `devague/cli/_commands/` — one module per verb, each exposing `register()`.
|
|
88
|
-
|
|
89
|
-
`
|
|
122
|
+
Frame verbs: `new`, `capture`, `interrogate`, `confirm`, `reject`, `park`,
|
|
123
|
+
`converge`, `export`, `show`, `list`, `learn`, `explain`. The plan engine adds
|
|
124
|
+
one module, `_commands/plan.py`, registering the nested `plan` subcommand group.
|
|
125
|
+
- Frame engine: `devague/frame.py`, `convergence.py`, `store.py`,
|
|
126
|
+
`render/{spec_md,frame_md}.py`. Plan engine (its peer): `devague/plan.py`,
|
|
127
|
+
`plan_convergence.py`, `plan_store.py`, `render/plan_md.py`, `cli/_plans.py`.
|
|
90
128
|
- `pyproject.toml`, `CHANGELOG.md`, `tests/`, `docs/`, `culture.yaml`,
|
|
91
129
|
`sonar-project.properties`, `uv.lock`.
|
|
92
130
|
|
devague-0.4.0/PKG-INFO
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: devague
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: devague — turns a vague feature idea into a buildable spec, then a buildable plan.
|
|
5
|
+
Project-URL: Homepage, https://github.com/agentculture/devague
|
|
6
|
+
Project-URL: Issues, https://github.com/agentculture/devague/issues
|
|
7
|
+
Author: AgentCulture
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Classifier: Topic :: Software Development
|
|
15
|
+
Requires-Python: >=3.12
|
|
16
|
+
Description-Content-Type: text/markdown
|
|
17
|
+
|
|
18
|
+
# devague
|
|
19
|
+
|
|
20
|
+
**`devague` is a command-line tool** that turns a vague feature idea into a
|
|
21
|
+
buildable **spec**, then that spec into a buildable **plan** — by working
|
|
22
|
+
backwards, then forwards. It is a small, deterministic Python CLI (no LLM calls
|
|
23
|
+
inside it, fully unit-tested) — not an agent, service, or daemon. You install it
|
|
24
|
+
and run `devague` from the repository you are speccing; state is plain JSON under
|
|
25
|
+
`.devague/`.
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
vague idea ──▶ buildable spec ──▶ buildable plan ──▶ build
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Install
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
uv tool install devague # or: pipx install devague / pip install devague
|
|
35
|
+
devague --version
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Two engines, one CLI
|
|
39
|
+
|
|
40
|
+
- **Frame engine** (idea→spec) — start from the announcement ("pretend it
|
|
41
|
+
shipped"), capture and pressure-test claims, park open vagueness, and `export`
|
|
42
|
+
a spec only once the frame *converges*. Flat verbs: `devague new` /
|
|
43
|
+
`capture` / `interrogate` / `confirm` / `converge` / `export` / …
|
|
44
|
+
- **Plan engine** (spec→plan) — seed a plan from a converged frame, cover every
|
|
45
|
+
target with tasks that carry acceptance criteria and an acyclic dependency
|
|
46
|
+
order, and `export` a plan only once it *converges*. Nested group:
|
|
47
|
+
`devague plan new` / `task` / `cover` / `converge` / `export` / …
|
|
48
|
+
|
|
49
|
+
Run `devague learn` (or `devague plan learn`) to learn the method, and `devague
|
|
50
|
+
explain <move>` for any single move.
|
|
51
|
+
|
|
52
|
+
## Driving it from an agent
|
|
53
|
+
|
|
54
|
+
Inside AgentCulture, an assistant drives this CLI through two operator skills —
|
|
55
|
+
**`/think`** (idea→spec) and **`/spec-to-plan`** (spec→plan) — which add a
|
|
56
|
+
portable wrapper and a `status` next-move helper over the convergence gate. The
|
|
57
|
+
CLI is the deterministic affordance; the agent decides the next move. See
|
|
58
|
+
`CLAUDE.md` for that workflow and `docs/superpowers/specs/` for the design docs.
|