deepflow 0.1.50 → 0.1.52
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 +25 -13
- package/bin/install.js +82 -3
- package/hooks/df-consolidation-check.js +67 -0
- package/package.json +1 -1
- package/src/commands/df/consolidate.md +58 -0
- package/src/commands/df/debate.md +0 -4
- package/src/commands/df/discover.md +0 -2
- package/src/commands/df/execute.md +11 -6
- package/src/commands/df/note.md +1 -0
- package/src/commands/df/plan.md +0 -4
- package/src/commands/df/spec.md +0 -4
- package/src/commands/df/verify.md +25 -5
- package/templates/decision-capture.md +0 -19
package/README.md
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
- **Spike-first planning** — Validate risky hypotheses before full implementation
|
|
28
28
|
- **Worktree isolation** — Main branch stays clean during execution
|
|
29
29
|
- **Parallel execution** with context-aware checkpointing
|
|
30
|
+
- **Automatic decision capture** on spec completion, periodic consolidation
|
|
30
31
|
- **Atomic commits** for clean rollback
|
|
31
32
|
|
|
32
33
|
## Quick Start
|
|
@@ -65,7 +66,6 @@ claude
|
|
|
65
66
|
```
|
|
66
67
|
/df:discover <name>
|
|
67
68
|
│ Socratic questioning (motivation, scope, constraints...)
|
|
68
|
-
│ Captures decisions to .deepflow/decisions.md
|
|
69
69
|
▼
|
|
70
70
|
/df:debate <topic> ← optional
|
|
71
71
|
│ 4 perspectives: User Advocate, Tech Skeptic,
|
|
@@ -90,7 +90,8 @@ claude
|
|
|
90
90
|
/df:verify
|
|
91
91
|
│ Checks requirements met
|
|
92
92
|
│ Merges worktree to main, cleans up
|
|
93
|
-
│
|
|
93
|
+
│ Extracts decisions → .deepflow/decisions.md
|
|
94
|
+
│ Deletes done-* spec after extraction
|
|
94
95
|
```
|
|
95
96
|
|
|
96
97
|
## Spec Lifecycle
|
|
@@ -99,7 +100,7 @@ claude
|
|
|
99
100
|
specs/
|
|
100
101
|
feature.md → new, needs /df:plan
|
|
101
102
|
doing-feature.md → in progress, has tasks in PLAN.md
|
|
102
|
-
done-feature.md →
|
|
103
|
+
done-feature.md → transient (decisions extracted, then deleted)
|
|
103
104
|
```
|
|
104
105
|
|
|
105
106
|
## Works With Any Project
|
|
@@ -129,6 +130,16 @@ Execution happens in an isolated git worktree:
|
|
|
129
130
|
- Resume with `/df:execute --continue`
|
|
130
131
|
- On success, `/df:verify` merges to main and cleans up
|
|
131
132
|
|
|
133
|
+
## LSP Integration
|
|
134
|
+
|
|
135
|
+
deepflow automatically enables Claude Code's LSP tools during install, giving agents access to `goToDefinition`, `findReferences`, and `workspaceSymbol` for precise code navigation instead of grep-based searching.
|
|
136
|
+
|
|
137
|
+
- **Global install:** sets `ENABLE_LSP_TOOL=1` in `~/.claude/settings.json`
|
|
138
|
+
- **Project install:** sets it in `.claude/settings.local.json`
|
|
139
|
+
- **Uninstall:** cleans up automatically
|
|
140
|
+
|
|
141
|
+
Agents prefer LSP tools when available and fall back to Grep/Glob silently. You'll need a language server installed for your language (e.g. `typescript-language-server`, `pyright`, `rust-analyzer`, `gopls`).
|
|
142
|
+
|
|
132
143
|
## Context-Aware Execution
|
|
133
144
|
|
|
134
145
|
Statusline shows context usage. At ≥50%:
|
|
@@ -145,8 +156,9 @@ Statusline shows context usage. At ≥50%:
|
|
|
145
156
|
| `/df:spec <name>` | Generate spec from conversation |
|
|
146
157
|
| `/df:plan` | Compare specs to code, create tasks |
|
|
147
158
|
| `/df:execute` | Run tasks with parallel agents |
|
|
148
|
-
| `/df:verify` | Check specs satisfied |
|
|
149
|
-
| `/df:note` | Capture decisions from conversation |
|
|
159
|
+
| `/df:verify` | Check specs satisfied, merge to main |
|
|
160
|
+
| `/df:note` | Capture decisions ad-hoc from conversation |
|
|
161
|
+
| `/df:consolidate` | Deduplicate and clean up decisions.md |
|
|
150
162
|
| `/df:resume` | Session continuity briefing |
|
|
151
163
|
| `/df:update` | Update deepflow to latest |
|
|
152
164
|
|
|
@@ -156,16 +168,16 @@ Statusline shows context usage. At ≥50%:
|
|
|
156
168
|
your-project/
|
|
157
169
|
├── specs/
|
|
158
170
|
│ ├── auth.md # new spec
|
|
159
|
-
│
|
|
160
|
-
│ └── done-payments.md # completed
|
|
171
|
+
│ └── doing-upload.md # in progress
|
|
161
172
|
├── PLAN.md # active tasks
|
|
162
173
|
└── .deepflow/
|
|
163
|
-
├── config.yaml
|
|
164
|
-
├── decisions.md
|
|
165
|
-
├──
|
|
166
|
-
├──
|
|
167
|
-
|
|
168
|
-
|
|
174
|
+
├── config.yaml # project settings
|
|
175
|
+
├── decisions.md # auto-extracted + ad-hoc decisions
|
|
176
|
+
├── last-consolidated.json # consolidation timestamp
|
|
177
|
+
├── context.json # context % tracking
|
|
178
|
+
├── experiments/ # spike results (pass/fail)
|
|
179
|
+
└── worktrees/ # isolated execution
|
|
180
|
+
└── upload/ # one worktree per spec
|
|
169
181
|
```
|
|
170
182
|
|
|
171
183
|
## Configuration
|
package/bin/install.js
CHANGED
|
@@ -142,6 +142,11 @@ async function main() {
|
|
|
142
142
|
await configureHooks(CLAUDE_DIR);
|
|
143
143
|
}
|
|
144
144
|
|
|
145
|
+
// Configure project settings (project only)
|
|
146
|
+
if (level === 'project') {
|
|
147
|
+
configureProjectSettings(CLAUDE_DIR);
|
|
148
|
+
}
|
|
149
|
+
|
|
145
150
|
console.log('');
|
|
146
151
|
console.log(`${c.green}Installation complete!${c.reset}`);
|
|
147
152
|
console.log('');
|
|
@@ -152,6 +157,7 @@ async function main() {
|
|
|
152
157
|
if (level === 'global') {
|
|
153
158
|
console.log(' hooks/ — statusline, update checker');
|
|
154
159
|
}
|
|
160
|
+
console.log(' env/ — ENABLE_LSP_TOOL (code navigation via goToDefinition, findReferences, workspaceSymbol)');
|
|
155
161
|
console.log('');
|
|
156
162
|
if (level === 'project') {
|
|
157
163
|
console.log(`${c.dim}Note: Statusline is only available with global install.${c.reset}`);
|
|
@@ -196,6 +202,7 @@ async function configureHooks(claudeDir) {
|
|
|
196
202
|
const settingsPath = path.join(claudeDir, 'settings.json');
|
|
197
203
|
const statuslineCmd = `node "${path.join(claudeDir, 'hooks', 'df-statusline.js')}"`;
|
|
198
204
|
const updateCheckCmd = `node "${path.join(claudeDir, 'hooks', 'df-check-update.js')}"`;
|
|
205
|
+
const consolidationCheckCmd = `node "${path.join(claudeDir, 'hooks', 'df-consolidation-check.js')}"`;
|
|
199
206
|
|
|
200
207
|
let settings = {};
|
|
201
208
|
|
|
@@ -207,6 +214,11 @@ async function configureHooks(claudeDir) {
|
|
|
207
214
|
}
|
|
208
215
|
}
|
|
209
216
|
|
|
217
|
+
// Enable LSP tool
|
|
218
|
+
if (!settings.env) settings.env = {};
|
|
219
|
+
settings.env.ENABLE_LSP_TOOL = "1";
|
|
220
|
+
log('LSP tool enabled');
|
|
221
|
+
|
|
210
222
|
// Configure statusline
|
|
211
223
|
if (settings.statusLine) {
|
|
212
224
|
const answer = await ask(
|
|
@@ -234,7 +246,7 @@ async function configureHooks(claudeDir) {
|
|
|
234
246
|
// Remove any existing deepflow update check hooks
|
|
235
247
|
settings.hooks.SessionStart = settings.hooks.SessionStart.filter(hook => {
|
|
236
248
|
const cmd = hook.hooks?.[0]?.command || '';
|
|
237
|
-
return !cmd.includes('df-check-update');
|
|
249
|
+
return !cmd.includes('df-check-update') && !cmd.includes('df-consolidation-check');
|
|
238
250
|
});
|
|
239
251
|
|
|
240
252
|
// Add update check hook
|
|
@@ -244,11 +256,40 @@ async function configureHooks(claudeDir) {
|
|
|
244
256
|
command: updateCheckCmd
|
|
245
257
|
}]
|
|
246
258
|
});
|
|
259
|
+
|
|
260
|
+
// Add consolidation check hook
|
|
261
|
+
settings.hooks.SessionStart.push({
|
|
262
|
+
hooks: [{
|
|
263
|
+
type: 'command',
|
|
264
|
+
command: consolidationCheckCmd
|
|
265
|
+
}]
|
|
266
|
+
});
|
|
247
267
|
log('SessionStart hook configured');
|
|
248
268
|
|
|
249
269
|
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
250
270
|
}
|
|
251
271
|
|
|
272
|
+
function configureProjectSettings(claudeDir) {
|
|
273
|
+
const settingsPath = path.join(claudeDir, 'settings.local.json');
|
|
274
|
+
|
|
275
|
+
let settings = {};
|
|
276
|
+
|
|
277
|
+
if (fs.existsSync(settingsPath)) {
|
|
278
|
+
try {
|
|
279
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
280
|
+
} catch (e) {
|
|
281
|
+
settings = {};
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Enable LSP tool
|
|
286
|
+
if (!settings.env) settings.env = {};
|
|
287
|
+
settings.env.ENABLE_LSP_TOOL = "1";
|
|
288
|
+
|
|
289
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
290
|
+
log('LSP tool enabled (project)');
|
|
291
|
+
}
|
|
292
|
+
|
|
252
293
|
function ask(question) {
|
|
253
294
|
const rl = readline.createInterface({
|
|
254
295
|
input: process.stdin,
|
|
@@ -330,7 +371,7 @@ async function uninstall() {
|
|
|
330
371
|
];
|
|
331
372
|
|
|
332
373
|
if (level === 'global') {
|
|
333
|
-
toRemove.push('hooks/df-statusline.js', 'hooks/df-check-update.js');
|
|
374
|
+
toRemove.push('hooks/df-statusline.js', 'hooks/df-check-update.js', 'hooks/df-consolidation-check.js');
|
|
334
375
|
}
|
|
335
376
|
|
|
336
377
|
for (const item of toRemove) {
|
|
@@ -359,7 +400,7 @@ async function uninstall() {
|
|
|
359
400
|
if (settings.hooks?.SessionStart) {
|
|
360
401
|
settings.hooks.SessionStart = settings.hooks.SessionStart.filter(hook => {
|
|
361
402
|
const cmd = hook.hooks?.[0]?.command || '';
|
|
362
|
-
return !cmd.includes('df-check-update');
|
|
403
|
+
return !cmd.includes('df-check-update') && !cmd.includes('df-consolidation-check');
|
|
363
404
|
});
|
|
364
405
|
if (settings.hooks.SessionStart.length === 0) {
|
|
365
406
|
delete settings.hooks.SessionStart;
|
|
@@ -374,6 +415,44 @@ async function uninstall() {
|
|
|
374
415
|
// Fail silently
|
|
375
416
|
}
|
|
376
417
|
}
|
|
418
|
+
|
|
419
|
+
// Remove ENABLE_LSP_TOOL from global settings
|
|
420
|
+
if (fs.existsSync(settingsPath)) {
|
|
421
|
+
try {
|
|
422
|
+
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf8'));
|
|
423
|
+
if (settings.env?.ENABLE_LSP_TOOL) {
|
|
424
|
+
delete settings.env.ENABLE_LSP_TOOL;
|
|
425
|
+
if (settings.env && Object.keys(settings.env).length === 0) delete settings.env;
|
|
426
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
427
|
+
console.log(` ${c.green}✓${c.reset} Removed ENABLE_LSP_TOOL from settings`);
|
|
428
|
+
}
|
|
429
|
+
} catch (e) {
|
|
430
|
+
// Fail silently
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
// Remove ENABLE_LSP_TOOL from project settings.local.json
|
|
436
|
+
if (level === 'project') {
|
|
437
|
+
const localSettingsPath = path.join(PROJECT_DIR, 'settings.local.json');
|
|
438
|
+
if (fs.existsSync(localSettingsPath)) {
|
|
439
|
+
try {
|
|
440
|
+
const localSettings = JSON.parse(fs.readFileSync(localSettingsPath, 'utf8'));
|
|
441
|
+
if (localSettings.env?.ENABLE_LSP_TOOL) {
|
|
442
|
+
delete localSettings.env.ENABLE_LSP_TOOL;
|
|
443
|
+
if (localSettings.env && Object.keys(localSettings.env).length === 0) delete localSettings.env;
|
|
444
|
+
if (Object.keys(localSettings).length === 0) {
|
|
445
|
+
fs.unlinkSync(localSettingsPath);
|
|
446
|
+
console.log(` ${c.green}✓${c.reset} Removed settings.local.json (empty after cleanup)`);
|
|
447
|
+
} else {
|
|
448
|
+
fs.writeFileSync(localSettingsPath, JSON.stringify(localSettings, null, 2));
|
|
449
|
+
console.log(` ${c.green}✓${c.reset} Removed ENABLE_LSP_TOOL from settings.local.json`);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
} catch (e) {
|
|
453
|
+
// Fail silently
|
|
454
|
+
}
|
|
455
|
+
}
|
|
377
456
|
}
|
|
378
457
|
|
|
379
458
|
console.log('');
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* deepflow consolidation checker
|
|
4
|
+
* Checks if decisions.md needs consolidation, outputs suggestion if overdue
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
|
|
10
|
+
const DAYS_THRESHOLD = 7;
|
|
11
|
+
const LINES_THRESHOLD = 20;
|
|
12
|
+
const DEEPFLOW_DIR = path.join(process.cwd(), '.deepflow');
|
|
13
|
+
const DECISIONS_FILE = path.join(DEEPFLOW_DIR, 'decisions.md');
|
|
14
|
+
const LAST_CONSOLIDATED_FILE = path.join(DEEPFLOW_DIR, 'last-consolidated.json');
|
|
15
|
+
|
|
16
|
+
function checkConsolidation() {
|
|
17
|
+
try {
|
|
18
|
+
// Check if decisions.md exists
|
|
19
|
+
if (!fs.existsSync(DECISIONS_FILE)) {
|
|
20
|
+
process.exit(0);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Check if decisions.md has more than LINES_THRESHOLD lines
|
|
24
|
+
const decisionsContent = fs.readFileSync(DECISIONS_FILE, 'utf8');
|
|
25
|
+
const lineCount = decisionsContent.split('\n').length;
|
|
26
|
+
if (lineCount <= LINES_THRESHOLD) {
|
|
27
|
+
process.exit(0);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Get last consolidated timestamp
|
|
31
|
+
let lastConsolidated;
|
|
32
|
+
if (fs.existsSync(LAST_CONSOLIDATED_FILE)) {
|
|
33
|
+
try {
|
|
34
|
+
const data = JSON.parse(fs.readFileSync(LAST_CONSOLIDATED_FILE, 'utf8'));
|
|
35
|
+
if (data.last_consolidated) {
|
|
36
|
+
lastConsolidated = new Date(data.last_consolidated);
|
|
37
|
+
}
|
|
38
|
+
} catch (e) {
|
|
39
|
+
// Fall through to use mtime
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Fallback: use mtime of decisions.md
|
|
44
|
+
if (!lastConsolidated || isNaN(lastConsolidated.getTime())) {
|
|
45
|
+
const stat = fs.statSync(DECISIONS_FILE);
|
|
46
|
+
lastConsolidated = stat.mtime;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Calculate days since last consolidation
|
|
50
|
+
const now = new Date();
|
|
51
|
+
const diffMs = now - lastConsolidated;
|
|
52
|
+
const diffDays = Math.floor(diffMs / (1000 * 60 * 60 * 24));
|
|
53
|
+
|
|
54
|
+
if (diffDays >= DAYS_THRESHOLD) {
|
|
55
|
+
process.stderr.write(
|
|
56
|
+
`\u{1F4A1} decisions.md hasn't been consolidated in ${diffDays} days. Run /df:consolidate to clean up.\n`
|
|
57
|
+
);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
} catch (e) {
|
|
61
|
+
// Fail silently
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
process.exit(0);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
checkConsolidation();
|
package/package.json
CHANGED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# /df:consolidate — Consolidate Decisions
|
|
2
|
+
|
|
3
|
+
## Purpose
|
|
4
|
+
Remove duplicates, superseded entries, and promote stale provisionals. Keep decisions.md dense and useful.
|
|
5
|
+
|
|
6
|
+
**NEVER:** use EnterPlanMode, use ExitPlanMode
|
|
7
|
+
|
|
8
|
+
## Usage
|
|
9
|
+
```
|
|
10
|
+
/df:consolidate # Consolidate decisions.md
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Behavior
|
|
14
|
+
|
|
15
|
+
### 1. LOAD
|
|
16
|
+
Read `.deepflow/decisions.md`. If missing or empty, report and exit.
|
|
17
|
+
|
|
18
|
+
### 2. ANALYZE
|
|
19
|
+
Model-driven analysis (not regex):
|
|
20
|
+
- Identify duplicate decisions (same meaning, different wording)
|
|
21
|
+
- Identify superseded decisions (later entry contradicts earlier)
|
|
22
|
+
- Identify stale `[PROVISIONAL]` entries (>30 days old, no resolution)
|
|
23
|
+
|
|
24
|
+
### 3. CONSOLIDATE
|
|
25
|
+
- Remove duplicates (keep the more precise wording)
|
|
26
|
+
- Silently remove superseded entries (the later decision wins)
|
|
27
|
+
- Promote stale `[PROVISIONAL]` to `[DEBT]` (needs revisiting)
|
|
28
|
+
- Preserve all `[APPROACH]` entries unless superseded
|
|
29
|
+
- Preserve all `[ASSUMPTION]` entries unless invalidated
|
|
30
|
+
- Target: 200-500 lines (if currently longer)
|
|
31
|
+
- When in doubt, keep both entries (conservative)
|
|
32
|
+
|
|
33
|
+
### 4. WRITE
|
|
34
|
+
- Rewrite `.deepflow/decisions.md` with consolidated content
|
|
35
|
+
- Write timestamp to `.deepflow/last-consolidated.json`:
|
|
36
|
+
```json
|
|
37
|
+
{ "last_consolidated": "{ISO-8601 timestamp}" }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### 5. REPORT
|
|
41
|
+
```
|
|
42
|
+
✓ Consolidated: {before} → {after} lines, {n} removed, {n} promoted to [DEBT]
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Tags
|
|
46
|
+
| Tag | Meaning | Source |
|
|
47
|
+
|-----|---------|--------|
|
|
48
|
+
| `[APPROACH]` | Firm decision | Auto-extraction, /df:note |
|
|
49
|
+
| `[PROVISIONAL]` | Revisit later | Auto-extraction, /df:note |
|
|
50
|
+
| `[ASSUMPTION]` | Unverified | Auto-extraction, /df:note |
|
|
51
|
+
| `[DEBT]` | Needs revisiting | Consolidation only |
|
|
52
|
+
|
|
53
|
+
## Rules
|
|
54
|
+
- Conservative: when in doubt, keep both entries
|
|
55
|
+
- Never add new decisions — only remove, merge, or re-tag
|
|
56
|
+
- [DEBT] is never manually assigned — only produced by consolidation
|
|
57
|
+
- Preserve chronological ordering within sections
|
|
58
|
+
- decisions.md stays a single flat file, human-readable
|
|
@@ -160,10 +160,6 @@ Create `specs/.debate-{name}.md` with sections: Context · Codebase Context · P
|
|
|
160
160
|
|
|
161
161
|
Present key tensions and open decisions, then: `Next: Run /df:spec {name} to formalize into a specification`
|
|
162
162
|
|
|
163
|
-
### 7. CAPTURE DECISIONS
|
|
164
|
-
|
|
165
|
-
Follow the **default** variant from `templates/decision-capture.md`. Command name: `debate`.
|
|
166
|
-
|
|
167
163
|
---
|
|
168
164
|
|
|
169
165
|
## Rules
|
|
@@ -85,8 +85,6 @@ Example questions:
|
|
|
85
85
|
- Keep your responses short between questions — don't lecture
|
|
86
86
|
- Acknowledge answers briefly before asking the next question
|
|
87
87
|
|
|
88
|
-
### Decision Capture
|
|
89
|
-
Follow the **default** variant from `templates/decision-capture.md`. Command name: `discover`.
|
|
90
88
|
### When the User Wants to Move On
|
|
91
89
|
When the user signals they want to advance (e.g., "I think that's enough", "let's move on", "ready for next step"):
|
|
92
90
|
|
|
@@ -328,6 +328,9 @@ Commit format: {commit_type}({spec}): {description}
|
|
|
328
328
|
Result file: {worktree_absolute_path}/.deepflow/results/{task_id}.yaml
|
|
329
329
|
|
|
330
330
|
STOP after writing the result file. Do NOT merge branches, rename spec files, remove worktrees, or run git checkout on main. These are handled by the orchestrator and /df:verify.
|
|
331
|
+
|
|
332
|
+
Navigation: Prefer LSP tools (goToDefinition, findReferences, workspaceSymbol) over Grep/Glob for code navigation. Fall back to Grep/Glob if LSP unavailable.
|
|
333
|
+
If LSP errors, install the language server (TS→typescript-language-server, Python→pyright, Rust→rust-analyzer, Go→gopls) and retry. If still unavailable, use Grep/Glob.
|
|
331
334
|
```
|
|
332
335
|
|
|
333
336
|
**Standard Task (append after preamble):**
|
|
@@ -380,13 +383,19 @@ When a task fails and cannot be auto-fixed:
|
|
|
380
383
|
When all tasks done for a `doing-*` spec:
|
|
381
384
|
1. Embed history in spec: `## Completed` section with task list and commit hashes
|
|
382
385
|
2. Rename: `doing-upload.md` → `done-upload.md`
|
|
383
|
-
3.
|
|
386
|
+
3. Extract decisions from done-* spec: Read the `done-{name}.md` file. Model-extract architectural decisions — look for explicit choices (→ `[APPROACH]`), unvalidated assumptions (→ `[ASSUMPTION]`), and "for now" decisions (→ `[PROVISIONAL]`). Append as a new section to **main tree** `.deepflow/decisions.md`:
|
|
387
|
+
```
|
|
388
|
+
### {YYYY-MM-DD} — {spec-name}
|
|
389
|
+
- [TAG] decision text — rationale
|
|
390
|
+
```
|
|
391
|
+
After successful append, delete `specs/done-{name}.md`. If write fails, preserve the file.
|
|
392
|
+
4. Remove the spec's ENTIRE section from PLAN.md:
|
|
384
393
|
- The `### doing-{spec}` header
|
|
385
394
|
- All task entries (`- [x] **T{n}**: ...` and their sub-items)
|
|
386
395
|
- Any `## Execution Summary` block for that spec
|
|
387
396
|
- Any `### Fix Tasks` sub-section for that spec
|
|
388
397
|
- Separators (`---`) between removed sections
|
|
389
|
-
|
|
398
|
+
5. Recalculate the Summary table at the top of PLAN.md (update counts for completed/pending)
|
|
390
399
|
|
|
391
400
|
### 10. ITERATE (Notification-Driven)
|
|
392
401
|
|
|
@@ -408,10 +417,6 @@ After spawning wave agents, your turn ENDS. Completion notifications drive the l
|
|
|
408
417
|
|
|
409
418
|
**Repeat** until: all done, all blocked, or context ≥50% (checkpoint).
|
|
410
419
|
|
|
411
|
-
### 11. CAPTURE DECISIONS
|
|
412
|
-
|
|
413
|
-
Follow the **main-tree** variant from `templates/decision-capture.md`. Command name: `execute`.
|
|
414
|
-
|
|
415
420
|
## Rules
|
|
416
421
|
|
|
417
422
|
| Rule | Detail |
|
package/src/commands/df/note.md
CHANGED
|
@@ -132,6 +132,7 @@ No decisions saved.
|
|
|
132
132
|
- `[APPROACH]` — deliberate design or implementation choice
|
|
133
133
|
- `[PROVISIONAL]` — works for now, will revisit at scale or with more information
|
|
134
134
|
- `[ASSUMPTION]` — treating something as true without full confirmation
|
|
135
|
+
- `[DEBT]` — needs revisiting; produced only by `/df:consolidate`, never manually assigned
|
|
135
136
|
|
|
136
137
|
**Contradiction handling:** Never delete prior entries. When a new decision contradicts an older one, include a reference in the rationale: `was "X", now "Y" because Z`.
|
|
137
138
|
|
package/src/commands/df/plan.md
CHANGED
|
@@ -154,10 +154,6 @@ Append tasks grouped by `### doing-{spec-name}`. Include spec gaps and validatio
|
|
|
154
154
|
|
|
155
155
|
`✓ Plan generated — {n} specs, {n} tasks. Run /df:execute`
|
|
156
156
|
|
|
157
|
-
### 12. CAPTURE DECISIONS
|
|
158
|
-
|
|
159
|
-
Follow the **default** variant from `templates/decision-capture.md`. Command name: `plan`.
|
|
160
|
-
|
|
161
157
|
## Rules
|
|
162
158
|
- **Spike-first** — Generate spike task before full implementation if no `--passed.md` experiment exists
|
|
163
159
|
- **Block on spike** — Full implementation tasks MUST be blocked by spike validation
|
package/src/commands/df/spec.md
CHANGED
|
@@ -130,10 +130,6 @@ Acceptance criteria: {count}
|
|
|
130
130
|
Next: Run /df:plan to generate tasks
|
|
131
131
|
```
|
|
132
132
|
|
|
133
|
-
### 6. CAPTURE DECISIONS
|
|
134
|
-
|
|
135
|
-
Follow the **default** variant from `templates/decision-capture.md`. Command name: `spec`.
|
|
136
|
-
|
|
137
133
|
## Rules
|
|
138
134
|
- **Orchestrator never searches** — Spawn agents for all codebase exploration
|
|
139
135
|
- Do NOT generate spec if critical gaps remain
|
|
@@ -72,6 +72,7 @@ Run the build command in the worktree:
|
|
|
72
72
|
|
|
73
73
|
Check requirements, acceptance criteria, and quality (stubs/TODOs).
|
|
74
74
|
Mark each: ✓ satisfied | ✗ missing | ⚠ partial
|
|
75
|
+
Prefer LSP tools (goToDefinition, findReferences, workspaceSymbol) when available; fall back to Grep/Glob silently.
|
|
75
76
|
|
|
76
77
|
**L4: Test execution** (if test command detected)
|
|
77
78
|
|
|
@@ -141,9 +142,9 @@ Files: ...
|
|
|
141
142
|
| Level | Check | Method | Runner |
|
|
142
143
|
|-------|-------|--------|--------|
|
|
143
144
|
| L0: Builds | Code compiles/builds | Run build command | Orchestrator (Bash) |
|
|
144
|
-
| L1: Exists | File/function exists | Glob/Grep | Explore agents |
|
|
145
|
+
| L1: Exists | File/function exists | Glob/Grep (prefer workspaceSymbol if available) | Explore agents |
|
|
145
146
|
| L2: Substantive | Real code, not stub | Read + analyze | Explore agents |
|
|
146
|
-
| L3: Wired | Integrated into system | Trace imports/calls | Explore agents |
|
|
147
|
+
| L3: Wired | Integrated into system | Trace imports/calls (prefer findReferences if available) | Explore agents |
|
|
147
148
|
| L4: Tested | Tests pass | Run test command | Orchestrator (Bash) |
|
|
148
149
|
|
|
149
150
|
**Default: L0 through L4.** L0 and L4 skipped ONLY if no build/test command detected (see step 1.5). L0 and L4 run via Bash — Explore agents cannot execute commands.
|
|
@@ -201,6 +202,28 @@ git branch -d "${WORKTREE_BRANCH}"
|
|
|
201
202
|
rm -f .deepflow/checkpoint.json
|
|
202
203
|
```
|
|
203
204
|
|
|
205
|
+
### 4. RENAME SPEC
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
# Rename spec to done
|
|
209
|
+
mv specs/doing-${SPEC_NAME}.md specs/done-${SPEC_NAME}.md
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
### 5. EXTRACT DECISIONS
|
|
213
|
+
|
|
214
|
+
Read the renamed `specs/done-${SPEC_NAME}.md` file. Model-extract architectural decisions:
|
|
215
|
+
- Explicit choices → `[APPROACH]`
|
|
216
|
+
- Unvalidated assumptions → `[ASSUMPTION]`
|
|
217
|
+
- "For now" decisions → `[PROVISIONAL]`
|
|
218
|
+
|
|
219
|
+
Append to `.deepflow/decisions.md`:
|
|
220
|
+
```
|
|
221
|
+
### {YYYY-MM-DD} — {spec-name}
|
|
222
|
+
- [TAG] decision text — rationale
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
After successful append, delete `specs/done-${SPEC_NAME}.md`. If write fails, preserve the file.
|
|
226
|
+
|
|
204
227
|
Output:
|
|
205
228
|
```
|
|
206
229
|
✓ Merged df/upload to main
|
|
@@ -210,6 +233,3 @@ Output:
|
|
|
210
233
|
Workflow complete! Ready for next feature: /df:spec <name>
|
|
211
234
|
```
|
|
212
235
|
|
|
213
|
-
### 4. CAPTURE DECISIONS (success path only)
|
|
214
|
-
|
|
215
|
-
Follow the **success-path-only** variant from `templates/decision-capture.md`. Command name: `verify`.
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# Decision Capture — Shared Pattern
|
|
2
|
-
|
|
3
|
-
## Common Flow
|
|
4
|
-
Extract up to 4 candidates → `AskUserQuestion(multiSelect: true)` → append confirmed to `.deepflow/decisions.md`.
|
|
5
|
-
Each option: `label: "[TAG] <decision>"`, `description: "<rationale>"`. Tags: `[APPROACH]` `[PROVISIONAL]` `[ASSUMPTION]`.
|
|
6
|
-
Format: `### {YYYY-MM-DD} — {command}` / `- [TAG] decision text — rationale`
|
|
7
|
-
|
|
8
|
-
## Variant: default
|
|
9
|
-
Used by: discover, debate, spec, plan, note.
|
|
10
|
-
Append confirmed decisions to `.deepflow/decisions.md` (create if missing). Max 4 candidates.
|
|
11
|
-
If a decision contradicts a prior entry, note conflict inline; never delete prior entries.
|
|
12
|
-
|
|
13
|
-
## Variant: main-tree
|
|
14
|
-
Used by: execute.
|
|
15
|
-
Same as default but write to **main tree** `.deepflow/decisions.md` (repo root, parent of `.deepflow/worktrees/`), not the worktree path.
|
|
16
|
-
|
|
17
|
-
## Variant: success-path-only
|
|
18
|
-
Used by: verify.
|
|
19
|
-
Same as default but **only run this step when verification passes**. Skip entirely on failure.
|