Repository navigation
feat: ship the PageRank lane the README credits (off by default) - #52
Conversation
Personalized PageRank over the [[wikilink]] graph, seeded by the dense hits, fused with the reranker by RRF; the reranker's top 5 positions are never touched. Ported from the maintainer's home module brain_graph.py (2026-09-16), same constants. Off by default: SGM_PPR=1 or sgm-ask --ppr. eval/run_eval.py --ppr scores it as a third mode. Any failure returns the reranker's order. tests/test_ppr.py: a hub note and its cluster push the reranker's rank-1 hit to position 11 when the guard is removed (head=0); the guard test goes red then. Closes #51 Assisted-by: claude-code/claude-opus-5-5 Machine: MacPro192 Account: a@paloalto.ai Operator: Anton Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: dab7d54187
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| numbers above came from the maintainer's home vault and home pipeline on 2026-09-16, and they | ||
| have not been re-run from the published package. The code is the same algorithm with the same |
There was a problem hiding this comment.
Run the required retrieval regression evaluation
Do not ship this retrieval-ordering change based only on the earlier home-pipeline result: this paragraph explicitly says the published implementation was not evaluated, so there is no evidence that it stays within the repository's 0.01 nDCG@12 regression limit. Run the same frozen gold set before and after enabling this implementation, and run the required eval mutant check before merging.
AGENTS.md reference: AGENTS.md:L45-L57
Useful? React with 👍 / 👎.
| by_stem = {} | ||
| for i, sc in ranked_idx: | ||
| by_stem.setdefault(Path(meta[i]['path']).stem.lower(), (i, sc)) | ||
| stems = list(by_stem) |
There was a problem hiding this comment.
Preserve distinct files that share a stem
When the candidate pool contains files such as team-a/foo.md and team-b/foo.md, this stem-keyed dictionary silently discards every occurrence after the highest-ranked one before fusion. Such duplicate filenames are explicitly valid in this repository, so enabling PPR can remove a legitimate result—including one from the supposedly protected top five—and substitute a lower-ranked candidate; retain path/index identity through fusion and use stems only for matching PPR votes.
Useful? React with 👍 / 👎.
| for m in meta: | ||
| h.update(str(m.get('path', '')).encode('utf-8', 'replace')) | ||
| h.update(b'\x1f') | ||
| h.update(str(m.get('sha', '')).encode('utf-8', 'replace')) | ||
| h.update(b'\x1e') |
There was a problem hiding this comment.
Include note contents in the graph cache key
The normal index metadata produced by index_notes.py has no sha field, so this component is always empty and the fingerprint effectively contains only the path sequence. If notes are reindexed in the same process after wikilinks change while paths and chunk counts remain unchanged, build() returns the old cached edges rather than reparsing the notes; include a real content hash or other changing file signature so the graph remains synchronized.
AGENTS.md reference: AGENTS.md:L65-L69
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit dab7d54. Configure here.
…e lane never ran Review panel findings on #52: - fuse_after_rerank deduplicated by file stem, so a/x.md and b/x.md collapsed into one result and the list came out shorter than topn. Fusion now works on positions over every item; one implementation instead of two (fuse_with_rerank removed). tests/test_ppr.py::test_same_name_in_two_folders_stays_two_results is red on the previous ppr.py. - run_eval --ppr: an empty lane on every question makes the ppr rows equal the graph rows, so it now prints a warning like the graph hop does. Assisted-by: claude-code/claude-opus-5-5 Machine: MacPro192 Account: a@paloalto.ai Operator: Anton Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…tays out of --ab Independent review (session P39382) on #52: 1. Graph.build kept only the first file per name, so b/index.md gave no edges. A node is a file name (what a wikilink addresses) and now carries the links of every file with that name. Red on the previous ppr.py. (Fusion keying by name was fixed in fdddf5d.) 2. Empty lane leaves the ppr column byte-identical to graph: pinned by a test. 3. --ab no longer applies the lane: ab_recall has no PPR column, so both arms would have been logged as plain vector vs graph. One stderr line says so. 4. README: the bridge numbers match `sgm-ask --graph --ppr`; BM25 hybrid and bi-temporal demotion rows now say they live in the home pipeline, not the package. ppr.py docstring explains 0.225 (diagnosis run) vs 0.251 (final baseline). Assisted-by: claude-code/claude-opus-5-5 Machine: MacPro192 Account: a@paloalto.ai Operator: Anton Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tonydzi
left a comment
There was a problem hiding this comment.
Mycroft (P39382): re-checked 7944c18 myself. Same-name repro (a/index.md + b/index.md) now returns 4 of 4; empty lane equals the no-PPR list exactly; --ab leaves ppr_stems empty so both arms skip the lane; README names sgm-ask --graph --ppr as the configuration the bridge numbers belong to and marks the BM25 and bi-temporal rows as home-pipeline only. 159 tests pass locally. Owner merge pinned to this head. Closes #51.

Mycroft here, Anton's synthetic AI co-founder. This closes the gap the issue names: the README credited the bridge gain to a lane the package did not contain.
Closes #51
What changed
src/sqlite_graph_memory/ppr.py: personalized PageRank over the[[wikilink]]file graph (numpy CSR power iteration, alpha 0.85, 20 iters, seeded by the top 15 dense files), RRF fusion (k=60) with the reranker, top 5 reranker positions protected, PPR only reorders the pool. Ported from the maintainer's home modulebrain_graph.py(live file pulled from the home machine, last written 2026-09-16), same constants.SGM_PPR=1orsgm-ask --ppr. Crash-safe like the graph hop: no edges, a PPR error, a fusion error or a missing module each return the reranker order and write one stderr line.eval/run_eval.py --ppradds a third modeppr(graph pool, one full rerank,graph= its top 12,ppr= fused). Without--pprthe output is unchanged.Tests
tests/test_ppr.py(18 tests): a hub note plus a 10-note cluster that every PPR seed links to; the reranker's rank-1 hit is not a seed. Measured on that fixture: with the guard (head=5) rank-1 stays at position 1; with head=0 it falls to position 11.Red proof, guard removed on a copy (
PPR_HEAD = 0):Review panel (5 outside models, 4 answered)
Fixed: fusion deduplicated by file name, so
a/x.mdandb/x.mdbecame one result and the list came out shorter than 12 (new test, red on the first commit).run_eval --pprnow warns when the lane returned nothing for every question, instead of printing ppr rows identical to graph rows.Checked and rejected: "
orderused before assignment" (assigned at line 310, used at 328); "negative teleport" (the seed starts at 0 and takes the max, so it cannot go negative; a test for it stayed green on the old code, so it was dropped). Kept as is: same-name notes share one graph node, as in the graph hop, because wikilinks address notes by name; with--ppr --abboth sides get the lane, so the diff still isolates the graph.Independent review (session P39382), fixed in 7944c18
Graph.buildkept only the first file per name; now a node (a file name, what a wikilink addresses) carries the links of every file with that name. New test red on the previous commit.pprcolumn identical tograph; pinned by a test.--abdoes not apply the lane, soab_recallstays vector against graph.sgm-ask --graph --ppr; the BM25 hybrid and bi-temporal rows now say they live in the home pipeline, not in this package.Not checked
No retrieval numbers were re-run for this PR: the machine that built it has no embedding stack installed, and
bench/does not score this lane yet.🖥️P · Opus 5.5 · 89706
🤖 Generated with Claude Code