deepflow 0.1.50 → 0.1.51

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
@@ -145,8 +146,9 @@ Statusline shows context usage. At ≥50%:
145
146
  | `/df:spec <name>` | Generate spec from conversation |
146
147
  | `/df:plan` | Compare specs to code, create tasks |
147
148
  | `/df:execute` | Run tasks with parallel agents |
148
- | `/df:verify` | Check specs satisfied |
149
- | `/df:note` | Capture decisions from conversation |
149
+ | `/df:verify` | Check specs satisfied, merge to main |
150
+ | `/df:note` | Capture decisions ad-hoc from conversation |
151
+ | `/df:consolidate` | Deduplicate and clean up decisions.md |
150
152
  | `/df:resume` | Session continuity briefing |
151
153
  | `/df:update` | Update deepflow to latest |
152
154
 
@@ -156,16 +158,16 @@ Statusline shows context usage. At ≥50%:
156
158
  your-project/
157
159
  ├── specs/
158
160
  │ ├── auth.md # new spec
159
- ├── doing-upload.md # in progress
160
- │ └── done-payments.md # completed
161
+ └── doing-upload.md # in progress
161
162
  ├── PLAN.md # active tasks
162
163
  └── .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
164
+ ├── config.yaml # project settings
165
+ ├── decisions.md # auto-extracted + ad-hoc decisions
166
+ ├── last-consolidated.json # consolidation timestamp
167
+ ├── context.json # context % tracking
168
+ ├── experiments/ # spike results (pass/fail)
169
+ └── worktrees/ # isolated execution
170
+ └── upload/ # one worktree per spec
169
171
  ```
170
172
 
171
173
  ## Configuration
package/bin/install.js CHANGED
@@ -196,6 +196,7 @@ async function configureHooks(claudeDir) {
196
196
  const settingsPath = path.join(claudeDir, 'settings.json');
197
197
  const statuslineCmd = `node "${path.join(claudeDir, 'hooks', 'df-statusline.js')}"`;
198
198
  const updateCheckCmd = `node "${path.join(claudeDir, 'hooks', 'df-check-update.js')}"`;
199
+ const consolidationCheckCmd = `node "${path.join(claudeDir, 'hooks', 'df-consolidation-check.js')}"`;
199
200
 
200
201
  let settings = {};
201
202
 
@@ -234,7 +235,7 @@ async function configureHooks(claudeDir) {
234
235
  // Remove any existing deepflow update check hooks
235
236
  settings.hooks.SessionStart = settings.hooks.SessionStart.filter(hook => {
236
237
  const cmd = hook.hooks?.[0]?.command || '';
237
- return !cmd.includes('df-check-update');
238
+ return !cmd.includes('df-check-update') && !cmd.includes('df-consolidation-check');
238
239
  });
239
240
 
240
241
  // Add update check hook
@@ -244,6 +245,14 @@ async function configureHooks(claudeDir) {
244
245
  command: updateCheckCmd
245
246
  }]
246
247
  });
248
+
249
+ // Add consolidation check hook
250
+ settings.hooks.SessionStart.push({
251
+ hooks: [{
252
+ type: 'command',
253
+ command: consolidationCheckCmd
254
+ }]
255
+ });
247
256
  log('SessionStart hook configured');
248
257
 
249
258
  fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
@@ -330,7 +339,7 @@ async function uninstall() {
330
339
  ];
331
340
 
332
341
  if (level === 'global') {
333
- toRemove.push('hooks/df-statusline.js', 'hooks/df-check-update.js');
342
+ toRemove.push('hooks/df-statusline.js', 'hooks/df-check-update.js', 'hooks/df-consolidation-check.js');
334
343
  }
335
344
 
336
345
  for (const item of toRemove) {
@@ -359,7 +368,7 @@ async function uninstall() {
359
368
  if (settings.hooks?.SessionStart) {
360
369
  settings.hooks.SessionStart = settings.hooks.SessionStart.filter(hook => {
361
370
  const cmd = hook.hooks?.[0]?.command || '';
362
- return !cmd.includes('df-check-update');
371
+ return !cmd.includes('df-check-update') && !cmd.includes('df-consolidation-check');
363
372
  });
364
373
  if (settings.hooks.SessionStart.length === 0) {
365
374
  delete settings.hooks.SessionStart;
@@ -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.51",
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
 
@@ -380,13 +380,19 @@ When a task fails and cannot be auto-fixed:
380
380
  When all tasks done for a `doing-*` spec:
381
381
  1. Embed history in spec: `## Completed` section with task list and commit hashes
382
382
  2. Rename: `doing-upload.md` → `done-upload.md`
383
- 3. Remove the spec's ENTIRE section from PLAN.md:
383
+ 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`:
384
+ ```
385
+ ### {YYYY-MM-DD} — {spec-name}
386
+ - [TAG] decision text — rationale
387
+ ```
388
+ After successful append, delete `specs/done-{name}.md`. If write fails, preserve the file.
389
+ 4. Remove the spec's ENTIRE section from PLAN.md:
384
390
  - The `### doing-{spec}` header
385
391
  - All task entries (`- [x] **T{n}**: ...` and their sub-items)
386
392
  - Any `## Execution Summary` block for that spec
387
393
  - Any `### Fix Tasks` sub-section for that spec
388
394
  - Separators (`---`) between removed sections
389
- 4. Recalculate the Summary table at the top of PLAN.md (update counts for completed/pending)
395
+ 5. Recalculate the Summary table at the top of PLAN.md (update counts for completed/pending)
390
396
 
391
397
  ### 10. ITERATE (Notification-Driven)
392
398
 
@@ -408,10 +414,6 @@ After spawning wave agents, your turn ENDS. Completion notifications drive the l
408
414
 
409
415
  **Repeat** until: all done, all blocked, or context ≥50% (checkpoint).
410
416
 
411
- ### 11. CAPTURE DECISIONS
412
-
413
- Follow the **main-tree** variant from `templates/decision-capture.md`. Command name: `execute`.
414
-
415
417
  ## Rules
416
418
 
417
419
  | 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
@@ -201,6 +201,28 @@ git branch -d "${WORKTREE_BRANCH}"
201
201
  rm -f .deepflow/checkpoint.json
202
202
  ```
203
203
 
204
+ ### 4. RENAME SPEC
205
+
206
+ ```bash
207
+ # Rename spec to done
208
+ mv specs/doing-${SPEC_NAME}.md specs/done-${SPEC_NAME}.md
209
+ ```
210
+
211
+ ### 5. EXTRACT DECISIONS
212
+
213
+ Read the renamed `specs/done-${SPEC_NAME}.md` file. Model-extract architectural decisions:
214
+ - Explicit choices → `[APPROACH]`
215
+ - Unvalidated assumptions → `[ASSUMPTION]`
216
+ - "For now" decisions → `[PROVISIONAL]`
217
+
218
+ Append to `.deepflow/decisions.md`:
219
+ ```
220
+ ### {YYYY-MM-DD} — {spec-name}
221
+ - [TAG] decision text — rationale
222
+ ```
223
+
224
+ After successful append, delete `specs/done-${SPEC_NAME}.md`. If write fails, preserve the file.
225
+
204
226
  Output:
205
227
  ```
206
228
  ✓ Merged df/upload to main
@@ -210,6 +232,3 @@ Output:
210
232
  Workflow complete! Ready for next feature: /df:spec <name>
211
233
  ```
212
234
 
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.