Skip to content

Commit 62f3eb8

Browse files
fix: address CodeRabbit review on stats exclusion and tests
- Enforce exclusion rules on GET .../stats (parity with session detail) - Clarify API error envelope exception for project sessions 400 - MD040 fences, CLI subprocess timeout, stricter search hit keys Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent 1d10287 commit 62f3eb8

5 files changed

Lines changed: 25 additions & 7 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ Reads from `~/.claude/projects/` which contains JSONL session files created by C
9898

9999
See **[`docs/architecture.md`](docs/architecture.md)** for layered design, data flow, and the dispatch-table ordering rationale.
100100

101-
```
101+
```text
102102
claude-code-chat-browser/
103103
├── app.py # Flask entry point (default port 5000)
104104
├── api/

api/sessions.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,13 @@ def get_session_stats(project_name: str, session_id: str) -> FlaskReturn:
7474

7575
try:
7676
session = parse_session(filepath)
77+
rules = current_app.config.get("EXCLUSION_RULES") or []
78+
if is_session_excluded(rules, session, project_name):
79+
return error_response(
80+
ErrorCode.SESSION_NOT_FOUND,
81+
"Session not found",
82+
404,
83+
)
7784
except _PARSE_ERRORS:
7885
current_app.logger.exception("Failed to parse session %s", session_id)
7986
return error_response(

docs/api-reference.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ None. The server binds to `127.0.0.1` by default and reads `~/.claude/projects/`
1616

1717
## Error envelope
1818

19-
Every `4xx` and `5xx` response from `/api/*` uses this shape:
19+
Most `/api/*` error responses use this shape:
2020

2121
```json
2222
{
@@ -25,6 +25,14 @@ Every `4xx` and `5xx` response from `/api/*` uses this shape:
2525
}
2626
```
2727

28+
**Exception (no `{error, code}` body):**
29+
30+
| Endpoint | Status | Body |
31+
|----------|--------|------|
32+
| `GET /api/projects/<project_name>/sessions` | 400 | `[]` (empty JSON array) when `project_name` fails path validation |
33+
34+
All other documented error paths below use the structured envelope.
35+
2836
Extra fields may appear for specific codes (for example `since` on invalid bulk-export mode).
2937

3038
| Field | Stability | Notes |

docs/architecture.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
## Component diagram
66

7-
```
7+
```text
88
┌─────────────────────────────┐
99
│ ~/.claude/projects/ │
1010
│ <project>/*.jsonl │ (read-only data source)

tests/test_search.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def _assert_search_hits(results: list, *, max_items: int) -> None:
2222
assert len(results) <= max_items
2323
for item in results:
2424
assert isinstance(item, dict)
25-
assert _SEARCH_HIT_KEYS.issubset(item.keys())
25+
assert set(item.keys()) == _SEARCH_HIT_KEYS
2626

2727

2828
def test_limit_integer_string(client_single):
@@ -50,9 +50,12 @@ def test_limit_default(client_single):
5050

5151

5252
def test_limit_whitespace_defaults(client_single):
53-
resp = client_single.get("/api/search?q=Hello&limit=%20%20%20")
54-
assert resp.status_code == 200
55-
_assert_search_hits(resp.get_json(), max_items=50)
53+
resp_default = client_single.get("/api/search?q=Hello")
54+
resp_ws = client_single.get("/api/search?q=Hello&limit=%20%20%20")
55+
assert resp_ws.status_code == 200
56+
assert resp_default.status_code == 200
57+
_assert_search_hits(resp_ws.get_json(), max_items=50)
58+
assert len(resp_ws.get_json()) == len(resp_default.get_json())
5659

5760

5861
def test_limit_zero(client_single):

0 commit comments

Comments
 (0)