-
Notifications
You must be signed in to change notification settings - Fork 65
fix(transcript): degrade session_transcript when no kb resolves #593
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -70,6 +70,19 @@ def _store() -> KBStore: | |
| ) from e | ||
|
|
||
|
|
||
| def _store_or_none() -> KBStore | None: | ||
| """The KB when one resolves, else None. | ||
|
|
||
| Only for reads whose data source is outside `.vouch/` — the KB is an | ||
| enrichment, not the subject. Every method that reads or writes knowledge | ||
| must keep using `_store()` so a missing KB stays a hard error. | ||
| """ | ||
| try: | ||
| return _store() | ||
| except RuntimeError: | ||
| return None | ||
|
Comment on lines
+80
to
+83
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win preserve non-missing-kb failures
🤖 Prompt for AI Agents |
||
|
|
||
|
|
||
| def _agent() -> str: | ||
| # An authenticated bearer subject (set by the /mcp transport) is the | ||
| # principal's real identity and must be what proposals/audit attribute to, | ||
|
|
@@ -685,12 +698,13 @@ def kb_session_transcript(session_id: str, agent: str | None = None) -> dict[str | |
| Read-only. Locates the raw Claude Code / Codex file on disk and normalizes | ||
| it into message blocks (text, thinking, tool_use with paired results). | ||
| ``agent`` restricts the search ("claude" | "codex"); omit to try both. | ||
| Degrades to compact capture observations when the raw file is unavailable. | ||
| Degrades to compact capture observations when the raw file is unavailable, | ||
| and to a bare unavailable result when no KB resolves at all. | ||
| """ | ||
| from . import transcript | ||
| if agent is not None and agent not in ("claude", "codex"): | ||
| raise ValueError(f"unknown agent: {agent!r} (expected 'claude' or 'codex')") | ||
| return transcript.load_transcript(_store(), session_id, agent=agent) | ||
| return transcript.load_transcript(_store_or_none(), session_id, agent=agent) | ||
|
|
||
|
|
||
| @mcp.tool() | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -215,6 +215,52 @@ def test_handler_returns_degraded_when_absent( | |
| assert resp["result"]["available"] is False | ||
|
|
||
|
|
||
| def test_handler_degrades_when_no_kb_resolves( | ||
| tmp_path: Path, monkeypatch: pytest.MonkeyPatch | ||
| ) -> None: | ||
| # The sibling test above covers "KB present, raw transcript missing". This | ||
| # one covers "no KB at all", which the handler used to answer with an | ||
| # internal error rather than the degraded envelope. | ||
| monkeypatch.chdir(tmp_path) | ||
| monkeypatch.delenv("VOUCH_KB_PATH", raising=False) | ||
| monkeypatch.delenv("VOUCH_PROJECT_DIR", raising=False) | ||
| monkeypatch.setenv("VOUCH_CLAUDE_PROJECTS_DIR", str(tmp_path / "no-claude")) | ||
| monkeypatch.setenv("CODEX_HOME", str(tmp_path / "no-codex")) | ||
| from vouch.jsonl_server import handle_request | ||
|
|
||
| resp = handle_request({ | ||
| "id": "3", "method": "kb.session_transcript", | ||
| "params": {"session_id": "11111111-1111-1111-1111-111111111111"}, | ||
| }) | ||
| assert resp["ok"] is True | ||
| assert resp["result"]["available"] is False | ||
| assert resp["result"]["observations"] == [] | ||
|
|
||
|
|
||
| def test_load_transcript_without_store_degrades( | ||
| tmp_path: Path, monkeypatch: pytest.MonkeyPatch | ||
| ) -> None: | ||
| monkeypatch.setenv("VOUCH_CLAUDE_PROJECTS_DIR", str(tmp_path / "projects")) | ||
| out = transcript.load_transcript(None, "11111111-1111-1111-1111-111111111111") | ||
|
Comment on lines
+240
to
+244
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win isolate both transcript lookup roots in the direct-load test with proposed fix monkeypatch.setenv("VOUCH_CLAUDE_PROJECTS_DIR", str(tmp_path / "projects"))
+ monkeypatch.setenv("CODEX_HOME", str(tmp_path / "codex"))🤖 Prompt for AI Agents |
||
| assert out["available"] is False | ||
| assert out["observations"] == [] | ||
|
|
||
|
|
||
| def test_mcp_session_transcript_degrades_without_kb( | ||
| tmp_path: Path, monkeypatch: pytest.MonkeyPatch | ||
| ) -> None: | ||
| monkeypatch.chdir(tmp_path) | ||
| monkeypatch.delenv("VOUCH_KB_PATH", raising=False) | ||
| monkeypatch.delenv("VOUCH_PROJECT_DIR", raising=False) | ||
| monkeypatch.setenv("VOUCH_CLAUDE_PROJECTS_DIR", str(tmp_path / "no-claude")) | ||
| monkeypatch.setenv("CODEX_HOME", str(tmp_path / "no-codex")) | ||
| from vouch.server import kb_session_transcript | ||
|
|
||
| out = kb_session_transcript("11111111-1111-1111-1111-111111111111") | ||
| assert out["available"] is False | ||
| assert out["observations"] == [] | ||
|
|
||
|
|
||
| # --- Task 9: Codex parser ------------------------------------------------- | ||
|
|
||
| _CODEX_LINES = [ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
keep added prose lowercase across the vouch sources.
The same path-level rule is violated in each changed docstring/comment:
src/vouch/jsonl_server.py#L87-L92: lowercaseThe,Only, andEvery.src/vouch/server.py#L73-L78: lowercaseThe,Only, andEvery.src/vouch/server.py#L701-L702: lowercaseDegrades.src/vouch/transcript.py#L367-L371: lowercaseNoandThe.src/vouch/transcript.py#L374-L386: lowercaseLocate,Returns, andThe.As per path instructions, comments and review notes under
src/vouch/**must use lowercase prose.📍 Affects 3 files
src/vouch/jsonl_server.py#L87-L92(this comment)src/vouch/server.py#L73-L78src/vouch/server.py#L701-L702src/vouch/transcript.py#L367-L371src/vouch/transcript.py#L374-L386🤖 Prompt for AI Agents
Source: Path instructions