Skip to content

fix: make citation labels more precise and observable#140

Closed
yilu331 wants to merge 1 commit into
mainfrom
codex/citation-labeling-precision
Closed

fix: make citation labels more precise and observable#140
yilu331 wants to merge 1 commit into
mainfrom
codex/citation-labeling-precision

Conversation

@yilu331

@yilu331 yilu331 commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Stop pre-building multi-item "copy all injected memories" citation markers (reduces over-cite false positives).
  • Resolve unique rank fingerprint drift so true markers still count as applied.
  • Persist unresolved marker ids locally for diagnostics (not on the publish wire).
  • Dashboard shows injected vs applied counts so low application badges are interpretable.

Context

FP (over-cite) is worse than FN. These changes improve label precision and observability without loosening the material-change cite bar or inventing applied credit.

Test plan

  • pytest tests/test_context_format.py tests/test_events.py tests/test_cs_cite.py tests/test_state.py tests/test_codex_support.py
  • Dashboard tsc --noEmit
  • Manual: open /sessions and confirm injected badge appears on sessions with registry files; open a turn with a bad marker id and confirm unresolved row (after install from this branch)

Summary by CodeRabbit

  • New Features

    • Added injected-learning counts to session lists, recent sessions, and session details.
    • Added visibility for unresolved citation markers within session transcripts.
    • Improved citation matching, including case-insensitive and unique rank-based matching.
  • Improvements

    • Unresolved citations are now recorded instead of silently omitted.
    • Updated citation guidance for clearer, more precise linked references.

Stop pre-building multi-item "copy this marker" instructions so models
are not nudged to over-cite every injected memory. Resolve unique rank
fingerprint drift so true markers still count, persist unresolved marker
ids locally for diagnostics (not on the publish wire), and show injected
vs applied counts in the dashboard.
@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change refines citation marker instructions and resolution, records unresolved citation identifiers, counts unique injected entries per session, and exposes both injected counts and unresolved markers in the dashboard.

Changes

Citation and dashboard tracking

Layer / File(s) Summary
Citation marker instructions
plugin/src/claude_smart/context_format.py, tests/test_context_format.py, tests/test_events.py
Citation instructions now emphasize qualifying items, hidden OSC 8 links, linked titles, and updated marker formatting.
Citation resolution and record propagation
plugin/src/claude_smart/events/stop.py, plugin/src/claude_smart/state.py, tests/test_events.py
Citation resolution reports unresolved tokens, supports unique rank-prefix matching, publishes unresolved citations, and tests ambiguous or missing identifiers.
Session counts and turn data
plugin/dashboard/lib/types.ts, plugin/dashboard/lib/session-reader.ts
Session data includes unresolved citation arrays and unique injected-learning counts derived from injection registries.
Injected and unresolved citation UI
plugin/dashboard/components/common/injected-badge.tsx, plugin/dashboard/app/dashboard/page.tsx, plugin/dashboard/app/sessions/page.tsx, plugin/dashboard/app/sessions/[sessionId]/page.tsx
Session lists and detail headers display injected counts, while transcript turns display unresolved citation identifiers.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant AssistantText
  participant StopHook
  participant SessionRecord
  participant DashboardReader
  participant DashboardUI
  AssistantText->>StopHook: provide citation markers
  StopHook->>SessionRecord: publish cited items and unresolved citations
  DashboardReader->>SessionRecord: read session and injected records
  DashboardReader-->>DashboardUI: return turn markers and injected count
  DashboardUI-->>DashboardUI: render badges and unresolved marker rows
Loading

Possibly related PRs

Suggested reviewers: yyiilluu

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: refining citation labels and making them visible in the dashboard and session data.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% 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.
✨ 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 codex/citation-labeling-precision

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.

@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 `@plugin/src/claude_smart/events/stop.py`:
- Around line 299-306: Update the citation-processing loop around
_registry_entry_for_citation to deduplicate resolved entries using the canonical
entry["id"], while maintaining a separate set for unresolved citation tokens.
Ensure case variants or different tokens resolving to the same registry entry
produce only one applied item, without changing unresolved-token handling.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 64da18a8-e432-4d38-a244-0936955998f7

📥 Commits

Reviewing files that changed from the base of the PR and between 045d8b3 and ac57191.

📒 Files selected for processing (11)
  • plugin/dashboard/app/dashboard/page.tsx
  • plugin/dashboard/app/sessions/[sessionId]/page.tsx
  • plugin/dashboard/app/sessions/page.tsx
  • plugin/dashboard/components/common/injected-badge.tsx
  • plugin/dashboard/lib/session-reader.ts
  • plugin/dashboard/lib/types.ts
  • plugin/src/claude_smart/context_format.py
  • plugin/src/claude_smart/events/stop.py
  • plugin/src/claude_smart/state.py
  • tests/test_context_format.py
  • tests/test_events.py

Comment on lines 299 to 306
seen: set[str] = set()
resolved: list[dict[str, Any]] = []
unresolved: list[str] = []
for cid in cited_ids:
if cid in seen:
continue
seen.add(cid)
entry = _registry_entry_for_citation(registry, cid)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Deduplicate by the resolved registry ID.

Case variants or multiple drifted tokens can resolve to the same entry but bypass seen, producing duplicate applied items. Track the canonical entry["id"] after resolution, while separately deduplicating unresolved tokens.

Proposed fix
-    seen: set[str] = set()
+    seen_resolved: set[str] = set()
+    seen_unresolved: set[str] = set()
     resolved: list[dict[str, Any]] = []
     unresolved: list[str] = []
     for cid in cited_ids:
-        if cid in seen:
-            continue
-        seen.add(cid)
         entry = _registry_entry_for_citation(registry, cid)
         if not entry:
+            unresolved_key = cid.lower()
+            if unresolved_key in seen_unresolved:
+                continue
+            seen_unresolved.add(unresolved_key)
             unresolved.append(cid)
             continue
+        canonical_id = str(entry.get("id") or cid).lower()
+        if canonical_id in seen_resolved:
+            continue
+        seen_resolved.add(canonical_id)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
seen: set[str] = set()
resolved: list[dict[str, Any]] = []
unresolved: list[str] = []
for cid in cited_ids:
if cid in seen:
continue
seen.add(cid)
entry = _registry_entry_for_citation(registry, cid)
seen_resolved: set[str] = set()
seen_unresolved: set[str] = set()
resolved: list[dict[str, Any]] = []
unresolved: list[str] = []
for cid in cited_ids:
entry = _registry_entry_for_citation(registry, cid)
if not entry:
unresolved_key = cid.lower()
if unresolved_key in seen_unresolved:
continue
seen_unresolved.add(unresolved_key)
unresolved.append(cid)
continue
canonical_id = str(entry.get("id") or cid).lower()
if canonical_id in seen_resolved:
continue
seen_resolved.add(canonical_id)
🤖 Prompt for 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.

In `@plugin/src/claude_smart/events/stop.py` around lines 299 - 306, Update the
citation-processing loop around _registry_entry_for_citation to deduplicate
resolved entries using the canonical entry["id"], while maintaining a separate
set for unresolved citation tokens. Ensure case variants or different tokens
resolving to the same registry entry produce only one applied item, without
changing unresolved-token handling.

@wenchanghan

Copy link
Copy Markdown
Contributor

Superseded by PR from wenchanghan fork.

@yilu331

yilu331 commented Jul 18, 2026

Copy link
Copy Markdown
Collaborator Author

Superseded by #141 (wenchanghan fork).

@yilu331 yilu331 closed this Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants