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,437 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Wogi Flow - End Session Properly
5
+ *
6
+ * Ensures all workflow state is saved, optionally commits and pushes.
7
+ */
8
+
9
+ const { execSync, execFileSync, spawnSync } = require('child_process');
10
+ const readline = require('readline');
11
+ const path = require('path');
12
+ const {
13
+ PATHS,
14
+ PROJECT_ROOT,
15
+ fileExists,
16
+ getConfig,
17
+ getConfigValue,
18
+ readFile,
19
+ writeFile,
20
+ isGitRepo,
21
+ getGitStatus,
22
+ color,
23
+ printSection,
24
+ success,
25
+ warn
26
+ } = require('./flow-utils');
27
+
28
+ // v1.7.0 context memory management
29
+ const { showContextBreakdown, checkContextHealth } = require('./flow-context-monitor');
30
+ const { resetSessionContext, getSessionContext, writeMemoryBlocks, readMemoryBlocks } = require('./flow-memory-blocks');
31
+ const { saveSessionSummary, loadSessionState } = require('./flow-session-state');
32
+ const { autoArchiveIfNeeded, getLogStats } = require('./flow-log-manager');
33
+
34
+ // v1.8.0 automatic memory management
35
+ let memoryDb = null;
36
+ try {
37
+ memoryDb = require('./flow-memory-db');
38
+ } catch (err) {
39
+ // Memory module not available
40
+ }
41
+
42
+ /**
43
+ * Prompt user for input
44
+ */
45
+ function prompt(question) {
46
+ const rl = readline.createInterface({
47
+ input: process.stdin,
48
+ output: process.stdout
49
+ });
50
+
51
+ return new Promise(resolve => {
52
+ rl.question(question, answer => {
53
+ rl.close();
54
+ resolve(answer);
55
+ });
56
+ });
57
+ }
58
+
59
+ /**
60
+ * Check session-end requirements from config
61
+ */
62
+ function checkRequirements() {
63
+ if (!fileExists(PATHS.config)) return;
64
+
65
+ console.log(color('yellow', 'Checking session-end requirements...'));
66
+
67
+ const config = getConfig();
68
+ const steps = config.mandatorySteps?.onSessionEnd || [];
69
+
70
+ if (steps.length > 0) {
71
+ console.log('Required:');
72
+ for (const step of steps) {
73
+ console.log(` • ${step}`);
74
+ }
75
+ }
76
+
77
+ console.log('');
78
+ }
79
+
80
+ /**
81
+ * Handle uncommitted changes
82
+ */
83
+ async function handleUncommittedChanges() {
84
+ const git = getGitStatus();
85
+
86
+ if (!git.isRepo) return;
87
+
88
+ if (git.uncommitted > 0) {
89
+ console.log(color('yellow', `Uncommitted changes: ${git.uncommitted} files`));
90
+
91
+ try {
92
+ const status = execSync('git status --short', { encoding: 'utf-8' });
93
+ console.log(status);
94
+ } catch {
95
+ // Ignore
96
+ }
97
+
98
+ const confirm = await prompt('Commit all changes? (y/N) ');
99
+
100
+ if (confirm.toLowerCase() === 'y') {
101
+ const msg = await prompt('Commit message: ');
102
+ const commitMsg = msg || 'checkpoint: end of session';
103
+
104
+ try {
105
+ execSync('git add -A', { stdio: 'pipe' });
106
+ // Use execFileSync to prevent command injection from commit message
107
+ execFileSync('git', ['commit', '-m', commitMsg], { stdio: 'pipe' });
108
+ success('Changes committed');
109
+ } catch (err) {
110
+ warn(`Commit failed: ${err.message}`);
111
+ }
112
+ }
113
+ } else {
114
+ success('No uncommitted changes');
115
+ }
116
+
117
+ console.log('');
118
+ }
119
+
120
+ /**
121
+ * Update progress.md timestamp
122
+ */
123
+ function updateProgress() {
124
+ if (!fileExists(PATHS.progress)) return;
125
+
126
+ console.log(color('yellow', 'Updating progress.md...'));
127
+
128
+ try {
129
+ let content = readFile(PATHS.progress);
130
+ const now = new Date();
131
+ const timestamp = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')} ${String(now.getHours()).padStart(2, '0')}:${String(now.getMinutes()).padStart(2, '0')}`;
132
+
133
+ // Update or add timestamp
134
+ if (content.includes('## Last Updated')) {
135
+ content = content.replace(/## Last Updated.*(\n|$)/, `## Last Updated\n${timestamp}\n`);
136
+ } else {
137
+ content = `## Last Updated\n${timestamp}\n\n${content}`;
138
+ }
139
+
140
+ writeFile(PATHS.progress, content);
141
+ success('Progress updated');
142
+ } catch (err) {
143
+ warn(`Failed to update progress: ${err.message}`);
144
+ }
145
+ }
146
+
147
+ /**
148
+ * Extract skill learnings if configured
149
+ */
150
+ function extractSkillLearnings() {
151
+ if (!fileExists(PATHS.config)) return;
152
+
153
+ const skillLearning = getConfigValue('skillLearning', {});
154
+
155
+ if (skillLearning.enabled && skillLearning.autoExtract) {
156
+ console.log('');
157
+ console.log(color('yellow', 'Extracting skill learnings...'));
158
+
159
+ const scriptPath = path.join(PROJECT_ROOT, 'scripts', 'flow-skill-learn.js');
160
+ if (fileExists(scriptPath)) {
161
+ const result = spawnSync('node', [scriptPath, '--trigger=session-end'], {
162
+ encoding: 'utf-8',
163
+ stdio: ['pipe', 'pipe', 'pipe']
164
+ });
165
+
166
+ if (result.status === 0) {
167
+ success('Skills updated');
168
+ }
169
+ }
170
+ }
171
+ }
172
+
173
+ /**
174
+ * Offer to push to remote
175
+ */
176
+ async function offerPush() {
177
+ if (!isGitRepo()) return;
178
+
179
+ try {
180
+ execSync('git remote get-url origin', { stdio: 'pipe' });
181
+
182
+ const confirm = await prompt('Push to remote? (y/N) ');
183
+
184
+ if (confirm.toLowerCase() === 'y') {
185
+ execSync('git push', { stdio: 'inherit' });
186
+ success('Pushed to remote');
187
+ }
188
+ } catch {
189
+ // No remote configured, skip
190
+ }
191
+ }
192
+
193
+ /**
194
+ * v1.7.0: Save session summary to state
195
+ */
196
+ function saveSessionSummaryToState() {
197
+ console.log('');
198
+ console.log(color('yellow', 'Saving session state...'));
199
+
200
+ try {
201
+ const sessionState = loadSessionState();
202
+ const memoryBlocks = readMemoryBlocks();
203
+
204
+ // Build summary from session data
205
+ const summary = {
206
+ tasksCompleted: sessionState.metrics?.tasksCompleted || 0,
207
+ filesModified: sessionState.recentFiles?.slice(0, 5) || [],
208
+ decisions: sessionState.recentDecisions?.map(d => d.decision).slice(0, 3) || [],
209
+ summary: memoryBlocks?.keyFacts?.slice(-3).join('; ') || 'Session ended'
210
+ };
211
+
212
+ saveSessionSummary(summary);
213
+ success('Session state saved');
214
+ } catch (err) {
215
+ if (process.env.DEBUG) console.error(`[DEBUG] Session save: ${err.message}`);
216
+ warn('Could not save session state');
217
+ }
218
+ }
219
+
220
+ /**
221
+ * v1.7.0: Archive request log if threshold exceeded
222
+ */
223
+ function archiveRequestLogIfNeeded() {
224
+ try {
225
+ const result = autoArchiveIfNeeded();
226
+ if (result && result.archived > 0) {
227
+ console.log('');
228
+ success(`Archived ${result.archived} request log entries`);
229
+ console.log(color('dim', ` Archive: ${result.archivePath}`));
230
+ }
231
+ } catch (err) {
232
+ if (process.env.DEBUG) console.error(`[DEBUG] Archive: ${err.message}`);
233
+ }
234
+ }
235
+
236
+ /**
237
+ * v1.7.0: Show context health summary
238
+ */
239
+ function showContextHealthSummary() {
240
+ try {
241
+ const health = checkContextHealth();
242
+ if (health.status !== 'disabled') {
243
+ console.log('');
244
+ console.log(color('yellow', 'Context health:'));
245
+ const statusColor = health.status === 'healthy' ? 'green'
246
+ : health.status === 'warning' ? 'yellow' : 'red';
247
+ console.log(` Status: ${color(statusColor, health.status.toUpperCase())} (${health.usagePercent}%)`);
248
+
249
+ if (health.recommendation) {
250
+ console.log(` ${color(statusColor, health.recommendation)}`);
251
+ }
252
+ }
253
+ } catch (err) {
254
+ if (process.env.DEBUG) console.error(`[DEBUG] Context health: ${err.message}`);
255
+ }
256
+ }
257
+
258
+ /**
259
+ * v1.8.0: Automatic memory management
260
+ * Part of automatic memory management for teams
261
+ */
262
+ async function automaticMemoryManagement() {
263
+ if (!memoryDb) return;
264
+
265
+ const config = getConfig();
266
+ const memConfig = config.automaticMemory || {};
267
+
268
+ if (!memConfig.enabled) return;
269
+
270
+ console.log('');
271
+ console.log(color('yellow', 'Automatic memory management:'));
272
+
273
+ try {
274
+ // 1. Apply relevance decay
275
+ if (memConfig.relevanceDecay?.enabled !== false) {
276
+ const decayResult = await memoryDb.applyRelevanceDecay({
277
+ decayRate: memConfig.relevanceDecay?.decayRate || 0.033,
278
+ neverAccessedPenalty: memConfig.relevanceDecay?.neverAccessedPenalty || 0.1
279
+ });
280
+ if (decayResult.decayed > 0) {
281
+ console.log(` Relevance decay: ${decayResult.decayed} facts updated`);
282
+ }
283
+ }
284
+
285
+ // 2. Check entropy and compact if needed
286
+ const memoryConfig = { maxLocalFacts: config.memory?.maxLocalFacts || 1000 };
287
+ const entropy = await memoryDb.getEntropyStats(memoryConfig);
288
+
289
+ const threshold = memConfig.entropyThreshold || 0.7;
290
+ const statusColor = entropy.status === 'healthy' ? 'green'
291
+ : entropy.status === 'moderate' ? 'yellow' : 'red';
292
+
293
+ console.log(` Entropy: ${color(statusColor, entropy.entropy)} (${entropy.status})`);
294
+ console.log(` Facts: ${entropy.totalFacts}/${entropy.maxFacts} | Cold: ${entropy.coldFacts}`);
295
+
296
+ if (entropy.needsCompaction && memConfig.compactOnSessionEnd) {
297
+ console.log(color('yellow', ' Auto-compacting memory...'));
298
+
299
+ // Demote low-relevance facts
300
+ const demotion = await memoryDb.demoteToColdStorage({
301
+ relevanceThreshold: memConfig.demotion?.relevanceThreshold || 0.3
302
+ });
303
+ if (demotion.demoted > 0) {
304
+ console.log(` Demoted: ${demotion.demoted} facts`);
305
+ }
306
+
307
+ // Merge duplicates
308
+ const merge = await memoryDb.mergeSimilarFacts({ mergeSimilarityThreshold: 0.95 });
309
+ if (merge.merged > 0) {
310
+ console.log(` Merged: ${merge.merged} duplicates`);
311
+ }
312
+
313
+ // Purge old cold facts
314
+ const purge = await memoryDb.purgeColdFacts({
315
+ coldRetentionDays: memConfig.demotion?.coldRetentionDays || 90
316
+ });
317
+ if (purge.purged > 0) {
318
+ console.log(` Purged: ${purge.purged} old facts`);
319
+ }
320
+ }
321
+
322
+ // 3. Check for promotion candidates and auto-promote if enabled
323
+ const promoConfig = config.automaticPromotion || {};
324
+ if (promoConfig.enabled) {
325
+ const candidates = await memoryDb.getPromotionCandidates({
326
+ minRelevance: promoConfig.minRelevance || 0.8,
327
+ minAccessCount: promoConfig.threshold || 3
328
+ });
329
+
330
+ const unpromoted = candidates.filter(c => !c.promoted_to);
331
+ if (unpromoted.length > 0) {
332
+ console.log(` ${color('cyan', `${unpromoted.length} pattern(s) ready for promotion`)}`);
333
+
334
+ // Auto-promote if approval not required
335
+ if (!promoConfig.requireApproval) {
336
+ try {
337
+ const memorySync = require('./flow-memory-sync');
338
+ if (memorySync && typeof memorySync.autoPromote === 'function') {
339
+ const result = await memorySync.autoPromote(config);
340
+ if (result.promoted > 0) {
341
+ console.log(` ${color('green', `Auto-promoted ${result.promoted} pattern(s) to decisions.md`)}`);
342
+ }
343
+ } else {
344
+ // Fallback: tell user to run manually
345
+ console.log(' Run: ./scripts/flow memory-sync --auto');
346
+ }
347
+ } catch (err) {
348
+ // Module not available or error, fall back to manual
349
+ console.log(' Run: ./scripts/flow memory-sync --auto');
350
+ }
351
+ } else {
352
+ console.log(' Run: ./scripts/flow memory-sync --auto (approval required)');
353
+ }
354
+ }
355
+ }
356
+
357
+ // 4. Record metric
358
+ await memoryDb.recordMemoryMetric('session_end');
359
+
360
+ success('Memory management complete');
361
+
362
+ } catch (err) {
363
+ if (process.env.DEBUG) console.error(`[DEBUG] Memory management: ${err.message}`);
364
+ warn('Memory management skipped');
365
+ } finally {
366
+ try {
367
+ memoryDb.closeDatabase();
368
+ } catch {}
369
+ }
370
+ }
371
+
372
+ /**
373
+ * Show status summary
374
+ */
375
+ function showSummary() {
376
+ console.log('');
377
+ console.log(color('green', 'Session ended cleanly.'));
378
+ console.log('');
379
+ console.log('Summary:');
380
+
381
+ const statusScript = path.join(PROJECT_ROOT, 'scripts', 'flow-status.js');
382
+ if (fileExists(statusScript)) {
383
+ try {
384
+ spawnSync('node', [statusScript], {
385
+ encoding: 'utf-8',
386
+ stdio: 'inherit'
387
+ });
388
+ } catch {
389
+ console.log(" (run 'flow status' for details)");
390
+ }
391
+ } else {
392
+ console.log(" (run 'flow status' for details)");
393
+ }
394
+ }
395
+
396
+ async function main() {
397
+ printSection('Ending Session');
398
+ console.log('===============');
399
+ console.log('');
400
+
401
+ // Check requirements
402
+ checkRequirements();
403
+
404
+ // Handle uncommitted changes
405
+ await handleUncommittedChanges();
406
+
407
+ // Update progress
408
+ updateProgress();
409
+
410
+ // Extract skill learnings
411
+ extractSkillLearnings();
412
+
413
+ // v1.7.0: Save session summary
414
+ saveSessionSummaryToState();
415
+
416
+ // v1.7.0: Auto-archive request log
417
+ archiveRequestLogIfNeeded();
418
+
419
+ // v1.7.0: Show context health
420
+ showContextHealthSummary();
421
+
422
+ // v1.8.0: Automatic memory management
423
+ await automaticMemoryManagement();
424
+
425
+ console.log('');
426
+
427
+ // Offer to push
428
+ await offerPush();
429
+
430
+ // Show summary
431
+ showSummary();
432
+ }
433
+
434
+ main().catch(e => {
435
+ console.error(console.error('Error:', err.message));
436
+ process.exit(1);
437
+ });