Skip to content

docs(feature-intentional-clustering): spec memo for #436 - #455

Merged
robotrocketscience merged 1 commit into
mainfrom
docs/issue-436-clustering-spec
May 6, 2026
Merged

docs(feature-intentional-clustering): spec memo for #436#455
robotrocketscience merged 1 commit into
mainfrom
docs/issue-436-clustering-spec

Conversation

@yoshi280

@yoshi280 yoshi280 commented May 5, 2026

Copy link
Copy Markdown
Collaborator

Spec memo for #436 — Intentional clustering. Closes the recovery-inventory line at docs/ROADMAP.md row 164 (Intentional clustering | v2.0.0).

What this PR is

Docs-only. New file at docs/feature-intentional-clustering.md. Converts the bare issue acceptance sketch into a buildable contract: cluster definition, two-stage pack algorithm, latency analysis, and bench-gate.

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

Cluster definition (issue acceptance #1)

Graph-connected components of the post-rank candidate pool, edge-weight ≥ cluster_edge_weight_floor=0.4 (floor includes CITES@0.5, excludes RELATES_TO@0.3 per models.py:55-66).

Topic-coherent and co-occurrence-derived alternatives rejected:

  • topic-coherent → requires embeddings (project posture: no embeddings in retrieval).
  • co-occurrence-derived → requires a queryable rebuild-logs view; deferred to v2.x.

Pack algorithm

Two-stage diversity-aware greedy, replacing the existing tail-trim (retrieval.py:1048-1085, :1197-1232):

Stage 1 — cluster representatives in descending seed score, until cluster_diversity_target=3 distinct clusters covered or budget exhausted.
Stage 2 — fill remaining budget by score, skipping already-included beliefs.

fallback_to_score=True default keeps single-fact recall non-degenerate when the candidate pool has fewer clusters than the diversity target.

Latency (issue acceptance #4)

Algorithmic profile: one batched edges_for_beliefs(candidate_ids) + one path-compressed union-find pass + score-ranked tail iteration. <1 ms expected at N=200, E=500. A microbench under tests/bench_gate/ confirms <5 ms p99 (A4).

Reconciliation

Substrate

All on main as of e646383:

  • dedup.py:248 — path-compressed union-find primitive
  • models.py:55-66EDGE_VALENCE informing the floor default
  • store.py — needs edges_for_beliefs(candidate_ids) (batched edge fetch; impl PR adds if missing)
  • retrieval.py:118-131 — flag-resolution convention
  • retrieval.py:1048-1085, :1197-1232 — pack loops to replace
  • tests/corpus/v2_0/, tests/bench_gate/ — corpus + harness

No new dependencies. No schema changes.

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 cluster_edge_weight_floor=0.4 default and the cluster_diversity_target=3 default.

Refs

Summary by Sourcery

Document the intentional clustering retrieval feature as a bench-gated spec, defining clustering behavior, pack-stage integration, and acceptance criteria without changing code.

Documentation:

  • Add a feature spec memo for intentional clustering that defines graph-connected cluster formation, a two-stage diversity-aware packing algorithm, configuration knobs, and interaction with existing retrieval components.
  • Describe latency expectations, benchmark gates, and acceptance criteria for enabling intentional clustering by default, including multi-fact recall uplift and non-regression constraints.

Summary by CodeRabbit

  • Documentation
    • Added comprehensive design specifications for retrieval clustering capabilities, covering architectural design, configuration parameters, performance expectations, and implementation guidance for future development.

@coderabbitai

coderabbitai Bot commented May 5, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f1f4445c-8739-4f8a-9921-ce3831fa0074

📥 Commits

Reviewing files that changed from the base of the PR and between 34ddfb8 and 985c367.

📒 Files selected for processing (1)
  • docs/feature-intentional-clustering.md

📝 Walkthrough

Walkthrough

A new specification document for Intentional Clustering in retrieval has been added, detailing the design of a two-stage API (cluster_candidates and pack_with_clusters), clustering criteria based on graph-connected components with weight thresholds, a diversity-aware greedy packing algorithm, configuration parameters, latency expectations, and reconciliation with existing components. No code implementation is included.

Changes

Intentional Clustering Specification

Layer / File(s) Summary
Design Specification
docs/feature-intentional-clustering.md
Complete design spec introducing RetrievalCluster data structure, two-stage API for clustering and packing, clustering criteria (graph-connected components with weight floor), diversity-aware greedy fill algorithm, configuration knobs, latency budget, and reconciliation with heat kernel and BFS components. Also documents implementation prerequisites and open questions.

Possibly Related Issues

  • Issue #436: This spec directly addresses the Intentional Clustering feature request by providing the complete design specification for the cluster_candidates and pack_with_clusters APIs, clustering criteria, and packing algorithms.

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/issue-436-clustering-spec

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

@sourcery-ai

sourcery-ai Bot commented May 5, 2026

Copy link
Copy Markdown

Reviewer's Guide

Docs-only spec memo that defines the intentional clustering feature (#436): it formalizes a graph-connected clustering definition, a two-stage diversity-aware pack algorithm, configuration and defaults, latency/bench expectations, and how this retrieval-time transform composes with existing features and test/bench gating.

Sequence diagram for retrieval pipeline with intentional clustering

sequenceDiagram
    actor User
    participant RetrieveAPI as RetrieveAPI
    participant RetrievalEngine as RetrievalEngine
    participant Store as Store

    User->>RetrieveAPI: retrieve(query, use_intentional_clustering)
    RetrieveAPI->>RetrievalEngine: lane_fan_out(query)
    RetrievalEngine-->>RetrievalEngine: BM25F + heat_kernel + HRR_structural + BFS
    RetrievalEngine-->>RetrievalEngine: score_composition_and_rank

    alt use_intentional_clustering is true
        RetrievalEngine->>Store: edges_for_beliefs(candidate_ids)
        Store-->>RetrievalEngine: edges
        RetrievalEngine-->>RetrievalEngine: cluster_candidates(candidates, candidate_scores, edges)
        RetrievalEngine-->>RetrievalEngine: pack_with_clusters(clusters, token_budget)
        RetrievalEngine-->>RetrieveAPI: packed_beliefs_with_clustering
    else use_intentional_clustering is false
        RetrievalEngine-->>RetrievalEngine: existing_pack_loop(candidates, token_budget)
        RetrievalEngine-->>RetrieveAPI: packed_beliefs_without_clustering
    end

    RetrieveAPI-->>User: RetrievalResult
Loading

Class diagram for RetrievalCluster and clustering contract

classDiagram
    class RetrievalCluster {
        +int cluster_id
        +tuple~str~ member_ids
        +str representative_id
        +float seed_score
    }

    class Belief {
        +str id
        +float score
        +int token_cost
    }

    class Edge {
        +str src_id
        +str dst_id
        +float weight
        +str edge_type
    }

    class ClusterModule {
        +list~RetrievalCluster~ cluster_candidates(candidates, candidate_scores, edges, edge_weight_floor)
        +list~Belief~ pack_with_clusters(clusters, token_budget, cluster_diversity_target, fallback_to_score)
    }

    class UnionFind {
        +make_set(node)
        +find(node)
        +union(node_a, node_b)
    }

    class Config {
        +float DEFAULT_CLUSTER_EDGE_FLOOR
        +int DEFAULT_CLUSTER_DIVERSITY_TARGET
        +bool use_intentional_clustering
        +float cluster_edge_weight_floor
        +int cluster_diversity_target
    }

    Belief "1" <-- "*" RetrievalCluster : member_ids
    RetrievalCluster "1" --> "1" Belief : representative_id

    ClusterModule --> RetrievalCluster : produces
    ClusterModule --> Belief : returns
    ClusterModule --> Edge : consumes
    ClusterModule --> UnionFind : uses
    ClusterModule --> Config : reads

    UnionFind <.. DedupDuplicateCluster : reused_pattern
    class DedupDuplicateCluster
Loading

Flow diagram for two stage diversity aware pack algorithm

flowchart TD
    A[Start pack_with_clusters] --> B[Init out list, used_tokens, covered_clusters]
    B --> C[Stage 1 iterate clusters sorted by descending seed_score]
    C --> D{covered_clusters size >= cluster_diversity_target?}
    D -- Yes --> H[Proceed to Stage 2]
    D -- No --> E[Select cluster representative rep]
    E --> F{rep token_cost fits within token_budget?}
    F -- Yes --> G[Append rep to out, update used_tokens and covered_clusters]
    G --> C
    F -- No --> I{fallback_to_score is true?}
    I -- Yes --> H
    I -- No --> C

    H[Stage 2] --> J[Build score_ranked_remaining from clusters excluding already selected beliefs]
    J --> K[Iterate beliefs in score_ranked_remaining]
    K --> L{belief token_cost fits within remaining token_budget?}
    L -- Yes --> M[Append belief to out and update used_tokens]
    M --> K
    L -- No --> N[Break Stage 2 loop]
    N --> O[Return out]
    K -->|no more beliefs| O[Return out]
Loading

File-Level Changes

Change Details Files
Add detailed feature spec for intentional clustering defining clustering contract, algorithms, configuration, and acceptance criteria.
  • Introduce docs/feature-intentional-clustering.md as the spec memo for [v2.0] Intentional clustering — co-locate related beliefs for multi-fact coherence #436 and ROADMAP recovery-inventory line.
  • Define RetrievalCluster, cluster_candidates, and pack_with_clusters contracts, including their inputs, outputs, and sequencing in retrieval.
  • Specify cluster definition as graph-connected components over candidate-induced edge subgraph with edge-weight floor and rationale against topic/co-occurrence-based clustering.
  • Describe two-stage diversity-aware pack algorithm, including cluster_diversity_target, fallback_to_score, and interaction with token budgets.
  • Document configuration knobs (use_intentional_clustering, cluster_edge_weight_floor, cluster_diversity_target) and how they’re resolved (kwargs, env, TOML).
  • Analyze latency profile and set explicit microbench gate (<5 ms p99 at N=200) plus composition with heat kernel, BFS multi-hop, dedup, type-aware compression, and doc linker.
  • Define acceptance criteria A1–A5 (multi-fact corpus, recall uplift, non-regression, latency, composition tracker) and bench-gated ship policy, plus open questions for future implementation review.
docs/feature-intentional-clustering.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

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

  • The interaction between pack_with_clusters and existing locked-belief handling is only briefly mentioned; consider explicitly specifying the exact pre-inclusion step and order of operations so the implementation can mirror current L0 semantics without guesswork.
  • The edge_weight_floor and cluster_diversity_target defaults are justified qualitatively, but you might want to spell out expected failure modes (e.g., over- or under-clustering) to guide future tuning and avoid misinterpreting bench results when these knobs are adjusted.
  • Stage 2 references flattened_score_order(clusters) and candidate_scores without fully defining that ordering in the contract; it would help to explicitly define how ties, cluster membership, and any secondary keys are handled so multiple implementations converge on the same behaviour.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The interaction between `pack_with_clusters` and existing locked-belief handling is only briefly mentioned; consider explicitly specifying the exact pre-inclusion step and order of operations so the implementation can mirror current L0 semantics without guesswork.
- The `edge_weight_floor` and `cluster_diversity_target` defaults are justified qualitatively, but you might want to spell out expected failure modes (e.g., over- or under-clustering) to guide future tuning and avoid misinterpreting bench results when these knobs are adjusted.
- Stage 2 references `flattened_score_order(clusters)` and `candidate_scores` without fully defining that ordering in the contract; it would help to explicitly define how ties, cluster membership, and any secondary keys are handled so multiple implementations converge on the same behaviour.

## Individual Comments

### Comment 1
<location path="docs/feature-intentional-clustering.md" line_range="165" />
<code_context>
+
+Issue acceptance #4: *"Cluster pass runs inside the retrieve() budget; no separate query."* The cost decomposes into:
+
+- **One `store.edges_for_beliefs(candidate_ids)` call.** Indexed lookup; existing pattern from BFS multi-hop. Cost is dominated by the `IN (...)` clause; at typical candidate-pool size (≤200) this is sub-ms in SQLite-backed numpy.
+- **One union-find pass.** Path-compressed union-by-size, the same primitive `dedup.py:248` uses. O(α(N)·E) where α is the inverse Ackermann. At N=200 candidates and E ≤ 1000 inter-candidate edges, this is microseconds.
+- **One score-ranked tail iteration.** Same as the existing pack loop, no algorithmic change.
</code_context>
<issue_to_address>
**nitpick (typo):** Consider capitalizing "NumPy" to match the library's official name.

You could update "SQLite-backed numpy" here to "SQLite-backed NumPy" for consistency with the official project name.

```suggestion
- **One `store.edges_for_beliefs(candidate_ids)` call.** Indexed lookup; existing pattern from BFS multi-hop. Cost is dominated by the `IN (...)` clause; at typical candidate-pool size (≤200) this is sub-ms in SQLite-backed NumPy.
```
</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.


Issue acceptance #4: *"Cluster pass runs inside the retrieve() budget; no separate query."* The cost decomposes into:

- **One `store.edges_for_beliefs(candidate_ids)` call.** Indexed lookup; existing pattern from BFS multi-hop. Cost is dominated by the `IN (...)` clause; at typical candidate-pool size (≤200) this is sub-ms in SQLite-backed numpy.

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 "NumPy" to match the library's official name.

You could update "SQLite-backed numpy" here to "SQLite-backed NumPy" for consistency with the official project name.

Suggested change
- **One `store.edges_for_beliefs(candidate_ids)` call.** Indexed lookup; existing pattern from BFS multi-hop. Cost is dominated by the `IN (...)` clause; at typical candidate-pool size (≤200) this is sub-ms in SQLite-backed numpy.
- **One `store.edges_for_beliefs(candidate_ids)` call.** Indexed lookup; existing pattern from BFS multi-hop. Cost is dominated by the `IN (...)` clause; at typical candidate-pool size (≤200) this is sub-ms in SQLite-backed NumPy.

@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 'docs/issue-436-clustering-spec' && 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 6, 2026

Copy link
Copy Markdown
Collaborator Author

[claim:review:Toug:2026-05-06T20:18:48Z]

@yoshi280

yoshi280 commented May 6, 2026

Copy link
Copy Markdown
Collaborator Author

[claim:review:kulili:2026-05-06T20:19:00Z]

@yoshi280

yoshi280 commented May 6, 2026

Copy link
Copy Markdown
Collaborator Author

[release:review:kulili:2026-05-06T20:19:05Z]

@yoshi280

yoshi280 commented May 6, 2026

Copy link
Copy Markdown
Collaborator Author

[claim:review:Setr:2026-05-06T20:20:28Z]

@yoshi280

yoshi280 commented May 6, 2026

Copy link
Copy Markdown
Collaborator Author

[release:review:Setr:2026-05-06T20:20:33Z]

Retrieval-time pack-stage selection bias toward graph-connected
clusters. Distinct from heat-kernel scoring (#150 boosts scores;
this changes selection at fixed scores) and dedup union-find
(#197 audits at offline-pass time, this runs per-retrieve).

Cluster definition: graph-connected components of the post-rank
candidate pool, edge_weight >= cluster_edge_weight_floor=0.4
(includes CITES at 0.5 valence, excludes RELATES_TO at 0.3).

Pack: two-stage greedy. Stage 1 covers cluster_diversity_target=3
distinct clusters via representatives. Stage 2 fills remaining
budget by score, preserving single-fact behaviour.
fallback_to_score=True on tight budgets.

Bench-gate: positive multi-fact recall + cluster_coverage uplift
on a new tests/corpus/v2_0/multi_fact/ fixture; non-regression on
the v0.1 retrieve_uplift fixture; <5ms p99 latency at N=200
candidates.

Substrate: union-find primitive at dedup.py:248; EDGE_VALENCE
weights at models.py:55-66; pack loops at retrieval.py:1048-1085,
:1197-1232. No schema changes.
@robotrocketscience
robotrocketscience force-pushed the docs/issue-436-clustering-spec branch from ac82311 to 985c367 Compare May 6, 2026 20:21
@robotrocketscience
robotrocketscience merged commit 985c367 into main May 6, 2026
14 of 15 checks passed
@robotrocketscience
robotrocketscience deleted the docs/issue-436-clustering-spec branch May 6, 2026 20:22
@yoshi280

yoshi280 commented May 6, 2026

Copy link
Copy Markdown
Collaborator Author

[release:review:Toug:2026-05-06T20:22:19Z]

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants