@comfanion/workflow 4.36.1 → 4.36.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@comfanion/workflow",
3
- "version": "4.36.1",
3
+ "version": "4.36.2",
4
4
  "description": "Initialize OpenCode Workflow system for AI-assisted development with semantic code search",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "3.0.0",
3
- "buildDate": "2026-01-24T14:49:34.378Z",
3
+ "buildDate": "2026-01-24T14:53:32.419Z",
4
4
  "files": [
5
5
  "config.yaml",
6
6
  "FLOW.yaml",
@@ -22,18 +22,22 @@ if (!DEBUG) {
22
22
  const INDEX_PRESETS = {
23
23
  code: {
24
24
  pattern: '**/*.{js,ts,jsx,tsx,mjs,cjs,py,go,rs,java,kt,swift,c,cpp,h,hpp,cs,rb,php,scala,clj}',
25
- description: 'Source code files'
25
+ ignore: ['**/node_modules/**', '**/.git/**', '**/dist/**', '**/build/**', '**/.opencode/**', '**/docs/**', '**/vendor/**', '**/__pycache__/**'],
26
+ description: 'Source code files (excludes docs, vendor, node_modules)'
26
27
  },
27
28
  docs: {
28
- pattern: '**/*.{md,mdx,txt,rst,adoc}',
29
- description: 'Documentation files'
29
+ pattern: 'docs/**/*.{md,mdx,txt,rst,adoc}',
30
+ ignore: [],
31
+ description: 'Documentation in docs/ folder'
30
32
  },
31
33
  config: {
32
34
  pattern: '**/*.{yaml,yml,json,toml,ini,env,xml}',
35
+ ignore: ['**/node_modules/**', '**/.git/**', '**/.opencode/**'],
33
36
  description: 'Configuration files'
34
37
  },
35
38
  all: {
36
39
  pattern: '**/*.{js,ts,jsx,tsx,mjs,cjs,py,go,rs,java,kt,swift,c,cpp,h,hpp,cs,rb,php,scala,clj,md,mdx,txt,rst,adoc,yaml,yml,json,toml}',
40
+ ignore: ['**/node_modules/**', '**/.git/**', '**/.opencode/**'],
37
41
  description: 'All supported files'
38
42
  }
39
43
  };
@@ -208,6 +212,43 @@ class CodebaseIndexer {
208
212
  return results;
209
213
  }
210
214
 
215
+ /**
216
+ * Check if index needs full reindex (files don't match current patterns)
217
+ * @param {string[]} extraIgnore - Additional patterns to ignore
218
+ * Returns { needsReindex, reason, currentCount, expectedCount }
219
+ */
220
+ async checkHealth(extraIgnore = []) {
221
+ const { glob } = await import('glob');
222
+ const preset = INDEX_PRESETS[this.indexName] || INDEX_PRESETS.code;
223
+
224
+ // Combine preset ignore with extra ignore patterns
225
+ const ignore = [...(preset.ignore || []), ...extraIgnore.map(p => `**/${p}/**`)];
226
+
227
+ const expectedFiles = await glob(preset.pattern, {
228
+ cwd: this.root,
229
+ nodir: true,
230
+ ignore
231
+ });
232
+
233
+ const indexedFiles = Object.keys(this.hashes);
234
+ const currentCount = indexedFiles.length;
235
+ const expectedCount = expectedFiles.length;
236
+
237
+ // Check if counts differ significantly (>20% difference or index is empty)
238
+ const diff = Math.abs(currentCount - expectedCount);
239
+ const threshold = Math.max(5, expectedCount * 0.2); // 20% or at least 5 files
240
+
241
+ if (currentCount === 0 && expectedCount > 0) {
242
+ return { needsReindex: true, reason: 'empty', currentCount, expectedCount };
243
+ }
244
+
245
+ if (diff > threshold) {
246
+ return { needsReindex: true, reason: 'mismatch', currentCount, expectedCount };
247
+ }
248
+
249
+ return { needsReindex: false, reason: 'ok', currentCount, expectedCount };
250
+ }
251
+
211
252
  /**
212
253
  * Freshen index - check for stale files and reindex only changed ones
213
254
  * Returns { checked, updated, deleted } counts
@@ -246,6 +287,46 @@ class CodebaseIndexer {
246
287
  return { checked, updated, deleted };
247
288
  }
248
289
 
290
+ /**
291
+ * Index all files matching the preset pattern
292
+ * @param {function} onProgress - Optional callback(indexed, total, currentFile)
293
+ * @param {string[]} extraIgnore - Additional patterns to ignore
294
+ * Returns { indexed, skipped } counts
295
+ */
296
+ async indexAll(onProgress = null, extraIgnore = []) {
297
+ const { glob } = await import('glob');
298
+ const preset = INDEX_PRESETS[this.indexName] || INDEX_PRESETS.code;
299
+
300
+ // Combine preset ignore with extra ignore patterns
301
+ const ignore = [...(preset.ignore || []), ...extraIgnore.map(p => `**/${p}/**`)];
302
+
303
+ const files = await glob(preset.pattern, {
304
+ cwd: this.root,
305
+ nodir: true,
306
+ ignore
307
+ });
308
+
309
+ let indexed = 0;
310
+ let skipped = 0;
311
+
312
+ for (const relPath of files) {
313
+ const filePath = path.join(this.root, relPath);
314
+ try {
315
+ const wasIndexed = await this.indexFile(filePath);
316
+ if (wasIndexed) {
317
+ indexed++;
318
+ if (onProgress) onProgress(indexed, files.length, relPath);
319
+ } else {
320
+ skipped++;
321
+ }
322
+ } catch (e) {
323
+ skipped++;
324
+ }
325
+ }
326
+
327
+ return { indexed, skipped, total: files.length };
328
+ }
329
+
249
330
  /**
250
331
  * Index a single file by path (convenience method)
251
332
  */