deepclause-pi 0.2.0 → 0.4.0
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.
- package/README.md +13 -0
- package/dist/config.d.ts +22 -0
- package/dist/config.js +60 -0
- package/dist/diagram/viewer.d.ts +6 -0
- package/dist/diagram/viewer.js +5 -0
- package/dist/index.d.ts +9 -1
- package/dist/index.js +423 -22
- package/dist/planner.d.ts +27 -2
- package/dist/planner.js +109 -4
- package/dist/runtime.d.ts +17 -1
- package/dist/runtime.js +139 -4
- package/dist/workspace.d.ts +3 -0
- package/dist/workspace.js +20 -0
- package/docs/SPECKIT.md +232 -0
- package/docs/SPEC_LAYER_PROPOSAL.md +1893 -0
- package/package.json +2 -2
- package/src/assets/AGENTS.md +66 -0
- package/src/assets/apply.dml +188 -0
- package/src/assets/spec_apply.dml +20 -0
- package/src/assets/spec_archive.dml +11 -0
- package/src/assets/spec_coverage.dml +26 -0
- package/src/assets/spec_graph.dml +12 -0
- package/src/assets/spec_merge.dml +10 -0
- package/src/assets/spec_query.dml +10 -0
- package/src/assets/spec_scaffold.dml +10 -0
- package/src/assets/spec_status.dml +7 -0
- package/src/assets/spec_validate.dml +9 -0
- package/src/assets/specs.dml +995 -0
- package/src/config.ts +91 -0
- package/src/diagram/viewer.ts +11 -0
- package/src/index.ts +454 -20
- package/src/planner.ts +123 -3
- package/src/runtime.ts +147 -4
- package/src/workspace.ts +24 -0
package/docs/SPECKIT.md
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# deepclause-pi speckit
|
|
2
|
+
|
|
3
|
+
Spec-driven changes for pi, without leaving the session.
|
|
4
|
+
|
|
5
|
+
`deepclause-pi speckit` adds a lightweight spec layer on top of the [DeepClause](https://github.com/deepclause/deepclause-sdk) runtime in pi:
|
|
6
|
+
|
|
7
|
+
- **Specs describe behaviour.** Plain Markdown under `.pi/deepclause/specs/` is the source of truth.
|
|
8
|
+
- **A change is a reviewed proposal.** `.pi/deepclause/changes/<slug>/` holds a proposal, delta specs, optional design notes, and an executable task plan.
|
|
9
|
+
- **Only the model touches prose.** Parsing, validation, merging, coverage, verification and rollback are deterministic DML — no model calls.
|
|
10
|
+
- **Nothing lands silently.** Every step that writes or executes is a gated, reviewable command.
|
|
11
|
+
|
|
12
|
+
```text
|
|
13
|
+
/dc-plan <request> --change=<slug> propose
|
|
14
|
+
/dc-check <slug> validate (0 tokens)
|
|
15
|
+
/dc-apply <slug> execute, verify, retry, resume
|
|
16
|
+
/dc-archive <slug> merge into specs/
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Why DML and DeepClause for spec-driven development
|
|
20
|
+
|
|
21
|
+
Most spec tools are a Markdown convention plus a program that parses it. The convention is the good idea; the program is where it gets fragile, because parsing, validating and merging structured text is usually written as regexes and imperative branches. OpenSpec, for example, needs a few thousand lines of TypeScript for what is essentially parsing requirements, checking coverage, and reconciling deltas — and its own docs warn about silent failures such as a scenario written with three hashes instead of four.
|
|
22
|
+
|
|
23
|
+
Spec work is logic. A requirement is a term; *every requirement has at least one scenario* is a rule; merging a delta is matching and rewriting; *which scenarios are uncovered?* and *do two in-flight changes touch the same requirement?* are queries. DML is a Prolog dialect, so these are expressed directly instead of emulated. Structure is parsed once into terms, so validation is a decision procedure with line numbers, merging preserves untouched blocks, and coverage and conflict checks are single queries — deterministic, zero tokens, reproducible in CI.
|
|
24
|
+
|
|
25
|
+
That determinism is the point. The value of agreeing on a spec is that the agreement is *checkable*; if the check is another model call, it is just another opinion. DML lets the model do what it is good at — drafting requirements, designing, implementing — and keeps correctness in logic. The same runtime supplies what raw Prolog lacks: `task/N` and `prompt/N` for bounded model calls with typed results, `exec/2` for tools, streaming events, cancellation, and usage accounting. Backtracking across model calls is what makes verify → repair → retry loops natural, and CLP(FD)/(Q)/(R) cover hard constraints instead of asking the model to do arithmetic.
|
|
26
|
+
|
|
27
|
+
DeepClause is what makes that practical inside pi: DML programs run with pi's active model, credentials, session context and approvals, so the spec engine, the task plan (`tasks.dml`), and the execution loop are one system in the session you already work in, rather than a separate CLI. You keep human-readable Markdown specs, but the thing enforcing them is a proof, not a prompt.
|
|
28
|
+
|
|
29
|
+
## Requirements
|
|
30
|
+
|
|
31
|
+
- pi with this extension installed (see the [README](../README.md#install)).
|
|
32
|
+
- Node.js 22+.
|
|
33
|
+
- Git, for apply snapshots and resumable/rollback behaviour. Without it everything still works, but the apply report says `rollback: unavailable`.
|
|
34
|
+
|
|
35
|
+
## Getting started
|
|
36
|
+
|
|
37
|
+
### A new project
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
git init
|
|
41
|
+
printf 'node_modules/\ndist/\n' > .gitignore
|
|
42
|
+
git add -A && git commit -m "init"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Then in pi, once, to seed the workspace:
|
|
46
|
+
|
|
47
|
+
```text
|
|
48
|
+
/dc
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Describe the first feature as a change:
|
|
52
|
+
|
|
53
|
+
```text
|
|
54
|
+
/dc-plan build a URL shortener with slugs and click counts --change=url_shortener
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Pi creates:
|
|
58
|
+
|
|
59
|
+
```text
|
|
60
|
+
.pi/deepclause/changes/url_shortener/
|
|
61
|
+
├── proposal.md # why / what / capabilities / impact
|
|
62
|
+
├── specs/shortener/links.spec.md # ## Purpose + ## ADDED Requirements + scenarios
|
|
63
|
+
├── design.md # approach (optional)
|
|
64
|
+
└── tasks.dml # one plan_task per step, with checks
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Commit the plan, then run it:
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
git add -A && git commit -m "plan: url_shortener"
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
```text
|
|
74
|
+
/dc-check url_shortener # grammar, delta, scenario coverage
|
|
75
|
+
/dc-apply url_shortener # shows the tasks and the exact command set → confirm
|
|
76
|
+
/dc-archive url_shortener # shows the merge diff → confirm
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
Archiving creates `specs/shortener/links.spec.md` and moves the change to `changes/archive/`. That is the bootstrap: **conversation → change → applied → spec.**
|
|
80
|
+
|
|
81
|
+
Every later feature is the same loop, but pi now reads the existing specs first and writes `## MODIFIED Requirements` when it changes behaviour that already exists.
|
|
82
|
+
|
|
83
|
+
### An existing project
|
|
84
|
+
|
|
85
|
+
There is no code-scanning onboarding yet. Two practical routes:
|
|
86
|
+
|
|
87
|
+
1. **Hand-write the first specs.** Create `specs/<capability>.spec.md` for behaviour you care about, then run `/dc-check` to validate it. This is often the fastest way to capture a system you already understand.
|
|
88
|
+
2. **Document as you go.** Use `/dc-plan ... --change=<slug>` for the next real change. Describe the current behaviour you are building on as `## ADDED Requirements` if it is not yet captured, or trust the code and only specify the new behaviour.
|
|
89
|
+
|
|
90
|
+
Either way, `specs/` grows one reviewed change at a time.
|
|
91
|
+
|
|
92
|
+
## Command reference
|
|
93
|
+
|
|
94
|
+
| Command | Effect |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `/dc` | Status: model, paths, context mode, runtime state |
|
|
97
|
+
| `/dc-list` | Skills, plans, specs and changes |
|
|
98
|
+
| `/dc-plan <request> [--name=slug]` | Standalone executable plan under `plans/` |
|
|
99
|
+
| `/dc-plan <request> --change=<slug>` | Change plan: proposal + delta specs + `tasks.dml` |
|
|
100
|
+
| `/dc-plan update --change=<slug> <request>` | Regenerate a change plan (`tasks.dml` statuses reset to pending) |
|
|
101
|
+
| `/dc-check` | Validate every spec, delta and coverage hole (0 tokens) |
|
|
102
|
+
| `/dc-apply <change>` | Execute tasks; verify, retry, resume |
|
|
103
|
+
| `/dc-apply <change> --abort` | Discard an interrupted apply and restore the snapshot |
|
|
104
|
+
| `/dc-archive <change>` | Merge the delta into `specs/` and move the change to `archive/` |
|
|
105
|
+
| `/dc-run <skill> [args]` | Run any DML skill, e.g. `spec_status`, `spec_query ui/theme` |
|
|
106
|
+
| `/dc-cancel` | Cancel the active execution |
|
|
107
|
+
| `/dc-tool enable\|disable\|status` | Control the model-callable `dc_run` tool |
|
|
108
|
+
|
|
109
|
+
`/dc-run` refuses skills marked `% Mutating: true` (`spec_apply`, `spec_archive`) so that mutating steps always go through the reviewed `/dc-apply` and `/dc-archive` paths.
|
|
110
|
+
|
|
111
|
+
### Read-only helpers
|
|
112
|
+
|
|
113
|
+
```text
|
|
114
|
+
/dc-run spec_status # capability + delta inventory
|
|
115
|
+
/dc-run spec_query ui/theme # one capability's requirements and scenarios
|
|
116
|
+
/dc-run spec_coverage url_shortener # uncovered scenarios, tasks without checks
|
|
117
|
+
/dc-run spec_merge url_shortener # merge preview
|
|
118
|
+
/dc-run spec_scaffold url_shortener # draft tasks.dml text
|
|
119
|
+
/dc-run spec_graph capabilities # Mermaid graph
|
|
120
|
+
/dc-run spec_graph changes
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Ask pi for "the graph of capabilities and changes" and it calls `dc_spec_graph`, which renders the graph in the same offline Mermaid viewer as `dc_diagram`.
|
|
124
|
+
|
|
125
|
+
## Files
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
.pi/deepclause/
|
|
129
|
+
├── specs/<capability>.spec.md behaviour, source of truth
|
|
130
|
+
├── changes/<slug>/
|
|
131
|
+
│ ├── proposal.md why / what / impact
|
|
132
|
+
│ ├── specs/<capability>.spec.md delta (ADDED / MODIFIED / REMOVED)
|
|
133
|
+
│ ├── design.md approach (optional)
|
|
134
|
+
│ ├── tasks.dml plan_task/2 + plan_task_status/2
|
|
135
|
+
│ └── change.json apply snapshot + applyState
|
|
136
|
+
├── changes/archive/<date>-<slug>/
|
|
137
|
+
├── lib/specs.dml parser, validator, merger, coverage
|
|
138
|
+
├── lib/apply.dml task driver
|
|
139
|
+
└── skills/spec_*.dml
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## Writing specs
|
|
143
|
+
|
|
144
|
+
A capability spec:
|
|
145
|
+
|
|
146
|
+
```markdown
|
|
147
|
+
# Theme Specification
|
|
148
|
+
|
|
149
|
+
## Purpose
|
|
150
|
+
Lets users choose between light and dark themes, defaulting to the OS preference.
|
|
151
|
+
|
|
152
|
+
## Requirements
|
|
153
|
+
|
|
154
|
+
### Requirement: Theme selection
|
|
155
|
+
The app SHALL let users switch between light and dark themes at runtime.
|
|
156
|
+
|
|
157
|
+
#### Scenario: User toggles dark mode
|
|
158
|
+
- **WHEN** the user clicks the theme toggle
|
|
159
|
+
- **THEN** the app switches to dark mode and persists the choice
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Rules the validator enforces:
|
|
163
|
+
|
|
164
|
+
- exactly **three** hashes for `### Requirement:` and **four** for `#### Scenario:` (the classic silent failure);
|
|
165
|
+
- every requirement has at least one scenario;
|
|
166
|
+
- no duplicate requirement names;
|
|
167
|
+
- specs are behaviour only — no commands, file paths, library choices, or task lists.
|
|
168
|
+
|
|
169
|
+
A delta wraps requirements in `## ADDED Requirements`, `## MODIFIED Requirements`, `## REMOVED Requirements` or `## RENAMED Requirements`:
|
|
170
|
+
|
|
171
|
+
- `MODIFIED` carries the **full** replacement requirement;
|
|
172
|
+
- `MODIFIED`/`REMOVED` must name a requirement that exists in the target spec (otherwise `/dc-archive` refuses rather than silently dropping it);
|
|
173
|
+
- a brand-new capability may only `ADD`;
|
|
174
|
+
- `RENAMED` is not supported by merge yet — `/dc-archive` refuses it.
|
|
175
|
+
|
|
176
|
+
Scenario ids are the join key between specs and tasks. They are derived from the scenario name: `Theme selection` in capability `ui/theme` → `ui/theme#theme-selection`. Renaming a scenario changes its id, so `/dc-check` will report the new scenario as uncovered until a task references it.
|
|
177
|
+
|
|
178
|
+
## The task plan
|
|
179
|
+
|
|
180
|
+
`tasks.dml` is data, not a program:
|
|
181
|
+
|
|
182
|
+
```prolog
|
|
183
|
+
plan_task("1.1", task{
|
|
184
|
+
executor: pi,
|
|
185
|
+
do: "Add a ThemeProvider context exposing theme and setTheme.",
|
|
186
|
+
tools: ["read", "edit"],
|
|
187
|
+
expected: "src/theme/ThemeProvider.tsx exports ThemeProvider and typechecks.",
|
|
188
|
+
satisfies: ["ui/theme#theme-selection"],
|
|
189
|
+
checks: [ exists("src/theme/ThemeProvider.tsx"),
|
|
190
|
+
cmd("npm run typecheck") ]
|
|
191
|
+
}).
|
|
192
|
+
|
|
193
|
+
% --- execution state (managed by apply.dml; do not edit by hand) ---
|
|
194
|
+
plan_task_status("1.1", pending).
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
- `executor: pi` delegates a bounded step to pi with exactly the listed tools; `executor: dml` uses contained model reasoning with no pi tools.
|
|
198
|
+
- `satisfies` links the step to delta scenarios; `/dc-check` fails if any delta scenario is uncovered.
|
|
199
|
+
- Checks are declarative: `exists("path")`, `cmd("command")`, `model("question")`.
|
|
200
|
+
- Use `plan_task/2` and `plan_task_status/2` — **not** `task/2`, which collides with DML's built-in `task/N` predicate.
|
|
201
|
+
|
|
202
|
+
## Verification, resume and rollback
|
|
203
|
+
|
|
204
|
+
- **Checks** run after each step. A failed check retries the step (up to 3 attempts) with the failure evidence — including command stderr — threaded into the repair instruction.
|
|
205
|
+
- **Verification commands are approved once per run** and then executed through the allowlisted `dc_verify_run` tool. Ordinary `pi_bash` approvals are unaffected.
|
|
206
|
+
- **Snapshots.** `/dc-apply` records a git ref before running and refuses to start on a dirty tree. On success it clears the ref.
|
|
207
|
+
- **Resume.** If a run stops — `/dc-cancel`, a crash, or exhausted retries — the working tree and the `done`/`failed` statuses are **preserved**. Re-run `/dc-apply <change>` and it resumes from the remaining tasks, reusing the original snapshot.
|
|
208
|
+
- **Abort.** `/dc-apply <change> --abort` discards the apply and restores the snapshot (`git reset --hard` + `git clean -fd`), which also resets `tasks.dml` statuses.
|
|
209
|
+
|
|
210
|
+
A step interrupted halfway is simply re-executed, because its task is not `done` yet and its checks re-verify.
|
|
211
|
+
|
|
212
|
+
## Committing
|
|
213
|
+
|
|
214
|
+
After `/dc-plan`, `/dc-apply` and `/dc-archive` leave uncommitted changes, the extension lists the changed files and offers to commit them (`git add -A` with an `<action>: <change>` message), or reminds you when you decline. A clean tree is what lets the next apply take a snapshot.
|
|
215
|
+
|
|
216
|
+
Suggested `.gitignore`:
|
|
217
|
+
|
|
218
|
+
```
|
|
219
|
+
.pi/deepclause/diagrams/
|
|
220
|
+
.pi/deepclause/changes/*/change.json
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Track `specs/` and `changes/` (including `tasks.dml`); ignore the generated viewer and the transient apply state.
|
|
224
|
+
|
|
225
|
+
## Limits
|
|
226
|
+
|
|
227
|
+
- `RENAMED` deltas are validated but not merged yet.
|
|
228
|
+
- There is no digest/drift check between a delta and `specs/` beyond the merge guard; run `/dc-check` after editing specs by hand.
|
|
229
|
+
- `/dc-archive` does not run `/dc-check` for you, and it writes per capability, so run the check first.
|
|
230
|
+
- The `deltas.dml` / `index.dml` derived-fact files from the design are not implemented; queries derive on demand.
|
|
231
|
+
|
|
232
|
+
See [SPEC_LAYER_PROPOSAL.md](SPEC_LAYER_PROPOSAL.md) for the full design and rationale.
|