Skip to content

fix(user-prompt): inject prompt-matched conclusions instead of stalest representation lines#63

Open
alvistar wants to merge 2 commits into
plastic-labs:mainfrom
alvistar:fix/inject-search-matched-conclusions
Open

fix(user-prompt): inject prompt-matched conclusions instead of stalest representation lines#63
alvistar wants to merge 2 commits into
plastic-labs:mainfrom
alvistar:fix/inject-search-matched-conclusions

Conversation

@alvistar

@alvistar alvistar commented Jun 12, 2026

Copy link
Copy Markdown

Problem

The UserPromptSubmit hook runs a semantic search over the user's prompt (peer.context({ searchQuery, ... })), but then formatCachedContext() injects the first 5 lines of the representation string. The representation merges search hits with frequent/recent conclusions into a single timestamp-ascending list, so the injected lines are always the oldest conclusions in the window — the search results never surface.

Measured on a live workspace (358 conclusions): with and without searchQuery, 4 of 5 injected lines were identical and unrelated to the prompt. In practice every turn re-injects the same stale facts regardless of what the user asks — closely related to the repetition reported in #39 (includeMostFrequent pinning is only half the story; head-of-representation selection is the other half).

A second, compounding issue: extractTopics() falls back to an English-stopword word filter, so non-English prompts produce low-signal queries ("come siamo messi" → word salad).

Fix

  • Query matched conclusions explicitly (conclusionScope.query(searchQuery, 5)) in parallel with peer.context() and put them first in the injected block (cached alongside the context, so cache-served turns keep them too)
  • Fill the remaining slots with the newest representation lines (timestamp-desc when lines carry a [timestamp] prefix) instead of the oldest, deduped by normalized text
  • Drop the English-only stopword fallback; fall back to the raw prompt (truncated to 300 chars), which embeds better for semantic search and keeps non-English prompts working

No new API surface: conclusionScope.query already exists in the SDK; failures degrade gracefully to the previous behavior (.catch(() => [])).

Before / after (live workspace, same prompts)

Prompt (Italian): "come va il deriver di honcho su kubernetes? flux ha applicato la modifica ai worker?"

Before — 5 conclusions about an unrelated design discussion from a previous day, identical to what every other prompt received.

After — all 5 conclusions about the user's Kubernetes/k3s work from the same day.

Prompt (English): "help me create the new jira tickets for the REORG board" → after: all 5 conclusions about the user's recent Jira board work.

Test plan

  • tsc --noEmit clean
  • Deterministic unit tests: bun test — 16 cases covering search-matched-first ordering, newest-not-oldest fill (regression for the head-of-representation bug), normalized dedup, the 5-slot cap, and the empty-topics return that drives the raw-prompt fallback (src/hooks/user-prompt.test.ts)
  • Fresh-fetch path: hook invoked with stdin payload, context cache cleared — injected conclusions match prompt topic (English and Italian prompts)
  • Search-failure path: conclusionScope.query rejection falls back to representation-only selection
  • Cache-served path: searchMatched survives the context cache round-trip (plain JSON property)

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • Improvements
    • Enhanced search query generation for more consistent results
    • Optimized context retrieval through concurrent processing for improved performance
    • Refined prioritization of search-matched conclusions in context display
    • Improved chronological ordering of context information for better relevance

…t representation lines

The UserPromptSubmit hook ran a semantic search via peer.context()
but then injected the first 5 lines of the representation string.
The representation merges search hits with frequent/recent conclusions
into one timestamp-ascending list, so the injected lines were always
the oldest conclusions — the search results never surfaced, and the
same stale facts repeated regardless of what the user asked.

- Query matched conclusions explicitly (conclusionScope.query) in
  parallel with peer.context() and put them first in the injection
- Fill remaining slots with the newest representation lines
  (timestamp-desc) instead of the oldest, deduped by normalized text
- Drop the English-only stopword fallback in extractTopics; fall back
  to the raw prompt (truncated), which embeds better for semantic
  search and keeps non-English prompts working

Measured before/after on a live workspace (358 conclusions): before,
4 of 5 injected lines were identical with and without searchQuery and
unrelated to the prompt; after, all 5 lines match the prompt topic for
both English and Italian prompts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Review Change Stack

Walkthrough

This PR refines the context search and formatting pipeline in the user-prompt hook. Topic extraction is simplified to return only high-signal terms; search operations are parallelized with matched conclusions stored for prioritized formatting; and context assembly now prioritizes prompt-matched conclusions with timestamp-aware deduplication and ordering.

Changes

Context Search and Formatting Improvements

Layer / File(s) Summary
Topic extraction simplification
plugins/honcho/src/hooks/user-prompt.ts
extractTopics() removes the fallback path that extracted non-stopword English words; now returns only high-signal terms (deduped).
Concurrent search execution and matched conclusion storage
plugins/honcho/src/hooks/user-prompt.ts
fetchFreshContext() always generates a search query (topics-joined or truncated); context retrieval and conclusion matching run in parallel; matched conclusions are stored in contextResult.searchMatched.
Context formatting with deduplication and timestamp-aware ordering
plugins/honcho/src/hooks/user-prompt.ts
formatCachedContext() prioritizes prompt-matched conclusions from context.searchMatched (deduplicated and stripped), then fills remaining slots from context.representation sorted newest-first by timestamp instead of taking the first 5 lines.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related issues

Poem

🐰 A rabbit hops through topics bright,
Now deduped with parallel light,
Fresh conclusions dance in time,
Sorted newest—a context sublime!
High-signal hops, no fallback blight. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main fix: prioritizing prompt-matched conclusions over stale representation lines in the user-prompt hook.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…ogic

Export extractTopics/stripConclusionLine/formatCachedContext and cover
them with bun test: search-matched-first ordering, newest-not-oldest
fill (regression for the head-of-representation bug), normalized dedup,
5-slot cap, header filtering, no-timestamp order preservation, JSON
cache round-trip, and the empty-topics return that drives the
raw-prompt fallback for non-English prompts.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
samdu added a commit to samdu/claude-honcho that referenced this pull request Jun 28, 2026
Brings the fork up to upstream 15d07cd (0.2.5): memory statusLine (plastic-labs#55),
async sessionStart (plastic-labs#43), skip `cd` in tool logging (#21a5c8a), host-level
apiKey, version-update nag, analyze-usage script.

Reconciled with our carried deltas (all preserved):
- plastic-labs#40 per-session dedup + plastic-labs#63 relevance ordering (still open upstream)
- retrieval config + relevance-fresh fetch, skip-patterns
- query_conclusions MCP tool (#2), 60s dialectic timeout (#1)
- tool-call uploads stay DISABLED

Conflicts resolved in user-prompt.ts (combined relevance-fresh logging with
upstream's setMemoryState("recalling"); kept both node:fs/path and
getRetrievalConfig imports) and CHANGELOG.md (query_conclusions under
[Unreleased], upstream's [0.2.5] below). Other overlapping files
(config.ts, post-tool-use.ts, pre-compact.ts, session-start.ts,
mcp/server.ts) auto-merged and were audited semantically correct.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HwfqcAc2kujJNmQG9UvPqa
ichoosetoaccept pushed a commit to detailobsessed/claude-honcho that referenced this pull request Jul 15, 2026
…facts

The hook ran a semantic search over the prompt but then injected the first
5 lines of the representation — which is ordered oldest-first, so the
search hits never surfaced and every turn re-showed the same stale facts.

- Query matched conclusions explicitly (conclusionScope.query) in parallel
  with the context call and inject them first (cached as searchMatched so
  cache-served turns keep them).
- Fill remaining slots with the NEWEST representation lines (timestamp-desc),
  deduped by normalized text, still honoring the per-session `seen` set.
- Drop extractTopics' English-only stopword fallback; fall back to the raw
  prompt (truncated 300 chars), which embeds better and keeps non-English
  prompts working.

Adapts upstream plastic-labs#63 to this fork's cross-turn
`seen`/`newConclusions` dedup layer. Adds conclusion-scope stubs to the
test mocks so the search path exercises end-to-end.
ichoosetoaccept pushed a commit to detailobsessed/claude-honcho that referenced this pull request Jul 15, 2026
Turn-path reliability and memory quality since 0.1.0:
- Non-blocking Stop hook + workspace-scoped outbox drain (#15)
- Strip pasted non-prose from user messages; tag tool actions (plastic-labs#34)
- Inject prompt-matched conclusions instead of the stalest facts (plastic-labs#63)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant