**The byte budget trusted server-declared sizes.** A manifest advertising
`size: 1` — or, since the wire schema deliberately accepts it for reporting,
no size at all — sailed through the declared budget and then served
arbitrarily large bodies. The 16 MiB safeguard protected against an honest
server only, which is no safeguard.
The walk now tracks bytes ACTUALLY received and stops issuing reads once the
real total crosses the cap, marking the report `incomplete` and so `ok:
false`. The declared prefilter is kept rather than replaced: it refuses to
schedule an obviously oversized set, and the received-byte counter stops one
that lied. The count happens after verifying the crossing file, so that file
is still reported rather than fetched and discarded.
⚠️ This bounds the total across responses, not any single one: a first
response larger than the cap is already in memory before it can be measured,
which would need a streaming read the client API does not expose. Stated in
the code rather than left to look closed.
**A modern `skills/get` did not require `resultType`.** The "left open"
question SEP-2640 states covers `ttlMs` / `cacheScope` and only those;
`resultType` is base-protocol per SEP-2322 and appears in the SEP's own
`skills/get` example. Requiring it of `resources/directory/read` but not here
was an inconsistency in the module rather than a distinction the spec draws.
Era-selected now, with the caching attributes still optional.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ND46Ci64DC3tzBy9aG81Nc
Signed-off-by: cliffhall <cliff@futurescale.com>