devague 0.4.0__tar.gz → 0.5.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 → devague-0.5.0}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +13 -41
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/think/SKILL.md +38 -16
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/think/scripts/think.sh +13 -47
- devague-0.5.0/.devague/current_plan +1 -0
- devague-0.5.0/.devague/frames/devague-now-ships-a-documented-spec-contract-every.json +263 -0
- devague-0.5.0/.devague/plans/devague-now-ships-a-documented-spec-contract-every.json +363 -0
- {devague-0.4.0 → devague-0.5.0}/CHANGELOG.md +28 -0
- {devague-0.4.0 → devague-0.5.0}/CLAUDE.md +9 -0
- {devague-0.4.0 → devague-0.5.0}/PKG-INFO +1 -1
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/capture.py +9 -1
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/converge.py +18 -7
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/export.py +2 -2
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/plan.py +20 -12
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_frames.py +16 -1
- devague-0.5.0/devague/convergence.py +149 -0
- {devague-0.4.0 → devague-0.5.0}/devague/frame.py +45 -1
- {devague-0.4.0 → devague-0.5.0}/devague/plan_convergence.py +47 -3
- {devague-0.4.0 → devague-0.5.0}/devague/render/frame_md.py +3 -3
- {devague-0.4.0 → devague-0.5.0}/devague/render/plan_md.py +11 -7
- {devague-0.4.0 → devague-0.5.0}/devague/render/spec_md.py +14 -12
- {devague-0.4.0 → devague-0.5.0}/devague/store.py +11 -1
- devague-0.5.0/docs/examples/contract-example.json +160 -0
- devague-0.5.0/docs/plans/devague-now-ships-a-documented-spec-contract-every.md +85 -0
- devague-0.5.0/docs/reviews/spec-contract-frame-review.md +150 -0
- devague-0.5.0/docs/spec-contract.md +180 -0
- devague-0.5.0/docs/specs/devague-now-ships-a-documented-spec-contract-every.md +55 -0
- {devague-0.4.0 → devague-0.5.0}/pyproject.toml +1 -1
- {devague-0.4.0 → devague-0.5.0}/tests/test_cli_converge_export.py +7 -7
- {devague-0.4.0 → devague-0.5.0}/tests/test_cli_moves.py +27 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_cli_plan.py +3 -3
- devague-0.5.0/tests/test_contract.py +129 -0
- devague-0.5.0/tests/test_convergence.py +97 -0
- devague-0.5.0/tests/test_frame.py +111 -0
- devague-0.5.0/tests/test_offline.py +58 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_plan_convergence.py +14 -14
- devague-0.5.0/tests/test_render.py +81 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_render_plan.py +7 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_store.py +43 -1
- {devague-0.4.0 → devague-0.5.0}/uv.lock +1 -1
- devague-0.4.0/devague/convergence.py +0 -72
- devague-0.4.0/tests/test_convergence.py +0 -62
- devague-0.4.0/tests/test_frame.py +0 -42
- devague-0.4.0/tests/test_render.py +0 -41
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/cicd/SKILL.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/cicd/scripts/workflow.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/communicate/SKILL.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/run-tests/SKILL.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/sonarclaude/SKILL.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/spec-to-plan/SKILL.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/version-bump/SKILL.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills/version-bump/scripts/bump.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/.claude/skills.local.yaml.example +0 -0
- {devague-0.4.0 → devague-0.5.0}/.flake8 +0 -0
- {devague-0.4.0 → devague-0.5.0}/.github/workflows/publish.yml +0 -0
- {devague-0.4.0 → devague-0.5.0}/.github/workflows/security-checks.yml +0 -0
- {devague-0.4.0 → devague-0.5.0}/.github/workflows/tests.yml +0 -0
- {devague-0.4.0 → devague-0.5.0}/.gitignore +0 -0
- {devague-0.4.0 → devague-0.5.0}/.markdownlint-cli2.yaml +0 -0
- {devague-0.4.0 → devague-0.5.0}/.pre-commit-config.yaml +0 -0
- {devague-0.4.0 → devague-0.5.0}/LICENSE +0 -0
- {devague-0.4.0 → devague-0.5.0}/README.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/culture.yaml +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/__init__.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/__main__.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/__init__.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/__init__.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/confirm.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/explain.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/interrogate.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/learn.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/list_frames.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/new.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/park.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/reject.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_commands/show.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_errors.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_output.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/cli/_plans.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/plan.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/plan_store.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/devague/render/__init__.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/docs/skill-sources.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/docs/superpowers/plans/2026-05-22-specifix-onboarding.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/docs/superpowers/plans/2026-05-23-devague-rename.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/docs/superpowers/plans/2026-05-23-devague-working-backwards-engine.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/docs/superpowers/specs/2026-05-22-specifix-onboarding-design.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/docs/superpowers/specs/2026-05-23-devague-spec-to-plan-design.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/docs/superpowers/specs/2026-05-23-devague-working-backwards-design.md +0 -0
- {devague-0.4.0 → devague-0.5.0}/sonar-project.properties +0 -0
- {devague-0.4.0 → devague-0.5.0}/tests/__init__.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_cli_affordances.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_cli_chassis.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_cli_errors.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_cli_output.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_package.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_plan.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_plan_store.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_spec_to_plan_skill.py +0 -0
- {devague-0.4.0 → devague-0.5.0}/tests/test_think_skill.py +0 -0
|
@@ -108,7 +108,6 @@ cmd_status() {
|
|
|
108
108
|
python3 - <<'PY'
|
|
109
109
|
import json
|
|
110
110
|
import os
|
|
111
|
-
import re
|
|
112
111
|
import sys
|
|
113
112
|
|
|
114
113
|
|
|
@@ -154,52 +153,25 @@ if conv is None:
|
|
|
154
153
|
print("next move: devague plan show # inspect the plan")
|
|
155
154
|
sys.exit(0)
|
|
156
155
|
|
|
157
|
-
if conv.get("
|
|
156
|
+
if conv.get("ready_for_plan"):
|
|
158
157
|
print("convergence: PASSED ✓")
|
|
158
|
+
for w in conv.get("warnings") or []:
|
|
159
|
+
print(f" ⚠ {w}")
|
|
159
160
|
print("next move: devague plan export # write the buildable plan")
|
|
160
161
|
sys.exit(0)
|
|
161
162
|
|
|
162
|
-
|
|
163
|
-
print(f"convergence: NOT passed — {len(
|
|
164
|
-
for
|
|
165
|
-
print(f" - {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
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:
|
|
163
|
+
blockers = conv.get("blockers") or []
|
|
164
|
+
print(f"convergence: NOT passed — {len(blockers)} gap(s):")
|
|
165
|
+
for b in blockers:
|
|
166
|
+
print(f" - {b}")
|
|
167
|
+
for w in conv.get("warnings") or []:
|
|
168
|
+
print(f" ⚠ {w}")
|
|
169
|
+
|
|
170
|
+
moves = conv.get("required_next_moves") or []
|
|
171
|
+
if moves:
|
|
200
172
|
print()
|
|
201
173
|
print("recommended next move (first gap):")
|
|
202
|
-
print(f" {
|
|
174
|
+
print(f" {moves[0]}")
|
|
203
175
|
PY
|
|
204
176
|
}
|
|
205
177
|
|
|
@@ -66,27 +66,31 @@ portable resolution and the `status` helper.
|
|
|
66
66
|
| `learn` / `explain <move>` | Teach the method / explain one move. |
|
|
67
67
|
|
|
68
68
|
Claim kinds: `announcement`, `audience`, `after_state`, `before_state`,
|
|
69
|
-
`why_it_matters`, `boundary`, `success_signal`, `open_question
|
|
70
|
-
`
|
|
69
|
+
`why_it_matters`, `boundary`, `success_signal`, `open_question`, `non_goal`,
|
|
70
|
+
`requirement`, `assumption`, `decision`. Vagueness kinds: `unknown_nonblocking`,
|
|
71
|
+
`unknown_blocking`, `out_of_scope`, `follow_up`.
|
|
71
72
|
|
|
72
73
|
These are exactly the kinds the **shipped CLI enforces** (`CLAIM_KINDS` /
|
|
73
74
|
`VAGUENESS_KINDS` in `devague/frame.py`) — the skill documents the surface as
|
|
74
|
-
built, so every command here passes the CLI's `choices=` validation.
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
75
|
+
built, so every command here passes the CLI's `choices=` validation. `requirement`
|
|
76
|
+
is spec-affecting (needs a confirmed honesty condition); `non_goal` / `decision`
|
|
77
|
+
are descriptive; an unconfirmed `assumption` is a convergence *warning*, not a
|
|
78
|
+
blocker. The formal entity model, the `(state × origin)` vocabulary, and the
|
|
79
|
+
per-move input/output/transition/error contract are documented in
|
|
80
|
+
[`docs/spec-contract.md`](../../../docs/spec-contract.md) (issue
|
|
81
|
+
[#5](https://github.com/agentculture/devague/issues/5)); for the authoritative
|
|
78
82
|
live shape of any move, run it with `--json` (or `devague learn --json` /
|
|
79
|
-
`devague explain <move>`).
|
|
83
|
+
`devague explain <move>`).
|
|
80
84
|
|
|
81
85
|
### `status` — the next-move helper
|
|
82
86
|
|
|
83
87
|
`status` is a wrapper-only verb (the CLI has no `status`). It reads
|
|
84
88
|
`converge --json` + `list --json` and prints where the current frame stands, the
|
|
85
|
-
remaining gaps, and the recommended next move
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
`
|
|
89
|
+
remaining gaps, and the recommended next move. `converge --json` emits the
|
|
90
|
+
structured result `{ready_for_spec, blockers, warnings, parked_items,
|
|
91
|
+
required_next_moves}` (issue [#5](https://github.com/agentculture/devague/issues/5));
|
|
92
|
+
the helper reads `ready_for_spec`, lists the `blockers` and `warnings`, and shows
|
|
93
|
+
`required_next_moves[0]` as the recommended move — no longer deriving it itself.
|
|
90
94
|
|
|
91
95
|
```text
|
|
92
96
|
frame: my-feature (1 frame total)
|
|
@@ -155,10 +159,28 @@ d converge # gate; resolve any listed gaps
|
|
|
155
159
|
d export # writes docs/specs/<slug>.md once converged
|
|
156
160
|
```
|
|
157
161
|
|
|
158
|
-
The exported spec-md is a buildable artifact.
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
+
The exported spec-md is a buildable artifact.
|
|
163
|
+
|
|
164
|
+
## After export — commit, then hand off
|
|
165
|
+
|
|
166
|
+
Once `export` writes the spec **and the user has reviewed it**, close the
|
|
167
|
+
idea→spec leg cleanly before moving on:
|
|
168
|
+
|
|
169
|
+
1. **Commit the spec.** Commit the exported `docs/specs/<slug>.md` (along with
|
|
170
|
+
the `.devague/<slug>.json` frame state and any review artifact under
|
|
171
|
+
`docs/reviews/`) so the converged frame is durable in history, not just on
|
|
172
|
+
disk. Use a focused message, e.g. `git commit -m "spec: <slug> (devague
|
|
173
|
+
/think)"`. The frame and the spec are the evidence trail for every confirmed
|
|
174
|
+
claim — keep them together. (Per the repo's standing convention this normally
|
|
175
|
+
becomes a branch + PR via the `cicd` skill; commit-only is fine when the user
|
|
176
|
+
asks for it.)
|
|
177
|
+
2. **Hand off to `/spec-to-plan`.** The forward leg is the sibling skill:
|
|
178
|
+
`devague plan new --frame <slug>` seeds a plan from the converged frame and
|
|
179
|
+
works it forward into a buildable plan (it can equally feed
|
|
180
|
+
`superpowers:writing-plans` or a normal implementation PR).
|
|
181
|
+
|
|
182
|
+
Don't pause for a "what next?" menu after a reviewed export — the standing flow
|
|
183
|
+
is **commit, then `/spec-to-plan`**.
|
|
162
184
|
|
|
163
185
|
## Provenance
|
|
164
186
|
|
|
@@ -114,7 +114,6 @@ cmd_status() {
|
|
|
114
114
|
python3 - <<'PY'
|
|
115
115
|
import json
|
|
116
116
|
import os
|
|
117
|
-
import re
|
|
118
117
|
import sys
|
|
119
118
|
|
|
120
119
|
|
|
@@ -161,58 +160,25 @@ if conv is None:
|
|
|
161
160
|
print("next move: devague show # inspect the frame")
|
|
162
161
|
sys.exit(0)
|
|
163
162
|
|
|
164
|
-
if conv.get("
|
|
163
|
+
if conv.get("ready_for_spec"):
|
|
165
164
|
print("convergence: PASSED ✓")
|
|
165
|
+
for w in conv.get("warnings") or []:
|
|
166
|
+
print(f" ⚠ {w}")
|
|
166
167
|
print("next move: devague export # write the buildable spec")
|
|
167
168
|
sys.exit(0)
|
|
168
169
|
|
|
169
|
-
|
|
170
|
-
print(f"convergence: NOT passed — {len(
|
|
171
|
-
for
|
|
172
|
-
print(f" - {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
# work. Spell out who confirms wherever a confirm is in play.
|
|
179
|
-
m = re.search(r"missing confirmed '([a-z_]+)' claim", gap)
|
|
180
|
-
if m:
|
|
181
|
-
kind = m.group(1)
|
|
182
|
-
return (f'devague capture --kind {kind} "<text>"'
|
|
183
|
-
f' (a user capture auto-confirms; an --origin llm capture'
|
|
184
|
-
f' then needs the USER to confirm it)')
|
|
185
|
-
if "before_state" in gap and "why_it_matters" in gap:
|
|
186
|
-
return 'devague capture --kind why_it_matters "<text>"'
|
|
187
|
-
if "boundary" in gap:
|
|
188
|
-
return 'devague capture --kind boundary "<text>"'
|
|
189
|
-
if "success_signal" in gap:
|
|
190
|
-
return 'devague capture --kind success_signal "<text>"'
|
|
191
|
-
m = re.search(r"claim (c\d+) still proposed", gap)
|
|
192
|
-
if m:
|
|
193
|
-
cid = m.group(1)
|
|
194
|
-
return (f'this is an LLM proposal — the USER decides:'
|
|
195
|
-
f' devague confirm {cid} (or: devague reject {cid})')
|
|
196
|
-
m = re.search(r"claim (c\d+) has no confirmed honesty condition", gap)
|
|
197
|
-
if m:
|
|
198
|
-
cid = m.group(1)
|
|
199
|
-
return (f'devague interrogate {cid} --honesty "<what must be true>"'
|
|
200
|
-
f' then the USER runs: devague confirm <hN>')
|
|
201
|
-
m = re.search(r"blocking vagueness (v\d+)", gap)
|
|
202
|
-
if m:
|
|
203
|
-
return (f"resolve {m.group(1)}: capture+confirm the answer, "
|
|
204
|
-
f"or re-park it as non-blocking")
|
|
205
|
-
m = re.search(r"blocking hard question (q\d+) on (c\d+)", gap)
|
|
206
|
-
if m:
|
|
207
|
-
return (f"resolve {m.group(1)} on {m.group(2)}: answer it, then "
|
|
208
|
-
f"capture/confirm the resulting claim")
|
|
209
|
-
return "devague show # inspect and decide"
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if missing:
|
|
170
|
+
blockers = conv.get("blockers") or []
|
|
171
|
+
print(f"convergence: NOT passed — {len(blockers)} gap(s):")
|
|
172
|
+
for b in blockers:
|
|
173
|
+
print(f" - {b}")
|
|
174
|
+
for w in conv.get("warnings") or []:
|
|
175
|
+
print(f" ⚠ {w}")
|
|
176
|
+
|
|
177
|
+
moves = conv.get("required_next_moves") or []
|
|
178
|
+
if moves:
|
|
213
179
|
print()
|
|
214
180
|
print("recommended next move (first gap):")
|
|
215
|
-
print(f" {
|
|
181
|
+
print(f" {moves[0]}")
|
|
216
182
|
PY
|
|
217
183
|
}
|
|
218
184
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
devague-now-ships-a-documented-spec-contract-every
|
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
{
|
|
2
|
+
"slug": "devague-now-ships-a-documented-spec-contract-every",
|
|
3
|
+
"title": "Devague now ships a documented spec contract: every frame is a durable, reloadable artifact, and converge returns a structured result (ready_for_spec, blockers, warnings, parked_items, required_next_moves) instead of prose-only advice",
|
|
4
|
+
"status": "exported",
|
|
5
|
+
"created": "2026-05-23T08:08:13Z",
|
|
6
|
+
"updated": "2026-05-23T09:17:12Z",
|
|
7
|
+
"claims": [
|
|
8
|
+
{
|
|
9
|
+
"id": "c1",
|
|
10
|
+
"kind": "announcement",
|
|
11
|
+
"text": "Devague now ships a documented spec contract: every frame is a durable, reloadable artifact, and converge returns a structured result (ready_for_spec, blockers, warnings, parked_items, required_next_moves) instead of prose-only advice",
|
|
12
|
+
"origin": "user",
|
|
13
|
+
"status": "confirmed",
|
|
14
|
+
"honesty_conditions": [
|
|
15
|
+
{
|
|
16
|
+
"id": "h1",
|
|
17
|
+
"text": "A frame round-trips losslessly (save then load yields an identical frame) including schema_version, the new claim types, and the structured convergence payload; existing 0.4.0 frames still load",
|
|
18
|
+
"status": "confirmed"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"hard_questions": [],
|
|
22
|
+
"links": []
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"id": "c2",
|
|
26
|
+
"kind": "audience",
|
|
27
|
+
"text": "Devague and the assisting LLM that drives it \u2014 they coordinate around structured feature-framing state without a rigid wizard",
|
|
28
|
+
"origin": "user",
|
|
29
|
+
"status": "confirmed",
|
|
30
|
+
"honesty_conditions": [
|
|
31
|
+
{
|
|
32
|
+
"id": "h2",
|
|
33
|
+
"text": "Every move accepts and emits documented JSON, and the contract spells out per-move input / output / state-transition / validation-errors so an LLM can drive devague without guessing internal state",
|
|
34
|
+
"status": "confirmed"
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"hard_questions": [],
|
|
38
|
+
"links": []
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"id": "c3",
|
|
42
|
+
"kind": "after_state",
|
|
43
|
+
"text": "A vague idea becomes a claim-based, pressure-tested, buildable spec held in a durable, reloadable artifact whose entities are validated",
|
|
44
|
+
"origin": "user",
|
|
45
|
+
"status": "confirmed",
|
|
46
|
+
"honesty_conditions": [
|
|
47
|
+
{
|
|
48
|
+
"id": "h3",
|
|
49
|
+
"text": "Matches shipped 0.4.0 reality \u2014 converge --json emits {passed, missing} today and no contract doc is committed (verifiable in the repo before relying on it)",
|
|
50
|
+
"status": "confirmed"
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"hard_questions": [],
|
|
54
|
+
"links": []
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "c4",
|
|
58
|
+
"kind": "before_state",
|
|
59
|
+
"text": "Framing state is partly implicit and undocumented; converge returns prose-only advice ({passed, missing}); there is no documented contract an LLM can rely on",
|
|
60
|
+
"origin": "user",
|
|
61
|
+
"status": "confirmed",
|
|
62
|
+
"honesty_conditions": [
|
|
63
|
+
{
|
|
64
|
+
"id": "h4",
|
|
65
|
+
"text": "The contract is enforced by validation on load: a schema-violating frame is rejected with a clear, actionable error rather than silently accepted",
|
|
66
|
+
"status": "confirmed"
|
|
67
|
+
}
|
|
68
|
+
],
|
|
69
|
+
"hard_questions": [],
|
|
70
|
+
"links": []
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": "c5",
|
|
74
|
+
"kind": "why_it_matters",
|
|
75
|
+
"text": "An LLM and devague can only coordinate reliably around a contract that is documented, validated, and machine-readable \u2014 convergence must mean something, not vibes",
|
|
76
|
+
"origin": "user",
|
|
77
|
+
"status": "confirmed",
|
|
78
|
+
"honesty_conditions": [
|
|
79
|
+
{
|
|
80
|
+
"id": "h5",
|
|
81
|
+
"text": "Convergence stays evidence-based and export stays gated on converge passing; the gate is computed only from confirmed claims and confirmed honesty conditions, never a hunch",
|
|
82
|
+
"status": "confirmed"
|
|
83
|
+
}
|
|
84
|
+
],
|
|
85
|
+
"hard_questions": [],
|
|
86
|
+
"links": []
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
"id": "c6",
|
|
90
|
+
"kind": "boundary",
|
|
91
|
+
"text": "Not a full PRD generator and not a fixed wizard; the move-driven, deterministic model stays",
|
|
92
|
+
"origin": "user",
|
|
93
|
+
"status": "confirmed",
|
|
94
|
+
"honesty_conditions": [
|
|
95
|
+
{
|
|
96
|
+
"id": "h6",
|
|
97
|
+
"text": "The deterministic move-driven model is preserved: no fixed prompt sequence is added; the CLI stays a state tracker and the LLM still chooses the next move",
|
|
98
|
+
"status": "confirmed"
|
|
99
|
+
}
|
|
100
|
+
],
|
|
101
|
+
"hard_questions": [],
|
|
102
|
+
"links": []
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"id": "c7",
|
|
106
|
+
"kind": "boundary",
|
|
107
|
+
"text": "The local contract requires no GitHub, agents, or external services",
|
|
108
|
+
"origin": "user",
|
|
109
|
+
"status": "confirmed",
|
|
110
|
+
"honesty_conditions": [
|
|
111
|
+
{
|
|
112
|
+
"id": "h7",
|
|
113
|
+
"text": "Every contract operation (create / load / mutate / show / converge / export) runs fully offline against local .devague/ state with zero network calls",
|
|
114
|
+
"status": "confirmed"
|
|
115
|
+
}
|
|
116
|
+
],
|
|
117
|
+
"hard_questions": [],
|
|
118
|
+
"links": []
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"id": "c8",
|
|
122
|
+
"kind": "boundary",
|
|
123
|
+
"text": "Convergence is never claimed on vibes, and LLM-proposed content is never silently promoted to confirmed truth",
|
|
124
|
+
"origin": "user",
|
|
125
|
+
"status": "confirmed",
|
|
126
|
+
"honesty_conditions": [
|
|
127
|
+
{
|
|
128
|
+
"id": "h8",
|
|
129
|
+
"text": "LLM-proposed claims and honesty conditions persist as proposed (origin=llm) and require an explicit user confirm before they affect convergence \u2014 nothing auto-confirms",
|
|
130
|
+
"status": "confirmed"
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
"hard_questions": [],
|
|
134
|
+
"links": []
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
"id": "c9",
|
|
138
|
+
"kind": "success_signal",
|
|
139
|
+
"text": "converge returns a structured result (ready_for_spec, blockers, warnings, parked_items, required_next_moves) with blockers instead of prose-only advice",
|
|
140
|
+
"origin": "user",
|
|
141
|
+
"status": "confirmed",
|
|
142
|
+
"honesty_conditions": [
|
|
143
|
+
{
|
|
144
|
+
"id": "h9",
|
|
145
|
+
"text": "converge --json emits ONLY the new structured shape {ready_for_spec, blockers, warnings, parked_items, required_next_moves} (hard break); the skill's status helper is updated in the same change; blockers block convergence and warnings do not",
|
|
146
|
+
"status": "confirmed"
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
"hard_questions": [],
|
|
150
|
+
"links": []
|
|
151
|
+
},
|
|
152
|
+
{
|
|
153
|
+
"id": "c10",
|
|
154
|
+
"kind": "success_signal",
|
|
155
|
+
"text": "A documented spec contract exists in the repo, with worked contract examples for at least one feature frame",
|
|
156
|
+
"origin": "user",
|
|
157
|
+
"status": "confirmed",
|
|
158
|
+
"honesty_conditions": [
|
|
159
|
+
{
|
|
160
|
+
"id": "h10",
|
|
161
|
+
"text": "The committed contract doc is the source of truth for kinds / states / fields / transitions and includes at least one worked frame example the CLI can actually round-trip",
|
|
162
|
+
"status": "confirmed"
|
|
163
|
+
}
|
|
164
|
+
],
|
|
165
|
+
"hard_questions": [],
|
|
166
|
+
"links": []
|
|
167
|
+
},
|
|
168
|
+
{
|
|
169
|
+
"id": "c11",
|
|
170
|
+
"kind": "success_signal",
|
|
171
|
+
"text": "The CLI can create, load, mutate, and display a frame locally; core entities are validated",
|
|
172
|
+
"origin": "user",
|
|
173
|
+
"status": "confirmed",
|
|
174
|
+
"honesty_conditions": [
|
|
175
|
+
{
|
|
176
|
+
"id": "h11",
|
|
177
|
+
"text": "create / load / mutate / show round-trip through the JSON store under validation, and the demonstrated operations are covered by passing tests",
|
|
178
|
+
"status": "confirmed"
|
|
179
|
+
}
|
|
180
|
+
],
|
|
181
|
+
"hard_questions": [],
|
|
182
|
+
"links": []
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
"id": "c12",
|
|
186
|
+
"kind": "success_signal",
|
|
187
|
+
"text": "Tests cover claim provenance, honesty-condition confirmation, parking vagueness, and convergence failure",
|
|
188
|
+
"origin": "user",
|
|
189
|
+
"status": "confirmed",
|
|
190
|
+
"honesty_conditions": [
|
|
191
|
+
{
|
|
192
|
+
"id": "h12",
|
|
193
|
+
"text": "Each of the four areas (provenance, honesty-condition confirmation, parking vagueness, convergence failure) has at least one test asserting the contract behavior, all green in CI",
|
|
194
|
+
"status": "confirmed"
|
|
195
|
+
}
|
|
196
|
+
],
|
|
197
|
+
"hard_questions": [],
|
|
198
|
+
"links": []
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
"id": "c13",
|
|
202
|
+
"kind": "boundary",
|
|
203
|
+
"text": "The contract formalizes 0.4.0's shipped vocabulary as canonical \u2014 state in {proposed,confirmed,rejected,parked} x origin in {user,llm}; no rename and no migration of existing frames",
|
|
204
|
+
"origin": "user",
|
|
205
|
+
"status": "confirmed",
|
|
206
|
+
"honesty_conditions": [
|
|
207
|
+
{
|
|
208
|
+
"id": "h13",
|
|
209
|
+
"text": "The doc maps the issue's proposed names (llm_proposed, user_confirmed, intentionally_out_of_scope, ...) onto the shipped (state x origin) model so no information is lost and no rename is required",
|
|
210
|
+
"status": "confirmed"
|
|
211
|
+
}
|
|
212
|
+
],
|
|
213
|
+
"hard_questions": [],
|
|
214
|
+
"links": []
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
"id": "c14",
|
|
218
|
+
"kind": "success_signal",
|
|
219
|
+
"text": "The claim-type vocabulary adds non_goal, requirement, assumption, and decision to the shipped set, each with a documented convergence-gate impact",
|
|
220
|
+
"origin": "user",
|
|
221
|
+
"status": "confirmed",
|
|
222
|
+
"honesty_conditions": [
|
|
223
|
+
{
|
|
224
|
+
"id": "h14",
|
|
225
|
+
"text": "Each new type's gate impact is documented and tested: requirement is spec-affecting (needs a confirmed honesty condition like other claims); non_goal and decision are descriptive (non-blocking); an unconfirmed assumption surfaces as a warning, not a blocker",
|
|
226
|
+
"status": "confirmed"
|
|
227
|
+
}
|
|
228
|
+
],
|
|
229
|
+
"hard_questions": [],
|
|
230
|
+
"links": []
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"id": "c15",
|
|
234
|
+
"kind": "success_signal",
|
|
235
|
+
"text": "Every frame carries a schema_version field; load validates by version so existing frames keep loading as the schema grows",
|
|
236
|
+
"origin": "user",
|
|
237
|
+
"status": "confirmed",
|
|
238
|
+
"honesty_conditions": [
|
|
239
|
+
{
|
|
240
|
+
"id": "h15",
|
|
241
|
+
"text": "schema_version is written on every save and checked on load; an unknown or newer version fails closed with a clear error rather than corrupting state",
|
|
242
|
+
"status": "confirmed"
|
|
243
|
+
}
|
|
244
|
+
],
|
|
245
|
+
"hard_questions": [],
|
|
246
|
+
"links": []
|
|
247
|
+
}
|
|
248
|
+
],
|
|
249
|
+
"open_vagueness": [
|
|
250
|
+
{
|
|
251
|
+
"id": "v1",
|
|
252
|
+
"text": "Whether to also publish a formal machine-readable JSON Schema file alongside the prose contract doc + dataclasses, or treat the dataclasses as the schema of record",
|
|
253
|
+
"kind": "follow_up",
|
|
254
|
+
"claim_id": null
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"id": "v2",
|
|
258
|
+
"text": "Whether requirement-type claims should eventually carry acceptance criteria like plan tasks do (overlaps the spec-to-plan leg), or stay prose-only in the frame",
|
|
259
|
+
"kind": "follow_up",
|
|
260
|
+
"claim_id": null
|
|
261
|
+
}
|
|
262
|
+
]
|
|
263
|
+
}
|