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 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
- Renames: doing-feature.mddone-feature.md
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 → completed, history embedded
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
- ├── doing-upload.md # in progress
160
- │ └── done-payments.md # completed
171
+ └── doing-upload.md # in progress
161
172
  ├── PLAN.md # active tasks
162
173
  └── .deepflow/
163
- ├── config.yaml # project settings
164
- ├── decisions.md # captured decisions (/df:note, /df:discover)
165
- ├── context.json # context % tracking
166
- ├── experiments/ # spike results (pass/fail)
167
- └── worktrees/ # isolated execution
168
- └── upload/ # one worktree per spec
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "deepflow",
3
- "version": "0.1.50",
3
+ "version": "0.1.52",
4
4
  "description": "Stay in flow state - lightweight spec-driven task orchestration for Claude Code",
5
5
  "keywords": [
6
6
  "claude",
@@ -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. Remove the spec's ENTIRE section from PLAN.md:
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
- 4. Recalculate the Summary table at the top of PLAN.md (update counts for completed/pending)
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 |
@@ -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
 
@@ -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
@@ -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.