Commit Graph

1 Commits

Author SHA1 Message Date
ruv aca2280f1c feat(intelligence): self-learning wiring + honest multi-path output (ADR-074, #2245)
The self-learning subsystem reported success but persisted nothing queryable.
Three surface-level bugs, all in the ruflo CLI's wiring of the existing
ruvector primitives (no upstream changes needed):

1. hooks_task-completed {trainPatterns:true} was a stub — hardcoded
   patternsLearned:0, ignored the trainPatterns flag entirely, noted in the
   response itself that work was "delegated to the intelligence pipeline
   (#1916 follow-up)." Now synthesizes a one-step trajectory from
   {taskId, success, quality, content} and calls recordTrajectory() on the
   real SONA + EWC++ path. Returns honest deltas and a learningPath field
   ('trajectory-pipeline' | 'recorded-only') so callers know what happened.

2. signalsProcessed was a dead counter — initialized in 3 places, read once,
   incremented zero times. Added recordSignalProcessed() to intelligence.ts
   (throttled persist) and wired it into bridgeStoreEntry. Also fixed
   loadPersistedStats() to restore patternsLearned + signalsProcessed across
   restarts (was only restoring trajectoriesRecorded — a separate "resets
   learning history on every restart" bug surfaced by the audit).

3. hooks_pretrain stored a 1-row summary bundle in the `pretrain` namespace
   but never wrote per-pattern rows to the neural store, so neural_patterns
   list returned [] right after pretrain "succeeded" with N patterns
   extracted. Now also calls storeNeuralPatterns() per pattern; surfaces
   patternsBundled + patternsIndexed + sources.stores in the response so
   callers can see exactly which stores were written.

Plus per the goal-condition "soften where possible to indicate multiple
paths":
- Every learning-adjacent handler returns explicit fields naming the path
  taken and the store(s) written.
- task-completed description lists the three paths (one-step train,
  multi-step trajectory, store-only).
- "[OK] Outcome recorded" theater replaced with notes that say what didn't
  happen as well as what did.

Plus OWASP ASI06 (Memory/Context Poisoning) hardening — basic input
sanitization on task-completed content before it feeds SONA: strip ASCII
control chars, cap to 4 KB. Surfaced by #2241 (Dream Cycle 2026-05-30).

Tests: __tests__/self-learning-2245.test.ts — 9 tests across EASY (primitives)
/ MEDIUM (MCP surfaces) / COMPLEX (multi-step + persistence) categories.

Proof harness: scripts/benchmark-self-learning.mjs — 5 sections (A–E),
writes a run JSON. Latest run: signalsProcessed +10, trained=10/10 via
trajectory pipeline at ~18 ms/call, pretrain stored=10/listed=10,
multi-step persisted=5/sonaUpdate=5. Overall: PASSED. See
docs/learning/self-learning-2245-proof.md for copy-paste reproduction.

Closes #2245.

Co-Authored-By: RuFlo <ruv@ruv.net>
2026-05-30 11:36:57 -04:00