feat(#192): Phase 1 — .musehooks.toml parser + `muse hooks list`
musehub#192: muse has no commit-lifecycle hook mechanism today, confirmed by direct source audit (no .muse/hooks/, no --no-verify, `muse commit`'s own documented algorithm has no hook step). This gap let two real incidents through in one session: musehub#182's un-guarded stale merge, and this workspace's own .museagent.md/CLAUDE.md drift going undetected because `muse agent-config status` never ran automatically.
Phase 1 of the MVP plan: a new tracked file format, `.musehooks.toml`, at repo root -- same naming family as .museignore/.museattributes/.museagent.md and deliberately NOT inside .muse/, since .muse/ is unconditionally excluded from every snapshot (muse/core/paths.py) and a file placed there can never be committed, pushed, or survive a clone -- the exact mistake that made `.muse/agent.md` dead on arrival.
Added: - muse/core/hooks.py: HooksFile dataclass + load_hooks() parser, following muse/core/attributes.py's established conventions (1 MiB size cap, explicit isinstance checks, missing file = valid empty state, malformed TOML/unknown hook point = ValueError with a clear message). MVP scope is deliberately just one hook point, VALID_HOOK_POINTS = {"pre-commit"} -- no arbitrary shell scripts, no other lifecycle points yet (see #192 "Out of Scope"). - muse/cli/commands/hooks.py: `muse hooks list` -- read-only, prints declared hook points and commands (table/JSON). This command only displays hook definitions, it never executes anything -- local activation (`muse hooks install`) lands in Phase 2, and only an installed hook ever runs, in Phase 3's `muse commit` integration. - Registered in muse/cli/app.py alphabetically between hash-object and hub.
Tests (TDD, red confirmed before implementation): - tests/test_core_hooks.py (13 tests): parsing (missing/empty/comment-only file, single/multiple commands, empty commands list, section with no commands key) and validation (malformed TOML, unknown hook point, non-string command, commands not a list, oversized file, VALID_HOOK_POINTS scope assertion). - tests/test_cmd_hooks.py (7 tests): `muse hooks list` with/without a .musehooks.toml file, JSON and text output, malformed-TOML and unknown-hook-point error paths (exit 1, message on stderr), not-a-repo (exit 2). - Manually smoke-tested against a real disposable repo via muse-dev (init, hooks list with/without file, --help) -- all correct.
20/20 new tests pass. tests/test_app.py (27 tests, covers CLI registration) still green.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Semantic Changes
186 symbols
Files Changed
+4
~1
1178 in snapshot
0 comments
muse hub commit comment sha256:4802c0281407b5de70ce1b34bbe1d1cd055533cbd4b8be35861a6a3eb545c1dc --body "your comment"
No comments yet. Be the first to start the discussion.