Repository navigation
Reimplement the engine in Node for native cross-platform support - #17
Closed
chris-peterson wants to merge 2 commits into
Closed
chris-peterson wants to merge 2 commits into
chris-peterson wants to merge 2 commits into
Conversation
Reimplement the PreToolUse engine in Node so it runs natively on every platform Claude Code runs on, removing the Python interpreter-resolution problem that blocks native Windows support (#15). watchdog.py stays in place and remains the engine hooks.json invokes; the cutover and its removal are a later step. The 20-file test corpus is re-pointed at the Node engine (invocations only, assertions unchanged) and passes, plus a new tests/test-node-port.sh pinning the port-specific behaviors a high-effort review surfaced: - flush stdout fully before exit, so a deny reason larger than the OS pipe buffer is not truncated into an unparseable decision - Python-faithful empty-needle Edit reconstruction and command_shape basename - first-line-only schema read on the logging hot path - microsecond ts format matching datetime.isoformat - documented JS RegExp semantics: ASCII \w \d \b and end-of-string $ as an accepted v1.0.0 limitation (SPEC [RL-03a]/[RL-03b]), and graceful invalid-UTF-8 Edit handling ([EN-13a]), an improvement over the Python engine
Wire hooks.json to invoke the Node engine and the ported Node hooks (node scripts/watchdog.mjs, hooks/emit-rules.mjs, hooks/cli-freshness.mjs), so the engine that runs on a user's machine no longer depends on a Python interpreter being resolvable — closing the native cross-platform gap (#15). - Port the decision-log analyzer and reset tool to Node (scripts/analyze.mjs, scripts/reset.mjs); analyze.mjs imports commandShape from watchdog.mjs so the engine (writer) and analyzer (reader) keep one shared shape definition. - Port the SessionStart scripts (emit-rules.mjs, cli-freshness.mjs). - Export commandShape from watchdog.mjs and guard main() so importing the module for the shared helper neither reads stdin nor emits a decision. - Delete the Python engine and the bash SessionStart scripts (watchdog.py, analyze-decisions.py, reset-decisions.py, emit-rules.sh, cli-freshness.sh) now that Node replaces them. - Inline the rules-YAML parser into build/gen-rules-doc.py, which had imported it from the deleted engine; generated docs are byte-identical. - Add .github/workflows/ci.yml: the Ubuntu job runs the corpus; a windows-latest job exercises the Node engine directly (deny, allow-by-silence, SessionStart emit) as the cross-platform evidence. - Re-point test-analyze / test-reset-decisions / test-ambient at the Node ports; full corpus green. Update SPEC/AGENTS/README/SCHEMA/STATUS for the Node engine. Build/release tooling that runs only in CI on Linux (gen-plugin-json.py, gen-rules-doc.py, changelog-prepend.py) stays Python.
Owner
Author
|
closing -- this can serve as a reference as/when committing to this direction |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
ClaudeWatch targeted Unix only:
hooks.jsoninvoked the engine aspython3 …, which doesn't resolve on a vanilla native-Windows install (nopython3on PATH, nobash), so a Windows user got no safety net — silently (#15). A portable-launcher approach was tried first (#16) buthooks.jsonhas no per-OS command syntax, so a.sh/.ps1pair can't be selected per platform. The supported cross-platform pattern is to invokenode, which ships with Claude Code and is always on PATH. So the engine is reimplemented in Node:node scripts/watchdog.mjsruns on every platform Claude Code runs on, and the interpreter-resolution problem disappears.What changed
scripts/watchdog.mjs(Node, stdlib-only, ESM) — behaviorally equivalent to the formerwatchdog.py, proven by the existing 20-file decision corpus re-pointed at it (assertions unchanged) plustests/test-node-port.shpinning port-specific behaviors.scripts/analyze.mjs/scripts/reset.mjs;analyze.mjsimportscommandShapefromwatchdog.mjsso writer and reader keep one shared shape definition.hooks/emit-rules.mjs/hooks/cli-freshness.mjs.hooks.jsonrewired: all four hook commands invokenode ….watchdog.py,analyze-decisions.py,reset-decisions.py,emit-rules.sh,cli-freshness.sh) — one engine, and the tested engine is now the shipped engine.build/gen-rules-doc.pyhad imported the rules parser from the engine; the parser is inlined into it (generated docs verified byte-identical). Release/CI-only Python tooling (gen-plugin-json.py,gen-rules-doc.py,changelog-prepend.py) stays Python — it never runs on a user's machine..github/workflows/ci.ymladded: Ubuntu runs the corpus; awindows-latestjob exercises the Node engine directly (deny, allow-by-silence, SessionStart emit) — the native-Windows evidence that can't be produced from a Mac.Accepted v1.0.0 limitations (documented in SPEC.md)
JS
RegExpsemantics differ from Pythonreat two edges, surfaced by a high-effort review and accepted rather than translated (the rules target ASCII shell tokens; a Unicode-faithful\brewrite would risk new divergence):\w/\d/\bare ASCII ([RL-03b]), and trailing$matches only at true end-of-string. Invalid-UTF-8 Edits are handled gracefully ([EN-13a]) where the Python engine crashed.Verification
bash tests/test-watchdog.sh— full corpus green (incl. the Node-ported analyze/reset/ambient suites andtest-node-port).just plugin-json-check— passes.windows-latestCI job on this PR.Release
Intended as the 1.0.0 release (runtime change). The version is written from the release tag, not in this PR; cut
v1.0.0on merge.Closes #15.