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,350 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow - Memory Compactor
5
+ *
6
+ * Manages memory compaction: demotion, cold storage, merging, and purging.
7
+ *
8
+ * Commands:
9
+ * ./scripts/flow compact-memory - Full compaction
10
+ * ./scripts/flow compact-memory --demote - Only demote low-relevance facts
11
+ * ./scripts/flow compact-memory --merge - Only merge duplicates
12
+ * ./scripts/flow compact-memory --purge - Only purge old cold facts
13
+ * ./scripts/flow compact-memory --restore <id> - Restore from cold storage
14
+ * ./scripts/flow compact-memory --cold - List cold storage contents
15
+ *
16
+ * Part of v1.8.0 - Automatic Memory Management
17
+ */
18
+
19
+ const fs = require('fs');
20
+ const path = require('path');
21
+ const memoryDb = require('./flow-memory-db');
22
+
23
+ // ============================================================
24
+ // Configuration
25
+ // ============================================================
26
+
27
+ const PROJECT_ROOT = process.env.WOGI_PROJECT_ROOT || process.cwd();
28
+ const CONFIG_PATH = path.join(PROJECT_ROOT, '.workflow', 'config.json');
29
+
30
+ function loadConfig() {
31
+ try {
32
+ if (fs.existsSync(CONFIG_PATH)) {
33
+ return JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf-8'));
34
+ }
35
+ } catch {}
36
+ return {};
37
+ }
38
+
39
+ // ============================================================
40
+ // Output Formatting
41
+ // ============================================================
42
+
43
+ function color(c, text) {
44
+ const colors = {
45
+ red: '\x1b[31m',
46
+ green: '\x1b[32m',
47
+ yellow: '\x1b[33m',
48
+ blue: '\x1b[34m',
49
+ cyan: '\x1b[36m',
50
+ gray: '\x1b[90m',
51
+ reset: '\x1b[0m'
52
+ };
53
+ return `${colors[c] || ''}${text}${colors.reset}`;
54
+ }
55
+
56
+ function formatEntropy(entropy) {
57
+ if (entropy < 0.4) return color('green', `${entropy}`);
58
+ if (entropy < 0.7) return color('yellow', `${entropy}`);
59
+ return color('red', `${entropy}`);
60
+ }
61
+
62
+ // ============================================================
63
+ // Commands
64
+ // ============================================================
65
+
66
+ /**
67
+ * Full compaction - all operations
68
+ */
69
+ async function fullCompaction(config) {
70
+ console.log(color('cyan', '\nMemory Compaction'));
71
+ console.log('═'.repeat(50));
72
+
73
+ const memoryConfig = { maxLocalFacts: config.memory?.maxLocalFacts || 1000 };
74
+ const beforeStats = await memoryDb.getEntropyStats(memoryConfig);
75
+
76
+ console.log(`\nBefore: ${beforeStats.totalFacts} facts | Entropy: ${formatEntropy(beforeStats.entropy)}`);
77
+
78
+ const results = {};
79
+
80
+ // 1. Apply relevance decay
81
+ console.log(`\n${color('blue', '1. Applying relevance decay...')}`);
82
+ results.decay = await memoryDb.applyRelevanceDecay({
83
+ decayRate: config.automaticMemory?.relevanceDecay?.decayRate || 0.033,
84
+ neverAccessedPenalty: config.automaticMemory?.relevanceDecay?.neverAccessedPenalty || 0.1
85
+ });
86
+ console.log(` ${color('green', '✓')} Updated ${results.decay.decayed} facts`);
87
+
88
+ // 2. Demote low-relevance facts
89
+ console.log(`\n${color('blue', '2. Demoting low-relevance facts...')}`);
90
+ results.demotion = await memoryDb.demoteToColdStorage({
91
+ relevanceThreshold: config.automaticMemory?.demotion?.relevanceThreshold || 0.3
92
+ });
93
+ console.log(` ${color('green', '✓')} Demoted ${results.demotion.demoted} facts to cold storage`);
94
+
95
+ // 3. Merge similar facts
96
+ console.log(`\n${color('blue', '3. Merging duplicate facts...')}`);
97
+ results.merge = await memoryDb.mergeSimilarFacts({
98
+ mergeSimilarityThreshold: 0.95
99
+ });
100
+ console.log(` ${color('green', '✓')} Merged ${results.merge.merged} duplicate pairs`);
101
+
102
+ // 4. Purge old cold facts
103
+ console.log(`\n${color('blue', '4. Purging old cold storage...')}`);
104
+ results.purge = await memoryDb.purgeColdFacts({
105
+ coldRetentionDays: config.automaticMemory?.demotion?.coldRetentionDays || 90
106
+ });
107
+ console.log(` ${color('green', '✓')} Purged ${results.purge.purged} old facts`);
108
+
109
+ // Record metric
110
+ await memoryDb.recordMemoryMetric('full_compact');
111
+
112
+ // Final stats
113
+ const afterStats = await memoryDb.getEntropyStats(memoryConfig);
114
+
115
+ console.log(color('cyan', '\n═══════════════════════════════════════════════════'));
116
+ console.log(color('cyan', 'Summary'));
117
+ console.log('═'.repeat(50));
118
+
119
+ console.log(`\nActive Facts: ${beforeStats.totalFacts} → ${afterStats.totalFacts}`);
120
+ console.log(`Cold Storage: ${beforeStats.coldFacts} → ${afterStats.coldFacts}`);
121
+ console.log(`Entropy: ${formatEntropy(beforeStats.entropy)} → ${formatEntropy(afterStats.entropy)}`);
122
+ console.log(`Avg Relevance: ${Math.round(beforeStats.avgRelevance * 100)}% → ${Math.round(afterStats.avgRelevance * 100)}%`);
123
+
124
+ console.log(color('green', '\n✓ Compaction complete\n'));
125
+
126
+ return { before: beforeStats, after: afterStats, results };
127
+ }
128
+
129
+ /**
130
+ * Demote only
131
+ */
132
+ async function demoteOnly(config) {
133
+ console.log(color('cyan', '\nDemoting Low-Relevance Facts'));
134
+ console.log('═'.repeat(50));
135
+
136
+ const threshold = config.automaticMemory?.demotion?.relevanceThreshold || 0.3;
137
+ console.log(`Threshold: ${Math.round(threshold * 100)}% relevance\n`);
138
+
139
+ const result = await memoryDb.demoteToColdStorage({ relevanceThreshold: threshold });
140
+
141
+ if (result.demoted === 0) {
142
+ console.log(color('green', '✓ No facts below threshold - nothing to demote\n'));
143
+ } else {
144
+ console.log(color('green', `✓ Demoted ${result.demoted} facts to cold storage\n`));
145
+ }
146
+
147
+ await memoryDb.recordMemoryMetric('demote');
148
+
149
+ return result;
150
+ }
151
+
152
+ /**
153
+ * Merge only
154
+ */
155
+ async function mergeOnly() {
156
+ console.log(color('cyan', '\nMerging Duplicate Facts'));
157
+ console.log('═'.repeat(50));
158
+
159
+ console.log('Similarity threshold: 95%\n');
160
+
161
+ const result = await memoryDb.mergeSimilarFacts({ mergeSimilarityThreshold: 0.95 });
162
+
163
+ if (result.merged === 0) {
164
+ console.log(color('green', '✓ No duplicates found\n'));
165
+ } else {
166
+ console.log(color('green', `✓ Merged ${result.merged} duplicate pairs\n`));
167
+
168
+ if (result.details.length > 0 && result.details.length <= 10) {
169
+ console.log('Details:');
170
+ for (const d of result.details) {
171
+ console.log(` Kept: ${d.kept.substring(0, 20)}... | Deleted: ${d.deleted.substring(0, 20)}...`);
172
+ }
173
+ console.log('');
174
+ }
175
+ }
176
+
177
+ await memoryDb.recordMemoryMetric('merge');
178
+
179
+ return result;
180
+ }
181
+
182
+ /**
183
+ * Purge only
184
+ */
185
+ async function purgeOnly(config) {
186
+ console.log(color('cyan', '\nPurging Old Cold Storage'));
187
+ console.log('═'.repeat(50));
188
+
189
+ const retentionDays = config.automaticMemory?.demotion?.coldRetentionDays || 90;
190
+ console.log(`Retention: ${retentionDays} days\n`);
191
+
192
+ const result = await memoryDb.purgeColdFacts({ coldRetentionDays: retentionDays });
193
+
194
+ if (result.purged === 0) {
195
+ console.log(color('green', '✓ No facts older than retention period\n'));
196
+ } else {
197
+ console.log(color('green', `✓ Purged ${result.purged} old facts\n`));
198
+ }
199
+
200
+ await memoryDb.recordMemoryMetric('purge');
201
+
202
+ return result;
203
+ }
204
+
205
+ /**
206
+ * List cold storage contents
207
+ */
208
+ async function listColdStorage() {
209
+ console.log(color('cyan', '\nCold Storage Contents'));
210
+ console.log('═'.repeat(70));
211
+
212
+ await memoryDb.initDatabase();
213
+
214
+ // Direct query for cold storage
215
+ const SQL = require('sql.js');
216
+ const db = await memoryDb.initDatabase();
217
+
218
+ // This is a workaround since we don't expose direct query in the module
219
+ // We'll use getEntropyStats to show cold count
220
+ const stats = await memoryDb.getEntropyStats();
221
+
222
+ console.log(`\nTotal cold facts: ${stats.coldFacts}`);
223
+
224
+ if (stats.coldFacts === 0) {
225
+ console.log(color('gray', '\nNo facts in cold storage.\n'));
226
+ return;
227
+ }
228
+
229
+ // Since we can't directly query cold storage through the module,
230
+ // inform user how to restore if needed
231
+ console.log(`
232
+ ${color('yellow', 'Note:')} To restore a fact from cold storage:
233
+ ./scripts/flow compact-memory --restore <fact_id>
234
+
235
+ To see fact IDs, check the database directly:
236
+ sqlite3 .workflow/memory/local.db "SELECT id, substr(fact,1,50) FROM facts_cold"
237
+ `);
238
+ }
239
+
240
+ /**
241
+ * Restore from cold storage
242
+ */
243
+ async function restoreFromCold(factId) {
244
+ console.log(color('cyan', '\nRestoring from Cold Storage'));
245
+ console.log('═'.repeat(50));
246
+
247
+ console.log(`Fact ID: ${factId}\n`);
248
+
249
+ const result = await memoryDb.restoreFromColdStorage(factId);
250
+
251
+ if (result.restored) {
252
+ console.log(color('green', '✓ Fact restored successfully'));
253
+ console.log('Relevance has been reset to 50%\n');
254
+ } else {
255
+ console.log(color('red', `✗ ${result.error || 'Failed to restore'}\n`));
256
+ }
257
+
258
+ return result;
259
+ }
260
+
261
+ /**
262
+ * Show compaction stats/preview
263
+ */
264
+ async function showPreview(config) {
265
+ console.log(color('cyan', '\nCompaction Preview'));
266
+ console.log('═'.repeat(50));
267
+
268
+ const memoryConfig = { maxLocalFacts: config.memory?.maxLocalFacts || 1000 };
269
+ const stats = await memoryDb.getEntropyStats(memoryConfig);
270
+
271
+ console.log(`\nCurrent State:`);
272
+ console.log(` Active Facts: ${stats.totalFacts}`);
273
+ console.log(` Cold Facts: ${stats.coldFacts}`);
274
+ console.log(` Entropy: ${formatEntropy(stats.entropy)}`);
275
+
276
+ console.log(`\n${color('blue', 'Would Affect:')}`);
277
+
278
+ const threshold = config.automaticMemory?.demotion?.relevanceThreshold || 0.3;
279
+ console.log(` Low Relevance (<${Math.round(threshold * 100)}%): ${stats.lowRelevanceCount} facts → would be demoted`);
280
+ console.log(` Never Accessed: ${stats.neverAccessed} facts → accelerated decay`);
281
+
282
+ // Estimate merged (can't know without running)
283
+ console.log(` Duplicates: Unknown (run --merge to detect)`);
284
+
285
+ console.log(`\n${color('yellow', 'Run ./scripts/flow compact-memory to execute')}\n`);
286
+ }
287
+
288
+ // ============================================================
289
+ // Main
290
+ // ============================================================
291
+
292
+ async function main() {
293
+ const args = process.argv.slice(2);
294
+ const config = loadConfig();
295
+
296
+ try {
297
+ if (args.includes('--demote')) {
298
+ await demoteOnly(config);
299
+ } else if (args.includes('--merge')) {
300
+ await mergeOnly();
301
+ } else if (args.includes('--purge')) {
302
+ await purgeOnly(config);
303
+ } else if (args.includes('--cold') || args.includes('--list')) {
304
+ await listColdStorage();
305
+ } else if (args.includes('--restore')) {
306
+ const idx = args.indexOf('--restore');
307
+ const factId = args[idx + 1];
308
+ if (!factId) {
309
+ console.error(color('red', 'Error: Missing fact ID'));
310
+ console.log('Usage: ./scripts/flow compact-memory --restore <fact_id>');
311
+ process.exit(1);
312
+ }
313
+ await restoreFromCold(factId);
314
+ } else if (args.includes('--preview')) {
315
+ await showPreview(config);
316
+ } else if (args.includes('--help') || args.includes('-h')) {
317
+ console.log(`
318
+ ${color('cyan', 'Memory Compactor')}
319
+
320
+ Usage: ./scripts/flow compact-memory [options]
321
+
322
+ Options:
323
+ (none) Full compaction (all operations)
324
+ --preview Show what would be affected without changing
325
+ --demote Only demote low-relevance facts to cold storage
326
+ --merge Only merge duplicate facts (>95% similar)
327
+ --purge Only purge old facts from cold storage
328
+ --cold, --list Show cold storage contents
329
+ --restore <id> Restore a fact from cold storage
330
+ --help, -h Show this help
331
+
332
+ Examples:
333
+ ./scripts/flow compact-memory # Full compaction
334
+ ./scripts/flow compact-memory --preview # Preview changes
335
+ ./scripts/flow compact-memory --demote # Just demote low relevance
336
+ ./scripts/flow compact-memory --restore fact_12345_abc
337
+ `);
338
+ } else {
339
+ await fullCompaction(config);
340
+ }
341
+ } catch (error) {
342
+ console.error(color('red', `Error: ${error.message}`));
343
+ if (process.env.DEBUG) console.error(error.stack);
344
+ process.exit(1);
345
+ } finally {
346
+ memoryDb.closeDatabase();
347
+ }
348
+ }
349
+
350
+ main();