feat(graph): rank the frontier — what to consolidate next (v6.5.0) - #207
Conversation
Every existing graph op answers a structural yes/no question: is this note connected, is that link broken, how big is the graph. None answered the ranking question — of everything in the vault, what should be worked on next? score = (out_degree - in_degree) * 0.5 ** (days_since_updated / 30) A high score means the note points at many things, few point at it, and it was touched recently: memory is accumulating there and consolidation has not caught up. A negative score is a hub the vault has already absorbed. `orphans` finds notes that are *disconnected*; a frontier note is connected but **unabsorbed**, which is a different and more actionable state. This complements `omind consolidate`, which finds merge candidates by similarity. Frontier finds them by structure, catching "this note has sprawled outward for weeks and nothing pulled it together" rather than "these two notes say the same thing". Journals, worklogs, and checkpoints are excluded by default — they link outward at everything by construction and would otherwise fill the whole ranking, the same reason searchindex._weight_generated de-prioritises them. Read-only, with no write path, following the source design's instinct. Costs no new scan and no new state: the links table was already built. The one addition is surfacing `mtime_ns` from the index's notes table, which the recency decay reads. Closes #197. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Warning Review limit reached
Next review available in: 10 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (11)
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 |
Closes #197.
The gap
omind graphanswersneighbors,path,orphans,dangling,stats. Every one is a structural yes/no: is this note connected, is that link broken, how big is the graph. None answers the ranking question — of everything in the vault, what should be worked on next?High score: points at many, pointed at by few, touched recently. That is a note where memory is actively accumulating and consolidation hasn't caught up. Negative: a hub the vault has already absorbed.
The distinction that makes this worth having: an orphan is disconnected; a frontier note is connected but unabsorbed. Only the second one tells you where to spend effort.
Surfaces
omind graph frontier [--limit N] [--include-generated] [--json]— table or JSON.graph(op="frontier")on the MCP tool, paged like every other list-shaped result (invariant 7). Ranking is computed over the whole graph, then paged.Design notes
linkstable was already built. The one addition is surfacingmtime_nsfrom the index'snotestable — already stored, previously not read.searchindex._weight_generated,--include-generatedto override.exp(-days / HALFLIFE), which decays to1/e— not a half — at the named value. This uses0.5 ** (days / 30), so "30-day half-life" means what it says.Verified against the live vault
Recent, outward-linking, unabsorbed — which is what it claims to find.
Tests
Four: hub-vs-frontier ordering; recency decay (a note aged exactly one half-life scores half as much,
pytest.approx); generated exclusion and the opt-in;limit=0returns everything in descending order. Plus MCP coverage and the paging contract.Gates
ruff check .·mypy src(strict) ·pytest(856 passed, 1 skipped) ·pip-audit— green locally.🤖 Generated with Claude Code