mirror of
https://github.com/ruvnet/ruflo.git
synced 2026-09-14 14:01:28 +08:00
0a0a246a62
* feat(neural): Phase 1 convergence (#1773) + neural README cleanup Adds @claude-flow/neural as cli runtime dep, ships a lazy-loading bridge so cli can call NeuralLearningSystem from the package, and documents the API gap Phase 2+ will cross. Bridge: cli/src/memory/neural-package-bridge.ts (88 LOC). Lazy-loads NLS on first call; idempotent; returns null on failure with CLAUDE_FLOW_DEBUG log (same pattern as #1770). Tests: 6 cases in __tests__/neural-package-bridge.test.ts. Lazy init, idempotent cache, stats shape when loaded, reset(). Tolerant of vitest module resolution. Neural README: fixed 5 factual errors. - 9 RL Algorithms -> 7 (PPO/A2C/DQN/QLearning/SARSA/DT/Curiosity) - Quick-start domain development was invalid (valid: code/creative/ reasoning/chat/math/general) - RL imports missing Algorithm suffix on PPO/A2C/DQN/SARSA - NeuralLearningSystem promoted to top quick-start - Added Integration with cli section Validation: 781 cli tests pass (769 baseline + 6 bandit + 6 bridge). Bumps all three packages to 3.7.0-alpha.6. Refs #1773. Co-Authored-By: RuFlo <ruv@ruv.net> * chore(cli): regenerate pnpm-lock.yaml for @claude-flow/neural dep (#1773) Phase 1 commit added "@claude-flow/neural": "^3.0.0-alpha.7" to cli/ package.json but did not regenerate pnpm-lock.yaml. The Type Check V3 and Test V3 Packages CI jobs run with --frozen-lockfile and refused the install. pnpm install --filter @claude-flow/cli --no-frozen-lockfile locally to bring the lockfile in sync with the package.json change. No source changes — just the lockfile. Co-Authored-By: RuFlo <ruv@ruv.net> --------- Co-authored-by: Reuven <cohen@ruv-mac-mini.local>
87 lines
3.2 KiB
TypeScript
87 lines
3.2 KiB
TypeScript
/**
|
|
* @claude-flow/neural package bridge — Phase 1 convergence smoke (#1773).
|
|
*
|
|
* Proves the BRIDGE contract: lazy init, idempotent caching, graceful failure
|
|
* when the package isn't resolvable. The actual package-loading is tested
|
|
* conditionally because vitest's module resolver can disagree with Node's
|
|
* runtime resolver for ESM workspace packages — direct `node` invocation
|
|
* loads the package fine, vitest doesn't always. The bridge itself handles
|
|
* both cases (returns null on failure), so these tests cover the contract
|
|
* without depending on test-runtime resolution behavior.
|
|
*
|
|
* Direct package shape testing happens in @claude-flow/neural's own test
|
|
* suite — not duplicated here.
|
|
*/
|
|
|
|
import { describe, expect, it, beforeEach } from 'vitest';
|
|
import {
|
|
getNeuralPackage,
|
|
isNeuralPackageLoaded,
|
|
getNeuralPackageStats,
|
|
resetNeuralPackageBridge,
|
|
} from '../src/memory/neural-package-bridge.js';
|
|
|
|
describe('@claude-flow/neural package bridge (#1773 Phase 1)', () => {
|
|
beforeEach(() => {
|
|
resetNeuralPackageBridge();
|
|
});
|
|
|
|
it('starts with the package not loaded (lazy init contract)', () => {
|
|
expect(isNeuralPackageLoaded()).toBe(false);
|
|
});
|
|
|
|
it('returns the same instance/result on subsequent calls (idempotent)', async () => {
|
|
const a = await getNeuralPackage();
|
|
const b = await getNeuralPackage();
|
|
// Whether the package loaded or not, both calls return identical refs.
|
|
// (null === null is also true, so this works for the not-loaded case.)
|
|
expect(a).toBe(b);
|
|
}, 30_000);
|
|
|
|
it('isNeuralPackageLoaded reflects post-load state', async () => {
|
|
expect(isNeuralPackageLoaded()).toBe(false);
|
|
const sys = await getNeuralPackage();
|
|
if (sys) {
|
|
// Package loaded — flag should be true now.
|
|
expect(isNeuralPackageLoaded()).toBe(true);
|
|
} else {
|
|
// Package failed to load (vitest resolver, missing dep, etc.) —
|
|
// the flag stays false. Bridge degrades gracefully.
|
|
expect(isNeuralPackageLoaded()).toBe(false);
|
|
}
|
|
}, 30_000);
|
|
|
|
it('getNeuralPackageStats returns the documented shape OR null', async () => {
|
|
const stats = await getNeuralPackageStats();
|
|
if (stats) {
|
|
// Documented shape per @claude-flow/neural NeuralLearningSystem.getStats()
|
|
expect(stats).toHaveProperty('sona');
|
|
expect(stats).toHaveProperty('reasoningBank');
|
|
expect(stats).toHaveProperty('patternLearner');
|
|
} else {
|
|
expect(stats).toBeNull();
|
|
}
|
|
}, 30_000);
|
|
|
|
it('exposes accessors when the package loads', async () => {
|
|
const sys = await getNeuralPackage();
|
|
if (sys) {
|
|
expect(typeof sys.getSONAManager).toBe('function');
|
|
expect(typeof sys.getReasoningBank).toBe('function');
|
|
expect(typeof sys.getPatternLearner).toBe('function');
|
|
expect(sys.getSONAManager()).toBeTruthy();
|
|
expect(sys.getReasoningBank()).toBeTruthy();
|
|
expect(sys.getPatternLearner()).toBeTruthy();
|
|
} else {
|
|
// No package, no accessors — bridge correctly returned null.
|
|
expect(sys).toBeNull();
|
|
}
|
|
}, 30_000);
|
|
|
|
it('resetNeuralPackageBridge() clears the cache', async () => {
|
|
await getNeuralPackage();
|
|
resetNeuralPackageBridge();
|
|
expect(isNeuralPackageLoaded()).toBe(false);
|
|
}, 30_000);
|
|
});
|