Skip to content

feat(reason): peer-aware graph walk (#690) - #712

Merged
github-actions[bot] merged 6 commits into
mainfrom
feat/issue-690-peer-aware-reason-walk
May 12, 2026
Merged

feat(reason): peer-aware graph walk (#690)#712
github-actions[bot] merged 6 commits into
mainfrom
feat/issue-690-peer-aware-reason-walk

Conversation

@robotrocketscience

@robotrocketscience robotrocketscience commented May 12, 2026

Copy link
Copy Markdown
Owner

Closes #690.

Sub-task of #650 (read-only federation umbrella). Extends aelf reason to follow edges originating in peer DBs when the seed lands on a foreign belief, completing the search→reason peer-aware parity flagged as a follow-up in the #655 / #670 CHANGELOG entry.

What ships

Five atomic commits, all signed (G):

  1. feat(store)edges_from_in_scope(src, owning_scope) and get_belief_in_scope(belief_id, owning_scope). Route to local DB when owning_scope=None, to the cached read-only peer connection (_peer_conn) when a peer name is passed. Unreachable peer / schema drift → [] / None, never raises.
  2. feat(bfs)ScoredHop gains owning_scope: str | None = None. expand_bfs takes seed_scopes: dict[str, str | None] | None and threads the scope through the frontier so a walk that enters a peer stays in that peer's edge graph. Edge fetches use edges_from_in_scope; belief materialisation uses get_belief_in_scope.
  3. feat(reason)SuggestedUpdate gains owning_scope. suggested_updates() propagates scope from each ScoredHop to its +1 row and from a {bid: scope} map for impasse-locus rows. This is the surface the slash skill's close-the-loop writeback reads to skip foreign rows (mutations on foreign ids raise ForeignBeliefError per v3.0 design decision: federation write model — multi-writer CRDT vs read-only #661 / feat(federation): read-only mechanics — knowledge_deps.json + SQLite ATTACH + foreign-ID rejection (#650 sub-task) #655).
  4. feat(cli)aelf reason human output annotates peer hops with [scope:<name>] before the belief id. --json adds owning_scope keys on hops[] and suggested_updates[].
  5. docs(changelog) — unreleased entry under [3.0.0].

Acceptance bullets from #690

  • BFS walk follows peer edges when the seed lands on a foreign belief — test_expand_bfs_follows_peer_edges_two_hops covers a SUPPORTS chain depth=1/depth=2.
  • Peer hops surface with scope:<name> annotation (human) and owning_scope (JSON) — aelf reason CLI patch.
  • Compound-confidence decay across boundary — peer edges contribute to the BFS-score product the same way local edges do (no separate path needed; BFS_EDGE_WEIGHTS is type-keyed, not scope-keyed). Not separately tested in this PR; the type-keyed nature of the weight table is the proof.
  • CONTRADICTS forks across boundary — same argument; the fork detection in derive_paths keys on path[-1] == EDGE_CONTRADICTS, not scope. Not separately tested.
  • R3 suggested_updates flag foreign belief ids — test_suggested_updates_flags_foreign_ids.
  • Tests: two-scope smoke, foreign-edge propagation, foreign-id flagging, unreachable-peer tolerance (4 new tests in tests/test_peer_aware_reason.py covering BFS walk + 4 covering store helpers + 1 covering SuggestedUpdate; 8 new tests total).

What this does NOT do

  • MCP aelf_reason tool: not present on main; nothing to extend. If it ships later, mirror the same owning_scope field on hops/updates payloads.
  • reason() integration: this PR ships the building blocks (expand_bfs peer-aware, SuggestedUpdate scope flag, CLI surface). The CLI _cmd_reason still calls retrieve() for seeds — when retrieve() returns peer seeds (post-feat(federation): read-only mechanics — knowledge_deps.json + SQLite ATTACH + foreign-ID rejection (#650 sub-task) #655), the caller needs to build the seed_scopes dict from find_foreign_owner() per seed. That is a small wiring follow-up; this PR keeps _cmd_reason unchanged to scope-limit the diff. The seed-wiring change is one-line in _cmd_reason and can land in a follow-up PR once we have a runner that exercises it end-to-end.

Verification

  • 5 commits, all SSH-signed (G).
  • uv run pytest: 3703 passed, 59 skipped, 75 xfailed in 108s — clean run, no regression.
  • Discretion grep on full diff vs github/main: clean.
  • Backwards compatible: seed_scopes=None keyword default produces byte-identical expand_bfs output to pre-feat(reason): peer-aware graph walk (#650 sub-task) #690 callers; owning_scope=None default on ScoredHop / SuggestedUpdate means existing test fixtures continue to construct these dataclasses positionally without TypeError.

Pre-requisites

Summary by Sourcery

Extend peer-aware reasoning so BFS graph walks and suggested updates correctly handle beliefs stored in peer databases while preserving pre-federation behaviour.

New Features:

  • Add scope-aware edge and belief lookups that route reads either to the local store or to a configured read-only peer database.
  • Extend multi-hop BFS expansion to accept per-seed scopes, propagate owning scope through hops, and follow edges within the appropriate peer or local graph.
  • Expose owning scope on ScoredHop and SuggestedUpdate so downstream consumers and tools can distinguish local from foreign beliefs.
  • Include owning_scope metadata in aelf reason CLI output (human and JSON) and annotate peer hops with a scope tag.

Enhancements:

  • Make peer lookups resilient by degrading unreachable or schema-drift peer databases to empty results instead of raising.
  • Document the peer-aware aelf reason graph walk and federation behaviour in the unreleased changelog entry.

Tests:

  • Add peer-aware reasoning tests covering scope-aware store helpers, BFS behaviour across peer boundaries, unreachable peer tolerance, local-only walks, and SuggestedUpdate owning_scope tagging.

Summary by CodeRabbit

  • New Features

    • Federation-enabled multi-hop reasoning that routes traversal through peer scopes and tags hops with their originating scope.
    • Reasoning outputs (JSON and human-readable) now surface per-hop scope annotations; suggested updates include scope context for peer-derived hops.
  • Tests

    • Added acceptance tests covering peer-aware traversal, in-scope reads, unreachable-peer tolerance, local passthrough behavior, and suggested-update scope tagging.

Review Change Stack

@robotrocketscience robotrocketscience added the author-Faraday PR coordination mutex label May 12, 2026
@sourcery-ai

sourcery-ai Bot commented May 12, 2026

Copy link
Copy Markdown

Reviewer's Guide

Implements peer-aware BFS graph walking for aelf reason by threading an owning_scope through store access, BFS hops, reasoning updates, and CLI output, plus tests and changelog documentation, while preserving pre-federation behavior when scopes are not provided.

Sequence diagram for peer-aware BFS expand_bfs walk

sequenceDiagram
    participant Reason as reason
    participant BFS as expand_bfs
    participant Store as MemoryStore
    participant PeerDB as peer_sqlite3_DB

    Reason->>BFS: expand_bfs(store, seeds, seed_scopes)
    Note over BFS: Seed belief_id has owning_scope=peerA
    BFS->>Store: edges_from_in_scope(belief_id, "peerA")
    Store->>Store: _peer_conn("peerA")
    Store->>PeerDB: SELECT * FROM edges WHERE src = belief_id
    PeerDB-->>Store: rows
    Store-->>BFS: list[Edge]

    loop for each Edge dst
        BFS->>Store: get_belief_in_scope(dst, "peerA")
        Store->>PeerDB: SELECT * FROM beliefs WHERE id = dst
        PeerDB-->>Store: row | None
        Store-->>BFS: Belief | None
        BFS->>BFS: create ScoredHop(owning_scope="peerA")
    end

    BFS-->>Reason: list[ScoredHop] with owning_scope threaded
Loading

File-Level Changes

Change Details Files
Make BFS walk scope-aware so that graph expansion follows edges and materializes beliefs from peer databases when seeds are foreign, while preserving old behavior for local-only callers.
  • Extend ScoredHop with an owning_scope field (None for local, peer name for foreign hops).
  • Add an optional seed_scopes mapping parameter to expand_bfs and propagate scope from each frontier entry to its children.
  • Update BFS frontier tuples to carry owning_scope and route edge and belief fetches through scope-aware store helpers.
  • Ensure pre-existing callers remain byte-compatible by defaulting seed_scopes to None and owning_scope to None.
src/aelfrice/bfs_multihop.py
Introduce scope-aware store helpers that transparently route read-only edge and belief lookups to either the local DB or a configured peer connection, tolerating unreachable or schema-drift peers.
  • Add edges_from_in_scope(src, owning_scope) that delegates to local edges_from when scope is None or queries the peer connection and returns [] on unreachable/schema-drift peers.
  • Add get_belief_in_scope(belief_id, owning_scope) that delegates to local get_belief when scope is None or queries the peer connection and returns None on unreachable/schema-drift peers.
  • Use cached read-only sqlite3 connections from _peer_conn for peer access and guard OperationalError to avoid raising.
src/aelfrice/store.py
Propagate owning_scope into SuggestedUpdate rows so downstream writeback logic can identify and skip foreign beliefs.
  • Extend SuggestedUpdate dataclass with an owning_scope field defaulting to None.
  • Collect a {belief_id: owning_scope} map from ScoredHop instances in suggested_updates.
  • Populate owning_scope on +1 rows directly from the originating hop and on impasse rows via the scope_by_id map so foreign impasse beliefs are also tagged.
src/aelfrice/reason.py
Expose scope information in the aelf reason CLI output for both human and JSON modes to make peer hops and foreign suggested updates visible to callers.
  • In --json mode, include owning_scope on each hop object and each suggested_updates row.
  • In human output, prefix foreign hop belief IDs with a [scope:] tag when owning_scope is non-None.
src/aelfrice/cli.py
Document the peer-aware aelf reason graph walk feature and add tests that cover store routing, BFS peer traversal, and SuggestedUpdate scope tagging.
  • Add a CHANGELOG entry under 3.0.0 describing the new peer-aware BFS behavior, store helpers, SuggestedUpdate scope tagging, CLI changes, and backward-compatibility guarantees.
  • Add peer-aware graph walk tests that set up a peer DB, wire it via AELFRICE_KNOWLEDGE_DEPS, and verify edges_from_in_scope/get_belief_in_scope routing, BFS two-hop traversal in a peer, local-only behavior without scopes, unreachable-peer degradation, and SuggestedUpdate owning_scope tagging.
CHANGELOG.md
tests/test_peer_aware_reason.py

Assessment against linked issues

Issue Objective Addressed Explanation
#690 Extend the aelf reason BFS walk to follow peer edges when the seed belief is foreign, and surface peer hops with appropriate scope:<name> / owning_scope annotations in human and --json output. The PR makes expand_bfs peer-aware via seed_scopes and owning_scope and updates CLI/JSON formatting, but _cmd_reason (and reason() wiring) still call expand_bfs without constructing or passing a seed_scopes map from find_foreign_owner(). As noted in the PR body, this wiring is explicitly deferred. In the shipped CLI, seeds always use owning_scope=None, so the live reason BFS still only walks local edges and will not actually follow peer graphs when seeds are foreign.
#690 Ensure compound-confidence decay and CONTRADICTS fork handling work correctly across the local/peer boundary in the BFS-based reasoning, treating peer edges identically to local edges.
#690 Have suggested_updates flag foreign belief IDs with an owning scope so that downstream writeback can skip them, and expose this in CLI / JSON output with tests covering foreign-id handling.

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 12, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ca429f7b-b0f8-4484-95f6-79ca77519562

📥 Commits

Reviewing files that changed from the base of the PR and between 58f828b and eb699e1.

⛔ Files ignored due to path filters (1)
  • CHANGELOG.md is excluded by !**/CHANGELOG.md
📒 Files selected for processing (5)
  • src/aelfrice/bfs_multihop.py
  • src/aelfrice/cli.py
  • src/aelfrice/reason.py
  • src/aelfrice/store.py
  • tests/test_peer_aware_reason.py
🚧 Files skipped from review as they are similar to previous changes (5)
  • src/aelfrice/cli.py
  • src/aelfrice/bfs_multihop.py
  • src/aelfrice/reason.py
  • src/aelfrice/store.py
  • tests/test_peer_aware_reason.py

📝 Walkthrough

Walkthrough

This PR adds federation-aware graph traversal to the BFS belief walk: seeds can target peer graph edges via seed_scopes, traversal propagates owning_scope through hops/frontier, and scope is surfaced in SuggestedUpdate rows and CLI output.

Changes

Peer-aware federation in BFS graph walk

Layer / File(s) Summary
Peer-scope-aware store read helpers
src/aelfrice/store.py
edges_from_in_scope() and get_belief_in_scope() route reads to peer databases when scoped, fall back to local reads when scope is None, and return empty/None gracefully on unreachable peers or schema drift.
BFS data model and federation integration
src/aelfrice/bfs_multihop.py
ScoredHop gains owning_scope field, expand_bfs() adds seed_scopes parameter, and BFS frontier now tracks and propagates scope through edge enumeration and belief materialization using scope-aware store reads.
Scope propagation through suggested updates
src/aelfrice/reason.py
SuggestedUpdate adds owning_scope field, and suggested_updates() populates it from hop scope data for both confident and impasse-locus beliefs.
CLI output integration
src/aelfrice/cli.py
aelf reason --json includes owning_scope on hops and suggested_updates rows; human-readable output adds optional [scope:...] prefix when scope is present.
Peer-aware traversal and routing acceptance tests
tests/test_peer_aware_reason.py
Twelve tests verify peer-scope read routing, BFS traversal across two peer hops, unreachable peer tolerance, local passthrough when scope is None, deterministic hop ordering, and suggested_updates scope tracking for foreign IDs.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant expand_bfs
  participant MemoryStore
  participant Frontier
  participant ScoredHop
  Caller->>expand_bfs: seeds + seed_scopes (id → owning_scope)
  expand_bfs->>Frontier: init entries with (belief_id, owning_scope)
  loop frontier entry
    expand_bfs->>MemoryStore: edges_from_in_scope(current_id, owning_scope)
    MemoryStore-->>expand_bfs: edges[]
    loop each edge
      expand_bfs->>MemoryStore: get_belief_in_scope(edge.dst, owning_scope)
      MemoryStore-->>expand_bfs: belief | None
      alt belief found
        expand_bfs->>ScoredHop: create(belief, owning_scope)
        expand_bfs->>Frontier: enqueue(neighbor_id, owning_scope)
      end
    end
  end
  expand_bfs-->>Caller: list[ScoredHop(owning_scope set)]
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related issues

Possibly related PRs

Suggested labels

attn:review, author-noether

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: adding peer-aware graph walk capability to the reason module for federation support.
Description check ✅ Passed The description is comprehensive, covering summary, linked issue, type of change (feat), verification steps, detailed implementation breakdown across 5 commits, acceptance criteria, and notes about intentional scope limitations.
Docstring Coverage ✅ Passed Docstring coverage is 84.21% which is sufficient. The required threshold is 80.00%.
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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-690-peer-aware-reason-walk

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.

@github-actions

github-actions Bot commented May 12, 2026

Copy link
Copy Markdown

PR-size soft cap

This PR is over the advisory size threshold:

  • 389 changed lines (limit: 200)
  • 6 changed files (limit: 3)

Bigger PRs collide with more open work, which under the parallel-session workflow tends to produce repeated attn:merge-conflict cycles (see #602). When practical, split into smaller PRs that each touch a focused surface.

This is advisory only — nothing is blocked. If the size is intentional (large refactor, module removal, generated code), apply the size:override label and this comment will be removed on the next push.

@robotrocketscience robotrocketscience added the attn:review Needs review (PR open, awaiting reviewer) label May 12, 2026
Comment thread tests/test_peer_aware_reason.py Fixed

@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 left some high level feedback:

  • In MemoryStore.edges_from_in_scope and get_belief_in_scope, catching a blanket sqlite3.OperationalError and returning empty/None will silently mask SQL or schema bugs; consider narrowing the exception handling (e.g., checking for missing-table errors) or at least logging unexpected failures to aid debugging.
  • edges_from_in_scope and get_belief_in_scope duplicate most of the SQL from edges_from/get_belief; you could factor the common query/row-mapping logic into a small helper that takes a Connection to keep these code paths consistent and reduce drift over time.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- In `MemoryStore.edges_from_in_scope` and `get_belief_in_scope`, catching a blanket `sqlite3.OperationalError` and returning empty/None will silently mask SQL or schema bugs; consider narrowing the exception handling (e.g., checking for missing-table errors) or at least logging unexpected failures to aid debugging.
- `edges_from_in_scope` and `get_belief_in_scope` duplicate most of the SQL from `edges_from`/`get_belief`; you could factor the common query/row-mapping logic into a small helper that takes a `Connection` to keep these code paths consistent and reduce drift over time.

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.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:noether:2026-05-12T02:49:12Z]

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Review verdict (noether): CODE-LGTM, one composition-gap to flag for follow-up.

Verified

  • 5 atomic commits, all SSH-signed (G).
  • Diff size: 379 / 13 across 6 files (260 of those lines are the new tests/test_peer_aware_reason.py).
  • All required CI checks green (pytest 3.12, pytest 3.13, secrets-scan, pattern-scan, history-scan, CodeQL, analyze, vulture, deptry, release-docs-check, etc.); CodeRabbit still null (non-blocking).
  • Local uv run pytest tests/test_peer_aware_reason.py -q → 8 passed.
  • Local uv run pytest tests/ --ignore=tests/bench_gate -q3688 passed, 32 skipped, 75 xfailed. No regressions.
  • Discretion grep on full diff vs github/main → clean.
  • Backwards compatible: seed_scopes=None (the default) walks local edges only, byte-identical to pre-feat(reason): peer-aware graph walk (#650 sub-task) #690 callers.

What's right

Composition gap (flag for follow-up, not a blocker)

aelf reason (cli.py:762) calls expand_bfs(seeds, store, max_depth=…, …) with no seed_scopes argument, and the seed-fetching path uses store.get_belief(sid) for --seed-id and store.search_beliefs(args.query) for the query path — both of which are local-only. Result: the only way to currently exercise the peer-walk from the user-facing CLI is for args.seed_id to happen to coincide with a foreign belief id (which the user has no easy way to learn).

So the AC bullet "BFS walk in reason() follows peer edges when the seed lands on a foreign belief" is satisfied at the BFS function level (and exercised by the new tests calling expand_bfs(..., seed_scopes={...}) directly), but not from the aelf reason CLI invocation that users actually run. The [scope:<name>] annotation is unreachable through normal CLI use.

This looks intentional given the size-cap and the PR title scoping ("peer-aware graph walk", not "peer-aware aelf reason CLI"), and it's the natural seam to split — wiring the seed side requires either UNIONing peer hits into search_beliefs (touches federation-search semantics) or extending the seed-fetcher to call find_foreign_owner() and pre-classify seed scopes. Either way it's a separate change worth its own PR + tests.

Recommend: approve and merge this PR as substrate, file a follow-up issue for the CLI seed-fetch wiring (could be ~50 LOC + an end-to-end CLI test that asserts aelf reason "query" --json surfaces a foreign hop with owning_scope='peerA' against a two-scope smoke fixture).

Minor observations (non-blocking)

  • get_belief_in_scope doesn't compute corroboration_count for foreign beliefs — the local get_belief JOINs belief_corroborations. Foreign-returned Belief rows will carry the dataclass-default corroboration_count=0. Probably fine since foreign-row corroboration counts aren't authoritative across scopes, but worth a one-line code comment if you re-touch the helper.
  • expand_bfs docstring is updated cleanly; ScoredHop and SuggestedUpdate docstrings explain owning_scope semantics clearly. No stale comments noticed.

Approving and adding ready-to-merge.

@robotrocketscience robotrocketscience added the ready-to-merge Trigger merge-train: FF main to this PR's head label May 12, 2026
@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:noether:2026-05-12T02:57:55Z]

@robotrocketscience robotrocketscience removed the attn:review Needs review (PR open, awaiting reviewer) label May 12, 2026
@github-actions

Copy link
Copy Markdown

merge-train: blocked

FF push to main failed:\n\n\nremote: error: GH006: Protected branch update failed for refs/heads/main. remote: remote: - All comments must be resolved. To https://github.com/robotrocketscience/aelfrice ! [remote rejected] 968401b005e10b60dd1e5a5fe1f3109bfc0f6ac0 -> main (protected branch hook declined) error: failed to push some refs to 'https://github.com/robotrocketscience/aelfrice'\n\n\nCommon causes: branch protection rule changed, force-push detected by another writer, or token permission insufficient. Re-add the label after investigating.

The ready-to-merge label has been removed. Address the issue above and re-add the label when you're ready for another attempt.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

Filed the CLI seed-fetch wiring follow-up flagged in the review: #713 (rook-tier, ~50 LOC). Tracks the gap between the BFS-level peer walk this PR ships and the user-facing aelf reason invocation.

@robotrocketscience

Copy link
Copy Markdown
Owner Author

[claim:review:pascal:2026-05-12T04:27:37Z]

yoshi280 added a commit that referenced this pull request May 12, 2026
CodeQL flagged the unused 'import pytest' at line 22. The tests use plain
assert statements and don't reference pytest fixtures, parametrize, or
raises; the import was leftover from an earlier draft.

Resolves the one outstanding review thread on PR #712.
@robotrocketscience robotrocketscience added the ready-to-merge Trigger merge-train: FF main to this PR's head label May 12, 2026
@robotrocketscience

Copy link
Copy Markdown
Owner Author

[release:review:pascal:2026-05-12T04:30:54Z]

@github-actions

Copy link
Copy Markdown

merge-train: blocked

one or more commits between main and feat/issue-690-peer-aware-reason-walk are not signed (per GitHub verification API):\n\n\ncaeb542f4ee5e05276376eb2b000733c6f7da884\n\n\nSign them locally and re-add the label. The bot cannot sign on your behalf.

The ready-to-merge label has been removed. Address the issue above and re-add the label when you're ready for another attempt.

@github-actions github-actions Bot removed the ready-to-merge Trigger merge-train: FF main to this PR's head label May 12, 2026

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/aelfrice/store.py`:
- Around line 3089-3094: The row mappers can raise IndexError when columns are
missing, so update edges_from_in_scope and get_belief_in_scope to catch
column-level schema drift: wrap the conversion of fetched rows (the list
comprehensions calling _row_to_edge and _row_to_belief) in a try/except that
catches IndexError (and optionally KeyError) and returns [] (the same graceful
degradation used for sqlite3.OperationalError); apply the same change to the
other occurrence that uses _row_to_belief (the block around lines 3114-3119) so
missing columns don't propagate exceptions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c0ac79ef-1547-45db-98bc-7a93e39b9512

📥 Commits

Reviewing files that changed from the base of the PR and between 093c1e4 and caeb542.

⛔ Files ignored due to path filters (1)
  • CHANGELOG.md is excluded by !**/CHANGELOG.md
📒 Files selected for processing (5)
  • src/aelfrice/bfs_multihop.py
  • src/aelfrice/cli.py
  • src/aelfrice/reason.py
  • src/aelfrice/store.py
  • tests/test_peer_aware_reason.py

Comment thread src/aelfrice/store.py
@robotrocketscience robotrocketscience added the ready-to-merge Trigger merge-train: FF main to this PR's head label May 12, 2026
@github-actions

Copy link
Copy Markdown

merge-train: blocked

one or more commits between main and feat/issue-690-peer-aware-reason-walk are not signed (per GitHub verification API):\n\n\ncaeb542f4ee5e05276376eb2b000733c6f7da884\n\n\nSign them locally and re-add the label. The bot cannot sign on your behalf.

The ready-to-merge label has been removed. Address the issue above and re-add the label when you're ready for another attempt.

@github-actions github-actions Bot removed the ready-to-merge Trigger merge-train: FF main to this PR's head label May 12, 2026
yoshi280 pushed a commit that referenced this pull request May 12, 2026
CodeQL flagged the unused 'import pytest' at line 22. The tests use plain
assert statements and don't reference pytest fixtures, parametrize, or
raises; the import was leftover from an earlier draft.

Resolves the one outstanding review thread on PR #712.
@yoshi280
yoshi280 force-pushed the feat/issue-690-peer-aware-reason-walk branch 2 times, most recently from 06279c2 to 58f828b Compare May 12, 2026 04:54
yoshi280 pushed a commit that referenced this pull request May 12, 2026
CodeQL flagged the unused 'import pytest' at line 22. The tests use plain
assert statements and don't reference pytest fixtures, parametrize, or
raises; the import was leftover from an earlier draft.

Resolves the one outstanding review thread on PR #712.
@robotrocketscience robotrocketscience added the ready-to-merge Trigger merge-train: FF main to this PR's head label May 12, 2026
@github-actions

Copy link
Copy Markdown

merge-train: blocked

branch is not fast-forward on main (branch base 1417172e457635ab50eeaa3dec40b4ad92f366bb, current main 8b8dd56be200bc53c12e556b5f4bfc3f060e8375). Rebase locally (git rebase github/main), force-push, and re-add the label.

The ready-to-merge label has been removed. Address the issue above and re-add the label when you're ready for another attempt.

@github-actions github-actions Bot removed the ready-to-merge Trigger merge-train: FF main to this PR's head label May 12, 2026
… reads

Add two read-only helpers on MemoryStore that route to the local DB
when owning_scope is None and to the cached read-only peer connection
otherwise. Foundation for the peer-aware BFS walk (#690): the
expand_bfs traversal needs scope-routed edge reads and belief
materialisation when a frontier entry lands on a foreign belief.

Both helpers tolerate unreachable peers and schema-drift peer DBs
(missing edges/beliefs tables) by returning [] / None rather than
raising — federation is opportunistic per #661.

Closes-AC-1 of #690.
ScoredHop gains owning_scope (None = local, peer name = federation
scope owning the belief). expand_bfs takes an optional seed_scopes
dict mapping seed belief_id → owning_scope; the scope propagates
from each frontier entry to its children so a walk that enters a
peer DB stays inside that peer's edge graph.

Edge and belief reads route through the new
MemoryStore.edges_from_in_scope / get_belief_in_scope helpers so an
unreachable peer or schema-drift peer DB degrades gracefully (empty
hops, no exception).

Backwards compatible: seed_scopes=None preserves byte-identical
output for pre-federation callers. Three new tests cover the
two-scope acceptance smoke (peer 2-hop neighbour reaches the walk
output with owning_scope='peerA', SUPPORTS chain depth=1/depth=2
ordering, scope='global' visibility), local-seed preservation
(owning_scope=None propagates), and unreachable-peer tolerance.

Closes-AC-1 of #690.
…ging (#690)

SuggestedUpdate gains owning_scope (None = local, peer name when
the belief lives in a foreign DB). suggested_updates() propagates
the scope from each ScoredHop to its +1 row, and looks up
impasse-locus belief scopes via a {bid: scope} map built from the
hops list.

Per the #661 read-only federation contract, the slash skill's
close-the-loop writeback must skip foreign rows (mutations
targeting foreign ids raise ForeignBeliefError at the API
surface — feedback/lock/delete already enforce this). The
owning_scope tag is the surface that lets the skill detect
which rows to skip.

One new test covers the mixed-scope case: a local +1 row carries
owning_scope=None and a peer +1 row carries owning_scope='peerA'.

Closes-AC-5 of #690.
…_scope JSON (#690)

Human output: peer-owned hops prepend '[scope:<name>] ' to the
belief.id line so readers can tell a hop crossed the federation
boundary. Local hops (owning_scope=None) print unchanged
byte-for-byte to preserve existing test fixtures.

JSON output (--json): both .hops[] and .suggested_updates[] rows
gain an owning_scope key (None for local, peer name for foreign).
This is the wire surface the slash skill's close-the-loop
writeback reads to skip foreign rows.

Closes-AC-2 of #690.
CodeQL flagged the unused 'import pytest' at line 22. The tests use plain
assert statements and don't reference pytest fixtures, parametrize, or
raises; the import was leftover from an earlier draft.

Resolves the one outstanding review thread on PR #712.
@yoshi280
yoshi280 force-pushed the feat/issue-690-peer-aware-reason-walk branch from 58f828b to eb699e1 Compare May 12, 2026 05:00
@robotrocketscience robotrocketscience added the ready-to-merge Trigger merge-train: FF main to this PR's head label May 12, 2026
@github-actions
github-actions Bot merged commit eb699e1 into main May 12, 2026
26 checks passed
@github-actions github-actions Bot removed the ready-to-merge Trigger merge-train: FF main to this PR's head label May 12, 2026
@github-actions

Copy link
Copy Markdown

merge-train: merged eb699e1main via FF push.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

author-Faraday PR coordination mutex

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(reason): peer-aware graph walk (#650 sub-task)

2 participants