Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 10 additions & 28 deletions plugin/src/claude_smart/context_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,42 +264,24 @@ def render_inline_compact_with_registry(


def _compact_citation_instruction(marker_parts: list[str] | None = None) -> str:
del marker_parts # compact guidance must not scale with injected memory count.
if os.environ.get("CLAUDE_SMART_CITATIONS", "on") == "off":
return ""
gate = cs_cite.WHEN_TO_CITE_COMPACT
link_style = os.environ.get(_CITATION_LINK_STYLE_ENV, "markdown")
if link_style == "osc8" and marker_parts:
marker = cs_cite.build_marker(" | ".join(marker_parts), "osc8")
separator_instruction = (
" Separate multiple linked memories with the visible ` | ` separator."
if len(marker_parts) > 1
else ""
)
return _remoteize_citation_instruction(
f"{gate} If you do, copy this final marker exactly, preserving its "
f"hidden OSC 8 terminal link: `{marker}`.{separator_instruction}"
)
if link_style == "osc8":
return _remoteize_citation_instruction(
f"{gate} If you do, end with `{cs_cite.MARKER_PREFIX}` "
"followed by the same linked memory text, then "
f"`{cs_cite.marker_attribution('osc8')}` linking to the reflexio "
"repo; keep the links, but do not show the URL."
)
if marker_parts:
marker = cs_cite.build_marker(" | ".join(marker_parts), "markdown")
separator_instruction = (
" Separate multiple linked memories with the visible ` | ` separator."
if len(marker_parts) > 1
else ""
)
return _remoteize_citation_instruction(
f"{gate} If you do, copy this final marker exactly with markdown "
f"links: `{marker}`.{separator_instruction}"
f"{gate} If you do, end with a final marker like "
f"`{cs_cite.build_marker(_osc8_link('http://localhost:3001/rules/s1-123', 'verify process state'), 'osc8')}` "
"using the linked title and shown rule URL for each memory you actually used; "
"preserve hidden OSC 8 terminal links, do not show raw URLs, and separate multiple "
"linked memories with the visible ` | ` separator."
)
return _remoteize_citation_instruction(
f"{gate} If you do, end with one final marker like "
f"`{cs_cite.MARKDOWN_EXAMPLE_ONE}` using the shown rule URL."
f"{gate} If you do, end with a final marker like "
f"`{cs_cite.MARKDOWN_EXAMPLE_ONE}` using the title and shown rule URL "
"for each memory you actually used; separate multiple linked memories "
"with the visible ` | ` separator."
)


Expand Down
45 changes: 37 additions & 8 deletions tests/test_context_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,17 +283,43 @@ def test_render_inline_compact_with_registry_is_one_logical_line(
assert "prefers concise answers" in md
assert "✨ claude-smart rule applied:" in md
assert md.count("✨ claude-smart rule applied:") == 1
assert "copy this final marker exactly with markdown links" in md
assert "copy this final marker exactly with markdown links" not in md
assert (
"✨ claude-smart rule applied: "
"[Run uv sync after pyproject edits](http://localhost:3001/rules/s1-17) | "
"[prefers concise answers](http://localhost:3001/rules/p1-pref)"
) in md
) not in md
assert cs_cite.MARKDOWN_EXAMPLE_ONE in md
assert "for each memory you actually used" in md
assert "visible ` | ` separator" in md
assert "\x1b]8;;" not in md
assert {entry["id"] for entry in registry} == {"s1-17", "p1-pref"}


def test_render_inline_compact_with_registry_does_not_prebuild_all_markdown_citations(
monkeypatch,
) -> None:
monkeypatch.delenv("CLAUDE_SMART_CITATION_LINK_STYLE", raising=False)

md, registry = context_format.render_inline_compact_with_registry(
project_id="demo",
user_playbooks=[
{"content": "used rule", "user_playbook_id": 1},
{"content": "unused rule", "user_playbook_id": 2},
],
agent_playbooks=[],
profiles=[],
)

assert {entry["id"] for entry in registry} == {"s1-1", "s2-2"}
assert "copy this final marker exactly" not in md
assert "[used rule](http://localhost:3001/rules/s1-1)" not in md
assert "[unused rule](http://localhost:3001/rules/s2-2)" not in md
assert cs_cite.MARKDOWN_EXAMPLE_ONE in md
assert "shown rule URL for each memory you actually used" in md
assert "visible ` | ` separator" in md


def test_render_inline_compact_with_registry_can_emit_osc8_when_requested(
monkeypatch,
) -> None:
Expand All @@ -313,9 +339,12 @@ def test_render_inline_compact_with_registry_can_emit_osc8_when_requested(
profiles=[{"content": "prefers concise answers", "profile_id": "pref"}],
)

assert "\x1b]8;;http://localhost:3001/rules/s1-123\x1b\\" in md
assert "\x1b]8;;http://localhost:3001/rules/s1-17\x1b\\" in md
assert "\x1b]8;;http://localhost:3001/rules/p1-pref\x1b\\" in md
assert "preserving its hidden OSC 8 terminal link" in md
assert "final marker like" in md
assert "for each memory you actually used" in md
assert "preserve hidden OSC 8 terminal links" in md
assert "open: http://localhost:3001/rules/s1-17" not in md
assert {entry["id"] for entry in registry} == {"s1-17", "p1-pref"}

Expand Down Expand Up @@ -414,16 +443,16 @@ def test_render_inline_compact_uses_remote_reflexio_item_pages(monkeypatch) -> N
profiles=[{"content": "prefers concise answers", "profile_id": "pref/one"}],
)

assert "use shared flow (title: use shared flow; open: https://www.reflexio.ai/playbooks?agent_playbook_id=42)" in md
assert (
"[use shared flow](https://www.reflexio.ai/playbooks?agent_playbook_id=42)"
) in md
assert (
"[use safe git flow](https://www.reflexio.ai/playbooks?"
"use safe git flow (title: use safe git flow; open: https://www.reflexio.ai/playbooks?"
"resource=user_playbook&user_playbook_id=17)"
) in md
assert (
"[prefers concise answers](https://www.reflexio.ai/profiles?profile_id=pref%2Fone)"
"prefers concise answers (title: prefers concise answers; open: "
"https://www.reflexio.ai/profiles?profile_id=pref%2Fone)"
) in md
assert "[use shared flow](https://www.reflexio.ai/playbooks?agent_playbook_id=42)" not in md
assert "http://localhost:3001/rules/" not in md


Expand Down
9 changes: 6 additions & 3 deletions tests/test_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Any

import pytest
from claude_smart import state
from claude_smart import cs_cite, state
from claude_smart.events import post_tool, session_start, stop, user_prompt

# -----------------------------------------------------------------------------
Expand Down Expand Up @@ -1061,12 +1061,15 @@ def test_user_prompt_injects_compact_context_for_codex(
assert "Run uv sync after pyproject edits: Run uv sync" not in markdown
assert "prefers anyio over asyncio" in markdown
assert "✨ claude-smart rule applied:" in markdown
assert "copy this final marker exactly with markdown links" in markdown
assert "copy this final marker exactly with markdown links" not in markdown
assert (
"✨ claude-smart rule applied: "
"[Run uv sync after pyproject edits](http://localhost:3001/rules/s1) | "
"[prefers anyio over asyncio](http://localhost:3001/rules/p1)"
) in markdown
) not in markdown
assert cs_cite.MARKDOWN_EXAMPLE_ONE in markdown
assert "for each memory you actually used" in markdown
assert "visible ` | ` separator" in markdown
assert "\x1b]8;;" not in markdown


Expand Down
Loading