Skip to content

ci/hooks: ban direct pyocd / esptool / dfu-util / picotool invocation (mirror FastLED check_forbidden_commands) #694

Description

@zackees

TL;DR

FastLED's ci/hooks/check_forbidden_commands.py blocks agents from invoking low-level build/debug tools directly (ninja, meson, clang++, gcc, pio, gdb, lldb) and points them at bash test / bash compile / bash debug. After FastLED #3336 / #3339 it also blocks raw powershell ... SerialPort patterns.

fbuild has tool_guard.py for soldr enforcement and worktree_guard.py, but no equivalent ban on agents reaching for pyocd, esptool, dfu-util, or direct subprocess.Command(["pyocd", ...]) calls. That's the exact pattern that burned two sessions on the LPC bring-up — agents typing pyocd flash ad-hoc instead of going through the deploy orchestrator that knows about the board's reset method, DTR/RTS conventions, and post-flash recovery.

This issue requests an fbuild-side check_forbidden_commands.py covering the deploy/debug surface.

What to ban

  • pyocd (CLI, any subcommand) — agents should go through fbuild deploy / bash autoresearch.
  • esptool / esptool.py — same; the wrapper knows about ROM-download-mode detection, retry policy, etc.
  • dfu-util (when SAMD/STM32 deploy paths land) — same reasoning.
  • picotool (RP2040) — same.
  • probe-rs CLI — same.
  • Optional bonus: raw cargo invocation (already tracked by tool_guard.py's soldr enforcement, but worth merging the rules into a single hook for discoverability).

Error message shape (mirror FastLED's)

pyocd is forbidden — use `fbuild deploy <board>` or `bash autoresearch <board>` instead.
The deploy orchestrator handles:
  - CMSIS-DAP / SWD reset method dispatch (see fbuild#687)
  - Post-flash VCOM unwedge timing (see fbuild#565)
  - Artifact size validation against board flash region (see fbuild#690)
  - Per-board handoff timing (see fbuild#691)
None of those are run when pyocd is invoked directly. The result is a wedged
VCOM on Windows, silent flash failures past the flash region boundary, and
race conditions on monitor open. Override with FL_AGENT_ALLOW_ALL_CMDS=1 only
for legitimate debug-the-hook cases.

Acceptance criteria

  • ci/hooks/check_forbidden_commands.py exists in fbuild's repo, mirrors FastLED's structure.
  • Bans pyocd, esptool, dfu-util, picotool, probe-rs standalone invocations.
  • Registered in .claude/settings.json as a PreToolUse hook on the Bash tool.
  • Override env var: FL_AGENT_ALLOW_ALL_CMDS=1 (same name as FastLED's for muscle memory).
  • Smoke-tested: each banned tool produces the expected block message; benign mentions in commit bodies / docs are not flagged (lesson from FastLED's first revision tightening, see #3339 review).

Why this matters

The structural lesson from FastLED #3300 / #3325 / #3339 is that "the device looks silent" bugs are almost always agents reaching for a low-level tool that bypasses the project's accumulated knowledge about that board. The fix isn't policy through documentation — agents drift fast — it's policy through hooks.

Refs

Filed from the audit fan-out on FastLED/FastLED#3339.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status
    Triage

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions