You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Fail the run command on failed actions and fix hotkey key codes
run exited 0 whenever the file loaded; the executor now counts the failures
it records and run exits 1 on any. A recording that could not start wrote []
over the output file, and a second recording leaked the first input hook.
Punctuation hotkeys registered unrelated virtual keys, combos Windows cannot
take were accepted and retried every tick, and a history or executor error
ended the hotkey listener. The legacy entry point reports a missing file or
directory without a traceback.
| Legacy CLI |`python -m je_auto_control` (`__main__.py`) |`-e/--execute_file FILE`, `-d/--execute_dir DIR`, `-c/--create_project PATH`, `--execute_str JSON`. `--execute_str` also accepts a double-encoded JSON string. Any error exits 1 with a log line rather than a traceback, and a `-d` path that is not a directory is an error. |
48
48
| MCP server |`je_auto_control_mcp` → `utils/mcp_server/__main__.py:main`| stdio; `start_mcp_stdio_server()`; HTTP transport via the `AC_start_mcp_http_server` command. |
-**What**: An audit of `cli.py`, the legacy `__main__.py`, the recording wrapper and recorder base, and `utils/hotkey`, with the platform input stubbed.
373
+
-**CLI**: (1) `run` returned 0 even when actions failed — the executor records a failure and goes on — so CI could not tell a failed run from a clean one. The executor now counts, per thread, the failures it records (`reset_recorded_failures` / `recorded_failures` in `action_executor.py`; failures that propagate, e.g. inside `AC_try`, are left to whoever catches them), and `run` exits 1 with "N action(s) failed". (2) `failure-bundle --context '[1]'` ended in a `TypeError` traceback; a non-object context is an error message. (3) A recording whose hook could not start still wrote `[]` over the output file and reported "Recorded 0 action(s)" with status 0. `record()` returns whether it started and `record_to_json` raises instead of writing; a negative `--duration` is refused.
374
+
-**Legacy entry point** (a cross-project contract; flags and the success exit code are unchanged): the `except` did not include `AutoControlException`, so a missing or invalid action file ended in a raw traceback — exit status 1 already, so only the output changes. A `-d` path that is not a directory ran nothing and exited 0; it is an error now. `architecture.md` §6 says both.
375
+
-**Recording**: `InputRecorder._start` replaced a running hook without stopping it, leaving the first low-level hook and its message pump installed for the process's life (`AC_record` twice, or `record_to_json` after a stray `record()`); it stops the old one.
376
+
-**Hotkeys**: (1) `_key_to_vk` used `ord()` for any single character, but a virtual-key code equals the code point only for A-Z and 0-9: `ctrl+.` registered VK_DELETE, `ctrl+[` VK_LWIN, `ctrl+,` VK_SNAPSHOT. The US-layout `VK_OEM_*` codes are mapped and other characters refused. (2) `bind` accepted combos `RegisterHotKey` cannot take (`ctrl+foo`); on Windows it validates with `parse_combo`. (3) The Windows backend retried a failed registration on every 50 ms tick, logging an error 20 times a second while another program owned the combo; a failed binding is retried only when its combo changes. (4) `_fire_binding` recorded the run in history outside its `try`, so a history failure ended the listener thread, and it caught a fixed tuple around an injected executor, so a `KeyError` did the same; history failures are logged and the executor call is a documented broad catch. `fired` is counted under the lock.
377
+
-**Checked and fine**: `run`, `validate`, `fmt` and `codegen` report bad files cleanly; the callback executor keeps trigger and callback errors apart; recorded actions validate and replay; timeline gaps are clamped; the recording editor's operations bound-check and do not mutate their input.
378
+
-**Tests**: `test_cli_hotkey_audit.py` (new, 21; 18 fail on the previous commit, the others guard a clean run and the A-Z / 0-9 mapping). `test_cli.py`'s record stub returns `True`, as `record()` now does.
0 commit comments