Skip to content

hooks force-learn crashes with TypeError: intel.tick is not a function (v0.2.27 + main HEAD) #529

@KevinAIP

Description

@KevinAIP

Summary

npx ruvector@0.2.27 hooks force-learn exits with code 1 and TypeError: intel.tick is not a function at npm/packages/ruvector/bin/cli.js:4420. The command is unusable. Confirmed still present on main (HEAD as of 2026-06-02) and in npm latest (0.2.27) — the code at that line is unchanged.

Root cause (confirmed)

The force-learn action constructs the lightweight, engine-disabled Intelligence wrapper and then calls intel.tick():

// npm/packages/ruvector/bin/cli.js
hooksCmd.command('force-learn')
  .description('Force an immediate learning cycle')
  .action(() => {
    const intel = new Intelligence({ skipEngine: true });  // Fast mode
    intel.tick();   // <-- line 4420: TypeError
    console.log(JSON.stringify({ success: true, result: 'Learning cycle triggered', stats: intel.stats() }));
  });

This is doubly wrong:

  1. tick() / forceLearn() exist only on the native IntelligenceEngine (dist/core/sona-wrapper.js, dist/core/intelligence-engine.js) — not on the cli.js Intelligence JSON wrapper, which has no tick().
  2. { skipEngine: true } guarantees the engine is never initialized, so even getEngineIfReady() would return null here.

By contrast, the correct pattern is used elsewhere in the same file — e.g. sessionEnd() does const eng = this.getEngineIfReady(); if (eng) eng.forceLearn();.

The engine itself works

Constructing the engine directly and calling forceLearn() works fine:

const { IntelligenceEngine } = require('ruvector/dist/core/intelligence-engine.js');
const e = new IntelligenceEngine({ enableSona: true, enableOnnx: false });
e.forceLearn();
// => "Forced learning: 0 trajectories -> 0 patterns, status: skipped: insufficient trajectories"

So this is purely a CLI wiring bug, not an engine failure. (hooks stats and mcp start are unaffected.)

Environment

  • ruvector: 0.2.27 (npm latest) and main HEAD
  • node: v24.15.0
  • OS: macOS (Darwin 25.4.0)
  • Install: npx ruvector@0.2.27 …

Stack trace

.../node_modules/ruvector/bin/cli.js:4420
    intel.tick();
          ^
TypeError: intel.tick is not a function
    at Command.<anonymous> (.../ruvector/bin/cli.js:4420:11)
    at Command.listener [as _actionHandler] (.../commander/lib/command.js:494:17)
    ...
Node.js v24.15.0

Suggested fix

Make the force-learn action use the engine the way sessionEnd() does — initialize the engine, then call forceLearn():

.action(() => {
  const intel = new Intelligence();      // engine enabled
  const eng = intel.getEngine();         // full init (imports existing data)
  const result = eng ? eng.forceLearn() : 'engine unavailable';
  intel.save();
  console.log(JSON.stringify({ success: true, result, stats: intel.stats() }));
});

Impact

A nightly automation calls hooks force-learn as a best-effort consolidation step. The rc=1 was suppressed for ~a week as a "known issue" — which also masked an unrelated silent reset of intelligence.json during a v0.1.x → v0.2.x bump (~525 memories / 439 trajectories lost). The two together meant the learning layer was effectively non-functional for several days with no signal beyond an rc=1 that was being ignored. A crash here is especially costly because it hides other failures.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions