Skip to content

docs(feature-doc-linker): spec memo for #435 - #453

Merged
robotrocketscience merged 1 commit into
mainfrom
docs/issue-435-doc-linker-spec
May 5, 2026
Merged

docs(feature-doc-linker): spec memo for #435#453
robotrocketscience merged 1 commit into
mainfrom
docs/issue-435-doc-linker-spec

Conversation

@yoshi280

@yoshi280 yoshi280 commented May 5, 2026

Copy link
Copy Markdown
Collaborator

Spec memo for #435 — Document / semantic linker. Closes the recovery-inventory line at docs/ROADMAP.md row 163 (Doc / semantic linker | v2.0.0).

What this PR is

Docs-only. New file at docs/feature-doc-linker.md. Converts the bare issue acceptance sketch into a buildable contract: storage schema, invocation point, retrieval surface, doc URI scheme, bench-gate, and out-of-scope list.

No code, no schema, no flag wiring yet. This PR moves #435 from needs-spec to bench-gated.

Storage decision

New table belief_documents (sibling of belief_corroborations #190 and belief_neighbors #227):

(belief_id, doc_uri, anchor_type, position_hint, created_at)
PK (belief_id, doc_uri); FK belief_id ON DELETE CASCADE

anchor_type ∈ {ingest, manual, derived}derived reserved for v2.x retrieval-time inference, no writer at v2.0.0.

Invocation

Ingest-time only at v2.0.0. Hooked into derivation.py:64, :223 where source_path is materialised. aelf remember --doc=URI adds a CLI surface for manual anchors. Retrieval-time inference deferred (out of scope, would require fuzzy matching on the hot path).

Retrieval surface

Opt-in: retrieve(..., with_doc_anchors=True) projects parallel doc_anchors: list[list[DocAnchor]] onto RetrievalResult. Default False keeps the byte-stable pack contract. Anchors are metadata, not body — no token_budget cost.

Reconciliation

#148 (BM25F anchor text) #435 (this)
direction belief A's incoming edges (citers) belief A's outgoing reference (source)
storage edges.anchor_text new belief_documents table
consumer BM25F scoring retrieval output projection

EDGE_CITES is belief→belief; this is belief→document. No overlap.

Substrate

All on main as of 68dafc0:

  • store.py:142-162belief_corroborations schema-pattern precedent
  • store.py:316-330 — migration block where the additive CREATE TABLE lands
  • derivation.py:64, :223source_path plumbing
  • derivation_worker.py — sibling writer pattern
  • tests/corpus/v2_0/, tests/bench_gate/ — corpus + harness

No new dependencies. One additive (forward-only) schema migration.

Test plan

  • Discretion grep on diff vs github/main — clean.
  • Commit SSH-signed (G).
  • CI matrix green (docs-only).
  • Reviewer: confirm A1–A5 are buildable; sanity-check the storage decision (sibling table vs column vs corroboration extension — spec argues for sibling).

Refs

Summary by Sourcery

Add a feature specification document for a belief-to-document linker, defining storage, invocation, retrieval projection, and acceptance criteria for future implementation.

Documentation:

  • Document the contract and schema for a new belief_documents table linking beliefs to document URIs with anchor metadata.
  • Describe ingest-time linker invocation, retrieval-time opt-in projection via with_doc_anchors, and CLI surface for manual anchors.
  • Record benchmarks, acceptance criteria, and out-of-scope items for shipping the document/semantic linker feature.

Belief↔document linker — distinct from CITES (belief→belief, models.py:27)
and from BM25F anchor text (#148, doc-side incoming-edge text).

Schema: new belief_documents table (sibling of belief_corroborations
and belief_neighbors) keyed (belief_id, doc_uri), CASCADE on belief
delete. anchor_type enum: ingest | manual | derived (last reserved).

Invocation: ingest-time only at v2.0.0, hooked into the
DerivationInput.source_path path (derivation.py:64,:223). Retrieval-
time inference (anchor_type="derived") is reserved but deferred.

Surface: opt-in with_doc_anchors=True kwarg on retrieve() projects
parallel doc_anchors list onto RetrievalResult. Default OFF, byte-
stable pack contract. Anchors are metadata, not body — no token-
budget cost.

Bench-gate: NDCG@k uplift on a labeled doc_linker fixture under
tests/corpus/v2_0/, comparing same beliefs with anchors populated
vs unpopulated.

URI scheme: opaque TEXT. file://abs/path#Lstart-Lend for local
ingest, https://... for external; validation deferred.
@sourcery-ai

sourcery-ai Bot commented May 5, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adds a detailed feature spec document for the planned document/semantic linker (#435), defining storage schema, invocation points, retrieval-surface behavior, configuration, acceptance criteria, and out-of-scope items, without changing any code.

Sequence diagram for ingest-time document linking

sequenceDiagram
    actor Operator
    participant CLI as aelf_remember
    participant Derivation as DerivationPipeline
    participant Store as MemoryStore
    participant DB as belief_documents_table

    Operator->>CLI: run aelf remember --doc=URI
    CLI->>Derivation: submit content with source_path
    Derivation->>Store: link_belief_to_document(belief_id, doc_uri, anchor_type="ingest", position_hint)
    Store->>DB: INSERT OR IGNORE (belief_id, doc_uri, anchor_type, position_hint, created_at)
    DB-->>Store: success
    Store-->>Derivation: DocAnchor
    Derivation-->>CLI: confirm belief stored with doc anchor
    CLI-->>Operator: output success message
Loading

Sequence diagram for retrieval with doc anchors

sequenceDiagram
    actor Client
    participant Retrieval as RetrievalService
    participant Store as MemoryStore
    participant DB as belief_documents_table

    Client->>Retrieval: retrieve(query, with_doc_anchors=True)
    Retrieval->>Store: fetch ranked beliefs for query
    Store-->>Retrieval: list of beliefs
    Retrieval->>Store: get_doc_anchors(belief_ids_batch)
    Store->>DB: SELECT * FROM belief_documents WHERE belief_id IN (belief_ids_batch)
    DB-->>Store: rows for matching anchors
    Store-->>Retrieval: grouped doc anchors per belief
    Retrieval-->>Client: RetrievalResult(beliefs, doc_anchors)
Loading

Entity relationship diagram for new belief_documents table

erDiagram
    beliefs {
        TEXT id PK
        TEXT content
        REAL created_at
    }

    belief_documents {
        TEXT belief_id FK
        TEXT doc_uri
        TEXT anchor_type
        TEXT position_hint
        REAL created_at
    }

    ingest_log {
        INTEGER id PK
        TEXT source_path
        TEXT source_kind
        REAL created_at
    }

    beliefs ||--o{ belief_documents : anchors
    beliefs ||--o{ ingest_log : ingests
Loading

Class diagram for DocAnchor and store/retrieval integration

classDiagram
    class DocAnchor {
        +str belief_id
        +str doc_uri
        +str anchor_type
        +str position_hint
        +float created_at
    }

    class MemoryStore {
        +link_belief_to_document(store, belief_id, doc_uri, anchor_type, position_hint) DocAnchor
        +get_doc_anchors(store, belief_id) list_DocAnchor
    }

    class RetrievalResult {
        +list_beliefs beliefs
        +list_list_DocAnchor doc_anchors
    }

    class RetrievalService {
        +retrieve(query, with_doc_anchors) RetrievalResult
        +retrieve_v2(query, with_doc_anchors) RetrievalResult
    }

    MemoryStore "1" o-- "many" DocAnchor : persists
    RetrievalResult "1" o-- "many" DocAnchor : projects
    RetrievalService ..> MemoryStore : uses
    RetrievalService ..> RetrievalResult : returns
Loading

Flow diagram for doc linker in ingest and retrieval pipelines

flowchart TD
    IngestLog[Ingest_log_events]
    Derive[Derivation_worker]
    DocLinker[Doc_linker_writer]
    Beliefs[Beliefs_table]
    BeliefDocs[Belief_documents_table]
    Retrieve[Retrieval_service]
    Client[Client_or_tooling]

    IngestLog --> Derive
    Derive --> Beliefs
    Derive --> DocLinker
    DocLinker --> BeliefDocs

    Client --> Retrieve
    Retrieve --> Beliefs
    Retrieve --> BeliefDocs
    Retrieve --> Client
Loading

File-Level Changes

Change Details Files
Introduce a feature-spec document that fully defines the document / semantic linker behavior, schema, and integration points while leaving implementation to a future PR.
  • Describe the DocAnchor contract and related store/retrieval APIs, including ingest-time linking, retrieval-time projection, and idempotency requirements.
  • Specify the new belief_documents table schema, indexing, and rationale for a sibling table instead of extending existing beliefs or belief_corroborations structures.
  • Define the invocation model (ingest-time only at v2.0.0, manual anchors via CLI) and where hooks will live in derivation, store, retrieval, and CLI modules.
  • Explain retrieval behavior with an opt-in with_doc_anchors flag, outlining how anchors are projected as metadata without affecting token-budget packing.
  • Lay out acceptance criteria, bench-gate policy, migration behavior, and explicitly list out-of-scope features and open design questions for future iterations.
docs/feature-doc-linker.md

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

@yoshi280 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 50 minutes 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: bb77c0f9-277f-4896-beea-684d84373643

📥 Commits

Reviewing files that changed from the base of the PR and between e646383 and 802041e.

📒 Files selected for processing (1)
  • docs/feature-doc-linker.md
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/issue-435-doc-linker-spec

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
@github-actions github-actions Bot added the docs 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

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="docs/feature-doc-linker.md" line_range="29" />
<code_context>
+    doc_uri: str            # see "Doc URI scheme" below
+    anchor_type: str        # "ingest" | "manual" | "derived"
+    position_hint: str | None  # e.g. "L42-L60", "#section-name"; nullable
+    created_at: float       # unix timestamp
+
+# Ingest-time: invoked by onboard / commit-ingest when source_path is known.
</code_context>
<issue_to_address>
**nitpick (typo):** Consider capitalizing "Unix" in the comment for `created_at`.

This matches the conventional term "Unix timestamp" used in most documentation.

```suggestion
    created_at: float       # Unix timestamp
```
</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.

doc_uri: str # see "Doc URI scheme" below
anchor_type: str # "ingest" | "manual" | "derived"
position_hint: str | None # e.g. "L42-L60", "#section-name"; nullable
created_at: float # unix timestamp

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): Consider capitalizing "Unix" in the comment for created_at.

This matches the conventional term "Unix timestamp" used in most documentation.

Suggested change
created_at: float # unix timestamp
created_at: float # Unix timestamp

@yoshi280

yoshi280 commented May 5, 2026

Copy link
Copy Markdown
Collaborator Author

[claim:review:Kulili:2026-05-05T19:46:07Z]

@yoshi280

yoshi280 commented May 5, 2026

Copy link
Copy Markdown
Collaborator Author

Reviewed at 802041e. Single signed commit (G), docs-only (+266 lines), CI green, FF-mergeable, discretion grep clean.

Spec-memo quality:

Three flags for impl-PR review (not blocking the spec):

  1. A2 threshold is "strictly positive uplift" vs Track A's ratified +5pp universal floor. The weaker bar may be intentional (output-projection vs graph-edge), but V2_REENTRY_QUEUE decision Add CI workflows, scan config, and README claim alignment #1 ("strict bench-impact gate") deserves an explicit operator call here. Recommend the impl-PR either ratifies the lower bar in the body or pulls A2 up to +5pp on a NDCG/@k metric of choice.

  2. Open Q4 (path normalization) is worth ratifying before the impl-PR ships — absolute paths in doc_uri leak local filesystem layout into the store, which is a discretion concern, not a tidiness one. Recommend the impl-PR defaults to repo-root-relative for file:// URIs, with the absolute-path form gated behind an explicit flag if anyone needs it. The aelf doctor --normalize-doc-uris cleanup path is a fine sibling, but should be a backstop, not the primary defense.

  3. Retrieval output shape: parallel-list pairing. RetrievalResult.doc_anchors[i] parallel to RetrievalResult.beliefs[i] is unusual — most consumers would prefer doc_anchors attached to each belief result item. The "byte-stable pack contract" motivation is good, but flagging because parallel-list shapes drift over time. Worth a one-paragraph justification in the impl-PR or a follow-up shape change.

Spec is mergeable as-is; the three points belong in the impl-PR conversation, not in another spec revision.

Merging by FF push.

@robotrocketscience
robotrocketscience merged commit 802041e into main May 5, 2026
15 of 22 checks passed
@robotrocketscience
robotrocketscience deleted the docs/issue-435-doc-linker-spec branch May 5, 2026 19:47
@yoshi280

yoshi280 commented May 5, 2026

Copy link
Copy Markdown
Collaborator Author

[release:review:Kulili:2026-05-05T19:47:32Z]

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

Labels

attn:review Needs review (PR open, awaiting reviewer) docs

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants