devague 0.4.1__tar.gz → 0.5.1__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.1 → devague-0.5.1}/.claude/skills/spec-to-plan/scripts/spec-to-plan.sh +13 -41
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/think/SKILL.md +16 -12
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/think/scripts/think.sh +13 -47
- devague-0.5.1/.devague/current_plan +1 -0
- devague-0.5.1/.devague/frames/devague-0-6-0-ships-the-human-review-loop-devague.json +299 -0
- devague-0.5.1/.devague/plans/devague-0-6-0-ships-the-human-review-loop-devague.json +288 -0
- {devague-0.4.1 → devague-0.5.1}/CHANGELOG.md +25 -0
- {devague-0.4.1 → devague-0.5.1}/CLAUDE.md +9 -0
- {devague-0.4.1 → devague-0.5.1}/PKG-INFO +1 -1
- {devague-0.4.1 → devague-0.5.1}/culture.yaml +1 -1
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/capture.py +9 -1
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/converge.py +18 -7
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/export.py +2 -2
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/plan.py +20 -12
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_frames.py +16 -1
- devague-0.5.1/devague/convergence.py +149 -0
- {devague-0.4.1 → devague-0.5.1}/devague/frame.py +45 -1
- {devague-0.4.1 → devague-0.5.1}/devague/plan_convergence.py +47 -3
- {devague-0.4.1 → devague-0.5.1}/devague/render/frame_md.py +5 -1
- devague-0.5.1/devague/render/spec_md.py +61 -0
- {devague-0.4.1 → devague-0.5.1}/devague/store.py +11 -1
- devague-0.5.1/docs/examples/contract-example.json +160 -0
- devague-0.5.1/docs/plans/devague-0-6-0-ships-the-human-review-loop-devague.md +71 -0
- devague-0.5.1/docs/spec-contract.md +180 -0
- devague-0.5.1/docs/specs/devague-0-6-0-ships-the-human-review-loop-devague.md +54 -0
- {devague-0.4.1 → devague-0.5.1}/pyproject.toml +1 -1
- {devague-0.4.1 → devague-0.5.1}/tests/test_cli_converge_export.py +7 -7
- {devague-0.4.1 → devague-0.5.1}/tests/test_cli_moves.py +27 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_cli_plan.py +2 -2
- devague-0.5.1/tests/test_contract.py +129 -0
- devague-0.5.1/tests/test_convergence.py +97 -0
- devague-0.5.1/tests/test_frame.py +111 -0
- devague-0.5.1/tests/test_offline.py +58 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_plan_convergence.py +14 -14
- {devague-0.4.1 → devague-0.5.1}/tests/test_render.py +44 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_store.py +43 -1
- {devague-0.4.1 → devague-0.5.1}/uv.lock +1 -1
- devague-0.4.1/.devague/current_plan +0 -1
- devague-0.4.1/devague/convergence.py +0 -72
- devague-0.4.1/devague/render/spec_md.py +0 -50
- devague-0.4.1/tests/test_convergence.py +0 -62
- devague-0.4.1/tests/test_frame.py +0 -42
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/cicd/SKILL.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/cicd/scripts/_resolve-nick.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/cicd/scripts/portability-lint.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/cicd/scripts/pr-reply.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/cicd/scripts/pr-status.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/cicd/scripts/workflow.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/communicate/SKILL.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/communicate/scripts/fetch-issues.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/communicate/scripts/mesh-message.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/communicate/scripts/post-comment.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/communicate/scripts/post-issue.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/communicate/scripts/templates/skill-update-brief.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/doc-test-alignment/SKILL.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/doc-test-alignment/scripts/check.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/run-tests/SKILL.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/run-tests/scripts/test.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/sonarclaude/SKILL.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/sonarclaude/scripts/sonar.sh +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/spec-to-plan/SKILL.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/version-bump/SKILL.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills/version-bump/scripts/bump.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/.claude/skills.local.yaml.example +0 -0
- {devague-0.4.1 → devague-0.5.1}/.devague/frames/devague-now-ships-a-documented-spec-contract-every.json +0 -0
- {devague-0.4.1 → devague-0.5.1}/.devague/plans/devague-now-ships-a-documented-spec-contract-every.json +0 -0
- {devague-0.4.1 → devague-0.5.1}/.flake8 +0 -0
- {devague-0.4.1 → devague-0.5.1}/.github/workflows/publish.yml +0 -0
- {devague-0.4.1 → devague-0.5.1}/.github/workflows/security-checks.yml +0 -0
- {devague-0.4.1 → devague-0.5.1}/.github/workflows/tests.yml +0 -0
- {devague-0.4.1 → devague-0.5.1}/.gitignore +0 -0
- {devague-0.4.1 → devague-0.5.1}/.markdownlint-cli2.yaml +0 -0
- {devague-0.4.1 → devague-0.5.1}/.pre-commit-config.yaml +0 -0
- {devague-0.4.1 → devague-0.5.1}/LICENSE +0 -0
- {devague-0.4.1 → devague-0.5.1}/README.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/__init__.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/__main__.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/__init__.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/__init__.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/confirm.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/explain.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/interrogate.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/learn.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/list_frames.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/new.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/park.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/reject.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_commands/show.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_errors.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_output.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/cli/_plans.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/plan.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/plan_store.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/render/__init__.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/devague/render/plan_md.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/docs/plans/devague-now-ships-a-documented-spec-contract-every.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/docs/reviews/spec-contract-frame-review.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/docs/skill-sources.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/docs/specs/devague-now-ships-a-documented-spec-contract-every.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/docs/superpowers/plans/2026-05-22-specifix-onboarding.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/docs/superpowers/plans/2026-05-23-devague-rename.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/docs/superpowers/plans/2026-05-23-devague-working-backwards-engine.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/docs/superpowers/specs/2026-05-22-specifix-onboarding-design.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/docs/superpowers/specs/2026-05-23-devague-spec-to-plan-design.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/docs/superpowers/specs/2026-05-23-devague-working-backwards-design.md +0 -0
- {devague-0.4.1 → devague-0.5.1}/sonar-project.properties +0 -0
- {devague-0.4.1 → devague-0.5.1}/tests/__init__.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_cli_affordances.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_cli_chassis.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_cli_errors.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_cli_output.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_package.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_plan.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_plan_store.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_render_plan.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/tests/test_spec_to_plan_skill.py +0 -0
- {devague-0.4.1 → devague-0.5.1}/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)
|
|
@@ -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-0-6-0-ships-the-human-review-loop-devague
|
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
{
|
|
2
|
+
"slug": "devague-0-6-0-ships-the-human-review-loop-devague",
|
|
3
|
+
"title": "devague 0.6.0 ships the Human Review Loop: 'devague review' surfaces every unconfirmed LLM proposal in one pass, and confirm/reject now take many ids at once \u2014 so honest human review scales to frames full of proposals without ever auto-confirming anything.",
|
|
4
|
+
"schema_version": 1,
|
|
5
|
+
"status": "exported",
|
|
6
|
+
"created": "2026-05-23T11:07:38Z",
|
|
7
|
+
"updated": "2026-05-23T11:24:24Z",
|
|
8
|
+
"claims": [
|
|
9
|
+
{
|
|
10
|
+
"id": "c1",
|
|
11
|
+
"kind": "announcement",
|
|
12
|
+
"text": "devague 0.6.0 ships the Human Review Loop: 'devague review' surfaces every unconfirmed LLM proposal in one pass, and confirm/reject now take many ids at once \u2014 so honest human review scales to frames full of proposals without ever auto-confirming anything.",
|
|
13
|
+
"origin": "user",
|
|
14
|
+
"status": "confirmed",
|
|
15
|
+
"honesty_conditions": [
|
|
16
|
+
{
|
|
17
|
+
"id": "h6",
|
|
18
|
+
"text": "At 0.6.0 release the announcement is literally true of the shipped CLI: 'devague review' exists, and a frame full of proposed items can be reviewed then bulk confirmed/rejected in one pass with no path that auto-confirms.",
|
|
19
|
+
"status": "confirmed"
|
|
20
|
+
}
|
|
21
|
+
],
|
|
22
|
+
"hard_questions": [],
|
|
23
|
+
"links": []
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
"id": "c2",
|
|
27
|
+
"kind": "audience",
|
|
28
|
+
"text": "The human operator driving devague who must review and confirm/reject LLM-proposed claims and honesty conditions, plus the assisting LLM agent that produces those proposals.",
|
|
29
|
+
"origin": "user",
|
|
30
|
+
"status": "confirmed",
|
|
31
|
+
"honesty_conditions": [
|
|
32
|
+
{
|
|
33
|
+
"id": "h7",
|
|
34
|
+
"text": "Both audiences are served: the operator gets a single review + bulk-decide path, and the LLM agent's proposals stay visibly 'proposed' until the operator explicitly acts.",
|
|
35
|
+
"status": "confirmed"
|
|
36
|
+
}
|
|
37
|
+
],
|
|
38
|
+
"hard_questions": [],
|
|
39
|
+
"links": []
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "c3",
|
|
43
|
+
"kind": "after_state",
|
|
44
|
+
"text": "In one pass the operator sees every unconfirmed proposal (proposed claims + proposed honesty conditions) without the frame needing to converge, then confirms or rejects many in a single command; pending design questions persist as durable .devague working state to decide later.",
|
|
45
|
+
"origin": "user",
|
|
46
|
+
"status": "confirmed",
|
|
47
|
+
"honesty_conditions": [
|
|
48
|
+
{
|
|
49
|
+
"id": "h8",
|
|
50
|
+
"text": "On a non-converged frame, one 'review' shows every proposed item and one 'confirm'/'reject' call resolves a chosen set \u2014 demonstrable end-to-end in a test.",
|
|
51
|
+
"status": "confirmed"
|
|
52
|
+
}
|
|
53
|
+
],
|
|
54
|
+
"hard_questions": [],
|
|
55
|
+
"links": []
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
"id": "c4",
|
|
59
|
+
"kind": "before_state",
|
|
60
|
+
"text": "Review was ad-hoc (hand-rolled from show / show --json) and confirmation was one id per command, so a frame with ~15 proposed conditions meant 15 sequential commands \u2014 pushing toward rubber-stamping instead of genuine review (surfaced dogfooding /think on #5).",
|
|
61
|
+
"origin": "user",
|
|
62
|
+
"status": "confirmed",
|
|
63
|
+
"honesty_conditions": [
|
|
64
|
+
{
|
|
65
|
+
"id": "h9",
|
|
66
|
+
"text": "The before-state pain is real and removed: the pre-0.6.0 flow needed N commands for N conditions with no review artifact; 0.6.0 replaces that with one review plus one bulk decision.",
|
|
67
|
+
"status": "confirmed"
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
"hard_questions": [],
|
|
71
|
+
"links": []
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"id": "c5",
|
|
75
|
+
"kind": "why_it_matters",
|
|
76
|
+
"text": "The user-only confirmation step is devague's whole anti-fabrication guarantee; it must be ergonomic enough to do honestly at scale and support out-of-band review (read proposals somewhere comfortable like NotebookLM or a shared doc, then apply decisions), or it gets skipped or rubber-stamped.",
|
|
77
|
+
"origin": "user",
|
|
78
|
+
"status": "confirmed",
|
|
79
|
+
"honesty_conditions": [
|
|
80
|
+
{
|
|
81
|
+
"id": "h10",
|
|
82
|
+
"text": "The anti-fabrication guarantee is preserved exactly: ergonomics improve but no proposal becomes authoritative without an explicit user action, asserted by test.",
|
|
83
|
+
"status": "confirmed"
|
|
84
|
+
}
|
|
85
|
+
],
|
|
86
|
+
"hard_questions": [],
|
|
87
|
+
"links": []
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"id": "c6",
|
|
91
|
+
"kind": "success_signal",
|
|
92
|
+
"text": "A frame with many proposed items is reviewed and resolved in a single 'devague review' plus one batched confirm/reject, and the test suite proves: review export works before convergence, multi-id confirm/reject works, and no review-flow command auto-confirms a proposal.",
|
|
93
|
+
"origin": "user",
|
|
94
|
+
"status": "confirmed",
|
|
95
|
+
"honesty_conditions": [
|
|
96
|
+
{
|
|
97
|
+
"id": "h11",
|
|
98
|
+
"text": "The success signals are verified by the committed test suite, not asserted by hand.",
|
|
99
|
+
"status": "confirmed"
|
|
100
|
+
}
|
|
101
|
+
],
|
|
102
|
+
"hard_questions": [],
|
|
103
|
+
"links": []
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
"id": "c7",
|
|
107
|
+
"kind": "boundary",
|
|
108
|
+
"text": "Scope is the review/confirm UX layered over the existing proposed-vs-confirmed contract (#5/#16); it does not change the state model itself \u2014 proposals still only become authoritative by explicit user action.",
|
|
109
|
+
"origin": "user",
|
|
110
|
+
"status": "confirmed",
|
|
111
|
+
"honesty_conditions": [
|
|
112
|
+
{
|
|
113
|
+
"id": "h12",
|
|
114
|
+
"text": "0.6.0 adds only review/confirm UX; the proposed-vs-confirmed state model and convergence gate from #5/#16 are unchanged \u2014 no new claim or condition states are introduced.",
|
|
115
|
+
"status": "confirmed"
|
|
116
|
+
}
|
|
117
|
+
],
|
|
118
|
+
"hard_questions": [],
|
|
119
|
+
"links": []
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"id": "c8",
|
|
123
|
+
"kind": "non_goal",
|
|
124
|
+
"text": "Does not generate a polished buildable spec from unconfirmed review output \u2014 review output stays explicitly non-authoritative, distinct from what 'export' produces post-convergence.",
|
|
125
|
+
"origin": "user",
|
|
126
|
+
"status": "confirmed",
|
|
127
|
+
"honesty_conditions": [],
|
|
128
|
+
"hard_questions": [],
|
|
129
|
+
"links": []
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"id": "c9",
|
|
133
|
+
"kind": "non_goal",
|
|
134
|
+
"text": "Does not auto-resolve questions and does not auto-confirm any LLM-proposed content anywhere in the review flow.",
|
|
135
|
+
"origin": "user",
|
|
136
|
+
"status": "confirmed",
|
|
137
|
+
"honesty_conditions": [],
|
|
138
|
+
"hard_questions": [],
|
|
139
|
+
"links": []
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"id": "c10",
|
|
143
|
+
"kind": "non_goal",
|
|
144
|
+
"text": "The CLI does not call an LLM.",
|
|
145
|
+
"origin": "user",
|
|
146
|
+
"status": "confirmed",
|
|
147
|
+
"honesty_conditions": [],
|
|
148
|
+
"hard_questions": [],
|
|
149
|
+
"links": []
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"id": "c11",
|
|
153
|
+
"kind": "non_goal",
|
|
154
|
+
"text": "Does not require GitHub, NotebookLM, or any external service.",
|
|
155
|
+
"origin": "user",
|
|
156
|
+
"status": "confirmed",
|
|
157
|
+
"honesty_conditions": [],
|
|
158
|
+
"hard_questions": [],
|
|
159
|
+
"links": []
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
"id": "c12",
|
|
163
|
+
"kind": "requirement",
|
|
164
|
+
"text": "'devague review' (and 'devague review --json') emits all proposed claims and proposed honesty conditions, with their ids, without requiring or triggering convergence.",
|
|
165
|
+
"origin": "user",
|
|
166
|
+
"status": "confirmed",
|
|
167
|
+
"honesty_conditions": [
|
|
168
|
+
{
|
|
169
|
+
"id": "h1",
|
|
170
|
+
"text": "Running 'devague review' on a frame that has NOT converged still exits 0 and lists every proposed claim and proposed honesty condition with ids; it never invokes the convergence gate nor mutates any claim/condition state.",
|
|
171
|
+
"status": "confirmed"
|
|
172
|
+
}
|
|
173
|
+
],
|
|
174
|
+
"hard_questions": [],
|
|
175
|
+
"links": []
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"id": "c13",
|
|
179
|
+
"kind": "requirement",
|
|
180
|
+
"text": "Review output is clearly labelled unconfirmed and non-authoritative, visually distinct from the buildable spec that 'export' produces only after convergence.",
|
|
181
|
+
"origin": "user",
|
|
182
|
+
"status": "confirmed",
|
|
183
|
+
"honesty_conditions": [
|
|
184
|
+
{
|
|
185
|
+
"id": "h2",
|
|
186
|
+
"text": "The review artifact carries an explicit 'nothing confirmed yet \u2014 non-authoritative' banner and is written to a path under .devague/reviews/<slug>.md, distinct from docs/specs/, so it cannot be mistaken for the buildable spec.",
|
|
187
|
+
"status": "confirmed"
|
|
188
|
+
}
|
|
189
|
+
],
|
|
190
|
+
"hard_questions": [],
|
|
191
|
+
"links": []
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
"id": "c14",
|
|
195
|
+
"kind": "requirement",
|
|
196
|
+
"text": "'devague confirm' accepts multiple claim/honesty ids in one invocation, and 'devague reject' likewise.",
|
|
197
|
+
"origin": "user",
|
|
198
|
+
"status": "confirmed",
|
|
199
|
+
"honesty_conditions": [
|
|
200
|
+
{
|
|
201
|
+
"id": "h3",
|
|
202
|
+
"text": "'devague confirm a b c' resolves every listed id in a single call (and 'reject a b c' likewise), and the handling of a batch containing an invalid/unknown id follows one defined, tested rule.",
|
|
203
|
+
"status": "confirmed"
|
|
204
|
+
}
|
|
205
|
+
],
|
|
206
|
+
"hard_questions": [],
|
|
207
|
+
"links": []
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"id": "c15",
|
|
211
|
+
"kind": "requirement",
|
|
212
|
+
"text": "Open questions / pending user decisions can be written as durable .devague working state (e.g. .devague/questions/<slug>.md), treated as uncommitted working state by default unless the user intentionally promotes one into docs.",
|
|
213
|
+
"origin": "user",
|
|
214
|
+
"status": "confirmed",
|
|
215
|
+
"honesty_conditions": [
|
|
216
|
+
{
|
|
217
|
+
"id": "h4",
|
|
218
|
+
"text": "A pending question the CLI writes persists across runs under .devague/questions/<slug>.md, is treated as uncommitted working state by default, and a documented path exists to apply a confirmed decision back into the frame.",
|
|
219
|
+
"status": "confirmed"
|
|
220
|
+
}
|
|
221
|
+
],
|
|
222
|
+
"hard_questions": [],
|
|
223
|
+
"links": []
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
"id": "c16",
|
|
227
|
+
"kind": "requirement",
|
|
228
|
+
"text": "No command in the review flow auto-confirms LLM-proposed content; every confirm/reject stays an explicit user action.",
|
|
229
|
+
"origin": "user",
|
|
230
|
+
"status": "confirmed",
|
|
231
|
+
"honesty_conditions": [
|
|
232
|
+
{
|
|
233
|
+
"id": "h5",
|
|
234
|
+
"text": "An automated test asserts that no review-flow command (review, multi-id confirm/reject, any --json path) transitions an llm-origin proposed item to confirmed without an explicit user confirm naming that id.",
|
|
235
|
+
"status": "confirmed"
|
|
236
|
+
}
|
|
237
|
+
],
|
|
238
|
+
"hard_questions": [],
|
|
239
|
+
"links": []
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"id": "c17",
|
|
243
|
+
"kind": "decision",
|
|
244
|
+
"text": "Batch confirm/reject is TRANSACTIONAL: validate all ids first; if any id is unknown/invalid, resolve none and exit non-zero with a hint \u2014 never a half-applied batch.",
|
|
245
|
+
"origin": "user",
|
|
246
|
+
"status": "confirmed",
|
|
247
|
+
"honesty_conditions": [],
|
|
248
|
+
"hard_questions": [],
|
|
249
|
+
"links": []
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
"id": "c18",
|
|
253
|
+
"kind": "decision",
|
|
254
|
+
"text": "'devague confirm --from-review <file>' IS in scope for 0.6.0: it parses a reviewed decision set (confirm/reject per id) from the review artifact and applies it, so the review artifact format must be documented and round-trippable.",
|
|
255
|
+
"origin": "user",
|
|
256
|
+
"status": "confirmed",
|
|
257
|
+
"honesty_conditions": [],
|
|
258
|
+
"hard_questions": [],
|
|
259
|
+
"links": []
|
|
260
|
+
},
|
|
261
|
+
{
|
|
262
|
+
"id": "c19",
|
|
263
|
+
"kind": "decision",
|
|
264
|
+
"text": "devague manages .gitignore: it ensures .devague/reviews/ and .devague/questions/ are git-ignored so review/question state is uncommitted working state by default; the user opts in to promote one into docs.",
|
|
265
|
+
"origin": "user",
|
|
266
|
+
"status": "confirmed",
|
|
267
|
+
"honesty_conditions": [],
|
|
268
|
+
"hard_questions": [],
|
|
269
|
+
"links": []
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
"id": "c20",
|
|
273
|
+
"kind": "decision",
|
|
274
|
+
"text": "Pending questions/decisions are produced by a CLI move that writes .devague/questions/<slug>.md and owns the format (first-class + unit-testable), not a hand-written skill artifact.",
|
|
275
|
+
"origin": "user",
|
|
276
|
+
"status": "confirmed",
|
|
277
|
+
"honesty_conditions": [],
|
|
278
|
+
"hard_questions": [],
|
|
279
|
+
"links": []
|
|
280
|
+
},
|
|
281
|
+
{
|
|
282
|
+
"id": "c21",
|
|
283
|
+
"kind": "requirement",
|
|
284
|
+
"text": "'devague confirm --from-review <file>' applies a reviewed decision set parsed from the review artifact; the artifact 'devague review' emits is documented and round-trippable (review -> edit decisions -> apply).",
|
|
285
|
+
"origin": "user",
|
|
286
|
+
"status": "confirmed",
|
|
287
|
+
"honesty_conditions": [
|
|
288
|
+
{
|
|
289
|
+
"id": "h13",
|
|
290
|
+
"text": "A review artifact emitted by 'devague review' can be edited with confirm/reject decisions and fed to 'devague confirm --from-review <file>' to apply exactly those decisions \u2014 proven by a round-trip test \u2014 and applying it still auto-confirms nothing the file did not mark confirmed.",
|
|
291
|
+
"status": "confirmed"
|
|
292
|
+
}
|
|
293
|
+
],
|
|
294
|
+
"hard_questions": [],
|
|
295
|
+
"links": []
|
|
296
|
+
}
|
|
297
|
+
],
|
|
298
|
+
"open_vagueness": []
|
|
299
|
+
}
|