Stops unbounded growth of patterns.rvf / brain.rvf.
- #495: AbortSignal in HybridMemoryBackend.initialize() so a 5s
createHybridBackendWithTimeout abort actually cancels the work
instead of leaking a 14-min runaway init (~20 GB / 12 MB/s leak
observed in the field). UnifiedMemoryManager.initialize() also
accepts {signal} with throwIfAborted() at each await seam.
- Post-dream compaction in DreamScheduler — threshold-gated compact()
against patterns.rvf and brain.rvf so append-only growth has a
steady-state janitor.
- Boot-time size guard in getSharedRvfAdapter() for one-shot recovery
of installations already in the bad state.
- Bounded SQLite→RVF backfill (top-1000 by last_used_at) so
`: > patterns.rvf` for disk recovery doesn't trigger an unbounded
replay (the "regrew to 59 GB" pathology).
- RvfDualWriter.compact() for brain.rvf parity.
Three operator env knobs added (no rebuild needed):
- AQE_RVF_SIZE_GUARD_BYTES (default 256 MB)
- AQE_RVF_DEAD_RATIO_THRESHOLD (default 0.30)
- AQE_RVF_BACKFILL_LIMIT (default 1000)
29 new unit tests. Performance gate 15/15 pass. test:ci 4035 pass
(3 pre-existing failures, verified identical on main).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Six user-reported MCP fixes (see CHANGELOG and docs/releases/v3.9.30.md):
- #467 __dirname ESM polyfill across 7 source files
- #469 real all-MiniLM-L6-v2 embeddings (was random-vector mock)
- #470 NaN guard in coherence_collapse risk categorization
- #472 default test phases when MCP wrapper omits the list
- #473 wire SessionOperationCache into MCP tools/call dispatch
- #474 validate language and auto-derive framework in test_generate
Also fixes a pre-existing field-name typo in
tests/integrations/agentic-flow/e2e-integration.test.ts (.similarity →
.score) that was vacuously passing because the previous mock embedding
generator rarely cleared the threshold to exercise the assertion.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hotfix for v3.9.28 — bridge payload shape (#482 round 3)
After v3.9.28 fixed the subscriber-loading order, handlers fired for
every bridge event but immediately short-circuited because
event.payload.experience was undefined. The bridge had been publishing a
flat payload { experienceId, domain, agent, task, ... } that didn't
match handleExperienceCaptured's destructure.
Fix: bridge now publishes the canonical nested
{ experience: TaskExperience-shaped, reward } shape that matches the
existing publisher in src/learning/experience-capture.ts:1043.
Also dropped the domain-specific fan-out events (test-execution.TestRunCompleted,
coverage-analysis.CoverageGapDetected, etc.) — their handlers expect
domain-event-specific fields (runId, passed, failed, gapId, riskScore)
that hooks don't capture, so publishing them with undefined fields
recorded degenerate experiences. Universal learning.ExperienceCaptured
is now the bridge's sole publication.
Integration test now uses requirements-validation domain (per Jordi's
suggestion) so the universal-event path is the sole thing being tested,
not masked by a fan-out side effect.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hotfix for v3.9.27 — bridge subscriber wiring (#482)
The CapturedExperienceBridge shipped in v3.9.27 published events into a
kernel with no subscribers because lazyLoading: true left domain plugins
un-initialized when the bridge's first drain ran. Cursor advanced past
the rows; events were silently lost.
Fix: kernel.initialize() now eagerly loads all enabled domain plugins
before starting the bridge. CLI commands opt out via the new
enableExperienceBridge: false flag to keep their fast startup. Added
end-to-end integration test (real kernel + real plugin + real drain →
asserts kv_store has learning:experience:* key).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- AbortSignal threading bounds ReasoningBank.initialize() (#478)
prevents leaked init from runaway patterns.rvf writes
- CapturedExperienceBridge wires hook activity to domain plugins (#479)
via kernel-side drain of captured_experiences
- Removes dead v3-qe-bridge.sh, two stale planning docs, five orphan
workers in qe-workers.ts (subsumed by LearningConsolidationWorker)
Net: +430 / -2,090 lines
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ten learning-pipeline fixes (#453, #454, #455, #456, #460, #461, #462,
#463, #464, #465) plus dup closures (#457-#459). Tightens the #465
sentinel sweep with the same task_json discriminator the LIMIT-1 close
uses, preserving the #451 ownership split (route sentinels owned by
post-route, pre-task sentinels by post-task). Updates the regression
suite to reflect the new sweep behavior.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(hooks): post-route Stop hook closes route sentinels 1:1 (#451)
The `route` hook fires on UserPromptSubmit and writes a sentinel row to
routing_outcomes with quality_score=-1, expecting `post-task` to close
it. But `post-task` only fires on PostToolUse ^(Task|Agent)$, which is
rare in direct-work sessions (Bash/Edit/Read without spawning sub-
agents). Sentinels accumulated indefinitely — Jordi reported 123+
unresolved rows per session. Stream D never converged.
Changes:
1. New `aqe hooks post-route` subcommand
(src/cli/commands/hooks-handlers/routing-hooks.ts)
Closes the most-recent unresolved route sentinel using a
`task_json NOT LIKE '%"taskId"%'` discriminator that isolates
route entries from pre-task entries. Quality formula collapses the
6-dim outcome formula for unknown duration:
0.325 + 0.25·success + 0.10·1.0
= 0.675 (success) / 0.425 (failure)
2. Inverse discriminator on updateRoutingOutcomeQuality
(src/cli/commands/hooks-handlers/hooks-dream-learning.ts)
Added `task_json LIKE '%"taskId"%'` to the WHERE clause so
post-task only ever closes pre-task sentinels. Without this,
post-task could grab a stale route sentinel by accident and
miscredit duration to a row that wasn't about a Task() call.
Symmetric counterpart to the post-route filter.
3. Stop-hook wiring in both init template paths
(src/init/phases/07-hooks.ts + src/init/init-wizard-hooks.ts)
Added `npx agentic-qe hooks post-route --success true --json`
to the Stop block. Timeout 5000ms, continueOnError: true, so a
failed post-route cannot block session teardown.
4. CLI help text (src/cli/commands/hooks.ts)
Added example for the new subcommand.
5. Regression test (tests/unit/cli/commands/post-route.test.ts)
4 tests using in-memory better-sqlite3:
- Closes most-recent route sentinel; leaves pre-task sentinels
and resolved rows untouched
- quality_score = 0.425 when --success false
- No-op when only pre-task sentinels exist (discriminator works)
- No-op on second invocation when only one sentinel was outstanding
Bug-introduce verification: stashed routing-hooks.ts, ran new test —
all 4 cases failed (Commander rejects unknown subcommand). Restored
fix, all 4 pass. Test distinguishes pre-fix and post-fix states.
Co-authored-by: Jordi Izquierdo <noreply@github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(release): bump version to v3.9.25
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(hooks): post-task runs Stream B/D/F when --task-id is missing (#449)
The shipped PostToolUse hook command for Task/Agent matchers is
`npx agentic-qe hooks post-task --task-id "$TOOL_RESULT_agent_id" --success --json`
Claude Code does not populate $TOOL_RESULT_agent_id, so the flag arrives
empty and options.taskId is falsy on every real hook invocation. The
`if (options.taskId)` gate inside post-task then short-circuited the
entire Stream B/D/F learning chain:
- reasoningBank.recordOutcome — never called
- persistTaskOutcome — never called (no captured_experiences,
experience_applications, qe_trajectories, dream_insights.applied)
- updateRoutingOutcomeQuality — never called (routing_outcomes
sentinels accumulated unfilled at success=0/quality_score=-1)
- updateHookRouterQValue — never called (rl_q_values stayed empty
forever)
Same regression was fixed in v3.9.21 (patch 030) and silently came
back in v3.9.23.
Fix:
- Remove the `if (options.taskId)` gate in post-task. Use
`hook-${Date.now()}` fallback for the patternId / experience id
when the caller didn't supply one. The bridge lookup in
persistTaskOutcome keys by `ORDER BY created_at DESC LIMIT 1`
(not by taskId), so Stream F's Bellman Q-update still finds the
bridge payload it needs.
- Remove the parallel `&& options.taskId` clause from the pre-task
routing_outcomes sentinel write at line 195 — same root cause.
- Add `DO NOT REINTRODUCE` comment blocks at both sites pointing
at #449 and patch 030.
Test: tests/unit/cli/commands/task-hooks-no-taskid.test.ts mocks
hooks-shared and asserts persistTaskOutcome / updateHookRouterQValue
fire when --task-id is absent. Bug-introduce verification:
re-introducing the gate makes the no-taskId test fail with the
expected "called 1 times, but got 0 times".
Co-authored-by: Jordi Izquierdo <noreply@github.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* chore(release): bump version to v3.9.24
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Fixes routing learning loop — bootstrap patterns now reach HNSW index
(#445). After this release, `patternCount` in routing hook output is
non-zero, existing installs auto-backfill `.agentic-qe/patterns.rvf` from
SQLite on next startup.
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bumps version + fleetVersion across package.json, plugin.json, and the
two skills-manifest.json copies. Adds CHANGELOG entry and release notes.
Includes one fix discovered during the release-prep e2e: stale-lock
recovery in shared-rvf-adapter's openOrCreateRvf ladder. The native
@ruvector/rvf-node binding leaves a `<file>.lock` artifact when a
process exits without calling close() — a behaviour that frequently
happens in CLI flows and that the previous always-create code path
masked. With open-or-create, those stale locks now surfaced as
`LockHeld` errors. The ladder now detects that, removes the stale
lock file, and retries open exactly once. E2E confirms RVF native
recovers cleanly across init → CLI invocation boundaries.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirrors the ruvnet/ruflo pattern (verified live in ~/.claude/plugins/marketplaces/ruflo/):
- .claude-plugin/marketplace.json — required manifest that lists agentic-qe-fleet
with relative source path, making this repo a valid Claude Code marketplace
- .claude-plugin/plugin.json — top-level metadata (engines, MCP server,
keywords) so the marketplace itself can be referenced
- .claude-plugin/README.md — picker-surface description with install command
and plugin overview
- README.md — new "Claude Code Plugin (Alternative Install)" section showing
/plugin marketplace add path and plugin-vs-aqe-init comparison; removed the
"once published" caveat now that the marketplace files exist
Users can now install via:
/plugin marketplace add proffesor-for-testing/agentic-qe
/plugin install agentic-qe-fleet
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>