feat(#192): Phase 3 — muse commit runs installed pre-commit hooks
Wires Phases 1-2's declared-hooks + local-activation machinery into the real commit path. This is the phase that actually closes the gap: nothing runs automatically until now.
Added: - muse/core/hooks.py: HookRunResult + run_hook_point(). No-op (executed=False, passed=True) when this clone doesn't have hooks installed or nothing is declared for the given hook point -- callers never need to check is_installed() separately. Runs commands via the shell (cwd=root), stopping at the first non-zero exit; subsequent commands never run once one fails (fail-fast, matching a pre-commit gate's purpose). - muse/cli/commands/commit.py: - New --no-verify flag: skips hook execution entirely. Never silent -- always adds a "Skipped pre-commit hooks (--no-verify)." warning (JSON `warnings` array, or a printed stderr line in text mode). - Hook execution inserted right before the dry-run/write branch: dry-run never executes hook commands (a pure preview shouldn't have side effects from arbitrary shell commands); real commits do. - "defined_not_installed" state adds a warning (not a hard block) -- hooks that were never activated for this clone don't silently gate anything, but the gap is visible in every commit's output. - A failing "installed" hook aborts the commit with exit 1 before any object is written, naming the exact failed command and its captured output (new _CommitHookFailedJson schema).
Tests (TDD, red confirmed before implementation): - tests/test_core_hooks_run.py (8 tests): not-installed no-op, nothing- declared no-op, passing/failing commands, first-failure short-circuits later commands, stderr capture, cwd=root. - tests/test_cmd_commit_hooks.py (12 tests, HK_20-23): passing hook allows commit; defined-not-installed doesn't block but does warn; failing hook blocks with exit 1 and names the command; failing hook writes zero objects (HEAD unchanged); --no-verify bypasses a failing hook and is never silent (including when nothing was installed at all, still harmless); no warning when hooks are properly installed or when nothing is defined; dry-run never executes hook commands even when one would fail. - Manually smoke-tested against a real disposable repo via muse-dev: failing hook blocks, --no-verify gets it through visibly.
90/90 across all hooks test files + tests/test_app.py (27). Full regression run of tests/test_cmd_commit.py + 5 related commit test files (151 tests) still green -- no regressions to existing commit behavior.
Note: HK_ACCEPT_01 (the full .museagent.md-drift reproduction using `muse agent-config status --fail-if-out-of-sync`) is deferred to Phase 5, once that flag exists.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Semantic Changes
50 symbols
Files Changed
+2
~2
1182 in snapshot
0 comments
muse hub commit comment sha256:5f7b38765462d4b092afecab903684171b41c9e7aabc0f6515088d43c5e2cb4f --body "your comment"
No comments yet. Be the first to start the discussion.