Skip to content

feat(edge_rerank): edge-type-keyed rerank consumer (#421) - #429

Merged
robotrocketscience merged 6 commits into
mainfrom
feat/issue-421-edge-type-rerank-consumer
May 5, 2026
Merged

feat(edge_rerank): edge-type-keyed rerank consumer (#421)#429
robotrocketscience merged 6 commits into
mainfrom
feat/issue-421-edge-type-rerank-consumer

Conversation

@yoshi280

@yoshi280 yoshi280 commented May 5, 2026

Copy link
Copy Markdown
Collaborator

Closes #421. Prerequisite for #387 POTENTIALLY_STALE demotion.

Summary

Acceptance map (issue #421)

Producer is out of scope

POTENTIALLY_STALE edge-writer (aelf doctor) is #387 — closes against this PR's substrate.

Test plan

  • uv run pytest tests/test_edge_rerank.py -v — 11 passed
  • uv run pytest tests/test_bfs_multihop.py tests/test_corpus_schema.py -q — passes (BFS spec-pin updated for new entry)
  • uv run pytest --ignore=tests/bench_gate -q — 2460 passed, 23 skipped, no regressions
  • uv run pytest tests/bench_gate/test_edge_rerank_potentially_stale.py — skips cleanly without corpus
  • Lab-side: AELFRICE_CORPUS_ROOT=... uv run pytest tests/bench_gate/test_edge_rerank_potentially_stale.py — runs once bfs_potentially_stale/ corpus is populated. Will gate [v2.0 / Track A] add POTENTIALLY_STALE edge type — bench-gated +5pp BFS multi-hop #387 closure.

Sequence

This PR will stack behind #425's soak-gate timer (same consecutive-green ≥ 7d Replay Soak Gate blocker).

Summary by Sourcery

Introduce an edge-type-keyed rerank consumer that demotes POTENTIALLY_STALE-tagged beliefs after BFS and wire it into the retrieval pipeline with tests, corpus schema, and documentation.

New Features:

  • Add apply_edge_type_rerank rerank pass that rescales BFS hits based on incoming edge types with a default POTENTIALLY_STALE penalty.
  • Introduce EDGE_POTENTIALLY_STALE marker edge type and a corresponding skip-during-BFS weight configuration.
  • Add MemoryStore.edges_to helper to query incoming edges for surfaced beliefs.

Enhancements:

  • Extend BFS edge weight spec and tests to explicitly pin POTENTIALLY_STALE to zero weight during expansion.
  • Register bfs_potentially_stale graded corpus module and document its schema in the corpus README.

Documentation:

  • Add edge_rerank.md explaining the edge-type-keyed rerank pass, its placement in the pipeline, configuration knobs, and determinism guarantees.

Tests:

  • Add unit tests for apply_edge_type_rerank covering penalties, composition, and determinism.
  • Add a bench-gated test using the bfs_potentially_stale corpus to enforce a minimum drop in stale-tagged retrieval after reranking.

@sourcery-ai

sourcery-ai Bot commented May 5, 2026

Copy link
Copy Markdown

Reviewer's Guide

Introduces a new edge-type-keyed rerank consumer that demotes BFS results based on incoming marker edges (notably POTENTIALLY_STALE), wires it into the BFS/graph model contracts, and adds tests, corpus schema, and docs plus a bench gate to enforce ≥1pp@k stale-drop.

Sequence diagram for BFS expansion with edge-type-keyed rerank

sequenceDiagram
    actor Caller
    participant BFS as expand_bfs
    participant Rerank as apply_edge_type_rerank
    participant Store as MemoryStore

    Caller->>BFS: expand_bfs(seeds)
    BFS-->>Caller: list ScoredHop hops

    Caller->>Rerank: apply_edge_type_rerank(hops, Store, penalties)
    loop for each hop in hops
        Rerank->>Store: edges_to(hop.belief.id)
        Store-->>Rerank: list Edge incoming
        Rerank->>Rerank: select firing edge types
        Rerank->>Rerank: multiply hop.score by penalties
    end
    Rerank->>Rerank: sort rescored hops by (-score, belief.id)
    Rerank-->>Caller: list ScoredHop rescored_hops
Loading

Class diagram for edge-type-keyed rerank consumer and MemoryStore updates

classDiagram
    class MemoryStore {
        +edges_from(src: str) list~Edge~
        +edges_to(dst: str) list~Edge~
        +iter_all_edges() Iterator~Edge~
    }

    class Edge {
        +id: str
        +src: str
        +dst: str
        +type: str
    }

    class ScoredHop {
        +belief: Belief
        +score: float
        +depth: int
        +path: list~Edge~
    }

    class Belief {
        +id: str
    }

    class edge_rerank_module {
        +DEFAULT_STALE_PENALTY: float
        +EDGE_TYPE_PENALTIES_DEFAULT: Mapping~str, float~
        +apply_edge_type_rerank(hops: list~ScoredHop~, store: MemoryStore, penalties: Mapping~str, float~)
    }

    class models_constants {
        +EDGE_POTENTIALLY_STALE: str
    }

    MemoryStore --> Edge : returns
    ScoredHop --> Belief : belief
    ScoredHop --> Edge : path
    edge_rerank_module --> ScoredHop : rescored
    edge_rerank_module --> MemoryStore : uses edges_to
    edge_rerank_module --> models_constants : uses EDGE_POTENTIALLY_STALE
Loading

File-Level Changes

Change Details Files
Add edge-type-keyed rerank consumer that rescales BFS hops based on incoming marker edges with configurable per-edge-type penalties.
  • Introduce DEFAULT_STALE_PENALTY and EDGE_TYPE_PENALTIES_DEFAULT keyed on EDGE_POTENTIALLY_STALE.
  • Implement apply_edge_type_rerank that looks up incoming edges via the store, applies multiplicative penalties per edge type, dedupes by type, and re-sorts results by (-score, belief.id).
  • Document the rerank pass, its placement in the pipeline, configuration knobs, multi-edge composition, determinism, and the skip-during-BFS contract in edge_rerank docs.
src/aelfrice/edge_rerank.py
docs/edge_rerank.md
Extend graph model and BFS to support POTENTIALLY_STALE as a marker edge that is skipped during expansion but available for rerank demotion.
  • Add EDGE_POTENTIALLY_STALE constant as a marker edge type, explicitly excluded from structural EDGE_TYPES/EDGE_VALENCE.
  • Wire EDGE_POTENTIALLY_STALE into BFS imports and pin BFS_EDGE_WEIGHTS[EDGE_POTENTIALLY_STALE] = 0.0 to enforce skip-during-BFS behavior.
  • Align BFS edge-weight spec tests with the new marker edge weight contract.
src/aelfrice/models.py
src/aelfrice/bfs_multihop.py
tests/test_bfs_multihop.py
Expose reverse edge lookup in MemoryStore to support incoming-edge-based rerank.
  • Add edges_to(dst) method symmetric to edges_from, querying edges by dst and returning Edge objects.
  • Use edges_to in the rerank logic to detect marker edges pointing at surfaced beliefs.
src/aelfrice/store.py
src/aelfrice/edge_rerank.py
Introduce targeted unit tests to cover rerank behavior, configuration, and determinism.
  • Add unit tests for empty input, empty-penalty identity behavior, default stale demotion, multi-edge and multi-type composition, no-incoming-edge behavior, tiebreak ordering, custom penalties, zero penalties, default config contents, and byte-identical determinism.
  • Use an in-memory MemoryStore fixture with helper builders for beliefs and ScoredHop instances.
tests/test_edge_rerank.py
Add a bench-gated corpus module and test harness to enforce ≥1pp@k stale-tagged drop from rerank on a labeled corpus.
  • Register bfs_potentially_stale corpus module with schema including stale_ids and document it in the test corpus README and schema test.
  • Implement a bench gate that builds a per-row store, runs BFS with and without rerank, measures stale rate at k before/after, and asserts at least STALE_DROP_FLOOR improvement, while skipping gracefully when corpus preconditions are not met.
tests/test_corpus_schema.py
tests/corpus/v2_0/README.md
tests/bench_gate/test_edge_rerank_potentially_stale.py

Assessment against linked issues

Issue Objective Addressed Explanation
#421 Implement an edge-type-keyed rerank consumer that operates downstream of BFS/lane fusion, uses edge metadata (incoming edges) and a per-edge-type penalty configuration, and enforces the schema contract that BFS_EDGE_WEIGHTS[POTENTIALLY_STALE] = 0.0 so demotion happens only in the rerank pass.
#421 Provide a bench harness and labeled corpus module for POTENTIALLY_STALE such that a rerank gate can measure and enforce a ≥1pp@k drop in stale-tagged retrieval (or equivalent uplift), suitable as the gate for issue #387.
#421 Document the rerank pass: where it lives in the retrieval pipeline, what configuration knobs exist (including POTENTIALLY_STALE penalties), and how penalties interact when multiple penalty-eligible edge types are present on the same belief.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@robotrocketscience has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 37 minutes and 11 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3eb07f49-f558-4e84-b524-3e6d28286798

📥 Commits

Reviewing files that changed from the base of the PR and between 95e563b and d3fd1db.

📒 Files selected for processing (10)
  • docs/edge_rerank.md
  • src/aelfrice/bfs_multihop.py
  • src/aelfrice/edge_rerank.py
  • src/aelfrice/models.py
  • src/aelfrice/store.py
  • tests/bench_gate/test_edge_rerank_potentially_stale.py
  • tests/corpus/v2_0/README.md
  • tests/test_bfs_multihop.py
  • tests/test_corpus_schema.py
  • tests/test_edge_rerank.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-421-edge-type-rerank-consumer

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.

@yoshi280 yoshi280 added the attn:review Needs review (PR open, awaiting reviewer) label May 5, 2026

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Hey - I've found 1 issue, and left some high level feedback:

  • The rerank path currently performs an edges_to query per hop, which is effectively an N+1 pattern; if this will ever run on large hop lists, consider a batched edges_to_many(dst_ids) API or prefetch to avoid repeated single-row scans.
  • apply_edge_type_rerank is hard-wired to MemoryStore; if you plan to plug in other store backends (or mocks), consider typing this parameter against a minimal protocol (e.g., Protocol with edges_to) to decouple the reranker from the concrete store implementation.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The rerank path currently performs an `edges_to` query per hop, which is effectively an N+1 pattern; if this will ever run on large hop lists, consider a batched `edges_to_many(dst_ids)` API or prefetch to avoid repeated single-row scans.
- `apply_edge_type_rerank` is hard-wired to `MemoryStore`; if you plan to plug in other store backends (or mocks), consider typing this parameter against a minimal protocol (e.g., `Protocol` with `edges_to`) to decouple the reranker from the concrete store implementation.

## Individual Comments

### Comment 1
<location path="docs/edge_rerank.md" line_range="24" />
<code_context>
+caller (e.g., retrieve_with_tiers token-budget pack)
+```
+
+The pass is pure: same `(hops, store, penalties)` produces
+byte-identical output. It uses `MemoryStore.edges_to(dst)` to query
+incoming edges per surfaced belief.
</code_context>
<issue_to_address>
**nitpick (typo):** Clarify grammar in the description of the pure pass.

Consider rephrasing "same `(hops, store, penalties)` produces" to something like "The pass is pure: the same `(hops, store, penalties)` produces byte-identical output" or "The pass is pure: the same inputs produce byte-identical output" for smoother grammar.

```suggestion
The pass is pure: the same `(hops, store, penalties)` produces
```
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment thread docs/edge_rerank.md
caller (e.g., retrieve_with_tiers token-budget pack)
```

The pass is pure: same `(hops, store, penalties)` produces

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nitpick (typo): Clarify grammar in the description of the pure pass.

Consider rephrasing "same (hops, store, penalties) produces" to something like "The pass is pure: the same (hops, store, penalties) produces byte-identical output" or "The pass is pure: the same inputs produce byte-identical output" for smoother grammar.

Suggested change
The pass is pure: same `(hops, store, penalties)` produces
The pass is pure: the same `(hops, store, penalties)` produces

@yoshi280

yoshi280 commented May 5, 2026

Copy link
Copy Markdown
Collaborator Author

[claim:review:Gylf:2026-05-05T16:33:16Z]

@github-actions github-actions Bot added the attn:merge-conflict PR branch needs rebase label May 5, 2026
@github-actions

github-actions Bot commented May 5, 2026

Copy link
Copy Markdown

This PR is now behind main. Rebase locally so your commit signatures stay intact:

git fetch origin && git checkout 'feat/issue-421-edge-type-rerank-consumer' && git rebase origin/main
# resolve conflicts if any, then
git push --force-with-lease

Auto-rebase was removed because the bot has no signing key; rebasing as the bot strips author signatures and the required_signatures rule on main then blocks the merge. See #341.

@yoshi280

yoshi280 commented May 5, 2026

Copy link
Copy Markdown
Collaborator Author

LGTM on code, but REBASE-NEEDED — main advanced when #425 landed (6dc4411) so this branch is no longer fast-forwardable. The protocol's FF-push merge requires the head to be ahead-only of main.

Inspection results:

Action to land:

  1. Rebase feat/issue-421-edge-type-rerank-consumer onto current github/main.
  2. Force-push (signed commits preserved/re-signed).
  3. Wait for CI re-run; soak gate will fail again on the new tip (same calendar blocker).
  4. Operator FF-push to main with override (per feat(retrieve_uplift): per-flag NDCG@k bench harness for v1.7 default-on flip (#154) #425 precedent).

Releasing review claim.

— Gylf

@yoshi280

yoshi280 commented May 5, 2026

Copy link
Copy Markdown
Collaborator Author

[release:review:Gylf:2026-05-05T16:35:04Z]

Tag-shaped edge distinct from EDGE_TYPES / EDGE_VALENCE. Carries no
propagation valence; consumed by the rerank pass in aelfrice.edge_rerank
(this issue), produced by aelf doctor (#387). Skip-during-BFS contract
lands in the next commit.
….0 (#421)

Per #421 acceptance #4. Demotion happens in the rerank pass, not in
BFS expansion. Pinned explicitly so the contract is reviewable rather
than implicit via the BFS_EDGE_WEIGHTS.get(..., 0.0) default. Updates
the spec-pinning test to include the new entry.
Symmetric companion to edges_from. Consumed by the edge-type-keyed
rerank pass to detect marker edges (POTENTIALLY_STALE) targeting a
surfaced belief; the rerank pass needs to ask 'does any incoming
edge to this dst tag it as stale?' rather than walking outbound.
Pure-function module that takes BFS hits, examines each surfaced
belief's incoming edges via store.edges_to, and applies a
configurable multiplicative penalty per matching edge type.
POTENTIALLY_STALE keyed by default at 0.5; multi-edge-type
composition is multiplicative. Returns a new ScoredHop list sorted
by (-score, belief.id) — the same tie-break used by expand_bfs so
the two passes compose without order surprises.

Acceptance #1, #2, #4 of the issue. Tests + bench-gate stub follow.
…on (#421)

11 unit tests cover the consumer's full contract: empty-hops/empty-cfg
no-ops, default POTENTIALLY_STALE demotion, set-based 'fires once per
type', multi-edge multiplicative composition, isolated-belief identity,
tie-break sort, custom-cfg override, zero-penalty zeroing, default-cfg
pin, byte-identical determinism.

Bench-gate stub at tests/bench_gate/test_edge_rerank_potentially_stale.py
implements #421 acceptance #3 / #387 acceptance #3: ≥1pp@k drop in
stale-tagged retrieval after the rerank pass. Skips on no AELFRICE_CORPUS_ROOT
or <30 non-seed rows. New corpus module 'bfs_potentially_stale' registered
in tests/test_corpus_schema.py with the same graded shape as the Track A
fixtures plus the 'stale_ids' subset field.
Pipeline placement, skip-during-BFS contract, config knob surface
(DEFAULT_STALE_PENALTY, EDGE_TYPE_PENALTIES_DEFAULT, override
semantics), multi-edge multiplicative composition, determinism, and
bench-gate pointer. Acceptance #5 of #421.
@robotrocketscience
robotrocketscience force-pushed the feat/issue-421-edge-type-rerank-consumer branch from 6ed47c3 to d3fd1db Compare May 5, 2026 16:38
@robotrocketscience
robotrocketscience merged commit d3fd1db into main May 5, 2026
20 of 21 checks passed
@robotrocketscience
robotrocketscience deleted the feat/issue-421-edge-type-rerank-consumer branch May 5, 2026 16:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

attn:merge-conflict PR branch needs rebase attn:review Needs review (PR open, awaiting reviewer)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(retrieval): edge-type-keyed rerank consumer — prerequisite for #387 POTENTIALLY_STALE demotion

2 participants