Skip to content

Commit b2a18ee

Browse files
nficanoclaude
andcommitted
refactor SDK structure
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d5411dd commit b2a18ee

374 files changed

Lines changed: 15777 additions & 13073 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.refactor/baseline.md

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Refactor Baseline (pre-work)
2+
3+
Captured: 2026-05-14
4+
5+
## Tests
6+
7+
- 139 passed, 3 skipped, 0 failed
8+
- Coverage: 73.27% (gate target: 90%)
9+
- Skipped tests are intentional documented races (see `tests/state/`)
10+
11+
## Ruff
12+
13+
- `ruff check .`**0 violations** (with current ruleset)
14+
- `ruff format --check .`**0 files would change**
15+
16+
## Mypy strict
17+
18+
- 14 errors across 8 files (after installing mypy)
19+
- Categories:
20+
-`no-any-return` at Pydantic `.model_dump()`/typed-dict boundaries
21+
- 2× missing `arcp.ARCPClient`/`StaticBearerVerifier` re-exports for CLI
22+
- 1× server `EventLog`/`InMemoryEventLog` Liskov mismatch
23+
- 1× server `_subscribe` missing `await` on async iter call
24+
- 1× client `Job*Payload` Liskov mismatch
25+
- 1× CLI `event_log` argument typing
26+
- misc unused-ignore / name-defined
27+
28+
## Hard-limit violations (Guide §0)
29+
30+
### Files > 300 lines
31+
- `src/arcp/_runtime/server.py` — 744
32+
- `src/arcp/_client/client.py` — 479
33+
- `src/arcp/_runtime/job.py` — 372
34+
- `src/arcp/_messages/execution.py` — 348
35+
36+
### Functions > 5 args / complexity > 8
37+
- `src/arcp/_auth/jwt.py:16``JWTVerifier.__init__` (7 args)
38+
- `src/arcp/_client/client.py:69``ARCPClient.__init__` (7 args)
39+
- `src/arcp/_client/client.py:183``submit` (8 args)
40+
- `src/arcp/_client/client.py:291``_handshake` (11 args)
41+
- `src/arcp/_runtime/server.py:110``ARCPRuntime.__init__` (>5 args)
42+
- `src/arcp/_runtime/server.py:340``_dispatch` (complexity 11)
43+
- `src/arcp/_runtime/server.py:532``_run_job` (complexity 11)
44+
- `src/arcp/_runtime/session.py:150``make_session_state` (6 args)
45+
46+
### Other inventory
47+
- `__all__` missing: `cli.py`, `__main__.py` (both are CLI entry points — acceptable)
48+
- `from __future__ import annotations` missing on a few `__init__.py` shims (acceptable; they have no annotations)
49+
- `setup.py` / `setup.cfg`: none (PEP 621 already)
50+
- `src/` layout: ✓ already
51+
- `py.typed` marker: present

.refactor/public_api.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Public API Surface (pre-refactor)
2+
3+
Captured from `__all__` in `src/arcp/__init__.py`, `src/arcp/client/__init__.py`,
4+
and `src/arcp/runtime/__init__.py`. **No symbol below may be removed or
5+
renamed without a major bump.**
6+
7+
## `arcp` (top-level)
8+
9+
### Envelope
10+
- `Envelope`
11+
12+
### Errors
13+
- `ARCPError`, `ERROR_CODES`, `error_class_for`, `error_from_payload`
14+
- `AgentNotAvailableError`, `AgentVersionNotAvailableError`,
15+
`BudgetExhaustedError`, `CancelledError`, `DuplicateKeyError`,
16+
`HeartbeatLostError`, `InternalError`, `InvalidRequestError`,
17+
`JobNotFoundError`, `LeaseExpiredError`, `LeaseSubsetViolationError`,
18+
`PermissionDeniedError`, `ResumeWindowExpiredError`, `TimeoutError`,
19+
`UnauthenticatedError`
20+
21+
### Messages
22+
- `Capabilities`, `ClientInfo`, `Lease`, `LeaseConstraints`,
23+
`ListJobsFilter`, `RuntimeInfo`, `SessionResume`,
24+
`SessionWelcomePayload`
25+
- `parse_agent_ref`, `parse_budget_amount`
26+
27+
### Transports
28+
- `Transport`, `TransportClosed`, `MemoryTransport`,
29+
`pair_memory_transports`, `StdioTransport`, `WebSocketTransport`,
30+
`serve_websocket`
31+
32+
### Version / features
33+
- `PROTOCOL_VERSION`, `IMPL_VERSION`, `V1_1_FEATURES`,
34+
`intersect_features`
35+
36+
## `arcp.client`
37+
- `ARCPClient`, `AutoAckOptions`, `JobHandle`, `JobSubscription`
38+
39+
## `arcp.runtime`
40+
- `ARCPRuntime`, `AuthorizationContext`, `JobAuthorizationPolicy`
41+
- `Agent`, `Job`, `JobContext`, `ResultStream`
42+
- `SessionContext`, `SessionState`
43+
- `BearerVerifier`, `Identity`, `StaticBearerVerifier`, `JWTVerifier`
44+
- `EventLog`, `InMemoryEventLog`, `SqliteEventLog`
45+
- `LeaseOpContext`, `assert_lease_subset`, `initial_budget_from_lease`,
46+
`is_lease_subset`, `validate_lease_constraints`,
47+
`validate_lease_op`, `validate_lease_shape`
48+
49+
## CLI entry point
50+
- `arcp` (console script → `arcp.cli:main`)
51+
52+
## Notes
53+
- The CLI imports `ARCPClient`/`StaticBearerVerifier` from `arcp` top-level
54+
(mypy flags this as missing). They are *not* re-exported there today;
55+
the CLI relies on the dynamic re-export chain. Honor either by
56+
(a) keeping CLI internal, or (b) adding top-level re-exports. Choice
57+
documented in CHANGELOG.

.refactor/violations.md

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Violations Inventory
2+
3+
## File length > 300 lines (Guide §0)
4+
5+
| File | Lines | Plan |
6+
| ----------------------------------- | ----- | ----------------------------------------------------- |
7+
| `src/arcp/_runtime/server.py` | 744 | Split: lifecycle / dispatch / job-run / housekeeping |
8+
| `src/arcp/_client/client.py` | 479 | Split: connection / handshake / job ops |
9+
| `src/arcp/_runtime/job.py` | 372 | Split: data classes vs. ResultStream impl |
10+
| `src/arcp/_messages/execution.py` | 348 | Split: payload models / helpers / parsers |
11+
12+
## Function-level violations (`ruff --select C901,PLR0913,PLR0912`)
13+
14+
| Location | Issue | Plan |
15+
| ------------------------------------------ | ------------------------------ | ----------------------------------- |
16+
| `_auth/jwt.py:16` JWTVerifier.__init__ | 7 args | Group into `JWTVerifierConfig` dc |
17+
| `_client/client.py:69` ARCPClient.__init__ | 7 args | Group into `ClientConfig` dc |
18+
| `_client/client.py:183` submit | 8 args | Group into `JobSubmit` dc |
19+
| `_client/client.py:291` _handshake | 11 args | Group into `HandshakeArgs` dc |
20+
| `_runtime/server.py:110` __init__ | >5 args | Group into `RuntimeConfig` dc |
21+
| `_runtime/server.py:340` _dispatch | complexity 11 | Dict-of-handlers |
22+
| `_runtime/server.py:532` _run_job | complexity 11 | Extract phases |
23+
| `_runtime/session.py:150` make_session_state | 6 args | Group into `SessionParams` dc |
24+
25+
## Mypy --strict errors (14 total)
26+
27+
| Location | Issue | Plan |
28+
| --------------------------------------- | ---------------------------------------------- | ------------------------------------ |
29+
| `middleware/asgi.py:48` | Any return on model_dump() | `cast(dict[str, Any], ...)` |
30+
| `middleware/aiohttp.py:43` | same | same |
31+
| `_transport/stdio.py:38` | same | same |
32+
| `_transport/websocket.py:46` | same | same |
33+
| `_transport/websocket.py:67` | Any return on int|None | explicit cast |
34+
| `_transport/websocket.py:86` | `Server` name-defined (TYPE_CHECKING) | proper import guard |
35+
| `_messages/execution.py:67` | unused type:ignore | drop comment |
36+
| `_client/client.py:213` | Liskov: payload class union narrowing | use match/cast |
37+
| `_client/client.py:366` | Any return | explicit cast |
38+
| `_runtime/server.py:135` | `EventLog|InMemoryEventLog` vs `EventLog` | hoist InMemoryEventLog into hierarchy |
39+
| `_runtime/server.py:679` | missing await on async iter | `async for x in await coro` |
40+
| `cli.py:13` | missing top-level `ARCPClient` | import from `arcp.client` |
41+
| `cli.py:13` | missing top-level `StaticBearerVerifier` | import from `arcp.runtime` |
42+
| `cli.py:48` | event_log subtype mismatch | widen param type |
43+
44+
## Coverage (60% → 90% target)
45+
46+
Currently 73.27%. Largest gaps:
47+
- `_runtime/server.py` 68%
48+
- `_runtime/session.py` 57%
49+
- `_transport/base.py` 63%
50+
- `_transport/in_memory.py` 84%
51+
- `_envelope.py` (check)
52+
53+
## Other inventory
54+
55+
- `print()` in library code: **none** (verified)
56+
- bare `except`: **none** (verified)
57+
- wildcard imports: **none** (verified)
58+
- mutable default args: **none flagged by ruff**
59+
- `Optional`/`Union` style: **none** (verified — already uses `X | None`)
60+
- `setup.py`/`setup.cfg`: **none**
61+
- `py.typed`: **present**
62+
- src layout: **present**
63+
64+
## Decisions for documented judgment calls
65+
66+
1. **`coverage --cov-fail-under=60` → 90.** The guide mandates 90.
67+
Bump in the same PR.
68+
2. **`ruff.lint.mccabe.max-complexity` not configured.** Set to 8.
69+
3. **`ruff.lint.pylint.max-args` not configured.** Set to 5.
70+
4. **`pyright` is in `pyproject.toml` (strict).** Add `mypy --strict`
71+
alongside, keep pyright for IDEs.
72+
5. **Doctests:** add `--doctest-modules` to default pytest invocation.
73+
6. **`pre-commit`:** add config invoking ruff + mypy.

0 commit comments

Comments
 (0)