cf-doctor 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 (50) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +161 -0
  3. package/bin/cf-doctor.js +18 -0
  4. package/dist/doctor.d.ts +21 -0
  5. package/dist/doctor.d.ts.map +1 -0
  6. package/dist/doctor.js +33 -0
  7. package/dist/doctor.js.map +1 -0
  8. package/dist/index.d.ts +9 -0
  9. package/dist/index.d.ts.map +1 -0
  10. package/dist/index.js +9 -0
  11. package/dist/index.js.map +1 -0
  12. package/dist/mcp-server.d.ts +12 -0
  13. package/dist/mcp-server.d.ts.map +1 -0
  14. package/dist/mcp-server.js +200 -0
  15. package/dist/mcp-server.js.map +1 -0
  16. package/dist/patches/apply.d.ts +7 -0
  17. package/dist/patches/apply.d.ts.map +1 -0
  18. package/dist/patches/apply.js +51 -0
  19. package/dist/patches/apply.js.map +1 -0
  20. package/dist/persistence/episodes.d.ts +42 -0
  21. package/dist/persistence/episodes.d.ts.map +1 -0
  22. package/dist/persistence/episodes.js +160 -0
  23. package/dist/persistence/episodes.js.map +1 -0
  24. package/dist/persistence/index.d.ts +4 -0
  25. package/dist/persistence/index.d.ts.map +1 -0
  26. package/dist/persistence/index.js +4 -0
  27. package/dist/persistence/index.js.map +1 -0
  28. package/dist/persistence/q-table.d.ts +42 -0
  29. package/dist/persistence/q-table.d.ts.map +1 -0
  30. package/dist/persistence/q-table.js +138 -0
  31. package/dist/persistence/q-table.js.map +1 -0
  32. package/dist/persistence/sona.d.ts +45 -0
  33. package/dist/persistence/sona.d.ts.map +1 -0
  34. package/dist/persistence/sona.js +142 -0
  35. package/dist/persistence/sona.js.map +1 -0
  36. package/package.json +63 -0
  37. package/patches/README.md +68 -0
  38. package/patches/neural-index.patch +8 -0
  39. package/patches/quick-test.patch +25 -0
  40. package/patches/sona-integration.patch +76 -0
  41. package/patches/version-bridge.patch +30 -0
  42. package/scripts/cf-doctor.sh +684 -0
  43. package/tests/run-all-tests.sh +32 -0
  44. package/tests/test-01-doctor-passes.sh +43 -0
  45. package/tests/test-02-mcp-init.sh +36 -0
  46. package/tests/test-03-agent-spawn-no-ruvector.sh +84 -0
  47. package/tests/test-04-agent-spawn-with-ruvector.sh +37 -0
  48. package/tests/test-05-learning-persists.sh +94 -0
  49. package/tests/test-06-hooks-version-bridge.sh +82 -0
  50. package/tests/test-helpers.sh +88 -0
@@ -0,0 +1,68 @@
1
+ # @ruvector/* Import Fix Patches
2
+
3
+ These patches fix crashes that occur when `@ruvector/*` WASM packages are not
4
+ installed. Each patch converts a hard static import into a dynamic import with
5
+ an in-memory fallback, so claude-flow runs correctly without the optional native
6
+ backends.
7
+
8
+ ## Patches
9
+
10
+ | File | Target Repo | Severity | Description |
11
+ |------|------------|----------|-------------|
12
+ | `sona-integration.patch` | claude-flow | CRITICAL | Replaces static `@ruvector/sona` import with lazy dynamic import + MockSonaEngine fallback |
13
+ | `neural-index.patch` | claude-flow | CRITICAL | Updates barrel file comments; safe once sona-integration is patched |
14
+ | `quick-test.patch` | claude-flow | LOW | Replaces static `@ruvector/attention` import in benchmark example |
15
+ | `version-bridge.patch` | ruvector | NORMAL | Detects claude-flow v2 vs v3 CLI syntax before spawning hooks |
16
+
17
+ ## Apply Instructions
18
+
19
+ ### claude-flow repo (Patches A, B, C)
20
+
21
+ ```bash
22
+ cd claude-flow
23
+ git apply /tmp/cf-integration-fixes/patches/sona-integration.patch
24
+ git apply /tmp/cf-integration-fixes/patches/neural-index.patch
25
+ git apply /tmp/cf-integration-fixes/patches/quick-test.patch
26
+ ```
27
+
28
+ ### ruvector repo (Patch D)
29
+
30
+ ```bash
31
+ cd ruvector
32
+ git apply /tmp/cf-integration-fixes/patches/version-bridge.patch
33
+ ```
34
+
35
+ ### Dry-run (check without applying)
36
+
37
+ ```bash
38
+ git apply --check /tmp/cf-integration-fixes/patches/sona-integration.patch
39
+ ```
40
+
41
+ ### Reverse a patch
42
+
43
+ ```bash
44
+ git apply -R /tmp/cf-integration-fixes/patches/sona-integration.patch
45
+ ```
46
+
47
+ ## Verification
48
+
49
+ After applying, confirm no static `@ruvector/*` imports remain in critical paths:
50
+
51
+ ```bash
52
+ # Should return zero results for patched files
53
+ grep -rn "from '@ruvector/" v3/@claude-flow/neural/src/sona-integration.ts
54
+ grep -rn "from '@ruvector/" v3/@claude-flow/performance/src/examples/quick-test.ts
55
+ ```
56
+
57
+ Test that the mock fallback activates cleanly (without @ruvector installed):
58
+
59
+ ```bash
60
+ npx tsx -e "
61
+ import { SonaIntegration } from './v3/@claude-flow/neural/index';
62
+ const s = new SonaIntegration();
63
+ s.storePattern('test', { v: 1 }).then(() => {
64
+ console.log('mock:', s.isUsingMock());
65
+ return s.recallPattern('test');
66
+ }).then(r => console.log('recalled:', r));
67
+ "
68
+ ```
@@ -0,0 +1,8 @@
1
+ --- a/v3/@claude-flow/neural/index.ts
2
+ +++ b/v3/@claude-flow/neural/index.ts
3
+ @@ -1,3 +1,4 @@
4
+ export { SonaIntegration } from './src/sona-integration';
5
+ export { NeuralRouter } from './src/neural-router';
6
+ -// ... other exports that depend on @ruvector
7
+ +// Re-exports are safe now because sona-integration uses dynamic import internally
8
+ +// No @ruvector/* static imports leak through this barrel file
@@ -0,0 +1,25 @@
1
+ --- a/v3/@claude-flow/performance/src/examples/quick-test.ts
2
+ +++ b/v3/@claude-flow/performance/src/examples/quick-test.ts
3
+ @@ -1,7 +1,19 @@
4
+ -import { FlashAttention } from '@ruvector/attention';
5
+ -
6
+ async function runBenchmark() {
7
+ - const attn = new FlashAttention({ headDim: 64 });
8
+ + let FlashAttention: any;
9
+ + try {
10
+ + const mod = await import('@ruvector/attention');
11
+ + FlashAttention = mod.FlashAttention;
12
+ + } catch {
13
+ + console.warn('[perf] @ruvector/attention not available, using mock');
14
+ + FlashAttention = class MockFlashAttention {
15
+ + constructor(private opts: any) {}
16
+ + async forward(q: any, k: any, v: any) {
17
+ + // Mock: return zero tensor of expected shape
18
+ + return { output: new Float32Array(this.opts.headDim || 64), mockResult: true };
19
+ + }
20
+ + };
21
+ + }
22
+ +
23
+ + const attn = new FlashAttention({ headDim: 64 });
24
+ // ...rest of benchmark
25
+ }
@@ -0,0 +1,76 @@
1
+ --- a/v3/@claude-flow/neural/src/sona-integration.ts
2
+ +++ b/v3/@claude-flow/neural/src/sona-integration.ts
3
+ @@ -1,27 +1,55 @@
4
+ -import { SonaEngine } from '@ruvector/sona';
5
+ +// Dynamic import with fallback - @ruvector/sona is optional
6
+ +let SonaEngineImpl: any = null;
7
+
8
+ -export class SonaIntegration {
9
+ - private engine: SonaEngine;
10
+ +async function loadSonaEngine(): Promise<any> {
11
+ + if (SonaEngineImpl !== null) return SonaEngineImpl;
12
+ + try {
13
+ + const mod = await import('@ruvector/sona');
14
+ + SonaEngineImpl = mod.SonaEngine;
15
+ + return SonaEngineImpl;
16
+ + } catch {
17
+ + // @ruvector/sona not installed - use in-memory mock
18
+ + SonaEngineImpl = class MockSonaEngine {
19
+ + private store = new Map<string, any>();
20
+
21
+ - constructor() {
22
+ - this.engine = new SonaEngine();
23
+ - }
24
+ + async store(key: string, pattern: any): Promise<void> {
25
+ + this.store.set(key, pattern);
26
+ + }
27
+
28
+ - async storePattern(key: string, pattern: any): Promise<void> {
29
+ - await this.engine.store(key, pattern);
30
+ - }
31
+ + async recall(key: string): Promise<any> {
32
+ + return this.store.get(key) ?? null;
33
+ + }
34
+
35
+ - async recallPattern(key: string): Promise<any> {
36
+ - return this.engine.recall(key);
37
+ + async learn(_input: any, _feedback: number): Promise<void> {
38
+ + // Mock: no-op learning without SONA neural backend
39
+ + }
40
+ + };
41
+ + return SonaEngineImpl;
42
+ }
43
+ +}
44
+
45
+ - async learn(input: any, feedback: number): Promise<void> {
46
+ - await this.engine.learn(input, feedback);
47
+ +export class SonaIntegration {
48
+ + private engine: any = null;
49
+ + private initialized = false;
50
+ +
51
+ + private async ensureInit(): Promise<void> {
52
+ + if (this.initialized) return;
53
+ + const Engine = await loadSonaEngine();
54
+ + this.engine = new Engine();
55
+ + this.initialized = true;
56
+ + }
57
+ +
58
+ + async storePattern(key: string, pattern: any): Promise<void> {
59
+ + await this.ensureInit();
60
+ + await this.engine.store(key, pattern);
61
+ + }
62
+ +
63
+ + async recallPattern(key: string): Promise<any> {
64
+ + await this.ensureInit();
65
+ + return this.engine.recall(key);
66
+ + }
67
+ +
68
+ + async learn(input: any, feedback: number): Promise<void> {
69
+ + await this.ensureInit();
70
+ + await this.engine.learn(input, feedback);
71
+ + }
72
+ +
73
+ + isUsingMock(): boolean {
74
+ + return SonaEngineImpl?.name === 'MockSonaEngine';
75
+ }
76
+ }
@@ -0,0 +1,30 @@
1
+ --- a/npm/packages/agentic-integration/swarm-manager.ts
2
+ +++ b/npm/packages/agentic-integration/swarm-manager.ts
3
+ @@ -1,4 +1,25 @@
4
+ +async function detectClaudeFlowVersion(): Promise<'v2' | 'v3' | null> {
5
+ + try {
6
+ + const { stdout } = await execAsync('npx claude-flow --version 2>/dev/null');
7
+ + const version = stdout.trim();
8
+ + if (version.startsWith('3.') || version.startsWith('v3.')) return 'v3';
9
+ + if (version.startsWith('2.') || version.startsWith('v2.') || version.includes('alpha')) return 'v2';
10
+ + return 'v3'; // default to v3 for newer versions
11
+ + } catch {
12
+ + return null;
13
+ + }
14
+ +}
15
+ +
16
+ async function registerHooks(config: SwarmConfig) {
17
+ - const proc = spawn('npx', ['claude-flow@alpha', 'hooks', 'register', '--swarm', config.name]);
18
+ + const cfVersion = await detectClaudeFlowVersion();
19
+ + if (!cfVersion) {
20
+ + console.warn('[swarm-manager] claude-flow not found, skipping hook registration');
21
+ + return;
22
+ + }
23
+ +
24
+ + const args = cfVersion === 'v3'
25
+ + ? ['claude-flow', 'mcp', '--hooks', JSON.stringify({ swarm: config.name })]
26
+ + : ['claude-flow@alpha', 'hooks', 'register', '--swarm', config.name];
27
+ +
28
+ + const proc = spawn('npx', args);
29
+ // ...
30
+ }