Skip to content

agent: surface ACK_FLASH_ERROR instead of returning empty bytes#101

Merged
widgetii merged 1 commit into
masterfrom
agent-client-loud-on-ack-rejection
May 15, 2026
Merged

agent: surface ACK_FLASH_ERROR instead of returning empty bytes#101
widgetii merged 1 commit into
masterfrom
agent-client-loud-on-ack-rejection

Conversation

@widgetii
Copy link
Copy Markdown
Member

Summary

  • FlashAgentClient.read_memory() previously broke its accumulator loop on any RSP_ACK and returned the buffer as-is. When the agent rejected the address — e.g. a probe outside the V3+/V4+ I/O whitelist in agent/main.c:addr_readable — that meant b\"\" silently. Now it inspects the ACK status byte and raises RuntimeError(\"Read rejected by agent: status=0x02 …; addr=… size=…\").
  • FlashAgentClient.crc32() had the same shape — a clean RSP_ACK rejection was reported as a generic "CRC32 response invalid". Now it explicitly detects the ACK and reports the status.
  • Adds the missing ACK_FLASH_ERROR = 0x02 to src/defib/agent/protocol.py (it already existed in agent/protocol.h). Updates the existing membw rejection test to reference the constant.

Context

Surfaced while studying flash on an eMMC-based hi3516av300 over the running agent. The eMMC controller MMIO lives at 0x10100000..0x101FFFFF which isn't in the agent's V3+/V4+ whitelist; probing there silently returned b\"\" for ~30s of wall time across multiple addresses, leading to wasted debugging.

Test plan

  • uv run pytest tests/ -x --ignore=tests/fuzz — 496 passed, 2 skipped
  • uv run ruff check src/defib/agent/ tests/test_agent_protocol.py — clean
  • uv run mypy src/defib/agent/ --ignore-missing-imports — clean
  • Verified on real hardware (hi3516av300, eMMC D9D16): probing 0x10100000 now reports Read rejected by agent: status=0x02 (outside agent's readable whitelist or flash read failed); addr=0x10100000 size=64 instead of returning empty bytes.

🤖 Generated with Claude Code

`FlashAgentClient.read_memory` previously broke its accumulator loop on
any RSP_ACK and returned whatever the buffer held — `b""` when the agent
rejected the address (e.g. a probe outside the V3+/V4+ I/O whitelist in
`agent/main.c:addr_readable`). Callers couldn't tell a successful empty
read from a rejection.

Same shape in `FlashAgentClient.crc32`, where a clean RSP_ACK rejection
was reported as a generic "CRC32 response invalid".

Now both inspect the ACK status byte and raise a RuntimeError naming the
status, the address, and the size — surfaced while probing eMMC controller
MMIO at 0x10100000 on hi3516av300 returned empty bytes silently for ~30s.

Also adds the missing `ACK_FLASH_ERROR = 0x02` to the Python protocol
constants (already in agent/protocol.h) and updates the existing membw
rejection test to use the constant instead of the 0x02 literal.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@widgetii widgetii merged commit 45da1d6 into master May 15, 2026
13 checks passed
@widgetii widgetii deleted the agent-client-loud-on-ack-rejection branch May 15, 2026 13:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant