moflo 4.8.42 → 4.8.44
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/.claude/guidance/shipped/memory-strategy.md +277 -276
- package/.claude/guidance/shipped/{task-swarm-integration.md → moflo-claude-swarm-cohesion.md} +4 -4
- package/.claude/guidance/shipped/moflo.md +2 -2
- package/.claude/guidance/shipped/{agent-bootstrap.md → subagents.md} +5 -19
- package/.claude/helpers/hook-handler.cjs +8 -1
- package/.claude/scripts/build-embeddings.mjs +549 -549
- package/.claude/scripts/generate-code-map.mjs +956 -776
- package/.claude/scripts/hooks.mjs +28 -79
- package/.claude/scripts/index-all.mjs +193 -127
- package/.claude/scripts/index-guidance.mjs +27 -3
- package/.claude/scripts/index-tests.mjs +729 -710
- package/.claude/scripts/lib/moflo-resolve.mjs +14 -0
- package/.claude/scripts/lib/process-manager.mjs +256 -0
- package/.claude/scripts/lib/registry-cleanup.cjs +41 -0
- package/.claude/scripts/semantic-search.mjs +1 -1
- package/.claude/scripts/session-start-launcher.mjs +16 -1
- package/README.md +15 -15
- package/bin/index-guidance.mjs +916 -905
- package/bin/setup-project.mjs +252 -252
- package/package.json +1 -1
- package/src/@claude-flow/cli/README.md +6 -6
- package/src/@claude-flow/cli/dist/src/commands/epic.js +767 -0
- package/src/@claude-flow/cli/dist/src/commands/index.js +1 -1
- package/src/@claude-flow/cli/dist/src/init/claudemd-generator.js +2 -2
- package/src/@claude-flow/cli/dist/src/init/moflo-init.js +7 -7
- package/src/@claude-flow/cli/dist/src/version.js +1 -1
- package/src/@claude-flow/cli/package.json +106 -106
|
@@ -27,7 +27,22 @@ import { createProcessManager } from './lib/process-manager.mjs';
|
|
|
27
27
|
|
|
28
28
|
const __filename = fileURLToPath(import.meta.url);
|
|
29
29
|
const __dirname = dirname(__filename);
|
|
30
|
-
|
|
30
|
+
|
|
31
|
+
// Detect project root by walking up from cwd to find package.json.
|
|
32
|
+
// IMPORTANT: Do NOT use resolve(__dirname, '..') or '../..' — this script lives
|
|
33
|
+
// in bin/ during development but gets synced to .claude/scripts/ in consumer
|
|
34
|
+
// projects, so __dirname-relative paths break. findProjectRoot() works everywhere.
|
|
35
|
+
function findProjectRoot() {
|
|
36
|
+
let dir = process.cwd();
|
|
37
|
+
const root = resolve(dir, '/');
|
|
38
|
+
while (dir !== root) {
|
|
39
|
+
if (existsSync(resolve(dir, 'package.json'))) return dir;
|
|
40
|
+
dir = dirname(dir);
|
|
41
|
+
}
|
|
42
|
+
return process.cwd();
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const projectRoot = findProjectRoot();
|
|
31
46
|
const logFile = resolve(projectRoot, '.swarm/hooks.log');
|
|
32
47
|
const pm = createProcessManager(projectRoot);
|
|
33
48
|
|
|
@@ -260,21 +275,14 @@ async function main() {
|
|
|
260
275
|
case 'session-start': {
|
|
261
276
|
// Start daemon quietly in background (no DB writes)
|
|
262
277
|
runDaemonStartBackground();
|
|
263
|
-
//
|
|
264
|
-
|
|
278
|
+
// Initialize embeddings engine (must run before indexers that generate embeddings)
|
|
279
|
+
runEmbeddingsInitBackground();
|
|
265
280
|
// Run all DB-writing indexers SEQUENTIALLY in a single background process.
|
|
266
|
-
// This avoids sql.js last-write-wins concurrency (
|
|
267
|
-
//
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
} else {
|
|
272
|
-
// Fallback to parallel if index-all.mjs not available
|
|
273
|
-
runIndexGuidanceBackground();
|
|
274
|
-
runCodeMapBackground();
|
|
275
|
-
runTestIndexBackground();
|
|
276
|
-
runHNSWRebuildBackground();
|
|
277
|
-
}
|
|
281
|
+
// This avoids sql.js last-write-wins concurrency (#78) and ensures
|
|
282
|
+
// HNSW rebuild runs after all indexers finish (#81).
|
|
283
|
+
// Chain: guidance → code-map → tests → patterns → pretrain → HNSW rebuild.
|
|
284
|
+
spawnWindowless('node', [resolve(__dirname, 'index-all.mjs')], 'sequential indexing chain');
|
|
285
|
+
// Neural patterns now loaded by moflo core routing — no external patching.
|
|
278
286
|
break;
|
|
279
287
|
}
|
|
280
288
|
|
|
@@ -469,55 +477,6 @@ function runIndexGuidanceBackground(specificFile = null) {
|
|
|
469
477
|
spawnWindowless('node', indexArgs, desc);
|
|
470
478
|
}
|
|
471
479
|
|
|
472
|
-
// Run structural code map generator in background (non-blocking)
|
|
473
|
-
function runCodeMapBackground() {
|
|
474
|
-
// Check auto_index.code_map flag in moflo.yaml (default: true)
|
|
475
|
-
const yamlPath = resolve(projectRoot, 'moflo.yaml');
|
|
476
|
-
if (existsSync(yamlPath)) {
|
|
477
|
-
try {
|
|
478
|
-
const content = readFileSync(yamlPath, 'utf-8');
|
|
479
|
-
const match = content.match(/auto_index:\s*\n(?:.*\n)*?\s+code_map:\s*(true|false)/);
|
|
480
|
-
if (match && match[1] === 'false') {
|
|
481
|
-
log('info', 'Code map generation disabled (auto_index.code_map: false)');
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
} catch { /* ignore, proceed with indexing */ }
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
const codeMapScript = resolveBinOrLocal('flo-codemap', 'generate-code-map.mjs');
|
|
488
|
-
|
|
489
|
-
if (!codeMapScript) {
|
|
490
|
-
log('warn', 'Code map generator not found (checked npm bin + .claude/scripts/)');
|
|
491
|
-
return;
|
|
492
|
-
}
|
|
493
|
-
|
|
494
|
-
spawnWindowless('node', [codeMapScript], 'background code map generation');
|
|
495
|
-
}
|
|
496
|
-
|
|
497
|
-
// Run test file indexer in background (non-blocking)
|
|
498
|
-
function runTestIndexBackground() {
|
|
499
|
-
// Check auto_index.tests flag in moflo.yaml (default: true)
|
|
500
|
-
const yamlPath = resolve(projectRoot, 'moflo.yaml');
|
|
501
|
-
if (existsSync(yamlPath)) {
|
|
502
|
-
try {
|
|
503
|
-
const content = readFileSync(yamlPath, 'utf-8');
|
|
504
|
-
const match = content.match(/auto_index:\s*\n(?:.*\n)*?\s+tests:\s*(true|false)/);
|
|
505
|
-
if (match && match[1] === 'false') {
|
|
506
|
-
log('info', 'Test indexing disabled (auto_index.tests: false)');
|
|
507
|
-
return;
|
|
508
|
-
}
|
|
509
|
-
} catch { /* ignore, proceed with indexing */ }
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
const testIndexScript = resolveBinOrLocal('flo-testmap', 'index-tests.mjs');
|
|
513
|
-
|
|
514
|
-
if (!testIndexScript) {
|
|
515
|
-
log('info', 'Test indexer not found (checked npm bin + .claude/scripts/)');
|
|
516
|
-
return;
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
spawnWindowless('node', [testIndexScript], 'background test indexing');
|
|
520
|
-
}
|
|
521
480
|
|
|
522
481
|
// Run ReasoningBank + MicroLoRA training + EWC++ consolidation in background (non-blocking)
|
|
523
482
|
function runBackgroundTraining() {
|
|
@@ -625,29 +584,19 @@ function runDaemonStartBackground() {
|
|
|
625
584
|
spawnWindowless('node', [localCli, 'daemon', 'start', '--quiet'], 'daemon');
|
|
626
585
|
}
|
|
627
586
|
|
|
628
|
-
// Run pretrain in background on session start (non-blocking)
|
|
629
|
-
function runBackgroundPretrain() {
|
|
630
|
-
const localCli = getLocalCliPath();
|
|
631
|
-
if (!localCli) {
|
|
632
|
-
log('warn', 'Local CLI not found, skipping background pretrain');
|
|
633
|
-
return;
|
|
634
|
-
}
|
|
635
587
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
// Force HNSW rebuild in background to ensure all processes use identical fresh index
|
|
640
|
-
// This fixes the issue where spawned agents return different search results than CLI/MCP
|
|
641
|
-
function runHNSWRebuildBackground() {
|
|
588
|
+
// Initialize embeddings ONNX engine on session start (non-blocking)
|
|
589
|
+
function runEmbeddingsInitBackground() {
|
|
642
590
|
const localCli = getLocalCliPath();
|
|
643
591
|
if (!localCli) {
|
|
644
|
-
log('warn', 'Local CLI not found, skipping
|
|
592
|
+
log('warn', 'Local CLI not found, skipping embeddings init');
|
|
645
593
|
return;
|
|
646
594
|
}
|
|
647
595
|
|
|
648
|
-
spawnWindowless('node', [localCli, '
|
|
596
|
+
spawnWindowless('node', [localCli, 'embeddings', 'init'], 'embeddings init');
|
|
649
597
|
}
|
|
650
598
|
|
|
599
|
+
|
|
651
600
|
// Neural pattern application — now handled by moflo core routing (learned patterns
|
|
652
601
|
// loaded from routing-outcomes.json by hooks-tools.ts getSemanticRouter).
|
|
653
602
|
// No external patch script needed.
|
|
@@ -1,127 +1,193 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Sequential indexer chain for session-start.
|
|
4
|
-
*
|
|
5
|
-
* Runs all DB-writing indexers one at a time to avoid sql.js last-write-wins
|
|
6
|
-
* concurrency issues, then triggers HNSW rebuild once everything is
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
function
|
|
37
|
-
const
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
//
|
|
114
|
-
if (
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Sequential indexer chain for session-start.
|
|
4
|
+
*
|
|
5
|
+
* Runs all DB-writing indexers one at a time to avoid sql.js last-write-wins
|
|
6
|
+
* concurrency issues (#78), then triggers HNSW rebuild once everything is
|
|
7
|
+
* committed (#81).
|
|
8
|
+
*
|
|
9
|
+
* Spawned as a single detached background process by hooks.mjs session-start.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { existsSync, appendFileSync, readFileSync } from 'fs';
|
|
13
|
+
import { resolve, dirname } from 'path';
|
|
14
|
+
import { fileURLToPath } from 'url';
|
|
15
|
+
import { execFileSync } from 'child_process';
|
|
16
|
+
|
|
17
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
18
|
+
|
|
19
|
+
// Detect project root by walking up from cwd to find package.json.
|
|
20
|
+
// IMPORTANT: Do NOT use resolve(__dirname, '..') — this script lives in bin/
|
|
21
|
+
// during development but gets synced to .claude/scripts/ in consumer projects,
|
|
22
|
+
// so __dirname-relative paths break. findProjectRoot() works in both locations.
|
|
23
|
+
function findProjectRoot() {
|
|
24
|
+
let dir = process.cwd();
|
|
25
|
+
const root = resolve(dir, '/');
|
|
26
|
+
while (dir !== root) {
|
|
27
|
+
if (existsSync(resolve(dir, 'package.json'))) return dir;
|
|
28
|
+
dir = dirname(dir);
|
|
29
|
+
}
|
|
30
|
+
return process.cwd();
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const projectRoot = findProjectRoot();
|
|
34
|
+
const LOG_PATH = resolve(projectRoot, '.swarm/hooks.log');
|
|
35
|
+
|
|
36
|
+
function log(msg) {
|
|
37
|
+
const ts = new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
38
|
+
const line = `[${ts}] [index-all] ${msg}\n`;
|
|
39
|
+
try { appendFileSync(LOG_PATH, line); } catch { /* ignore */ }
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function resolveBin(binName, localScript) {
|
|
43
|
+
const mofloScript = resolve(projectRoot, 'node_modules/moflo/bin', localScript);
|
|
44
|
+
if (existsSync(mofloScript)) return mofloScript;
|
|
45
|
+
const npmBin = resolve(projectRoot, 'node_modules/.bin', binName);
|
|
46
|
+
if (existsSync(npmBin)) return npmBin;
|
|
47
|
+
const localPath = resolve(projectRoot, '.claude/scripts', localScript);
|
|
48
|
+
if (existsSync(localPath)) return localPath;
|
|
49
|
+
// Also check bin/ directory (for development use)
|
|
50
|
+
const binPath = resolve(projectRoot, 'bin', localScript);
|
|
51
|
+
if (existsSync(binPath)) return binPath;
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function getLocalCliPath() {
|
|
56
|
+
const paths = [
|
|
57
|
+
resolve(projectRoot, 'node_modules/moflo/src/@claude-flow/cli/bin/cli.js'),
|
|
58
|
+
resolve(projectRoot, 'node_modules/moflo/bin/cli.js'),
|
|
59
|
+
resolve(projectRoot, 'node_modules/.bin/flo'),
|
|
60
|
+
// Development: local CLI
|
|
61
|
+
resolve(projectRoot, 'src/@claude-flow/cli/bin/cli.js'),
|
|
62
|
+
];
|
|
63
|
+
for (const p of paths) {
|
|
64
|
+
if (existsSync(p)) return p;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/** Read moflo.yaml once and cache auto_index flags. */
|
|
70
|
+
let _autoIndexFlags = null;
|
|
71
|
+
function isIndexEnabled(key) {
|
|
72
|
+
if (_autoIndexFlags === null) {
|
|
73
|
+
_autoIndexFlags = {};
|
|
74
|
+
const yamlPath = resolve(projectRoot, 'moflo.yaml');
|
|
75
|
+
if (existsSync(yamlPath)) {
|
|
76
|
+
try {
|
|
77
|
+
const content = readFileSync(yamlPath, 'utf-8');
|
|
78
|
+
for (const k of ['guidance', 'code_map', 'tests', 'patterns']) {
|
|
79
|
+
const re = new RegExp(`auto_index:\\s*\\n(?:.*\\n)*?\\s+${k}:\\s*(true|false)`);
|
|
80
|
+
const match = content.match(re);
|
|
81
|
+
_autoIndexFlags[k] = match ? match[1] !== 'false' : true;
|
|
82
|
+
}
|
|
83
|
+
} catch { /* ignore, all default to true */ }
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return _autoIndexFlags[key] !== false;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function runStep(label, cmd, args, timeoutMs = 120_000) {
|
|
90
|
+
const start = Date.now();
|
|
91
|
+
log(`START ${label}`);
|
|
92
|
+
try {
|
|
93
|
+
execFileSync(cmd, args, {
|
|
94
|
+
cwd: projectRoot,
|
|
95
|
+
timeout: timeoutMs,
|
|
96
|
+
stdio: 'ignore',
|
|
97
|
+
windowsHide: true,
|
|
98
|
+
});
|
|
99
|
+
const elapsed = ((Date.now() - start) / 1000).toFixed(1);
|
|
100
|
+
log(`DONE ${label} (${elapsed}s)`);
|
|
101
|
+
return true;
|
|
102
|
+
} catch (err) {
|
|
103
|
+
const elapsed = ((Date.now() - start) / 1000).toFixed(1);
|
|
104
|
+
log(`FAIL ${label} (${elapsed}s): ${err.message?.split('\n')[0] || 'unknown'}`);
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function main() {
|
|
110
|
+
const startTime = Date.now();
|
|
111
|
+
log('Sequential indexing chain started');
|
|
112
|
+
|
|
113
|
+
// 1. Guidance indexer
|
|
114
|
+
if (isIndexEnabled('guidance')) {
|
|
115
|
+
const guidanceScript = resolveBin('flo-index', 'index-guidance.mjs');
|
|
116
|
+
if (guidanceScript) {
|
|
117
|
+
runStep('guidance-index', 'node', [guidanceScript, '--no-embeddings']);
|
|
118
|
+
} else {
|
|
119
|
+
log('SKIP guidance-index (script not found)');
|
|
120
|
+
}
|
|
121
|
+
} else {
|
|
122
|
+
log('SKIP guidance-index (disabled in moflo.yaml)');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// 2. Code map generator (the big one — ~22s)
|
|
126
|
+
if (isIndexEnabled('code_map')) {
|
|
127
|
+
const codeMapScript = resolveBin('flo-codemap', 'generate-code-map.mjs');
|
|
128
|
+
if (codeMapScript) {
|
|
129
|
+
runStep('code-map', 'node', [codeMapScript, '--no-embeddings'], 180_000);
|
|
130
|
+
} else {
|
|
131
|
+
log('SKIP code-map (script not found)');
|
|
132
|
+
}
|
|
133
|
+
} else {
|
|
134
|
+
log('SKIP code-map (disabled in moflo.yaml)');
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// 3. Test indexer
|
|
138
|
+
if (isIndexEnabled('tests')) {
|
|
139
|
+
const testScript = resolveBin('flo-testmap', 'index-tests.mjs');
|
|
140
|
+
if (testScript) {
|
|
141
|
+
runStep('test-index', 'node', [testScript, '--no-embeddings']);
|
|
142
|
+
} else {
|
|
143
|
+
log('SKIP test-index (script not found)');
|
|
144
|
+
}
|
|
145
|
+
} else {
|
|
146
|
+
log('SKIP test-index (disabled in moflo.yaml)');
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 4. Patterns indexer
|
|
150
|
+
if (isIndexEnabled('patterns')) {
|
|
151
|
+
const patternsScript = resolveBin('flo-patterns', 'index-patterns.mjs');
|
|
152
|
+
if (patternsScript) {
|
|
153
|
+
runStep('patterns-index', 'node', [patternsScript]);
|
|
154
|
+
} else {
|
|
155
|
+
log('SKIP patterns-index (script not found)');
|
|
156
|
+
}
|
|
157
|
+
} else {
|
|
158
|
+
log('SKIP patterns-index (disabled in moflo.yaml)');
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// 5. Pretrain (extracts patterns from repository)
|
|
162
|
+
const localCli = getLocalCliPath();
|
|
163
|
+
if (localCli) {
|
|
164
|
+
runStep('pretrain', 'node', [localCli, 'hooks', 'pretrain']);
|
|
165
|
+
} else {
|
|
166
|
+
log('SKIP pretrain (CLI not found)');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// 6. Build embeddings — single pass for ALL namespaces, after all indexers finish.
|
|
170
|
+
// Individual indexers are called with --no-embeddings to prevent background
|
|
171
|
+
// embedding spawns that race with this chain (sql.js last-write-wins).
|
|
172
|
+
const embeddingsScript = resolveBin('flo-embeddings', 'build-embeddings.mjs');
|
|
173
|
+
if (embeddingsScript) {
|
|
174
|
+
runStep('build-embeddings', 'node', [embeddingsScript], 300_000);
|
|
175
|
+
} else {
|
|
176
|
+
log('SKIP build-embeddings (script not found)');
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// 7. HNSW rebuild — MUST run last, after all writes are committed (#81)
|
|
180
|
+
if (localCli) {
|
|
181
|
+
runStep('hnsw-rebuild', 'node', [localCli, 'memory', 'rebuild', '--force']);
|
|
182
|
+
} else {
|
|
183
|
+
log('SKIP hnsw-rebuild (CLI not found)');
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const totalElapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
187
|
+
log(`Sequential indexing chain complete (${totalElapsed}s)`);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
main().catch(err => {
|
|
191
|
+
log(`FATAL: ${err.message}`);
|
|
192
|
+
process.exit(1);
|
|
193
|
+
});
|
|
@@ -106,7 +106,18 @@ function loadGuidanceDirs() {
|
|
|
106
106
|
? bundledShippedDir
|
|
107
107
|
: resolve(mofloRoot, '.claude/guidance');
|
|
108
108
|
const projectGuidanceDir = resolve(projectRoot, '.claude/guidance');
|
|
109
|
+
|
|
110
|
+
// Detect self-reference: if the project IS the moflo package, skip bundled scan
|
|
111
|
+
// to avoid double-indexing the same files under two prefixes.
|
|
112
|
+
let isSelfRef = false;
|
|
113
|
+
try {
|
|
114
|
+
const projPkg = JSON.parse(readFileSync(resolve(projectRoot, 'package.json'), 'utf-8'));
|
|
115
|
+
const mofloPkg = JSON.parse(readFileSync(resolve(mofloRoot, 'package.json'), 'utf-8'));
|
|
116
|
+
isSelfRef = projPkg.name === mofloPkg.name;
|
|
117
|
+
} catch { /* ignore — defaults to false */ }
|
|
118
|
+
|
|
109
119
|
if (
|
|
120
|
+
!isSelfRef &&
|
|
110
121
|
existsSync(bundledGuidanceDir) &&
|
|
111
122
|
resolve(bundledGuidanceDir) !== resolve(projectGuidanceDir) &&
|
|
112
123
|
resolve(bundledGuidanceDir) !== resolve(projectGuidanceDir, 'shipped')
|
|
@@ -819,8 +830,17 @@ if (!specificFile) {
|
|
|
819
830
|
}
|
|
820
831
|
}
|
|
821
832
|
|
|
822
|
-
// Write changes back to disk
|
|
833
|
+
// Write changes back to disk
|
|
823
834
|
if (docsIndexed > 0 || chunksIndexed > 0 || staleRemoved > 0) saveDb(db);
|
|
835
|
+
|
|
836
|
+
// Check for entries missing embeddings (e.g. prior background run failed)
|
|
837
|
+
let missingEmbeddings = 0;
|
|
838
|
+
{
|
|
839
|
+
const stmt = db.prepare(`SELECT COUNT(*) as cnt FROM memory_entries WHERE namespace = ? AND (embedding IS NULL OR embedding = '')`);
|
|
840
|
+
stmt.bind([NAMESPACE]);
|
|
841
|
+
if (stmt.step()) missingEmbeddings = stmt.getAsObject().cnt;
|
|
842
|
+
stmt.free();
|
|
843
|
+
}
|
|
824
844
|
db.close();
|
|
825
845
|
|
|
826
846
|
console.log('');
|
|
@@ -840,9 +860,13 @@ log(` • Hierarchical links (h2 -> h3 parent/children)`);
|
|
|
840
860
|
log(` • Context overlap: ${overlapPercent}% (contextBefore/contextAfter)`);
|
|
841
861
|
log('═══════════════════════════════════════════════════════════');
|
|
842
862
|
|
|
843
|
-
// Generate embeddings for new entries
|
|
863
|
+
// Generate embeddings for new entries or backfill missing ones
|
|
844
864
|
// Runs in BACKGROUND to avoid blocking startup
|
|
845
|
-
|
|
865
|
+
const needsEmbeddings = (docsIndexed > 0 || chunksIndexed > 0 || missingEmbeddings > 0);
|
|
866
|
+
if (!skipEmbeddings && needsEmbeddings) {
|
|
867
|
+
if (missingEmbeddings > 0 && docsIndexed === 0 && chunksIndexed === 0) {
|
|
868
|
+
log(`${missingEmbeddings} entries missing embeddings — backfilling...`);
|
|
869
|
+
}
|
|
846
870
|
console.log('');
|
|
847
871
|
log('Spawning embedding generation in background...');
|
|
848
872
|
|