Critical fixes:
- Separate notification and command connections to eliminate dual-reader
race condition on the TCL RPC stream (C-1)
- Fix _get_or_create_loop() swallowing its own RuntimeError, causing
deadlock when sync API called from async context (C-2)
- Add bounds checking to config string parser (C-3)
- Clean up OpenOCD subprocess on connection failure in Session.start (H-1)
Defense in depth:
- Add MAX_RESPONSE_SIZE (10MB) guard against unbounded buffer growth
- Preserve bytes after separator in _read_until_separator remainder buffer
- Set notification_failed flag when listener crashes, warn on next send
- Standardize error detection to case-insensitive across all modules
- Escape TCL special characters in RTT channelwrite to prevent injection
- Redirect OpenOCD stdout to DEVNULL to prevent pipe buffer deadlock
- Run SVD XML parsing in asyncio.to_thread to avoid blocking event loop
Consistency:
- Cache SyncSession subsystem wrappers (match async Session pattern)
- Make DecodedRegister frozen (match all other dataclasses)
- Add py.typed marker for PEP 561 type checker support
- Accept list[str] config in OpenOCDProcess.start for paths with spaces
Tests:
- Add 50 error-path tests covering connection, target, memory, register,
flash, breakpoint, session, process, and notification failure modes
Standalone PyPI package providing structured access to the full OpenOCD
command surface via the TCL RPC protocol (port 6666). Async-first API
with sync wrappers for every method.
Subsystems: target control, memory read/write, CPU registers, flash
programming, JTAG chain/scan/boundary, breakpoints/watchpoints, SVD
peripheral decoding, RTT channels, transport/adapter config.
79 tests passing against a mock TCL RPC server.