* fix(gateway): keep custom-skill rollback filesystem IO off the event loop
Closes#5747. Three blocking sites remained on the Gateway event loop in
the rollback route and its shared response reader, all offloaded through
asyncio.to_thread following the #5729 pattern:
- storage.validate_skill_markdown_content() creates a temp dir and writes
SKILL.md into it (site 1)
- the post-scan read of the file being replaced (site 2, named by #5729's
test docstring)
- _read_custom_skill_response(): load_skills() walks every skill directory
and read_custom_skill() opens SKILL.md — O(installed skills) loop time
paid per accepted rollback and per GET /skills/custom/{name} (site 3)
A blocking_io regression drives the full accepted-rollback path (past the
security scan) under the strict gate; the two pre-existing cases only
covered the pre-scan branches.
* fix(gateway): keep the skill element type in the response-parts closure
Review nit on #5751: tuple[object, ...] erased the element type for the
_skill_to_response call; Skill is already imported in this module.