Skip to content

v0.4.0 — hardware link and client executor

Choose a tag to compare

@musokean musokean released this 29 Sep 07:19
· 39 commits to main since this release

forge v0.4.0 — hardware link and client executor

All 18 modules are in. This release closes the last two: the hardware control plane (#16) and the client executor (#17) — an agent that drives other PCs. The offline suite is at 332 cases, CI covers 19 test files across Python 3.9 / 3.11 / 3.13.

Highlights

  • Hardware control plane (#16, Phase 1) — one protocol, two transports:
    • one message = one line of JSON with CRC and seq/ack/state, protocol v1; the same frame goes over serial and MQTT, so swapping the transport does not touch the protocol
    • pyserial's URL mechanism means COM5, a socket:// bridge and loop:// all run the same code path (the tests exercise the real one)
    • the control plane keeps the parts that bite in practice: device aliases that drift, commands crossing sites, inconsistent ACK semantics — plus a staged policy (stage, max level, max temperature, max runtime, cooldown), a command state machine with timeout, retry, rollback and an audit trail
    • device_sim.py is the device-side stand-in that speaks the real protocol; hardware/esp32_beauty_device.ino is a reference firmware skeleton (not compiled or flashed here — honest disclosure, see docs/hardware.md)
    • try it: /device · /device connect · /device mode serial socket://127.0.0.1:9132 · /device audit 5
  • Client executor (#17) — the agent drives other machines. A25's shape, the boring way:
    • each controlled PC runs a light executor that only dials out (HTTP long poll, no inbound port, no firewall change, no new dependencies)
    • capabilities are declared by the client and filtered twice: at the hub (allow-list, staged release readonly/low_risk/approval/closed_loop, timeout, size caps) and again on the client (allow-list, path jail, size caps, and shell runs through that machine's own sandbox)
    • GUI sits behind an injectable driver. Without the optional [executor] extra the client does not declare screenshot/input at all — commands fail with E_NO_GUI instead of pretending to have worked
    • four-role Computer Use: planner → executor → (dispatch → raw evidence) → evaluator → supervisor. Four separate model calls with separate prompts, bindable to different models per role, and the evaluator only ever sees raw evidence — never the executor's own explanation
    • try it: forge --serve on the centre, python executor_agent.py --center <url> --token <KEY> --id pc-01 --root D:/work on the controlled PC, then /executor, /executor run pc-01 "whoami", /executor cua pc-01 "…"
  • 20 tools, up from 14 — the six new ones are executor_list / executor_run / executor_file / executor_screen / executor_input / cua_task

Fixes

  • Dispatched REPL commands were also sent to the model. /web, /serve, /logs and /device were missing continue, so the command ran and the same line went to the router as a task — a silent double execution that burned tokens. test_cli.py now asserts at the source level that every _*_command() call in the dispatch chain is followed by continue
  • Upgraded installs could not switch modes. A config generated before a section existed made /device mode … fail with "no device section". The config writers now append the missing section (device and sandbox) instead of giving up
  • The four-role loop reported finished tasks as failures. First real-machine run: 70s, six steps, ❌ — on a task that had actually been completed and verified. The executor simply never emitted done. Added a completion gate (when the plan runs out, the evaluator judges the whole task from all the evidence); the executor is now told where it may write (the client's path jail travels in the device brief) and to return done as soon as the goal is met. Same task afterwards: 13.2s, 3 steps, ok
  • pytest . no longer collects the release copies — build/ and release/ are excluded (norecursedirs), so a local full run works after a build
  • build/ was accidentally committed once and has been removed and gitignored

Upgrading

pip install --upgrade "handcraft-agent[server,device] @ git+https://github.com/musokean/forge.git@v0.4.0"

Optional extras: [server] HTTP API · [device] serial/MQTT hardware link · [executor] GUI capabilities for the client executor.