wogiflow 1.0.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.
Files changed (221) hide show
  1. package/.workflow/agents/reviewer.md +81 -0
  2. package/.workflow/agents/security.md +94 -0
  3. package/.workflow/agents/story-writer.md +58 -0
  4. package/.workflow/bridges/base-bridge.js +395 -0
  5. package/.workflow/bridges/claude-bridge.js +434 -0
  6. package/.workflow/bridges/index.js +130 -0
  7. package/.workflow/lib/assumption-detector.js +481 -0
  8. package/.workflow/lib/config-substitution.js +371 -0
  9. package/.workflow/lib/failure-categories.js +478 -0
  10. package/.workflow/state/app-map.md.template +15 -0
  11. package/.workflow/state/architecture.md.template +24 -0
  12. package/.workflow/state/component-index.json.template +5 -0
  13. package/.workflow/state/decisions.md.template +15 -0
  14. package/.workflow/state/feedback-patterns.md.template +9 -0
  15. package/.workflow/state/knowledge-sync.json.template +6 -0
  16. package/.workflow/state/progress.md.template +14 -0
  17. package/.workflow/state/ready.json.template +7 -0
  18. package/.workflow/state/request-log.md.template +14 -0
  19. package/.workflow/state/session-state.json.template +11 -0
  20. package/.workflow/state/stack.md.template +33 -0
  21. package/.workflow/state/testing.md.template +36 -0
  22. package/.workflow/templates/claude-md.hbs +257 -0
  23. package/.workflow/templates/correction-report.md +67 -0
  24. package/.workflow/templates/gemini-md.hbs +52 -0
  25. package/README.md +1802 -0
  26. package/bin/flow +205 -0
  27. package/lib/index.js +33 -0
  28. package/lib/installer.js +467 -0
  29. package/lib/release-channel.js +269 -0
  30. package/lib/skill-registry.js +526 -0
  31. package/lib/upgrader.js +401 -0
  32. package/lib/utils.js +305 -0
  33. package/package.json +64 -0
  34. package/scripts/flow +985 -0
  35. package/scripts/flow-adaptive-learning.js +1259 -0
  36. package/scripts/flow-aggregate.js +488 -0
  37. package/scripts/flow-archive +133 -0
  38. package/scripts/flow-auto-context.js +1015 -0
  39. package/scripts/flow-auto-learn.js +615 -0
  40. package/scripts/flow-bridge.js +223 -0
  41. package/scripts/flow-browser-suggest.js +316 -0
  42. package/scripts/flow-bug.js +247 -0
  43. package/scripts/flow-cascade.js +711 -0
  44. package/scripts/flow-changelog +85 -0
  45. package/scripts/flow-checkpoint.js +483 -0
  46. package/scripts/flow-cli.js +403 -0
  47. package/scripts/flow-code-intelligence.js +760 -0
  48. package/scripts/flow-complexity.js +502 -0
  49. package/scripts/flow-config-set.js +152 -0
  50. package/scripts/flow-constants.js +157 -0
  51. package/scripts/flow-context +152 -0
  52. package/scripts/flow-context-init.js +482 -0
  53. package/scripts/flow-context-monitor.js +384 -0
  54. package/scripts/flow-context-scoring.js +886 -0
  55. package/scripts/flow-correct.js +458 -0
  56. package/scripts/flow-damage-control.js +985 -0
  57. package/scripts/flow-deps +101 -0
  58. package/scripts/flow-diff.js +700 -0
  59. package/scripts/flow-done +151 -0
  60. package/scripts/flow-done.js +489 -0
  61. package/scripts/flow-durable-session.js +1541 -0
  62. package/scripts/flow-entropy-monitor.js +345 -0
  63. package/scripts/flow-export-profile +349 -0
  64. package/scripts/flow-export-scanner.js +1046 -0
  65. package/scripts/flow-figma-confirm.js +400 -0
  66. package/scripts/flow-figma-extract.js +496 -0
  67. package/scripts/flow-figma-generate.js +683 -0
  68. package/scripts/flow-figma-index.js +909 -0
  69. package/scripts/flow-figma-match.js +617 -0
  70. package/scripts/flow-figma-mcp-server.js +518 -0
  71. package/scripts/flow-figma-pipeline.js +414 -0
  72. package/scripts/flow-file-ops.js +301 -0
  73. package/scripts/flow-gate-confidence.js +825 -0
  74. package/scripts/flow-guided-edit.js +659 -0
  75. package/scripts/flow-health +185 -0
  76. package/scripts/flow-health.js +413 -0
  77. package/scripts/flow-hooks.js +556 -0
  78. package/scripts/flow-http-client.js +249 -0
  79. package/scripts/flow-hybrid-detect.js +167 -0
  80. package/scripts/flow-hybrid-interactive.js +591 -0
  81. package/scripts/flow-hybrid-test.js +152 -0
  82. package/scripts/flow-import-profile +439 -0
  83. package/scripts/flow-init +253 -0
  84. package/scripts/flow-instruction-richness.js +827 -0
  85. package/scripts/flow-jira-integration.js +579 -0
  86. package/scripts/flow-knowledge-router.js +522 -0
  87. package/scripts/flow-knowledge-sync.js +589 -0
  88. package/scripts/flow-linear-integration.js +631 -0
  89. package/scripts/flow-links.js +774 -0
  90. package/scripts/flow-log-manager.js +559 -0
  91. package/scripts/flow-loop-enforcer.js +1246 -0
  92. package/scripts/flow-loop-retry-learning.js +630 -0
  93. package/scripts/flow-lsp.js +923 -0
  94. package/scripts/flow-map-index +348 -0
  95. package/scripts/flow-map-sync +201 -0
  96. package/scripts/flow-memory-blocks.js +668 -0
  97. package/scripts/flow-memory-compactor.js +350 -0
  98. package/scripts/flow-memory-db.js +1110 -0
  99. package/scripts/flow-memory-sync.js +484 -0
  100. package/scripts/flow-metrics.js +353 -0
  101. package/scripts/flow-migrate-ids.js +370 -0
  102. package/scripts/flow-model-adapter.js +802 -0
  103. package/scripts/flow-model-router.js +884 -0
  104. package/scripts/flow-models.js +1231 -0
  105. package/scripts/flow-morning.js +517 -0
  106. package/scripts/flow-multi-approach.js +660 -0
  107. package/scripts/flow-new-feature +86 -0
  108. package/scripts/flow-onboard +1042 -0
  109. package/scripts/flow-orchestrate-llm.js +459 -0
  110. package/scripts/flow-orchestrate.js +3592 -0
  111. package/scripts/flow-output.js +123 -0
  112. package/scripts/flow-parallel-detector.js +399 -0
  113. package/scripts/flow-parallel-dispatch.js +987 -0
  114. package/scripts/flow-parallel.js +428 -0
  115. package/scripts/flow-pattern-enforcer.js +600 -0
  116. package/scripts/flow-prd-manager.js +282 -0
  117. package/scripts/flow-progress.js +323 -0
  118. package/scripts/flow-project-analyzer.js +975 -0
  119. package/scripts/flow-prompt-composer.js +487 -0
  120. package/scripts/flow-providers.js +1381 -0
  121. package/scripts/flow-queue.js +308 -0
  122. package/scripts/flow-ready +82 -0
  123. package/scripts/flow-ready.js +189 -0
  124. package/scripts/flow-regression.js +396 -0
  125. package/scripts/flow-response-parser.js +450 -0
  126. package/scripts/flow-resume.js +284 -0
  127. package/scripts/flow-rules-sync.js +439 -0
  128. package/scripts/flow-run-trace.js +718 -0
  129. package/scripts/flow-safety.js +587 -0
  130. package/scripts/flow-search +104 -0
  131. package/scripts/flow-security.js +481 -0
  132. package/scripts/flow-session-end +106 -0
  133. package/scripts/flow-session-end.js +437 -0
  134. package/scripts/flow-session-state.js +671 -0
  135. package/scripts/flow-setup-hooks +216 -0
  136. package/scripts/flow-setup-hooks.js +377 -0
  137. package/scripts/flow-skill-create.js +329 -0
  138. package/scripts/flow-skill-creator.js +572 -0
  139. package/scripts/flow-skill-generator.js +1046 -0
  140. package/scripts/flow-skill-learn.js +880 -0
  141. package/scripts/flow-skill-matcher.js +578 -0
  142. package/scripts/flow-spec-generator.js +820 -0
  143. package/scripts/flow-stack-wizard.js +895 -0
  144. package/scripts/flow-standup +162 -0
  145. package/scripts/flow-start +74 -0
  146. package/scripts/flow-start.js +235 -0
  147. package/scripts/flow-status +110 -0
  148. package/scripts/flow-status.js +301 -0
  149. package/scripts/flow-step-browser.js +83 -0
  150. package/scripts/flow-step-changelog.js +217 -0
  151. package/scripts/flow-step-comments.js +306 -0
  152. package/scripts/flow-step-complexity.js +234 -0
  153. package/scripts/flow-step-coverage.js +218 -0
  154. package/scripts/flow-step-knowledge.js +193 -0
  155. package/scripts/flow-step-pr-tests.js +364 -0
  156. package/scripts/flow-step-regression.js +89 -0
  157. package/scripts/flow-step-review.js +516 -0
  158. package/scripts/flow-step-security.js +162 -0
  159. package/scripts/flow-step-silent-failures.js +290 -0
  160. package/scripts/flow-step-simplifier.js +346 -0
  161. package/scripts/flow-story +105 -0
  162. package/scripts/flow-story.js +500 -0
  163. package/scripts/flow-suspend.js +252 -0
  164. package/scripts/flow-sync-daemon.js +654 -0
  165. package/scripts/flow-task-analyzer.js +606 -0
  166. package/scripts/flow-team-dashboard.js +748 -0
  167. package/scripts/flow-team-sync.js +752 -0
  168. package/scripts/flow-team.js +977 -0
  169. package/scripts/flow-tech-options.js +528 -0
  170. package/scripts/flow-templates.js +812 -0
  171. package/scripts/flow-tiered-learning.js +728 -0
  172. package/scripts/flow-trace +204 -0
  173. package/scripts/flow-transcript-chunking.js +1106 -0
  174. package/scripts/flow-transcript-digest.js +7918 -0
  175. package/scripts/flow-transcript-language.js +465 -0
  176. package/scripts/flow-transcript-parsing.js +1085 -0
  177. package/scripts/flow-transcript-stories.js +2194 -0
  178. package/scripts/flow-update-map +224 -0
  179. package/scripts/flow-utils.js +2242 -0
  180. package/scripts/flow-verification.js +644 -0
  181. package/scripts/flow-verify.js +1177 -0
  182. package/scripts/flow-voice-input.js +638 -0
  183. package/scripts/flow-watch +168 -0
  184. package/scripts/flow-workflow-steps.js +521 -0
  185. package/scripts/flow-workflow.js +1029 -0
  186. package/scripts/flow-worktree.js +489 -0
  187. package/scripts/hooks/adapters/base-adapter.js +102 -0
  188. package/scripts/hooks/adapters/claude-code.js +359 -0
  189. package/scripts/hooks/adapters/index.js +79 -0
  190. package/scripts/hooks/core/component-check.js +341 -0
  191. package/scripts/hooks/core/index.js +35 -0
  192. package/scripts/hooks/core/loop-check.js +241 -0
  193. package/scripts/hooks/core/session-context.js +294 -0
  194. package/scripts/hooks/core/task-gate.js +177 -0
  195. package/scripts/hooks/core/validation.js +230 -0
  196. package/scripts/hooks/entry/claude-code/post-tool-use.js +65 -0
  197. package/scripts/hooks/entry/claude-code/pre-tool-use.js +89 -0
  198. package/scripts/hooks/entry/claude-code/session-end.js +87 -0
  199. package/scripts/hooks/entry/claude-code/session-start.js +46 -0
  200. package/scripts/hooks/entry/claude-code/stop.js +43 -0
  201. package/scripts/postinstall.js +139 -0
  202. package/templates/browser-test-flow.json +56 -0
  203. package/templates/bug-report.md +43 -0
  204. package/templates/component-detail.md +42 -0
  205. package/templates/component.stories.tsx +49 -0
  206. package/templates/context/constraints.md +83 -0
  207. package/templates/context/conventions.md +177 -0
  208. package/templates/context/stack.md +60 -0
  209. package/templates/correction-report.md +90 -0
  210. package/templates/feature-proposal.md +35 -0
  211. package/templates/hybrid/_base.md +254 -0
  212. package/templates/hybrid/_patterns.md +45 -0
  213. package/templates/hybrid/create-component.md +127 -0
  214. package/templates/hybrid/create-file.md +56 -0
  215. package/templates/hybrid/create-hook.md +145 -0
  216. package/templates/hybrid/create-service.md +70 -0
  217. package/templates/hybrid/fix-bug.md +33 -0
  218. package/templates/hybrid/modify-file.md +55 -0
  219. package/templates/story.md +68 -0
  220. package/templates/task.json +56 -0
  221. package/templates/trace.md +69 -0
@@ -0,0 +1,668 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow - Memory Blocks Manager
5
+ *
6
+ * Handles structured memory blocks within progress.md.
7
+ * Allows programmatic access while maintaining human readability.
8
+ *
9
+ * Memory blocks are JSON stored in a markdown comment block,
10
+ * allowing both machine parsing and human readability.
11
+ *
12
+ * Part of v1.7.0 Context Memory Management
13
+ */
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+ const {
18
+ getConfig,
19
+ PATHS,
20
+ STATE_DIR,
21
+ colors,
22
+ color,
23
+ warn,
24
+ success,
25
+ error,
26
+ readFile,
27
+ writeFile,
28
+ fileExists,
29
+ printHeader
30
+ } = require('./flow-utils');
31
+
32
+ // ============================================================
33
+ // Constants
34
+ // ============================================================
35
+
36
+ const PROGRESS_PATH = PATHS.progress;
37
+ const BLOCK_START = '<!-- MEMORY-BLOCKS-START -->';
38
+ const BLOCK_END = '<!-- MEMORY-BLOCKS-END -->';
39
+
40
+ // ============================================================
41
+ // Default Structures
42
+ // ============================================================
43
+
44
+ /**
45
+ * Default memory blocks structure
46
+ */
47
+ function getDefaultBlocks() {
48
+ return {
49
+ currentTask: null,
50
+ sessionContext: {
51
+ filesModified: [],
52
+ decisionsThisSession: [],
53
+ blockers: []
54
+ },
55
+ keyFacts: [],
56
+ lastUpdated: new Date().toISOString()
57
+ };
58
+ }
59
+
60
+ /**
61
+ * Default progress.md template with memory blocks section
62
+ */
63
+ function getDefaultProgress() {
64
+ const blocks = getDefaultBlocks();
65
+ const now = new Date().toISOString().split('T')[0];
66
+
67
+ return `# Progress & Handoff Notes
68
+
69
+ Session handoff notes for human readability.
70
+
71
+ ---
72
+
73
+ ## Last Updated
74
+ ${now}
75
+
76
+ ---
77
+
78
+ ## Memory Blocks
79
+ ${BLOCK_START}
80
+ \`\`\`json
81
+ ${JSON.stringify(blocks, null, 2)}
82
+ \`\`\`
83
+ ${BLOCK_END}
84
+
85
+ ---
86
+
87
+ ## Last Session
88
+ _No previous session recorded_
89
+
90
+ ## In Progress
91
+ _Nothing in progress_
92
+
93
+ ## Next
94
+ _No next steps defined_
95
+
96
+ ## Blockers
97
+ _None_
98
+
99
+ ## Notes
100
+ _No notes_
101
+
102
+ ---
103
+ `;
104
+ }
105
+
106
+ // ============================================================
107
+ // Core Operations
108
+ // ============================================================
109
+
110
+ /**
111
+ * Read memory blocks from progress.md
112
+ * Returns null if blocks section doesn't exist or is invalid
113
+ */
114
+ function readMemoryBlocks() {
115
+ if (!fileExists(PROGRESS_PATH)) {
116
+ return null;
117
+ }
118
+
119
+ try {
120
+ const content = fs.readFileSync(PROGRESS_PATH, 'utf-8');
121
+
122
+ const startIdx = content.indexOf(BLOCK_START);
123
+ const endIdx = content.indexOf(BLOCK_END);
124
+
125
+ if (startIdx === -1 || endIdx === -1) {
126
+ return null;
127
+ }
128
+
129
+ // Extract JSON from within the markdown code block
130
+ const blockSection = content.slice(startIdx + BLOCK_START.length, endIdx);
131
+ const jsonMatch = blockSection.match(/```json\n([\s\S]*?)\n```/);
132
+
133
+ if (!jsonMatch) {
134
+ return null;
135
+ }
136
+
137
+ return JSON.parse(jsonMatch[1].trim());
138
+ } catch (err) {
139
+ if (process.env.DEBUG) {
140
+ console.error(`[DEBUG] Failed to read memory blocks: ${err.message}`);
141
+ }
142
+ return null;
143
+ }
144
+ }
145
+
146
+ /**
147
+ * Write memory blocks to progress.md
148
+ * Creates the section if it doesn't exist
149
+ */
150
+ function writeMemoryBlocks(blocks) {
151
+ // Clone to avoid mutating caller's data
152
+ const toWrite = { ...blocks, lastUpdated: new Date().toISOString() };
153
+
154
+ let content;
155
+ if (!fileExists(PROGRESS_PATH)) {
156
+ content = getDefaultProgress();
157
+ } else {
158
+ content = fs.readFileSync(PROGRESS_PATH, 'utf-8');
159
+ }
160
+
161
+ const blockContent = `${BLOCK_START}
162
+ \`\`\`json
163
+ ${JSON.stringify(toWrite, null, 2)}
164
+ \`\`\`
165
+ ${BLOCK_END}`;
166
+
167
+ const startIdx = content.indexOf(BLOCK_START);
168
+ const endIdx = content.indexOf(BLOCK_END);
169
+
170
+ if (startIdx !== -1 && endIdx !== -1) {
171
+ // Replace existing blocks
172
+ content = content.slice(0, startIdx) + blockContent + content.slice(endIdx + BLOCK_END.length);
173
+ } else {
174
+ // Insert after "## Memory Blocks" header if it exists
175
+ const headerIdx = content.indexOf('## Memory Blocks');
176
+ if (headerIdx !== -1) {
177
+ const insertPoint = content.indexOf('\n', headerIdx) + 1;
178
+ content = content.slice(0, insertPoint) + blockContent + '\n' + content.slice(insertPoint);
179
+ } else {
180
+ // Insert after "## Last Updated" section
181
+ const lastUpdatedIdx = content.indexOf('## Last Updated');
182
+ if (lastUpdatedIdx !== -1) {
183
+ // Find end of Last Updated section (next ---)
184
+ const nextDivider = content.indexOf('---', lastUpdatedIdx + 10);
185
+ if (nextDivider !== -1) {
186
+ const insertPoint = nextDivider + 4;
187
+ content = content.slice(0, insertPoint) + '\n## Memory Blocks\n' + blockContent + '\n\n---\n' + content.slice(insertPoint);
188
+ }
189
+ }
190
+ }
191
+ }
192
+
193
+ fs.writeFileSync(PROGRESS_PATH, content);
194
+ return true;
195
+ }
196
+
197
+ /**
198
+ * Get memory blocks, creating defaults if needed
199
+ */
200
+ function getOrCreateBlocks() {
201
+ let blocks = readMemoryBlocks();
202
+ if (!blocks) {
203
+ blocks = getDefaultBlocks();
204
+ writeMemoryBlocks(blocks);
205
+ }
206
+ return blocks;
207
+ }
208
+
209
+ // ============================================================
210
+ // Update Operations
211
+ // ============================================================
212
+
213
+ /**
214
+ * Update a specific block by key
215
+ */
216
+ function updateBlock(key, value) {
217
+ const blocks = getOrCreateBlocks();
218
+ blocks[key] = value;
219
+ writeMemoryBlocks(blocks);
220
+ return blocks;
221
+ }
222
+
223
+ /**
224
+ * Update current task
225
+ */
226
+ function setCurrentTask(taskId, taskTitle, metadata = {}) {
227
+ return updateBlock('currentTask', {
228
+ id: taskId,
229
+ title: taskTitle,
230
+ startedAt: new Date().toISOString(),
231
+ ...metadata
232
+ });
233
+ }
234
+
235
+ /**
236
+ * Clear current task
237
+ */
238
+ function clearCurrentTask() {
239
+ return updateBlock('currentTask', null);
240
+ }
241
+
242
+ /**
243
+ * Add a key fact (max 10 kept)
244
+ */
245
+ function addKeyFact(fact) {
246
+ const blocks = getOrCreateBlocks();
247
+
248
+ if (!blocks.keyFacts.includes(fact)) {
249
+ blocks.keyFacts.push(fact);
250
+
251
+ // Keep only last 10 facts
252
+ if (blocks.keyFacts.length > 10) {
253
+ blocks.keyFacts = blocks.keyFacts.slice(-10);
254
+ }
255
+
256
+ writeMemoryBlocks(blocks);
257
+ }
258
+
259
+ return blocks;
260
+ }
261
+
262
+ /**
263
+ * Remove a key fact
264
+ */
265
+ function removeKeyFact(fact) {
266
+ const blocks = getOrCreateBlocks();
267
+ blocks.keyFacts = blocks.keyFacts.filter(f => f !== fact);
268
+ writeMemoryBlocks(blocks);
269
+ return blocks;
270
+ }
271
+
272
+ /**
273
+ * Track a file modification
274
+ */
275
+ function trackFileModified(filePath) {
276
+ const blocks = getOrCreateBlocks();
277
+ const relPath = path.relative(process.cwd(), filePath);
278
+
279
+ if (!blocks.sessionContext.filesModified.includes(relPath)) {
280
+ blocks.sessionContext.filesModified.push(relPath);
281
+
282
+ // Keep only last 20 files
283
+ if (blocks.sessionContext.filesModified.length > 20) {
284
+ blocks.sessionContext.filesModified = blocks.sessionContext.filesModified.slice(-20);
285
+ }
286
+
287
+ writeMemoryBlocks(blocks);
288
+ }
289
+
290
+ return blocks;
291
+ }
292
+
293
+ /**
294
+ * Track a decision made this session
295
+ */
296
+ function trackDecision(decision) {
297
+ const blocks = getOrCreateBlocks();
298
+
299
+ if (!blocks.sessionContext.decisionsThisSession.includes(decision)) {
300
+ blocks.sessionContext.decisionsThisSession.push(decision);
301
+
302
+ // Keep only last 10 decisions
303
+ if (blocks.sessionContext.decisionsThisSession.length > 10) {
304
+ blocks.sessionContext.decisionsThisSession = blocks.sessionContext.decisionsThisSession.slice(-10);
305
+ }
306
+
307
+ writeMemoryBlocks(blocks);
308
+ }
309
+
310
+ return blocks;
311
+ }
312
+
313
+ /**
314
+ * Add a blocker
315
+ */
316
+ function addBlocker(blocker) {
317
+ const blocks = getOrCreateBlocks();
318
+
319
+ if (!blocks.sessionContext.blockers.includes(blocker)) {
320
+ blocks.sessionContext.blockers.push(blocker);
321
+ writeMemoryBlocks(blocks);
322
+ }
323
+
324
+ return blocks;
325
+ }
326
+
327
+ /**
328
+ * Remove a blocker
329
+ */
330
+ function removeBlocker(blocker) {
331
+ const blocks = getOrCreateBlocks();
332
+ blocks.sessionContext.blockers = blocks.sessionContext.blockers.filter(b => b !== blocker);
333
+ writeMemoryBlocks(blocks);
334
+ return blocks;
335
+ }
336
+
337
+ /**
338
+ * Clear all blockers
339
+ */
340
+ function clearBlockers() {
341
+ const blocks = getOrCreateBlocks();
342
+ blocks.sessionContext.blockers = [];
343
+ writeMemoryBlocks(blocks);
344
+ return blocks;
345
+ }
346
+
347
+ /**
348
+ * Reset session context (for new session)
349
+ */
350
+ function resetSessionContext() {
351
+ const blocks = getOrCreateBlocks();
352
+ blocks.sessionContext = {
353
+ filesModified: [],
354
+ decisionsThisSession: [],
355
+ blockers: []
356
+ };
357
+ // Don't clear currentTask or keyFacts - those persist
358
+ writeMemoryBlocks(blocks);
359
+ return blocks;
360
+ }
361
+
362
+ // ============================================================
363
+ // Query Operations
364
+ // ============================================================
365
+
366
+ /**
367
+ * Get current task info
368
+ */
369
+ function getCurrentTask() {
370
+ const blocks = readMemoryBlocks();
371
+ return blocks?.currentTask || null;
372
+ }
373
+
374
+ /**
375
+ * Get all key facts
376
+ */
377
+ function getKeyFacts() {
378
+ const blocks = readMemoryBlocks();
379
+ return blocks?.keyFacts || [];
380
+ }
381
+
382
+ /**
383
+ * Get session context
384
+ */
385
+ function getSessionContext() {
386
+ const blocks = readMemoryBlocks();
387
+ return blocks?.sessionContext || {
388
+ filesModified: [],
389
+ decisionsThisSession: [],
390
+ blockers: []
391
+ };
392
+ }
393
+
394
+ /**
395
+ * Get summary for Claude (useful for resume context)
396
+ */
397
+ function getResumeContext() {
398
+ const blocks = readMemoryBlocks();
399
+ if (!blocks) return null;
400
+
401
+ const lines = [];
402
+
403
+ if (blocks.currentTask) {
404
+ lines.push(`**Resuming task**: ${blocks.currentTask.id} - ${blocks.currentTask.title}`);
405
+ if (blocks.currentTask.startedAt) {
406
+ const started = new Date(blocks.currentTask.startedAt);
407
+ lines.push(` Started: ${started.toLocaleString()}`);
408
+ }
409
+ }
410
+
411
+ if (blocks.sessionContext?.filesModified?.length > 0) {
412
+ lines.push(`**Recently modified**: ${blocks.sessionContext.filesModified.slice(-5).join(', ')}`);
413
+ }
414
+
415
+ if (blocks.keyFacts?.length > 0) {
416
+ lines.push(`**Key context**:`);
417
+ for (const fact of blocks.keyFacts.slice(-5)) {
418
+ lines.push(` - ${fact}`);
419
+ }
420
+ }
421
+
422
+ if (blocks.sessionContext?.blockers?.length > 0) {
423
+ lines.push(`**Blockers**: ${blocks.sessionContext.blockers.join(', ')}`);
424
+ }
425
+
426
+ return lines.length > 0 ? lines.join('\n') : null;
427
+ }
428
+
429
+ // ============================================================
430
+ // Migration
431
+ // ============================================================
432
+
433
+ /**
434
+ * Migrate existing progress.md to include memory blocks
435
+ * Only adds blocks section if it doesn't exist
436
+ */
437
+ function migrateProgressFile() {
438
+ if (!fileExists(PROGRESS_PATH)) {
439
+ // Create with template
440
+ fs.writeFileSync(PROGRESS_PATH, getDefaultProgress());
441
+ return { migrated: true, action: 'created' };
442
+ }
443
+
444
+ const content = fs.readFileSync(PROGRESS_PATH, 'utf-8');
445
+
446
+ if (content.includes(BLOCK_START)) {
447
+ return { migrated: false, reason: 'already has memory blocks' };
448
+ }
449
+
450
+ // Add memory blocks section
451
+ writeMemoryBlocks(getDefaultBlocks());
452
+ return { migrated: true, action: 'updated' };
453
+ }
454
+
455
+ // ============================================================
456
+ // CLI Interface
457
+ // ============================================================
458
+
459
+ function printUsage() {
460
+ console.log(`
461
+ Usage: flow-memory-blocks.js [command] [args]
462
+
463
+ Commands:
464
+ show Show current memory blocks
465
+ migrate Add memory blocks to existing progress.md
466
+ task <id> <title> Set current task
467
+ task clear Clear current task
468
+ fact add <fact> Add a key fact
469
+ fact remove <idx> Remove a key fact by index
470
+ fact list List all key facts
471
+ file <path> Track file modification
472
+ decision <text> Track a decision
473
+ blocker add <b> Add a blocker
474
+ blocker clear Clear all blockers
475
+ reset-session Reset session context
476
+ resume Show resume context
477
+ --help Show this help
478
+
479
+ Examples:
480
+ node scripts/flow-memory-blocks.js show
481
+ node scripts/flow-memory-blocks.js task TASK-042 "Add login form"
482
+ node scripts/flow-memory-blocks.js fact add "Using React 18 with TypeScript"
483
+ `);
484
+ }
485
+
486
+ // Main CLI handler
487
+ if (require.main === module) {
488
+ const args = process.argv.slice(2);
489
+ const command = args[0];
490
+
491
+ switch (command) {
492
+ case 'show': {
493
+ const blocks = readMemoryBlocks();
494
+ if (blocks) {
495
+ printHeader('Memory Blocks');
496
+ console.log(JSON.stringify(blocks, null, 2));
497
+ } else {
498
+ warn('No memory blocks found. Run "migrate" to add them.');
499
+ }
500
+ break;
501
+ }
502
+
503
+ case 'migrate': {
504
+ const result = migrateProgressFile();
505
+ if (result.migrated) {
506
+ success(`Progress file ${result.action} with memory blocks`);
507
+ } else {
508
+ console.log(`No migration needed: ${result.reason}`);
509
+ }
510
+ break;
511
+ }
512
+
513
+ case 'task': {
514
+ if (args[1] === 'clear') {
515
+ clearCurrentTask();
516
+ success('Current task cleared');
517
+ } else if (args[1] && args[2]) {
518
+ setCurrentTask(args[1], args.slice(2).join(' '));
519
+ success(`Set current task: ${args[1]}`);
520
+ } else {
521
+ const task = getCurrentTask();
522
+ if (task) {
523
+ console.log(`Current task: ${task.id} - ${task.title}`);
524
+ } else {
525
+ console.log('No current task');
526
+ }
527
+ }
528
+ break;
529
+ }
530
+
531
+ case 'fact': {
532
+ if (args[1] === 'add' && args[2]) {
533
+ addKeyFact(args.slice(2).join(' '));
534
+ success('Key fact added');
535
+ } else if (args[1] === 'remove' && args[2]) {
536
+ const facts = getKeyFacts();
537
+ const idx = parseInt(args[2], 10);
538
+ if (idx >= 0 && idx < facts.length) {
539
+ removeKeyFact(facts[idx]);
540
+ success(`Removed fact: "${facts[idx]}"`);
541
+ } else {
542
+ error(`Invalid index: ${args[2]}`);
543
+ }
544
+ } else if (args[1] === 'list') {
545
+ const facts = getKeyFacts();
546
+ if (facts.length > 0) {
547
+ console.log('Key facts:');
548
+ facts.forEach((f, i) => console.log(` ${i}. ${f}`));
549
+ } else {
550
+ console.log('No key facts');
551
+ }
552
+ } else {
553
+ error('Usage: fact [add|remove|list] [args]');
554
+ }
555
+ break;
556
+ }
557
+
558
+ case 'file': {
559
+ if (args[1]) {
560
+ trackFileModified(args[1]);
561
+ success(`Tracked file: ${args[1]}`);
562
+ } else {
563
+ const ctx = getSessionContext();
564
+ console.log('Modified files:', ctx.filesModified.join(', ') || 'none');
565
+ }
566
+ break;
567
+ }
568
+
569
+ case 'decision': {
570
+ if (args[1]) {
571
+ trackDecision(args.slice(1).join(' '));
572
+ success('Decision tracked');
573
+ } else {
574
+ const ctx = getSessionContext();
575
+ console.log('Decisions:', ctx.decisionsThisSession.join(', ') || 'none');
576
+ }
577
+ break;
578
+ }
579
+
580
+ case 'blocker': {
581
+ if (args[1] === 'add' && args[2]) {
582
+ addBlocker(args.slice(2).join(' '));
583
+ success('Blocker added');
584
+ } else if (args[1] === 'clear') {
585
+ clearBlockers();
586
+ success('Blockers cleared');
587
+ } else {
588
+ const ctx = getSessionContext();
589
+ console.log('Blockers:', ctx.blockers.join(', ') || 'none');
590
+ }
591
+ break;
592
+ }
593
+
594
+ case 'reset-session': {
595
+ resetSessionContext();
596
+ success('Session context reset');
597
+ break;
598
+ }
599
+
600
+ case 'resume': {
601
+ const ctx = getResumeContext();
602
+ if (ctx) {
603
+ printHeader('Resume Context');
604
+ console.log(ctx);
605
+ } else {
606
+ console.log('No resume context available');
607
+ }
608
+ break;
609
+ }
610
+
611
+ case '--help':
612
+ case '-h':
613
+ printUsage();
614
+ break;
615
+
616
+ default:
617
+ if (command) {
618
+ error(`Unknown command: ${command}`);
619
+ }
620
+ printUsage();
621
+ process.exit(command ? 1 : 0);
622
+ }
623
+ }
624
+
625
+ // ============================================================
626
+ // Exports
627
+ // ============================================================
628
+
629
+ module.exports = {
630
+ // Core operations
631
+ readMemoryBlocks,
632
+ writeMemoryBlocks,
633
+ getOrCreateBlocks,
634
+ updateBlock,
635
+
636
+ // Task operations
637
+ setCurrentTask,
638
+ clearCurrentTask,
639
+ getCurrentTask,
640
+
641
+ // Key facts
642
+ addKeyFact,
643
+ removeKeyFact,
644
+ getKeyFacts,
645
+
646
+ // Session tracking
647
+ trackFileModified,
648
+ trackDecision,
649
+ addBlocker,
650
+ removeBlocker,
651
+ clearBlockers,
652
+ getSessionContext,
653
+ resetSessionContext,
654
+
655
+ // Resume context
656
+ getResumeContext,
657
+
658
+ // Migration
659
+ migrateProgressFile,
660
+
661
+ // Defaults
662
+ getDefaultBlocks,
663
+ getDefaultProgress,
664
+
665
+ // Constants
666
+ BLOCK_START,
667
+ BLOCK_END
668
+ };