Skip to content

feat: improve Memory v5 task/chat classification with LLM classifier#5493

Merged
SivanCola merged 8 commits into
esengine:main-v2from
XTLine:fix/memory-v5-citation-noise
Jun 28, 2026
Merged

feat: improve Memory v5 task/chat classification with LLM classifier#5493
SivanCola merged 8 commits into
esengine:main-v2from
XTLine:fix/memory-v5-citation-noise

Conversation

@XTLine

@XTLine XTLine commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Closes #5486

Summary

Improve Memory v5 task/chat detection logic, addressing false positives and false negatives in the keyword-matching approach.

Implemented in two phases:

Phase 1: Keyword-based Gating (first 3 commits)

  1. 59dc039 - Throttle memory compiler prompt injection

    • Add gating logic in memorycompiler/runtime.go
    • Use shouldInjectPrompt() to decide whether to inject the contract
    • Add E2E tests to verify throttling behavior
  2. bc9b7f2 - Hide memory compiler citations in transcript

    • Filter Memory v5 citation display in frontend Message.tsx
    • Add memoryCitationVisibility.ts utility function
    • Add unit tests for citation visibility logic
  3. 76852fe - Gate memory compiler prompt injection for chat

    • Add shouldInjectMemoryCompilerContractForInput() in agent.go
    • Use keyword whitelist (greetings) and blacklist (action words)
    • Support EN/ZH detection: hello, hi, 你好, fix, 修复, etc.
    • Add unit tests in memory_compiler_gate_test.go

Problem: The keyword approach suffers from false positives ("thanks for fixing" → task) and false negatives ("auth isn't working" → chat).

Phase 2: LLM-based Classifier (last 3 commits)

  1. d916d0c - Add task/chat classifier infrastructure

    • New task_classifier.go:
      • TaskClassifier interface
      • llmClassifier: classifies via Haiku model (2s timeout)
      • heuristicClassifier: improved keyword fallback
      • classificationCache: session-scoped cache (LRU + 5min TTL)
    • Add full unit tests (including mock provider)
  2. bbc2d87 - Integrate classifier to gate Memory v5

    • Integrate classifier in agent.go:
      • Chat inputs completely skip Memory v5 (not just suppress injection)
      • Fall back to heuristic classifier on LLM error
    • Add feature flag in boot.go:
      • Env var: REASONIX_MEMORY_COMPILER_LLM_CLASSIFICATION
      • Default: false (gradual rollout)
    • Clear classifier cache on SetSession()
  3. 097a49d - Update and add E2E tests for classifier behavior

    • Update TestRunDoesNotInjectMemoryCompilerContractForGreeting:
      • Expect 0 stats events (chat completely skips Memory v5)
    • New tests:
      • TestClassifierSkipsMemoryV5ForChat
      • TestClassifierUsesMemoryV5ForTask

Cache-impact: low - New session-scoped cache (max 100 entries, ~10KB) only active when feature flag enabled (default: false). Cleared on session boundary.

Cache-guard: Comprehensive unit tests in internal/agent/task_classifier_cache_test.go covering Get/Set, TTL expiration, LRU eviction, normalization, and Clear behavior. Run: go test ./internal/agent/... -run TestClassificationCache -v

System-prompt-review: No system prompt content changes. Modified boot.go only adds feature flag configuration
(REASONIX_MEMORY_COMPILER_LLM_CLASSIFICATION) without altering prompt templates or agent instructions.

Verification

All tests pass:

  go test ./internal/agent/... -v

Test coverage

  • Heuristic classifier unit tests (greetings, tasks, false positive/negative scenarios)
  • LLM classifier unit tests (mock provider)
  • Cache behavior tests (Get/Set, TTL, LRU, normalization)
  • E2E tests (chat skips, task uses Memory v5)
  • Gating tests (keyword-matching logic)

Cache details

New cache: classificationCache (only when feature flag is enabled)

  • Scope: session-scoped (cleared on SetSession())
  • Size: max 100 entries (LRU eviction)
  • TTL: 5 minutes
  • Key: SHA256(normalized_input)
  • Memory footprint: ~10KB (100 entries × ~100 bytes/entry)

Cache strategy:

  • Hit: return directly (<1ms)
  • Miss: call LLM (~100-300ms) → cache result
  • LLM error: fall back to heuristic → do not cache error results

XTLine added 6 commits June 28, 2026 16:24
Add TaskClassifier interface with two implementations:
- llmClassifier: uses provider with 2s timeout, fallback to heuristic
- heuristicClassifier: improved keyword matching + file reference detection

Add classificationCache with LRU eviction (100 entries max) and 5min TTL.

Includes comprehensive unit tests for both classifiers and cache behavior.
Update Agent to use TaskClassifier:
- Add classifier field and UseMemoryCompilerLLMClassification option
- Initialize classifier in New() (LLM or heuristic based on flag)
- Completely skip Memory v5 for chat inputs (not just injection)
- Clear cache on session boundary

Add REASONIX_MEMORY_COMPILER_LLM_CLASSIFICATION env var (default: false).

When disabled (default), uses heuristic classifier. When enabled, uses LLM
classifier with heuristic fallback on error/timeout.
Update TestRunDoesNotInjectMemoryCompilerContractForGreeting to expect
zero stats events (chat inputs now completely skip Memory v5).

Add two new E2E tests:
- TestClassifierSkipsMemoryV5ForChat: verifies chat skips Memory v5
- TestClassifierUsesMemoryV5ForTask: verifies tasks use Memory v5
@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development desktop Wails desktop app (desktop/**) agent Core agent loop (internal/agent, internal/control) config Configuration & setup (internal/config) and removed v2 Go rewrite (1.x) — main-v2 branch, active development labels Jun 28, 2026

@SivanCola SivanCola left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. This is now a well-scoped fix for the Memory v5 chat/task noise reported in #5486 and the related user-visible compiler citation noise.

The selected mechanism is the right one: Memory v5 startup is gated by task/chat classification, the heuristic classifier remains the default path, the optional LLM classifier is explicitly opt-in, simple greetings and acknowledgements skip execution-contract injection, real task/failure descriptions still use Memory v5, and Memory v5 compiler citations are kept out of the visible transcript.

Why this fits the architecture:

  • The default path stays local and cache-friendly; it does not add provider calls unless the opt-in environment flag is enabled.
  • The classifier controls the Memory v5 startup/injection boundary instead of only decorating it, so non-imperative task reports like "the auth isn't working" still get the compiler path.
  • It remains compatible with #5487: #5487 filters backend evidence citations, while this PR handles chat/task gating and transcript visibility.

The main thing I wanted tightened was the classifier-to-injection contract and the boundary coverage. The follow-up commits now cover the Memory v5 gating path, classifier caching, heuristic chat exclusions, Chinese task phrases, failure semantics, English boundary cases, and frontend citation visibility. Related older work in #5376 is superseded by this PR's newer implementation path.

Verified:

  • latest GitHub checks are green: CI, race, desktop, lint, coverage, govulncheck, CodeQL, and cache-impact
  • clean local merge against current main-v2 succeeded
  • go test ./internal/agent/... ./internal/memorycompiler/... passed after that merge
  • git diff --check passed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent Core agent loop (internal/agent, internal/control) config Configuration & setup (internal/config) desktop Wails desktop app (desktop/**) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Memory v5 treats simple greeting as execution task and triggers noisy planner/tool flow

2 participants