Skip to content

feat: add source filter to knowledge graph visualization - #4640

Open
severity1 wants to merge 1 commit into
kirodotdev:mainfrom
severity1:feat/knowledge-graph-source-filter
Open

feat: add source filter to knowledge graph visualization#4640
severity1 wants to merge 1 commit into
kirodotdev:mainfrom
severity1:feat/knowledge-graph-source-filter

Conversation

@severity1

@severity1 severity1 commented Aug 20, 2026

Copy link
Copy Markdown

Problem / Motivation

When multiple knowledge sources are registered, the graph visualization shows all entities from all sources mixed together. With many sources this becomes a dense hairball where it's hard to see the structure of any single source's entities and relationships.

Why it matters

Users who index several projects or document collections need to explore each source's entity graph independently. Without filtering, the visualization is unusable at scale — entities from unrelated sources obscure the relationships that matter.

What changed (motivation → approach → change)

Goal: Let users isolate the knowledge graph to a single source.

Approach: Filter at the entity level via the existing mentions → items → sources relationship chain. This avoids duplicating graph-building logic and reuses the same join pattern already used by list_items.

Changes:

  • Backend (src/kiro_crew/dashboard/handlers/knowledge.py): Added optional source_id query parameter to GET /api/knowledge/graph. When set, only entities mentioned in items belonging to those sources are included. Parameterized SQL, backward compatible.
  • Frontend (website/src/pages/knowledge/KnowledgeGraph.tsx): Added a SimpleSelect source filter dropdown in the graph toolbar. Only renders when 2+ sources exist. Selecting a source re-queries with source_id.
  • i18n (all 13 locale files): Added all_sources and filter_by_source keys with translations.

Tests

  • test_source_id_filter_restricts_to_mentioned_entities — creates two sources with distinct entities, verifies filtering returns only the correct source's entities
  • test_source_id_filter_with_no_mentions_returns_empty — verifies a source with no entity mentions returns an empty graph
  • Existing 102 knowledge handler tests pass with no regressions

Manual verification

  • Confirmed via API: unfiltered graph returns 200 nodes / 413 edges; filtering to a 5-file source returns 24 nodes / 32 edges; filtering to a 66-file source returns 200 nodes / 398 edges
  • Frontend: dropdown renders in the graph toolbar, selecting a source triggers re-query, graph re-renders with filtered data

Screenshots / video

Screenshot 2026-08-20 at 6 42 43 PM Screenshot 2026-08-20 at 6 42 28 PM Screenshot 2026-08-20 at 6 42 11 PM

(entity extraction was contended during testing). The UI change is a single SimpleSelect dropdown added to the existing graph toolbar.

Related Issues

Closes #4636

Checklist

  • Single commit with a Conventional Commits title
  • Existing tests pass and new tests added for new functionality
  • Self-review completed; code follows project style guidelines
  • Documentation updated (if applicable) — N/A, no separate API spec doc for this endpoint
  • No secrets, credentials, or internal references in the diff

@severity1
severity1 requested a review from a team August 20, 2026 06:31
@severity1
severity1 requested a review from a team as a code owner August 20, 2026 06:31
@github-actions github-actions Bot added fork Pull request from a fork (external contributor) readiness: action required A blocking check or review needs attention labels Aug 20, 2026
@iamwhatever

Copy link
Copy Markdown
Collaborator

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## Why it matters
  • ## What changed
  • ## Tests

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

1 similar comment
@bolichen97

Copy link
Copy Markdown
Collaborator

👋 Hi! This PR's description is missing some required sections from our PR template. Workflow runs won't be auto-approved until the description is updated.

Missing sections:

  • ## Problem / Motivation
  • ## Why it matters
  • ## What changed
  • ## Tests

Please update your PR description to include these sections, then push or re-save the description. The workflows will be approved on the next cycle.

@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: action required A blocking check or review needs attention and removed readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running labels Aug 20, 2026
@severity1
severity1 force-pushed the feat/knowledge-graph-source-filter branch from a5c3dfe to 82750d4 Compare August 20, 2026 06:56
@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running and removed readiness: checking Automated validation is still running readiness: action required A blocking check or review needs attention labels Aug 20, 2026
@severity1
severity1 force-pushed the feat/knowledge-graph-source-filter branch from 82750d4 to b234244 Compare August 20, 2026 07:33
@github-actions github-actions Bot added readiness: checking Automated validation is still running and removed readiness: action required A blocking check or review needs attention labels Aug 20, 2026
@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

UX Review (Fable 5, fork) — 🟡 CONCERNS

UX-level review of a336b01d8375ea9fe31618add977c2616fe97cdc via the fork AI-review pipeline — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

UX-Verdict: CONCERNS

Selecting a source with no entities collapses the whole panel — filter control included — into a misleading "No graph data yet" dead end.

Watch

  • The toolbar (and the new dropdown) live below the component's early returns. KnowledgeGraph.tsx:236-237 returns Loading graph... or the EmptyState ("No graph data yet" / "ingest documents to build the entity graph") before the toolbar renders, and the diff's filter now routes users into both: a source with zero mentions returns {"nodes": [], "edges": []} (the PR's own test_source_id_filter_with_no_mentions_returns_empty), so the graph, the dropdown, and any exit vanish, and the copy falsely claims no data exists while 200 nodes sit behind the filter — recovery requires leaving the page to reset the useState. Every filter change also swaps the panel for the bare loading line, unmounting the control the user just interacted with. Frequency: every empty source and every filter switch; impact: dead-end plus misleading copy; persistence: every time. Fix: keep the toolbar mounted always, scope loading/empty to the canvas, and give the filtered-empty case its own string (e.g. "No entities from this source yet") instead of the ingest-onboarding copy.

Suggestions

  • The bare <Filter size={10} /> icon floats unlabeled beside the select; the trigger's own "All sources" text already signals the function — drop the icon or fold it into the trigger.

[UX-REVIEWED] a336b01

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

GPT 5.6 Review (fork) — ✅ no blocking findings

Reviewed a336b01d8375ea9fe31618add977c2616fe97cdc via the fork AI-review pipeline; updated in place on each push.

Review details

No findings.
[GPT-REVIEWED] a336b01

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Design Review (Fable 5, fork) — ✅ PASS

Design-level review of a336b01d8375ea9fe31618add977c2616fe97cdc via the fork AI-review pipeline — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

Design-Verdict: PASS

Real hairball problem, solved at the right layer with the existing mentions→items→sources join pattern; proportionate and backward compatible.

Suggestions

  • docs/system-specs/modules/knowledge.md §5 ("Source-scoped list API") already documents the source_id scoping family (/items, /source-counts); the new graph param belongs there in the same commit — the checklist's "no spec doc for this endpoint" is not quite true.
  • Entity-level filtering renders edges whose relation was extracted from another source's items (entity_relations.source_item_id carries provenance but is unused), so a filtered view can assert a relationship the selected source never stated — worth a deliberate note or a follow-up decision, since the PR's stated goal is per-source relationships.
  • Backend accepts comma-separated multi-source values the UI never sends; either wire multi-select later or keep the contract single-value to avoid unexercised public surface.

[DESIGN-REVIEWED] a336b01

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

First Principles Review (Fable 5, fork) — 🟡 CONCERNS

Premise-level review of a336b01d8375ea9fe31618add977c2616fe97cdc via the fork AI-review pipeline — why this exists and whether the shipped surface is the smallest honest version. Updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

Reading the contract, intent file, patch, and the base handler and SimpleSelect component is done; here is the review.

First-Principles-Verdict: CONCERNS

The comma-separated multi-source source_id is a generalized form with exactly one consumer that only ever sends one id — and it diverges from list_items' single-value spelling.

What this change ships

Intent: let a user isolate the knowledge graph to one source so multi-source graphs stop being a hairball — an ADDITION (closes #4636).

  1. Graph API can filter entities by source — justified
  2. source_id accepts a comma-separated list — one consumer, generalized
  3. Filter also matches items held by location after dedup collapse — undeclared
  4. Source dropdown appears in the graph toolbar when 2+ sources exist — justified
  5. Two new strings in 13 locales — justified (documented i18n invariant)
  6. Empty/comma-only filter returns an empty graph instead of erroring — justified

Watch

  • Generalized list, singular use. Grepped source_id across website/src: the only caller is KnowledgeGraph.tsx:340, which always sends a single id from a single-select. The sibling param on /api/knowledge/items (knowledge.py:291) is single-value (i.source_id = ?), so this endpoint now carries a second spelling of the same filter that must stay maintained.
  • Description contradicts the diff on semantics. "reuses the same join pattern already used by list_items" — list_items has no mentions join and no source_locations branch (_matches_source, knowledge.py:248, checks ownership only). The location-OR branch is defensible (it mirrors source_counts' dedup rationale, knowledge.py:587) but is a real, tested behavior the description never declares: filtering by source B surfaces entities from items source A owns.

Subtractions

  • Drop the comma-split and second IN (...) bind in get_full_graph — take one source_id = ? like list_items; re-generalize only when a multi-select consumer exists.

[FIRST-PRINCIPLES-REVIEWED] a336b01

@github-actions

github-actions Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Opus 4.8 Review (fork) — ✅ no blocking findings

Reviewed a336b01d8375ea9fe31618add977c2616fe97cdc via the fork AI-review pipeline; updated in place on each push.

Review details

Both candidates are self-rated low confidence. Let me verify the two factual anchors.

Candidate 1: Source IDs are str(uuid4()) (store.py:1328) — URL-safe, no &/#/space possible. The candidate itself concedes "not currently exploitable." Fails (a)/(c): no concrete input produces a malformed query. Dropped.

Candidate 2: The unfiltered graph is built from store.graph.nodes (all entities, status-agnostic), while the filter adds i.status = 'active'. A divergence exists, but whether non-active items should count toward a source filter is a product-semantics judgment, not an observable wrong outcome — the candidate concedes "could be deliberate." No crash, data loss, or boundary harm. Fails the 80+ bar. Dropped.

No Step 2 finding grounds out: the to_thread correctly resolves store.db per-thread, all IDs are parameterized, and has_node guards every graph access.

No findings.

[OPUS-REVIEWED] a336b01

@github-actions github-actions Bot added readiness: action required A blocking check or review needs attention and removed readiness: checking Automated validation is still running labels Aug 20, 2026
Add a source_id query parameter to GET /api/knowledge/graph that filters
entities to only those mentioned in items belonging to the specified
sources. On the frontend, render a source dropdown in the graph toolbar
when multiple sources exist, allowing users to isolate the graph to a
single knowledge source.

Backward compatible: omitting source_id returns the same result as before.
@severity1
severity1 force-pushed the feat/knowledge-graph-source-filter branch from b234244 to a336b01 Compare August 20, 2026 09:00
@github-actions github-actions Bot added readiness: checking Automated validation is still running readiness: passed Eligible automated validation passed for the current revision and removed readiness: action required A blocking check or review needs attention readiness: checking Automated validation is still running labels Aug 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fork Pull request from a fork (external contributor) readiness: passed Eligible automated validation passed for the current revision

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Knowledge graph visualization: add source filter

3 participants