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.
Files changed (100) hide show
  1. devague-0.4.0/.claude/skills/spec-to-plan/SKILL.md +149 -0
  2. devague-0.4.0/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +226 -0
  3. {devague-0.3.3/.claude/skills/devague → devague-0.4.0/.claude/skills/think}/SKILL.md +25 -18
  4. devague-0.3.3/.claude/skills/devague/scripts/devague.sh → devague-0.4.0/.claude/skills/think/scripts/think.sh +10 -5
  5. {devague-0.3.3 → devague-0.4.0}/CHANGELOG.md +12 -0
  6. {devague-0.3.3 → devague-0.4.0}/CLAUDE.md +52 -14
  7. devague-0.4.0/PKG-INFO +58 -0
  8. devague-0.4.0/README.md +41 -0
  9. {devague-0.3.3 → devague-0.4.0}/devague/cli/__init__.py +2 -0
  10. devague-0.4.0/devague/cli/_commands/plan.py +436 -0
  11. devague-0.4.0/devague/cli/_plans.py +29 -0
  12. devague-0.4.0/devague/plan.py +179 -0
  13. devague-0.4.0/devague/plan_convergence.py +142 -0
  14. devague-0.4.0/devague/plan_store.py +60 -0
  15. devague-0.4.0/devague/render/plan_md.py +91 -0
  16. {devague-0.3.3 → devague-0.4.0}/docs/skill-sources.md +13 -5
  17. devague-0.4.0/docs/superpowers/specs/2026-05-23-devague-spec-to-plan-design.md +198 -0
  18. {devague-0.3.3 → devague-0.4.0}/pyproject.toml +2 -2
  19. devague-0.4.0/tests/test_cli_plan.py +291 -0
  20. devague-0.4.0/tests/test_plan.py +102 -0
  21. devague-0.4.0/tests/test_plan_convergence.py +121 -0
  22. devague-0.4.0/tests/test_plan_store.py +67 -0
  23. devague-0.4.0/tests/test_render_plan.py +71 -0
  24. devague-0.4.0/tests/test_spec_to_plan_skill.py +124 -0
  25. devague-0.3.3/tests/test_devague_skill.py → devague-0.4.0/tests/test_think_skill.py +6 -5
  26. {devague-0.3.3 → devague-0.4.0}/uv.lock +1 -1
  27. devague-0.3.3/PKG-INFO +0 -23
  28. devague-0.3.3/README.md +0 -6
  29. {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/SKILL.md +0 -0
  30. {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
  31. {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
  32. {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
  33. {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
  34. {devague-0.3.3 → devague-0.4.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
  35. {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/SKILL.md +0 -0
  36. {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
  37. {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
  38. {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
  39. {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
  40. {devague-0.3.3 → devague-0.4.0}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
  41. {devague-0.3.3 → devague-0.4.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
  42. {devague-0.3.3 → devague-0.4.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
  43. {devague-0.3.3 → devague-0.4.0}/.claude/skills/run-tests/SKILL.md +0 -0
  44. {devague-0.3.3 → devague-0.4.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
  45. {devague-0.3.3 → devague-0.4.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
  46. {devague-0.3.3 → devague-0.4.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
  47. {devague-0.3.3 → devague-0.4.0}/.claude/skills/version-bump/SKILL.md +0 -0
  48. {devague-0.3.3 → devague-0.4.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
  49. {devague-0.3.3 → devague-0.4.0}/.claude/skills.local.yaml.example +0 -0
  50. {devague-0.3.3 → devague-0.4.0}/.flake8 +0 -0
  51. {devague-0.3.3 → devague-0.4.0}/.github/workflows/publish.yml +0 -0
  52. {devague-0.3.3 → devague-0.4.0}/.github/workflows/security-checks.yml +0 -0
  53. {devague-0.3.3 → devague-0.4.0}/.github/workflows/tests.yml +0 -0
  54. {devague-0.3.3 → devague-0.4.0}/.gitignore +0 -0
  55. {devague-0.3.3 → devague-0.4.0}/.markdownlint-cli2.yaml +0 -0
  56. {devague-0.3.3 → devague-0.4.0}/.pre-commit-config.yaml +0 -0
  57. {devague-0.3.3 → devague-0.4.0}/LICENSE +0 -0
  58. {devague-0.3.3 → devague-0.4.0}/culture.yaml +0 -0
  59. {devague-0.3.3 → devague-0.4.0}/devague/__init__.py +0 -0
  60. {devague-0.3.3 → devague-0.4.0}/devague/__main__.py +0 -0
  61. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/__init__.py +0 -0
  62. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/capture.py +0 -0
  63. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/confirm.py +0 -0
  64. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/converge.py +0 -0
  65. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/explain.py +0 -0
  66. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/export.py +0 -0
  67. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/interrogate.py +0 -0
  68. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/learn.py +0 -0
  69. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/list_frames.py +0 -0
  70. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/new.py +0 -0
  71. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/park.py +0 -0
  72. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/reject.py +0 -0
  73. {devague-0.3.3 → devague-0.4.0}/devague/cli/_commands/show.py +0 -0
  74. {devague-0.3.3 → devague-0.4.0}/devague/cli/_errors.py +0 -0
  75. {devague-0.3.3 → devague-0.4.0}/devague/cli/_frames.py +0 -0
  76. {devague-0.3.3 → devague-0.4.0}/devague/cli/_output.py +0 -0
  77. {devague-0.3.3 → devague-0.4.0}/devague/convergence.py +0 -0
  78. {devague-0.3.3 → devague-0.4.0}/devague/frame.py +0 -0
  79. {devague-0.3.3 → devague-0.4.0}/devague/render/__init__.py +0 -0
  80. {devague-0.3.3 → devague-0.4.0}/devague/render/frame_md.py +0 -0
  81. {devague-0.3.3 → devague-0.4.0}/devague/render/spec_md.py +0 -0
  82. {devague-0.3.3 → devague-0.4.0}/devague/store.py +0 -0
  83. {devague-0.3.3 → devague-0.4.0}/docs/superpowers/plans/2026-05-22-specifix-onboarding.md +0 -0
  84. {devague-0.3.3 → devague-0.4.0}/docs/superpowers/plans/2026-05-23-devague-rename.md +0 -0
  85. {devague-0.3.3 → devague-0.4.0}/docs/superpowers/plans/2026-05-23-devague-working-backwards-engine.md +0 -0
  86. {devague-0.3.3 → devague-0.4.0}/docs/superpowers/specs/2026-05-22-specifix-onboarding-design.md +0 -0
  87. {devague-0.3.3 → devague-0.4.0}/docs/superpowers/specs/2026-05-23-devague-working-backwards-design.md +0 -0
  88. {devague-0.3.3 → devague-0.4.0}/sonar-project.properties +0 -0
  89. {devague-0.3.3 → devague-0.4.0}/tests/__init__.py +0 -0
  90. {devague-0.3.3 → devague-0.4.0}/tests/test_cli_affordances.py +0 -0
  91. {devague-0.3.3 → devague-0.4.0}/tests/test_cli_chassis.py +0 -0
  92. {devague-0.3.3 → devague-0.4.0}/tests/test_cli_converge_export.py +0 -0
  93. {devague-0.3.3 → devague-0.4.0}/tests/test_cli_errors.py +0 -0
  94. {devague-0.3.3 → devague-0.4.0}/tests/test_cli_moves.py +0 -0
  95. {devague-0.3.3 → devague-0.4.0}/tests/test_cli_output.py +0 -0
  96. {devague-0.3.3 → devague-0.4.0}/tests/test_convergence.py +0 -0
  97. {devague-0.3.3 → devague-0.4.0}/tests/test_frame.py +0 -0
  98. {devague-0.3.3 → devague-0.4.0}/tests/test_package.py +0 -0
  99. {devague-0.3.3 → devague-0.4.0}/tests/test_render.py +0 -0
  100. {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: devague
2
+ name: think
3
3
  description: >
4
- Operate the devague working-backwards spec tool: turn a vague feature idea
5
- into a buildable, pressure-tested spec by starting from the announcement
6
- ("pretend it shipped"), capturing and classifying claims, interrogating them
7
- with honesty conditions and hard questions, parking open vagueness as a
8
- first-class object, and exporting a spec only once the frame *converges*. Use
9
- when the user says "spec this", "work backwards", "turn this idea into a
10
- spec", "announcement frame", or "devague", or when a feature request is too
11
- vague to build yet. Authored and maintained in agentculture/devague (origin =
12
- devague); steward pulls this skill from here and broadcasts it to the
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
- # devague — work an idea backwards into a buildable spec
17
+ # think — work an idea backwards into a buildable spec
17
18
 
18
- `devague` turns a vague feature idea into a buildable spec by **working
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/devague.sh`. Invoke it from the repository you are
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/devague/scripts/devague.sh <move> [args...]
39
- bash .claude/skills/devague/scripts/devague.sh status
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/devague/scripts/devague.sh "$@"; }
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; it can feed directly into
154
- `superpowers:writing-plans` or a normal implementation PR.
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
- # devague.sh — operate the devague working-backwards spec tool.
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
- devague.sh — operate the devague working-backwards spec tool.
52
+ think.sh — drive devague's working-backwards idea→spec engine (the /think skill).
51
53
 
52
54
  Usage:
53
- devague.sh <move> [args...] forward a devague move
54
- devague.sh status [--frame S] where the frame stands + the next move
55
- devague.sh help this help
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
- **Working-backwards engine landed (v0.3.0).** The full deterministic spec
8
- engine is implemented: Frame domain model, persistent JSON store, convergence
9
- gate, pluggable renderer registry, and all CLI moves `new` / `capture` /
10
- `interrogate` / `confirm` / `reject` / `park` / `converge` / `export` / `show`
11
- / `list` — plus real `learn` / `explain` bodies that teach the method.
12
- Coverage is 94 %; all linters pass. Run `git ls-files` to see the real surface.
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** by working backwards. The method: start from the
46
- announcement ("pretend it shipped what would you announce?"), build an
47
- **Announcement Frame** by capturing and classifying claims, pressure-testing
48
- them with honesty conditions and hard questions, parking unresolved uncertainty
49
- as first-class "open vagueness," and only exporting a buildable spec once the
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
- Implemented verbs: `new`, `capture`, `interrogate`, `confirm`, `reject`,
89
- `park`, `converge`, `export`, `show`, `list`, `learn`, `explain`.
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.