feat(themes): cross-session pattern detection via entity co-occurrence#332
Conversation
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Pull request overview
This PR implements cross-session pattern detection (issue #311). It adds a new src/vouch/themes.py module with a read-only detect_themes() detector that scores recurring entity co-occurrence clusters across completed sessions (deterministic session_count * log(1 + claim_count) scoring, union-find pair merging, exclusion of archived/superseded/redacted/unapproved claims), plus a propose_theme() path that routes detected clusters through the existing propose_page() review gate as "theme" pages. The feature is wired onto all four surfaces (MCP tool, JSONL handler, CLI vouch detect-themes, capabilities list), adds PageType.THEME, and dedups against existing/pending theme pages.
Changes:
- New
themes.pymodule:detect_themes(read-only detection) andpropose_theme(gated proposal), with deterministic co-occurrence scoring and dedup. - Registers
kb.detect_themes/kb.propose_themeacross MCP server, JSONL server, CLI, and capabilities; addsTHEMEtoPageType. - Adds
tests/test_themes.pycovering detection, thresholds, read-only invariant, archived exclusion, config disable, proposal gating, dedup, determinism, and top-k.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| src/vouch/themes.py | New detector + gated proposal logic; config read is not fully defensive, and dedup can miss when entities are dropped at propose time. |
| src/vouch/server.py | Adds kb_detect_themes / kb_propose_theme MCP tools mirroring the module API. |
| src/vouch/jsonl_server.py | Adds matching JSONL handlers and HANDLERS map entries. |
| src/vouch/cli.py | Adds vouch detect-themes command; --propose --json interleaves human text with JSON on stdout. |
| src/vouch/capabilities.py | Registers the two new methods in METHODS for parity. |
| src/vouch/models.py | Adds THEME = "theme" to PageType. |
| tests/test_themes.py | Comprehensive tests for detection and proposal behavior. |
Note: CHANGELOG.md under [Unreleased] was not updated for this user-visible feature, which the repository's contribution rules require.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| click.echo( | ||
| f"proposed: {p['theme_page_id']} " | ||
| f"({p['claim_count']} claims, {p['session_count']} sessions)" | ||
| ) |
| themes = cfg.get("themes", {}) | ||
| return { | ||
| "enabled": bool(themes.get("enabled", True)), | ||
| "min_sessions": int(themes.get("min_sessions", 2)), | ||
| "min_claims": int(themes.get("min_claims", 3)), | ||
| "top_k": int(themes.get("top_k", 10)), | ||
| } |
| # --- cross-session themes ------------------------------------------------- | ||
|
|
||
|
|
||
| @cli.command(name="detect-themes") |
| valid_entities: list[str] = [] | ||
| for eid in cluster.entities: | ||
| try: | ||
| store.get_entity(eid) | ||
| valid_entities.append(eid) | ||
| except Exception: | ||
| pass | ||
| if not valid_entities: | ||
| raise ProposalError("no valid entities in cluster") |
adds kb.detect_themes (read-only cluster detector) and kb.propose_theme (routes synthesis pages through the review gate). scoring is deterministic — entity pair co-occurrence across sessions, weighted by log(1 + claim_count). registered on all four surfaces (mcp, jsonl, cli, capabilities). the cli exposes `vouch detect-themes` with --propose for one-shot propose-all. adds THEME to the PageType enum so theme pages pass the page-kind gate. deduplication prevents re-proposing clusters that already have pending or approved theme pages. closes vouchdev#311
…utput - config reader now type-checks every value and falls back to defaults on malformed input (mirrors salience.reflex_cfg pattern) - dedup in detect_themes now compares on the resolvable entity subset so it stays consistent with what propose_theme actually stores - --propose --json no longer interleaves human-readable lines on stdout - adds changelog entry under [unreleased]
23557ee to
7e495fc
Compare
summary
kb.detect_themes— read-only detector that finds recurring entity clusters across completed sessions using deterministic co-occurrence scoring (no LLM)kb.propose_theme— routes detected clusters through the review gate as "theme" synthesis pages, visible inkb.list_pendingvouch detect-themes), and capabilities listTHEMEto thePageTypeenum; deduplicates against existing/pending theme pagesdesign
scoring:
session_count * log(1 + claim_count)over entity-pair co-occurrence. pairs sharing entities are merged via union-find into larger clusters. archived, superseded, redacted, and unapproved claims are excluded.config (defensive defaults):
cli:
test plan
tests/test_themes.pycovering detection, thresholds, read-only invariant, archived exclusion, config disable, proposal gating, deduplication, determinism, and top-ktest_capabilitiespasses (method list parity)test_volunteer_contextunrelated to this change)closes #311